Apache2-AuthenSecurID
view release on metacpan or search on metacpan
Auth/Auth.pm view on Meta::CPAN
# $Id: Auth.pm,v 1.10 2007/12/08 03:19:43 atobey Exp $
package Apache2::AuthenSecurID::Auth;
use strict;
use ModPerl::Registry;
use Apache2::porting;
use Apache2::Request;
use Apache2::Const qw(:common);
use IO::Socket::INET;
use Crypt::CBC;
use CGI qw(:standard);
use vars qw($VERSION);
$VERSION = '0.5';
sub handler {
my $r = shift;
my $req = Apache2::Request->new($r);
# seed the random number generator
srand( time ^ $$ ^ unpack "%L*", `ps axww | gzip -f` );
#get params
my $username = $req->param('username');
my $passcode = $req->param('passcode');
my $type = $req->param('type');
my $uri = $req->param('a');
# get ace_initd config directives
my $ace_initd_server = $r->dir_config("ace_initd_server") || "localhost";
my $ace_initd_port = $r->dir_config("ace_initd_port") || 1969;
# grab apache session cookie
my ($session_id) =
( ( $r->headers_in->{"Cookie"} || "" ) =~ /Apache=([^;]+)/ );
my $client = IO::Socket::INET->new(
PeerAddr => $ace_initd_server,
PeerPort => $ace_initd_port,
Proto => 'udp'
);
my %ACE;
my $request;
my $message;
my $extra_input;
if ( ( !$username && !$passcode )
|| ( $type ne "pin" && !$passcode )
|| ( $passcode =~ /\:/ ) )
{
$message = qq{
Please enter your username and passcode<br/>
Your passcode is your 4 - 8 digit pin plus<br/>
6 digit SecurID code. If you do not have<br/>
a PIN yet just enter the 6 digit SecurID code.
};
$extra_input = qq{
<label for="passcode">Passcode :</label>
<input type="password" name="passcode" id="passcode"/>
<input type="hidden" name="type" value="check"/>
<input type="hidden" name="a" value="$uri"/>
};
}
else {
if ( $type eq "pin" ) {
( $passcode, $message, $extra_input ) = check_pin( $r, $req );
if ($passcode) {
( $message, $extra_input ) =
Do_ACE( $username, $passcode, $type, $session_id, $client, $r, $req );
}
}
else {
( $message, $extra_input ) =
Do_ACE( $username, $passcode, $type, $session_id, $client, $r, $req );
}
}
my $head = qq|
<body>
<head>
<title>SecurID Authentication</title>
<style>
label {
font-family: monospace;
}
p {
font-family: sans-serif;
margin-left: auto;
margin-right: auto;
}
</style>
</head>
<html>
<!-- $session_id -->
<form method="post">
<fieldset style="width: 500px; margin-left: auto; margin-right: auto; background: #cccccc;">
<legend>SecurID Authorization</legend>
<p>$message</p>
<br/>
<label for="username">Username :</label>
<input type="text" name="username" value="$username" id="username"/>
<br/>
$extra_input
<br/>
<br/>
<input type="submit" name="Submit" value="Enter"/>
<input type="reset" name="reset"/>
<br/>
</fieldset>
</form>
</html>
|;
$r->content_type('text/html');
#$r->send_http_header;
$r->print($head);
return Apache2::Const::OK;
}
sub check_pin {
my ( $r, $req ) = @_;
my $pin1 = $req->param('pin1');
my $pin2 = $req->param('pin2');
my $alphanumeric = $req->param('alphanumeric');
my $min_pin_len = $req->param('min_pin_len');
my $max_pin_len = $req->param('max_pin_len');
my $uri = $req->param('a');
my $message;
my $extra_info = qq{
<span style="font-weight: bold;">User Authenticated</span>
<label for="pin1">PIN :</label>
<input type="password" name="pin1" id="pin1"/>
<input type="hidden" name="type" value="pin"/>
<input type="hidden" name="a" value="$uri"/>
<input type="hidden" name="alphanumeric" value="$alphanumeric"/>
<input type="hidden" name="min_pin_len" value="$min_pin_len"/>
<input type="hidden" name="max_pin_len" value="$max_pin_len"/>
<label for="pin1">PIN ( Again ) :</label>
<input type="password" name="pin2" id="pin2"/>
};
if ( $pin1 != $pin2 ) {
$message = qq{
<span style="font-weight: bold;">New Pin Required</span>
<p>
Pins do not match!!
</p>
<p>
Please enter a $min_pin_len to $max_pin_len digit pin.
</p>
};
return ( 0, $message, $extra_info );
}
if ($alphanumeric) {
if ( $pin1 =~ /[^0-9a-zA-Z]/ ) {
$message = qq{
<span style="font-weight: bold;">New Pin Required</span>
<p>
Pin must be alphanumeric!!
</p>
<p>
Please enter a $min_pin_len to $max_pin_len digit pin.
</p>
};
return ( 0, $message, $extra_info );
}
}
else {
if ( $pin1 =~ /[^0-9]/ ) {
$message = qq{
<span style="font-weight: bold;">New Pin Required</span>
<p>
Pin must be numeric!!
</p>
<p>
Please enter a $min_pin_len to $max_pin_len digit pin.
</p>
};
return ( 0, $message, $extra_info );
}
}
my $pin_length = length($pin1);
if ( $pin_length < $min_pin_len || $pin_length > $max_pin_len ) {
$message = qq{
<span style="font-weight: bold;">New Pin Required</span>
<p>
Pin must be the correct length!!
</p>
<p>
Please enter a $min_pin_len to $max_pin_len digit pin.
</p>
};
return ( 0, $message, $extra_info );
}
return ( $pin1, 0, 0 );
}
sub Do_ACE {
my ( $username, $passcode, $type, $session_id, $client, $r, $req ) = @_;
$ENV{'VAR_ACE'} ||= "/opt/ace/data";
my $message;
my $extra_input;
my $result;
my %info;
my $ace;
my $mesg;
my $my_rand = rand();
my $return_rand;
my $crypt_key = $r->dir_config("AuthCryptKey");
my $crypt = new Crypt::CBC( $crypt_key, "Blowfish" );
$mesg =
$crypt->encrypt_hex("$my_rand:$session_id:$type:$username:$passcode");
$client->send($mesg);
$client->recv( $mesg, 1024 );
$mesg = $crypt->decrypt_hex($mesg);
(
$return_rand, $result, $info{system_pin}, $info{min_pin_len},
$info{max_pin_len}, $info{alphanumeric}, $info{user_selectable}
) = split /\:/, $mesg;
if ( $my_rand ne $return_rand ) {
$result = 100;
}
( $message, $extra_input ) =
Ace_Result( $result, \%info, $r, $crypt, $req, $username );
return ( $message, $extra_input );
}
sub Ace_Result {
my ( $result, $info, $r, $crypt, $req, $username ) = @_;
my $message;
my $uri = $req->param('a');
my $extra_input = qq{
<label for="passcode">Passcode :</label>
<input type="password" name="passcode" id="passcode"/>
<input type="hidden" name="type" value="check"/>
<input type="hidden" name="a" value="$uri"/>
};
my $time = time();
if ( $result == 0 ) {
my $auth_cookie = $r->dir_config("AuthCookie") || "SecurID";
my $auth_user_cookie = $r->dir_config("AuthUserCookie")
|| "SecurID_User";
my $crypt_cookie = $crypt->encrypt_hex("$time:$username");
$r->headers_out->add( "Set-Cookie" => $auth_user_cookie . "="
. $username
. "; path="
. "/" );
$r->headers_out->add( "Set-Cookie" => $auth_cookie . "="
. $crypt_cookie
. "; path="
. "/" );
$uri = $crypt->decrypt_hex($uri);
# success
$message = qq{
<span style="font-weight: bold;">User Authenticated</span>
<script language="javascript">
window.location="$uri";
</script>
<!-- <p>
If you do not have Java Script enabled<br/>
please click <a href="$uri">here</a> to go to<br/>
the protected page.
</p> -->
<p>
Plase enter your username and passcode<br/>
Your passcode is your 4 - 8 digit pin plus<br/>
6 digit SecurID code. If you do not have<br/>
a PIN yet just enter the 6 digit SecurID code.
</p>
};
$extra_input = '';
}
elsif ( $result == 1 ) {
# failure
$message = qq{
<span style="font-weight: bold;">User Authenticated Failed</span>
<p>
Plase enter your username and passcode<br/>
Your passcode is your 4 - 8 digit pin plus<br/>
6 digit SecurID code. If you do not have<br/>
a PIN yet just enter the 6 digit SecurID code.
</p>
};
}
elsif ( $result == 100 ) {
# failure
$message = qq{
<span style="font-weight: bold;">User Authenticated Failed</span>
<p>
The ACE server is either down or behaving<br/>
incorrectly. Please conact your system<br/>
administrator.
</p>
};
}
elsif ( $result == 2 ) {
# next token code
$message = qq{
<span style="font-weight: bold;">Next Token Required</span>
<p>
Plase wait for you token to change and enter<br/>
the 6 digit SecurID token code.
</p>
};
$extra_input = qq{
<label for="passcode">Passcode :</label>
<input type="password" name="passcode" id="passcode"/>
<input type="hidden" name="type" value="next"/>
<input type="hidden" name="a" value="$uri"/>
};
}
elsif ( $result == 5 ) {
# New PIN required.
if ( $$info{user_selectable} >= 1 ) {
$message = qq|
<span style="font-weight: bold;">New Pin Required</span>
<p>
Please enter a $$info{min_pin_len} to $$info{max_pin_len} digit pin.
</p>
|;
$extra_input = qq|
<label for="pin1">PIN :</label>
<input type="password" name="pin1" id="pin1"/>
<input type="hidden" name="type" value="pin"/>
<input type="hidden" name="a" value="$uri"/>
<input type="hidden" name="alphanumeric" value="$$info{alphanumeric}"/>
<input type="hidden" name="min_pin_len" value="$$info{min_pin_len}"/>
<input type="hidden" name="max_pin_len" value="$$info{max_pin_len}"/>
<label for="pin1">PIN ( Again ) :</label>
<input type="password" name="pin2" id="pin2"/>
|;
}
else {
$message = qq|
<span style="font-weight: bold;">You have been assigned a new PIN.</span>
<p>
Your PIN is: <$$info{system_pin}</span><p>
Please remember your PIN. Do not share it<br/>
with anyone else.
</p>
<p>
Please enter your username and passcode<br/>
Your passcode is your 4 - 8 digit pin plus<br/>
6 digit SecurID code.
</p>
|;
}
}
elsif ( $result == 6 ) {
$message = qq{
<span style="font-weight: bold;">PIN Accepted</span>
<p>
Please remember you PIN. Do not share it<br/>
with anyone else.
</p>
<p>
Please enter your username and passcode<br/>
Your passcode is your 4 - 8 digit pin plus<br/>
6 digit SecurID code.
</p>
};
}
elsif ( $result == 7 ) {
$message = qq{
<span style="font-weight: bold;">PIN Rejected</span>
<p>
If you're having difficulties, please contact<br/>
the system administrator.<br/><br/>
Please enter your username and passcode<br/>
Your passcode is your 4 - 8 digit pin plus<br/>
6 digit SecurID code.
</p>
};
}
return ( $message, $extra_input );
}
1;
__END__
=head1 NAME
Apache2::AuthenSecurID::Auth - Authentication handler for Apache2::AuthenSecurID
=head1 SYNOPSIS
# Configuration in httpd.conf
( run in 0.905 second using v1.01-cache-2.11-cpan-5837b0d9d2c )