X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=cgi-auth-hybrid.pm;h=76342e4aef319d4f4cc465b22661ae43ff1762f2;hb=5800c9b719b18dc727171cf66b8dcd410b18b434;hp=e258bdc2b613a26ff95e14702e251e06e25fa0c8;hpb=eae7a8e60d250db29b7f7cc58afd6f46b388c26f;p=cgi-auth-flexible.git diff --git a/cgi-auth-hybrid.pm b/cgi-auth-hybrid.pm index e258bdc..76342e4 100644 --- a/cgi-auth-hybrid.pm +++ b/cgi-auth-hybrid.pm @@ -1,5 +1,21 @@ # -*- perl -*- +# This is part of CGI::Auth::Hybrid, a perl CGI authentication module. +# Copyright (C) 2012 Ian Jackson. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + BEGIN { use Exporter (); our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); @@ -14,8 +30,11 @@ BEGIN { our @EXPORT_OK; use DBI; +use CGI; + +#---------- verifier object methods ---------- -sub new { +sub new_verifier { my $class = shift; my $s = { S => { @@ -29,12 +48,11 @@ sub new { login_timeout => 86400, # seconds param_name => 'cah_associd', cookie_name => 'cah_associd', # make undef to disable cookie - cgi => undef, - get_param => sub { $s->_c()->param($s->{S}{param_name}) }, + get_param => sub { $_[0]->param($s->{S}{param_name}) }, get_cookie => sub { $s->{S}{cookie_name} - ? $s->_c()->cookie($s->{S}{cookie_name}) + ? $_[0]->cookie($s->{S}{cookie_name}) : '' }, - get_method => sub { $s->_c()->request_method() }, + get_method => sub { $_[0]->request_method() }, }, D => undef, }; @@ -44,14 +62,10 @@ sub new { $s->{S}{$k} = $v; } bless $s, $class; + $s->_dbopen(); return $s; } -sub _c ($) { - my ($s) = @_; - return $s->{S}{cgi}; -} - sub _dbopen ($) { my ($s) = @_; my $dbh = $s->{D}; @@ -79,67 +93,116 @@ sub _dbopen ($) { return $dbh; } +#---------- request object methods ---------- + +sub new_request { + my ($classbase, $cgi, @extra) = @_; + if (!ref $classbase) { + $classbase = $classbase->new_verifier(@extra); + } else { + die if @extra; + } + my $r = { + S => $classbase->{S}, + D => $classbase->{D}, + C => $cgi, + }; + bless $r, ref $classbase; +} + +sub _cm ($$@) { + my ($r,$methname, @args) = @_; + my $methfunc = $r->{S}{$methname}; + return $methfunc->($r->{C}, $r, @args); +} + sub record_login ($$) { - my ($s,$nusername) = @_; - my $rsp = $s->{S}{random_source}; + my ($r,$nusername) = @_; + my $rsp = $r->{S}{random_source}; my $rsf = new IO::File $rsp, '<' or die "$rsp $!"; - my $bytes = ($s->{S}{associdlen} + 7) >> 3; + my $bytes = ($r->{S}{associdlen} + 7) >> 3; my $nassocbin; $!=0; read($rsf,$nassocbin,$bytes) == $bytes or die "$rsp $!"; close $rsf; my $nassoc = unpack "H*", $nassocbin; - my $dbh = $s->_dbopen(); - $dbh->do("INSERT INTO $s->{S}{assocdb_table}". + my $dbh = $r->{D}; + $dbh->do("INSERT INTO $r->{S}{assocdb_table}". " (associd, username, last) VALUES (?,?,?)", {}, $nassoc, $nusername, time); $dbh->do("COMMIT"); - $username = $nusername; - $assoc = $nassoc; + $r->{U} = $nusername; + $r->{A} = $nassoc; } sub _check ($) { - my ($s) = @_; - my $qassoc = $s->{S}{param_get}(); + my ($r) = @_; + my $qassoc = $r->_cm('get_param'); if (!defined $qassoc) { - $qassoc = $s->{S}{cookie_get}(); + $qassoc = $r->_cm('get_cookie'); return undef unless defined $qassoc; - return undef unless $s->{S}{get_method}() eq 'GET'; + return undef unless $r->_cm('get_method') eq 'GET'; } - my $dbh = $s->_dbopen(); + my $dbh = $r->_dbopen(); my ($nusername, $nlast) = $dbh->selectrow_array("SELECT username, last". - " FROM $s->{S}{assocdb_table}". + " FROM $r->{S}{assocdb_table}". " WHERE associd = ?", {}, $qassoc); return undef unless defined $nusername; - my $timeout = $s->{S}{login_timeout}; + my $timeout = $r->{S}{login_timeout}; return undef unless !defined $timeout || time <= $nlast + $timeout; return ($nusername, $qassoc); } sub check ($) { - my ($s) = @_; + my ($r) = @_; - my ($nusername, $qassoc) = $s->_check() or return undef; + my ($nusername, $qassoc) = $r->_check() or return undef; # hooray - $dbh->do("UPDATE $s->{S}{assocdb_table}". + $dbh->do("UPDATE $r->{S}{assocdb_table}". " SET last = ?". " WHERE associd = ?", {}, time, $qassoc); $dbh->do("COMMIT"); - $username = $nusername; - $assoc = $qassoc; + $r->{U} = $nusername; + $r->{A} = $qassoc; return $username; } sub logout ($) { - my ($s) = @_; + my ($r) = @_; - if (my ($nusername, $qassoc) = $s->_check()) { - $dbh->do("DELETE FROM $s->{S}{assocdb_table}". + if (my ($nusername, $qassoc) = $r->_check()) { + $dbh->do("DELETE FROM $r->{S}{assocdb_table}". " WHERE associd = ?", {}, $qassoc); $dbh->do("COMMIT"); } } + +sub username ($) { + my ($r) = @_; + return $r->{U}; + +sub hiddenv ($) { + my ($r) = @_; + return defined $r->{A} ? $r->{A} : ''; +} + +sub hiddena ($) { + my ($r) = @_; + return (-name => $r->{param_name}, + -default => $r->hiddenv()); +} + +sub hiddenh ($) { + my ($r) = @_; + return hidden($r->hiddena()); +} + +sub cookieac ($) { + my ($r) = @_; + return (-name => $r->{cookie_name}, + -value => hiddenv()); +