[system] / branches / rel-2-1-a1 / webwork-modperl / lib / WeBWorK / Authen.pm Repository:
ViewVC logotype

Annotation of /branches/rel-2-1-a1/webwork-modperl/lib/WeBWorK/Authen.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 817 - (view) (download) (as text)
Original Path: trunk/webwork-modperl/lib/WeBWorK/Authen.pm

1 : sh002i 455 ################################################################################
2 : sh002i 494 # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project
3 : sh002i 455 # $Id$
4 :     ################################################################################
5 :    
6 : malsyned 305 package WeBWorK::Authen;
7 :    
8 : sh002i 455 =head1 NAME
9 :    
10 :     WeBWorK::Authen - Check user identity, manage session keys.
11 :    
12 :     =cut
13 :    
14 : malsyned 441 use strict;
15 :     use warnings;
16 : malsyned 335
17 : malsyned 305 sub new($$$) {
18 : malsyned 323 my $invocant = shift;
19 :     my $class = ref($invocant) || $invocant;
20 : malsyned 305 my $self = {};
21 : sh002i 817 ($self->{r}, $self->{ce}, $self->{db}) = @_;
22 : malsyned 305 bless $self, $class;
23 :     return $self;
24 :     }
25 :    
26 : sh002i 817 # um, this isn't used. move it to Utils?
27 :     #sub generatePassword($$$) {
28 :     # my ($self, $userID, $clearPassword) = @_;
29 :     # my $salt = join("", ('.','/','0'..'9','A'..'Z','a'..'z')[rand 64, rand 64]);
30 :     # my $cryptPassword = crypt($clearPassword, $salt);
31 :     # return WeBWorK::DB::Record::Password->new(user_id=>$userID, password=>$password);
32 :     #}
33 : malsyned 343
34 : sh002i 817 sub checkPassword($$$) {
35 :     my ($self, $userID, $possibleClearPassword) = @_;
36 :     my $Password = $self->{db}->getPassword($userID);
37 :     return 0 unless $Password;
38 :     my $possibleCryptPassword = crypt($possibleClearPassword, $Password->password());
39 :     return $possibleCryptPassword eq $Password->password();
40 :     }
41 :    
42 :     sub generateKey($$) {
43 :     my ($self, $userID) = @_;
44 :     my @chars = @{ $self->{ce}->{sessionKeyChars} };
45 :     my $length = $self->{ce}->{sessionKeyLength};
46 : malsyned 323 srand;
47 : sh002i 817 my $key = join ("", @chars[map rand(@chars), 1 .. $length]);
48 :     return WeBWorK::DB::Record::Key->new(user_id=>$userID, key=>$key, timestamp=>time);
49 :     }
50 :    
51 :     sub checkKey($$$) {
52 :     my ($self, $userID, $possibleKey) = @_;
53 :     my $Key = $self->{db}->getKey($userID);
54 :     return 0 unless $Key;
55 :     if (time <= $Key->timestamp()+$self->{ce}->{sessionKeyTimeout}) {
56 :     if ($possibleKey eq $Key->key()) {
57 :     # unexpired and matches -- update timestamp
58 :     $Key->timestamp(time);
59 :     $self->{db}->putKey($Key);
60 :     return 1;
61 :     } else {
62 :     # unexpired but doesn't match -- leave timestamp alone
63 :     # we do this to keep an attacker from keeping someone's session
64 :     # alive. (yeah, we don't match IPs.)
65 :     return 0;
66 :     }
67 :     } else {
68 :     # expired -- delete key
69 :     $self->{db}->deleteKey($userID);
70 :     return 0;
71 : malsyned 323 }
72 :     }
73 :    
74 : sh002i 817 sub unexpiredKeyExists($$) {
75 :     my ($self, $userID) = @_;
76 :     my $Key = $self->{db}->getKey($userID);
77 :     return 0 unless $Key;
78 :     if (time <= $Key->timestamp()+$self->{ce}->{sessionKeyTimeout}) {
79 :     # unexpired, but leave timestamp alone
80 :     return 1;
81 :     } else {
82 :     # expired -- delete key
83 :     $self->{db}->deleteKey($userID);
84 :     return 0;
85 :     }
86 :     }
87 :    
88 : malsyned 313 # verify will return 1 if the person is who they say the are.
89 :     # If the verification failed because of of invalid authentication data,
90 :     # a note will be written in the request explaining why it failed.
91 :     # If the request failed because no authentication data was provided, however,
92 :     # no note will be written, as this is expected to happen whenever someone
93 :     # types in a URL manually, and is not considered an error condition.
94 : malsyned 305 sub verify($) {
95 :     my $self = shift;
96 :     my $r = $self->{r};
97 : sh002i 817 my $ce = $self->{ce};
98 :     my $db = $self->{db};
99 : malsyned 305
100 : sh002i 817 my $practiceUserPrefix = $ce->{practiceUserPrefix};
101 :     my $debugPracticeUser = $ce->{debugPracticeUser};
102 :    
103 : malsyned 313 my $user = $r->param('user');
104 :     my $passwd = $r->param('passwd');
105 :     my $key = $r->param('key');
106 :    
107 : malsyned 441 my $error;
108 : sh002i 817 my $failWithoutError = 0;
109 : malsyned 313
110 : sh002i 817 VERIFY: {
111 :     # This block is here so we can "last" out of it when we've
112 :     # decided whether we're going to succeed or fail.
113 :    
114 :     # no authentication data was given. this is OK.
115 :     unless (defined $user or defined $passwd or defined $key) {
116 :     $failWithoutError = 1;
117 :     last VERIFY;
118 :     }
119 :    
120 :     # no user was supplied.
121 :     unless ($user) {
122 :     $error = "You must specify a username.";
123 :     last VERIFY;
124 :     }
125 :    
126 :     # it's a practice user.
127 : malsyned 349 if ($practiceUserPrefix and $user =~ /^$practiceUserPrefix/) {
128 : sh002i 817 # we're not interested in a practice user's password
129 :     $r->param("passwd", "");
130 :    
131 :     # it's a practice user that doesn't exist.
132 :     unless ($db->getUser($user)) {
133 :     $error = "That practice account does not exist.";
134 :     last VERIFY;
135 :     }
136 :    
137 :     # we've got a key.
138 :     if ($key) {
139 :     if ($self->checkKey($user, $key)) {
140 :     # they key was valid.
141 :     last VERIFY;
142 :     } else {
143 :     # the key was invalid.
144 :     $error = "Your session has expired. You must login again.";
145 :     last VERIFY;
146 :     }
147 :     }
148 :    
149 :     # -- here we know that a key was not supplied. --
150 :    
151 :     # it's the debug user.
152 :     if ($debugPracticeUser and $user eq $debugPracticeUser) {
153 :     # clobber any existing session, valid or not.
154 :     my $Key = $self->generateKey($user);
155 :     $db->deleteKey($user);
156 :     $db->addKey($Key);
157 :     $r->param("key", $Key->key());
158 :     last VERIFY;
159 :     }
160 :    
161 :     # an unexpired key exists -- the account is in use.
162 :     if ($self->unexpiredKeyExists($user)) {
163 :     $error = "That practice account is in use.";
164 :     last VERIFY;
165 :     }
166 :    
167 :     # here we know the account is not in use, so we
168 :     # generate a new session key (unexpiredKeyExists
169 :     # deleted any expired key) and succeed!
170 :     my $Key = $self->generateKey($user);
171 :     $db->addKey($Key);
172 :     $r->param("key", $Key->key());
173 :     last VERIFY;
174 :     }
175 :    
176 :     # -- here we know it's a regular user. --
177 :    
178 :     # a key was supplied.
179 :     if ($key) {
180 :     # we're not interested in a user's password if they're
181 :     # supplying a key
182 :     $r->param("passwd", "");
183 :    
184 :     if ($self->checkKey($user, $key)) {
185 :     # valid key, so succeed.
186 :     last VERIFY;
187 : malsyned 349 } else {
188 : sh002i 817 # invalid key. the login page doesn't propogate the key,
189 :     # so we know this is an expired session.
190 :     $error = "Your session has expired. You must login again.";
191 :     last VERIFY;
192 : malsyned 349 }
193 :     }
194 : sh002i 817
195 :     # a password was supplied.
196 :     if ($passwd) {
197 :     if ($self->checkPassword($user, $passwd)) {
198 :     # valid password, so create a new session. (we don't want
199 :     # to reuse an old one, duh.)
200 :     my $Key = $self->generateKey($user);
201 :     $db->deleteKey($user);
202 :     $db->addKey($Key);
203 :     $r->param("key", $Key->key());
204 :     # also delete the password
205 :     $r->param("passwd", "");
206 :     last VERIFY;
207 :     } else {
208 :     # incorrect password. fail.
209 :     $error = "Incorrect username or password.";
210 :     last VERIFY;
211 :     }
212 : malsyned 313 }
213 : sh002i 817
214 :     # neither a key or a password were supplied.
215 :     $error = "You must enter a password."
216 :     }
217 :    
218 :     if (defined $error) {
219 :     $r->notes("authen_error",$error);
220 :     return 0;
221 : malsyned 313 } else {
222 : sh002i 817 return not $failWithoutError;
223 : malsyned 305 }
224 : malsyned 313
225 :     # Whatever you do, don't delete this!
226 :     critical($r);
227 : malsyned 305 }
228 :    
229 :     1;
230 : malsyned 522
231 :     __END__
232 :    
233 :     =head1 AUTHOR
234 :    
235 : sh002i 817 Written by Dennis Lambe Jr., malsyned (at) math.rochester.edu, and Sam Hathaway, sh002i (at) math.rochester.edu.
236 : malsyned 522
237 :     =cut

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9