#  This is version 0.3 of absent
#
#               Copyright (c) 1999 by AT&T.
#  Permission to use, copy, and modify this software without fee is
#  hereby granted, provided that this entire notice is included in all
#  copies of any software which is or includes a copy or modification
#  of this software and in all copies of the supporting documentation
#  for such software.
#
#  SOME PARTS OF ABSENT MAY BE RESTRICTED UNDER UNITED STATES EXPORT
#  REGULATIONS.
#
#  THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
#  IMPLIED WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE
#  ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
#  MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
#  PURPOSE.
package Otp;
use strict;
use Carp;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);

require Exporter;
require DynaLoader;
require AutoLoader;

@ISA = qw(Exporter DynaLoader);
@EXPORT = qw();

$VERSION = "0.01";

sub AUTOLOAD {
    # This AUTOLOAD is used to 'autoload' constants from the constant()
    # XS function.  If a constant is not found then control is passed
    # to the AUTOLOAD in AutoLoader.

    my $constname;
    ($constname = $AUTOLOAD) =~ s/.*:://;
    my $val = constant($constname, @_ ? $_[0] : 0);
    if ($! != 0) {
	if ($! =~ /Invalid/) {
	    $AutoLoader::AUTOLOAD = $AUTOLOAD;
	    goto &AutoLoader::AUTOLOAD;
	}
	else {
	    croak "Your vendor has not defined otp macro $constname";
	}
    }
    eval "sub $AUTOLOAD { $val }";
    goto &$AUTOLOAD;
}

bootstrap Otp $VERSION;

# Called: $result = register_user($name,$phrase,$n)

sub register_user {
   my ($name,$phrase,$n) = @_;

   return(otp_register_user($name,$phrase,$n));

}


# Called: $challenge = make_challenge($name)

sub make_challenge {
 my ($name) = @_;
 my $challenge = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

    otp_make_challenge($name,$challenge);
    return($challenge);

}


# Called: $result = check_response($name,$response)

sub check_response {
  my ($name,$response) = @_;

  return(otp_check_response($name,$response));

}

sub login_user {
  my ($name) = @_;

  otp_login_user($name);

}

1;
__END__

=head1 NAME

Otp, make_challenge, check_response, login_user - Front ends to OPIE functions

=head1 SYNOPSIS

    use Otp;
    
    # register user frebblebit with passphrase 'munchkin', 250 challenges
    if(Otp::register_user('frebblebit', 'munchkin', 250) < 0)
    # ... 
    # elided: frebblebit was not successfully registered
    # ...
    # get a new challenge for user frebblebit
    $challenge=Otp::make_challenge('frebblebit');
    # ...
    # elided: send challenge to user, read response into $rsp
    # ...
    if(Otp::check_response('frebblebit', $rsp)) {
	Otp::login_user('frebblebit');
    }

=head1 DESCRIPTION

This module is a set of front-ends to the one-time-password system
OPIE.  It is not mature, stable, or complete enough for general use.
It is a wrapper around the otp.c file shipped as part of the absent
system, and is intended for use with absent.  It is unlikely to be
useful for any other purpose.

3 Functions are implemented:

=over

=item register_user NAME, PASSPHRASE, N

Add user NAME to the OPIE database, with passphrase PASSPHRASE, and set
the number of challenges for NAME to N.  The system will generate a seed
and store the name, seed, and hashed passphrase.  If N is 0, the default
value for N, 499, will be used.  No checking is performed to ensure that
a valid user is not being overwritten.  The calling function is assumed
to perform any necessary authentication.

=item make_challenge NAME

Returns a string containing the next OPIE challenge for user NAME.  Challenge
is empty if NAME isn't a known user.

=item check_response NAME, RESPONSE

Returns 1 if RESPONSE is a correct response to the current challenge for NAME.
Returns 0 otherwise.

=item login_user NAME

This function is only meaningful for the absent system, where it is used
to note that a user has succesfully answered the challenge and that a new
key and user table entry should be generated for the user.

=head1 BUGS

This code probably won't work outside of absent.

=head1 AUTHOR

The absent project, absent@research.att.com

=back

=cut

