X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=lib%2FCGI%2FEx%2FAuth.pm;h=38797d784c16a9dad699046cb9e496c0ff025a8b;hb=refs%2Ftags%2Fv2.24;hp=85c28fe0dc0794c0c8d82a09698a14bb13b8a0cb;hpb=a2f50b1efd2bc986617e1de5f5a0bfd8a2953b0e;p=chaz%2Fp5-CGI-Ex diff --git a/lib/CGI/Ex/Auth.pm b/lib/CGI/Ex/Auth.pm index 85c28fe..38797d7 100644 --- a/lib/CGI/Ex/Auth.pm +++ b/lib/CGI/Ex/Auth.pm @@ -18,7 +18,7 @@ use MIME::Base64 qw(encode_base64 decode_base64); use Digest::MD5 qw(md5_hex); use CGI::Ex; -$VERSION = '2.19'; +$VERSION = '2.24'; ###----------------------------------------------------------------### @@ -49,6 +49,8 @@ sub get_valid_auth { local $self->{'no_cookie_verify'} = 1; $self->check_valid_auth; # verify the logout so we can capture the username if possible + $self->logout_hook; + if ($self->bounce_on_logout) { my $key_c = $self->key_cookie; $self->delete_cookie({key => $key_c}) if $self->cookies->{$key_c}; @@ -72,6 +74,7 @@ sub get_valid_auth { next if ! defined $hash->{$key}; last if ! $is_form && $had_form_data; # if form info was passed in - we must use it only $had_form_data = 1 if $is_form; + next if ! length $hash->{$key}; ### if it looks like a bare username (as in they didn't have javascript) - add in other items my $data; @@ -88,7 +91,6 @@ sub get_valid_auth { user => delete $hash->{$key}, test_pass => delete $hash->{ $self->key_pass }, expires_min => delete($hash->{ $self->key_save }) ? -1 : delete($hash->{ $self->key_expires_min }) || $self->expires_min, - payload => delete $hash->{ $self->key_payload } || '', }, from => 'form', }) || next; @@ -99,12 +101,13 @@ sub get_valid_auth { } ### generate a fresh cookie if they submitted info on plaintext types - if ($self->use_plaintext || ($data->{'type'} && $data->{'type'} eq 'crypt')) { + if ($is_form + && ($self->use_plaintext || ($data->{'type'} && $data->{'type'} eq 'crypt'))) { $self->set_cookie({ key => $self->key_cookie, val => $self->generate_token($data), no_expires => ($data->{ $self->key_save } ? 0 : 1), # make it a session cookie unless they ask for saving - }) if $is_form; # only set the cookie if we found info in the form - the cookie will be a session cookie after that + }); ### always generate a cookie on types that have expiration } else { @@ -138,6 +141,7 @@ sub handle_success { ### if they have cookies we are done } elsif (scalar(keys %{$self->cookies}) || $self->no_cookie_verify) { + $self->success_hook; return $self; ### need to verify cookies are set-able @@ -151,6 +155,22 @@ sub handle_success { } } +sub success_hook { + my $self = shift; + if (my $meth = $self->{'success_hook'}) { + return $meth->($self); + } + return; +} + +sub logout_hook { + my $self = shift; + if (my $meth = $self->{'logout_hook'}) { + return $meth->($self); + } + return; +} + sub handle_failure { my $self = shift; my $args = shift || {}; @@ -181,10 +201,19 @@ sub handle_failure { ### allow for a sleep to help prevent brute force sleep($self->failed_sleep) if defined($data) && $data->error ne 'Login expired' && $self->failed_sleep; + $self->failure_hook; return; } +sub failure_hook { + my $self = shift; + if (my $meth = $self->{'failure_hook'}) { + return $meth->($self); + } + return; +} + sub check_valid_auth { my $self = shift; $self = $self->new(@_) if ! ref $self; @@ -269,7 +298,6 @@ sub key_expires_min { shift->{'key_expires_min'} ||= 'cea_expires_min' } sub form_name { shift->{'form_name'} ||= 'cea_form' } sub key_verify { shift->{'key_verify'} ||= 'cea_verify' } sub key_redirect { shift->{'key_redirect'} ||= 'cea_redirect' } -sub key_payload { shift->{'key_payload'} ||= 'cea_payload' } sub key_loggedout { shift->{'key_loggedout'} ||= 'loggedout' } sub bounce_on_logout { shift->{'bounce_on_logout'} ||= 0 } sub secure_hash_keys { shift->{'secure_hash_keys'} ||= [] } @@ -281,6 +309,7 @@ sub use_plaintext { my $s = shift; $s->use_crypt || ($s->{'use_plaintext'} || sub use_base64 { my $s = shift; $s->{'use_base64'} = 1 if ! defined $s->{'use_base64'}; $s->{'use_base64'} } sub expires_min { my $s = shift; $s->{'expires_min'} = 6 * 60 if ! defined $s->{'expires_min'}; $s->{'expires_min'} } sub failed_sleep { shift->{'failed_sleep'} ||= 0 } +sub disable_simple_cram { shift->{'disable_simple_cram'} } sub logout_redirect { my ($self, $user) = @_; @@ -305,19 +334,20 @@ sub no_cookies_print { sub login_print { my $self = shift; my $hash = $self->login_hash_common; - my $template = $self->login_template; + my $file = $self->login_template; ### allow for a hooked override if (my $meth = $self->{'login_print'}) { - $meth->($self, $template, $hash); + $meth->($self, $file, $hash); return 0; } ### process the document - require CGI::Ex::Template; - my $cet = CGI::Ex::Template->new($self->template_args); + my $args = $self->template_args; + $args->{'INCLUDE_PATH'} ||= $args->{'include_path'} || $self->template_include_path, + my $t = $self->template_obj($args); my $out = ''; - $cet->process_simple($template, $hash, \$out) || die $cet->error; + $t->process_simple($file, $hash, \$out) || die $t->error; ### fill in form fields require CGI::Ex::Fill; @@ -330,14 +360,17 @@ sub login_print { return 0; } -sub template_args { - my $self = shift; - return $self->{'template_args'} ||= { - INCLUDE_PATH => $self->template_include_path, +sub template_obj { + my ($self, $args) = @_; + return $self->{'template_obj'} || do { + require Template::Alloy; + Template::Alloy->new($args); }; } -sub template_include_path { shift->{'template_include_path'} || '' } +sub template_args { $_[0]->{'template_args'} ||= {} } + +sub template_include_path { $_[0]->{'template_include_path'} || '' } sub login_hash_common { my $self = shift; @@ -353,17 +386,14 @@ sub login_hash_common { key_time => $self->key_time, key_save => $self->key_save, key_expires_min => $self->key_expires_min, - key_payload => $self->key_payload, key_redirect => $self->key_redirect, form_name => $self->form_name, script_name => $self->script_name, path_info => $self->path_info, md5_js_path => $self->js_uri_path ."/CGI/Ex/md5.js", - use_plaintext => $self->use_plaintext, $self->key_user => $data->{'user'} || '', $self->key_pass => '', # don't allow for this to get filled into the form $self->key_time => $self->server_time, - $self->key_payload => $self->generate_payload({%$data, login_form => 1}), $self->key_expires_min => $self->expires_min, text_user => $self->text_user, text_pass => $self->text_pass, @@ -378,7 +408,7 @@ sub login_hash_common { sub verify_token { my $self = shift; my $args = shift; - my $token = delete $args->{'token'} || die "Missing token"; + my $token = delete $args->{'token'}; die "Missing token" if ! length $token; my $data = $self->new_auth_data({token => $token, %$args}); my $meth; @@ -523,9 +553,10 @@ sub verify_password { } } - ### looks like a normal cram + ### looks like a simple_cram } elsif ($data->{'cram_time'}) { - $data->add_data(type => 'cram'); + $data->add_data(type => 'simple_cram'); + die "Type simple_cram disabled during verify_password" if $self->disable_simple_cram; my $real = $pass =~ /^[a-f0-9]{32}$/ ? lc($pass) : md5_hex($pass); my $str = join("/", @{$data}{qw(user cram_time expires_min payload)}); my $sum = md5_hex($str .'/'. $real); @@ -577,7 +608,7 @@ sub generate_token { my $pass = defined($data->{'test_pass'}) ? $data->{'test_pass'} : $data->{'real_pass'}; $token = $data->{'user'} .'/'. $pass; - ### all other types go to cram - secure_hash_cram, cram, plaintext and md5 + ### all other types go to cram - secure_hash_cram, simple_cram, plaintext and md5 } else { my $user = $data->{'user'} || die "Missing user"; my $real = defined($data->{'real_pass'}) ? ($data->{'real_pass'} =~ /^[a-f0-9]{32}$/ ? lc($data->{'real_pass'}) : md5_hex($data->{'real_pass'})) @@ -588,7 +619,7 @@ sub generate_token { die "User can not contain a \"/\." if $user =~ m|/|; my $array; - if (! $data->{'prefer_cram'} + if (! $data->{'prefer_simple_cram'} && ($array = eval { $self->secure_hash_keys }) && @$array) { my $rand1 = int(rand @$array); @@ -597,6 +628,7 @@ sub generate_token { my $sum = md5_hex($str .'/'. $real .('/sh.'.$array->[$rand1].'.'.$rand2)); $token = $str .'/'. $sum . '/sh.'.$rand1.'.'.$rand2; } else { + die "Type simple_cram disabled during generate_token" if $self->disable_simple_cram; my $str = join("/", $user, $self->server_time, $exp, $load); my $sum = md5_hex($str .'/'. $real); $token = $str .'/'. $sum; @@ -719,7 +751,6 @@ sub login_form { [% error %]