Merged with arensb-context branch: use C4::Context->dbh instead of
[koha.git] / C4 / Auth.pm
1 package C4::Auth;
2
3
4 # Copyright 2000-2002 Katipo Communications
5 #
6 # This file is part of Koha.
7 #
8 # Koha is free software; you can redistribute it and/or modify it under the
9 # terms of the GNU General Public License as published by the Free Software
10 # Foundation; either version 2 of the License, or (at your option) any later
11 # version.
12 #
13 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License along with
18 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
19 # Suite 330, Boston, MA  02111-1307 USA
20
21 use strict;
22 use Digest::MD5 qw(md5_base64);
23
24
25 require Exporter;
26 use C4::Context;
27
28 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
29
30 # set the version for version checking
31 $VERSION = 0.01;
32
33 @ISA = qw(Exporter);
34 @EXPORT = qw(
35              &checkauth
36 );
37
38
39
40 sub checkauth {
41     my $query=shift;
42     # $authnotrequired will be set for scripts which will run without authentication
43     my $authnotrequired=shift;
44     if (my $userid=$ENV{'REMOTE_USERNAME'}) {
45         # Using Basic Authentication, no cookies required
46         my $cookie=$query->cookie(-name => 'sessionID',
47                                   -value => '',
48                                   -expires => '+1y');
49         return ($userid, $cookie, '');
50     }
51     my $sessionID=$query->cookie('sessionID');
52     my $message='';
53
54     my $dbh = C4::Context->dbh;
55     my $sth=$dbh->prepare("select userid,ip,lasttime from sessions where sessionid=?");
56     $sth->execute($sessionID);
57     if ($sth->rows) {
58         my ($userid, $ip, $lasttime) = $sth->fetchrow;
59         if ($lasttime<time()-45 && $userid ne 'tonnesen') {
60             # timed logout
61             $message="You have been logged out due to inactivity.";
62             my $sti=$dbh->prepare("delete from sessions where sessionID=?");
63             $sti->execute($sessionID);
64             my $scriptname=$ENV{'SCRIPT_NAME'};
65             my $selfurl=$query->self_url();
66             $sti=$dbh->prepare("insert into sessionqueries (sessionID, userid, value) values (?, ?, ?)");
67             $sti->execute($sessionID, $userid, $selfurl);
68             open L, ">>/tmp/sessionlog";
69             my $time=localtime(time());
70             printf L "%20s from %16s logged out at %30s (inactivity).\n", $userid, $ip, $time;
71             close L;
72         } elsif ($ip ne $ENV{'REMOTE_ADDR'}) {
73             # Different ip than originally logged in from
74             my $newip=$ENV{'REMOTE_ADDR'};
75
76             $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)";
77         } else {
78             my $cookie=$query->cookie(-name => 'sessionID',
79                                       -value => $sessionID,
80                                       -expires => '+1y');
81             my $sti=$dbh->prepare("update sessions set lasttime=? where sessionID=?");
82             $sti->execute(time(), $sessionID);
83             return ($userid, $cookie, $sessionID);
84         }
85     }
86
87
88
89     if ($authnotrequired) {
90         my $cookie=$query->cookie(-name => 'sessionID',
91                                   -value => '',
92                                   -expires => '+1y');
93         return('', $cookie, '');
94     } else {
95         ($sessionID) || ($sessionID=int(rand()*100000).'-'.time());
96         my $userid=$query->param('userid');
97         my $password=$query->param('password');
98         if (checkpw($dbh, $userid, $password)) {
99             my $sti=$dbh->prepare("delete from sessions where sessionID=? and userid=?");
100             $sti->execute($sessionID, $userid);
101             $sti=$dbh->prepare("insert into sessions (sessionID, userid, ip,lasttime) values (?, ?, ?, ?)");
102             $sti->execute($sessionID, $userid, $ENV{'REMOTE_ADDR'}, time());
103             $sti=$dbh->prepare("select value from sessionqueries where sessionID=? and userid=?");
104             $sti->execute($sessionID, $userid);
105             if ($sti->rows) {
106                 my $stj=$dbh->prepare("delete from sessionqueries where sessionID=?");
107                 $stj->execute($sessionID);
108                 my ($selfurl) = $sti->fetchrow;
109                 print $query->redirect($selfurl);
110                 exit;
111             }
112             open L, ">>/tmp/sessionlog";
113             my $time=localtime(time());
114             printf L "%20s from %16s logged in  at %30s.\n", $userid, $ENV{'REMOTE_ADDR'}, $time;
115             close L;
116             my $cookie=$query->cookie(-name => 'sessionID',
117                                       -value => $sessionID,
118                                       -expires => '+1y');
119             return ($userid, $cookie, $sessionID);
120         } else {
121             if ($userid) {
122                 $message="Invalid userid or password entered.";
123             }
124             my $parameters;
125             foreach (param $query) {
126                 $parameters->{$_}=$query->{$_};
127             }
128             my $cookie=$query->cookie(-name => 'sessionID',
129                                       -value => $sessionID,
130                                       -expires => '+1y');
131             print $query->header(-cookie=>$cookie);
132             print qq|
133 <html>
134 <body background=/images/kohaback.jpg>
135 <center>
136 <h2>$message</h2>
137
138 <form method=post>
139 <table border=0 cellpadding=10 cellspacing=0 width=60%>
140     <tr><td align=center valign=top>
141
142     <table border=0 bgcolor=#dddddd cellpadding=10 cellspacing=0>
143     <tr><th colspan=2 background=/images/background-mem.gif><font size=+2>Koha Login</font></th></tr>
144     <tr><td>Name:</td><td><input name=userid></td></tr>
145     <tr><td>Password:</td><td><input type=password name=password></td></tr>
146     <tr><td colspan=2 align=center><input type=submit value=login></td></tr>
147     </table>
148     
149     </td><td align=center valign=top>
150
151     <table border=0 bgcolor=#dddddd cellpadding=10 cellspacing=0>
152     <tr><th background=/images/background-mem.gif><font size=+2>Demo Information</font></th></tr>
153     <td>
154     Log in as librarian/koha or patron/koha.  The timeout is set to 40 seconds of
155     inactivity for the purposes of this demo.  You can navigate to the Circulation
156     or Acquisitions modules and you should see an indicator in the upper left of
157     the screen saying who you are logged in as.  If you want to try it out with
158     a longer timout period, log in as tonnesen/koha and there will be no
159     timeout period.
160     <p>
161     You can also log in using a patron cardnumber.   Try V10000008 and
162     V1000002X with password koha.
163     </td>
164     </tr>
165     </table>
166     </td></tr>
167 </table>
168 </form>
169 </body>
170 </html>
171 |;
172             exit;
173         }
174     }
175 }
176
177
178 sub checkpw {
179
180 # This should be modified to allow a select of authentication schemes (ie LDAP)
181 # as well as local authentication through the borrowers tables passwd field
182 #
183     my ($dbh, $userid, $password) = @_;
184     my $sth=$dbh->prepare("select password from borrowers where userid=?");
185     $sth->execute($userid);
186     if ($sth->rows) {
187         my ($md5password) = $sth->fetchrow;
188         if (md5_base64($password) eq $md5password) {
189             return 1;
190         }
191     }
192     # FIXME - There's already a $sth in this scope.
193     my $sth=$dbh->prepare("select password from borrowers where cardnumber=?");
194     $sth->execute($userid);
195     if ($sth->rows) {
196         my ($md5password) = $sth->fetchrow;
197         if (md5_base64($password) eq $md5password) {
198             return 1;
199         }
200     }
201     return 0;
202 }
203
204
205 END { }       # module clean-up code here (global destructor)