Auth.pm now caches form submissions and resubmits them if a user logs back in
[koha.git] / C4 / Auth.pm
1 package C4::Auth;
2
3 use strict;
4 use Digest::MD5 qw(md5_base64);
5
6
7 require Exporter;
8 use C4::Database;
9
10 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
11
12 # set the version for version checking
13 $VERSION = 0.01;
14
15 @ISA = qw(Exporter);
16 @EXPORT = qw(
17              &checkauth
18 );
19
20
21
22 sub checkauth {
23     my $query=shift;
24     # $authnotrequired will be set for scripts which will run without authentication
25     my $authnotrequired=shift;
26     if (my $userid=$ENV{'REMOTE_USERNAME'}) {
27         # Using Basic Authentication, no cookies required
28         my $cookie=$query->cookie(-name => 'sessionID',
29                                   -value => '',
30                                   -expires => '+1y');
31         return ($userid, $cookie, '');
32     }
33     my $sessionID=$query->cookie('sessionID');
34     my $message='';
35     warn "SID: ".$sessionID;
36
37     my $dbh=C4Connect();
38     my $sth=$dbh->prepare("select userid,ip,lasttime from sessions where sessionid=?");
39     $sth->execute($sessionID);
40     if ($sth->rows) {
41         my ($userid, $ip, $lasttime) = $sth->fetchrow;
42         if ($lasttime<time()-15 && $userid ne 'tonnesen') {
43             # timed logout
44             warn "$sessionID logged out due to inactivity.";
45             $message="You have been logged out due to inactivity.";
46             my $sti=$dbh->prepare("delete from sessions where sessionID=?");
47             $sti->execute($sessionID);
48             my $scriptname=$ENV{'SCRIPT_NAME'};
49             my $selfurl=$query->self_url();
50             $sti=$dbh->prepare("insert into sessionqueries (sessionID, userid, value) values (?, ?, ?)");
51             $sti->execute($sessionID, $userid, $selfurl);
52             open L, ">>/tmp/sessionlog";
53             my $time=localtime(time());
54             printf L "%20s from %16s logged out at %30s (inactivity).\n", $userid, $ip, $time;
55             close L;
56         } elsif ($ip ne $ENV{'REMOTE_ADDR'}) {
57             # Different ip than originally logged in from
58             my $newip=$ENV{'REMOTE_ADDR'};
59             warn "$sessionID came from a new ip address (authenticated from $ip, this request from $newip).";
60
61             $message="ERROR ERROR ERROR ERROR<br>Attempt to re-use a cookie from a different ip address.<br>(authenticated from $ip, this request from $newip)";
62         } else {
63             my $cookie=$query->cookie(-name => 'sessionID',
64                                       -value => $sessionID,
65                                       -expires => '+1y');
66             warn "$sessionID had a valid cookie.";
67             my $sti=$dbh->prepare("update sessions set lasttime=? where sessionID=?");
68             $sti->execute(time(), $sessionID);
69             return ($userid, $cookie, $sessionID);
70         }
71     }
72
73
74
75     warn "$sessionID wasn't in sessions table.";
76     if ($authnotrequired) {
77         my $cookie=$query->cookie(-name => 'sessionID',
78                                   -value => '',
79                                   -expires => '+1y');
80         return('', $cookie, '');
81     } else {
82         ($sessionID) || ($sessionID=int(rand()*100000).'-'.time());
83         my $userid=$query->param('userid');
84         my $password=$query->param('password');
85         if (checkpw($dbh, $userid, $password)) {
86             my $sti=$dbh->prepare("insert into sessions (sessionID, userid, ip,lasttime) values (?, ?, ?, ?)");
87             $sti->execute($sessionID, $userid, $ENV{'REMOTE_ADDR'}, time());
88             $sti=$dbh->prepare("select value from sessionqueries where sessionID=? and userid=?");
89             $sti->execute($sessionID, $userid);
90             if ($sti->rows) {
91                 my $stj=$dbh->prepare("delete from sessionqueries where sessionID=?");
92                 $stj->execute($sessionID);
93                 my ($selfurl) = $sti->fetchrow;
94                 print $query->redirect($selfurl);
95                 exit;
96             }
97             open L, ">>/tmp/sessionlog";
98             my $time=localtime(time());
99             printf L "%20s from %16s logged in  at %30s.\n", $userid, $ENV{'REMOTE_ADDR'}, $time;
100             close L;
101             my $cookie=$query->cookie(-name => 'sessionID',
102                                       -value => $sessionID,
103                                       -expires => '+1y');
104             return ($userid, $cookie, $sessionID);
105         } else {
106             if ($userid) {
107                 $message="Invalid userid or password entered.";
108             }
109             my $parameters;
110             foreach (param $query) {
111                 $parameters->{$_}=$query->{$_};
112             }
113             my $cookie=$query->cookie(-name => 'sessionID',
114                                       -value => $sessionID,
115                                       -expires => '+1y');
116             print $query->header(-cookie=>$cookie);
117             print qq|
118 <html>
119 <body background=/images/kohaback.jpg>
120 <center>
121 <h2>$message</h2>
122
123 <form method=post>
124 <table border=0 cellpadding=10 cellspacing=0 width=60%>
125     <tr><td align=center valign=top>
126
127     <table border=0 bgcolor=#dddddd cellpadding=10 cellspacing=0>
128     <tr><th colspan=2 background=/images/background-mem.gif><font size=+2>Koha Login</font></th></tr>
129     <tr><td>Name:</td><td><input name=userid></td></tr>
130     <tr><td>Password:</td><td><input type=password name=password></td></tr>
131     <tr><td colspan=2 align=center><input type=submit value=login></td></tr>
132     </table>
133     
134     </td><td align=center valign=top>
135
136     <table border=0 bgcolor=#dddddd cellpadding=10 cellspacing=0>
137     <tr><th background=/images/background-mem.gif><font size=+2>Demo Information</font></th></tr>
138     <td>
139     Log in as librarian/koha or patron/koha.  The timeout is set to 40 seconds of
140     inactivity for the purposes of this demo.  You can navigate to the Circulation
141     or Acquisitions modules and you should see an indicator in the upper left of
142     the screen saying who you are logged in as.  If you want to try it out with
143     a longer timout period, log in as tonnesen/koha and there will be no
144     timeout period.
145     <p>
146     You can also log in using a patron cardnumber.   Try V10000008 and
147     V1000002X with password koha.
148     </td>
149     </tr>
150     </table>
151     </td></tr>
152 </table>
153 </form>
154 </body>
155 </html>
156 |;
157             exit;
158         }
159     }
160 }
161
162
163 sub checkpw {
164
165 # This should be modified to allow a select of authentication schemes (ie LDAP)
166 # as well as local authentication through the borrowers tables passwd field
167 #
168     my ($dbh, $userid, $password) = @_;
169     my $sth=$dbh->prepare("select password from borrowers where userid=?");
170     $sth->execute($userid);
171     if ($sth->rows) {
172         my ($md5password) = $sth->fetchrow;
173         if (md5_base64($password) eq $md5password) {
174             return 1;
175         }
176     }
177     my $sth=$dbh->prepare("select password from borrowers where cardnumber=?");
178     $sth->execute($userid);
179     if ($sth->rows) {
180         my ($md5password) = $sth->fetchrow;
181         if (md5_base64($password) eq $md5password) {
182             return 1;
183         }
184     }
185     return 0;
186 }
187
188
189 END { }       # module clean-up code here (global destructor)