3 # This is part of CGI::Auth::Hybrid, a perl CGI authentication module.
4 # Copyright (C) 2012 Ian Jackson.
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Affero General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU Affero General Public License for more details.
16 # You should have received a copy of the GNU Affero General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
26 %EXPORT_TAGS = ( ); # eg: TAG => [ qw!name1 name2! ],
28 @EXPORT_OK = qw(setup);
39 assocdb_path => 'cah-assocs.db';
42 assocdb_password => '',
43 assocdb_table => 'assocs',
44 random_source => '/dev/urandom',
45 associdlen => 128, # bits
46 login_timeout => 86400, # seconds
47 param_name => 'cah_associd',
48 cookie_name => 'cah_associd', # make undef to disable cookie
50 get_param => sub { $s->_c()->param($s->{S}{param_name}) },
51 get_cookie => sub { $s->{S}{cookie_name}
52 ? $s->_c()->cookie($s->{S}{cookie_name})
54 get_method => sub { $s->_c()->request_method() },
59 while (($k,$v,@_) = @_) {
60 die "unknown setting $k" unless exists $s->{S}{$k};
77 $s->{S}{assocdb_dsn} ||= "dbi:SQLite:dbname=$s->{S}{assocdb_path}";
80 $dbh = DBI->open($s->{S}{assocdb_dsn}, $s->{S}{assocdb_user},
81 $s->{S}{assocdb_password}, {
82 AutoCommit => 0, RaiseError => 1,
84 die "${assocdb_dsn} $! ?" unless $dbh;
90 $dbh->do("CREATE TABLE $s->{S}{assocdb_table} (".
91 " associd VARCHAR PRIMARY KEY,".
99 sub record_login ($$) {
100 my ($s,$nusername) = @_;
101 my $rsp = $s->{S}{random_source};
102 my $rsf = new IO::File $rsp, '<' or die "$rsp $!";
103 my $bytes = ($s->{S}{associdlen} + 7) >> 3;
106 read($rsf,$nassocbin,$bytes) == $bytes or die "$rsp $!";
108 my $nassoc = unpack "H*", $nassocbin;
109 my $dbh = $s->_dbopen();
110 $dbh->do("INSERT INTO $s->{S}{assocdb_table}".
111 " (associd, username, last) VALUES (?,?,?)", {},
112 $nassoc, $nusername, time);
114 $s->{U} = $nusername;
120 my $qassoc = $s->{S}{param_get}();
121 if (!defined $qassoc) {
122 $qassoc = $s->{S}{cookie_get}();
123 return undef unless defined $qassoc;
124 return undef unless $s->{S}{get_method}() eq 'GET';
126 my $dbh = $s->_dbopen();
127 my ($nusername, $nlast) =
128 $dbh->selectrow_array("SELECT username, last".
129 " FROM $s->{S}{assocdb_table}".
130 " WHERE associd = ?", {}, $qassoc);
131 return undef unless defined $nusername;
132 my $timeout = $s->{S}{login_timeout};
133 return undef unless !defined $timeout || time <= $nlast + $timeout;
135 return ($nusername, $qassoc);
141 my ($nusername, $qassoc) = $s->_check() or return undef;
144 $dbh->do("UPDATE $s->{S}{assocdb_table}".
146 " WHERE associd = ?", {}, time, $qassoc);
149 $s->{U} = $nusername;
157 if (my ($nusername, $qassoc) = $s->_check()) {
158 $dbh->do("DELETE FROM $s->{S}{assocdb_table}".
159 " WHERE associd = ?", {}, $qassoc);
170 return defined $s->{A} ? $s->{A} : '';
175 return (-name => $s->{param_name},
176 -default => $s->hiddenv());
181 return hidden($s->hiddena());
186 return (-name => $s->{cookie_name},
187 -value => hiddenv());