blib/lib/Digest/Auth.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 1 | 3 | 33.3 |
branch | n/a | ||
condition | n/a | ||
subroutine | 1 | 1 | 100.0 |
pod | n/a | ||
total | 2 | 4 | 50.0 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package Digest::Auth; | ||||||
2 | |||||||
3 | # --- Required Packages | ||||||
4 | #use Carp; # Generate better errors with more context | ||||||
5 | 1 | 1 | 28622 | use DBI; # Database connector | |||
0 | |||||||
0 | |||||||
6 | use CGI; # For the cookie handeling and output tools. | ||||||
7 | use strict; # Enforce restictions on good programming | ||||||
8 | |||||||
9 | # --- Headers --- | ||||||
10 | my $PACKAGE = 'Auth'; | ||||||
11 | my $VERSION = '0.01_2'; | ||||||
12 | use vars qw($VERSION); | ||||||
13 | |||||||
14 | # Routines | ||||||
15 | sub new { | ||||||
16 | my $package = shift; | ||||||
17 | my %opts = @_; | ||||||
18 | my $class = ref($package) || $package; | ||||||
19 | |||||||
20 | my(%DM) = ( | ||||||
21 | session => { | ||||||
22 | table => "session", | ||||||
23 | ip => "ip", | ||||||
24 | cert => "cert", | ||||||
25 | hash => "hash", | ||||||
26 | userid => "userid", | ||||||
27 | firstactive => "firstactive", | ||||||
28 | lastactive => "lastactive", | ||||||
29 | }, | ||||||
30 | sessionlocks => { | ||||||
31 | table => "sessionlocks", | ||||||
32 | ip => "ip", | ||||||
33 | stamp => "stamp", | ||||||
34 | cert => "cert", | ||||||
35 | hash => "hash", | ||||||
36 | userid => "userid", | ||||||
37 | }, | ||||||
38 | sessionattempts => { | ||||||
39 | table => "sessionattempts", | ||||||
40 | ip => "ip", | ||||||
41 | stamp => "stamp", | ||||||
42 | cert => "cert", | ||||||
43 | hash => "hash", | ||||||
44 | userid => "userid", | ||||||
45 | password => "password", | ||||||
46 | }, | ||||||
47 | user => { | ||||||
48 | table => "user", | ||||||
49 | userid => "userid", | ||||||
50 | password => "password", | ||||||
51 | }, | ||||||
52 | ); | ||||||
53 | |||||||
54 | # Options hash init | ||||||
55 | my($self) = { | ||||||
56 | dbh => undef, # data base handel | ||||||
57 | debug => 0, # level of debug: 0=off,1=Error,2=Warn,3=Verbose | ||||||
58 | debuginfo => "", # store debug information here. | ||||||
59 | cookiename => "SessionCert", # Cookie name to use for authorization | ||||||
60 | domain => ".", # Domain name for cookie | ||||||
61 | usecookies => 1, # Use cookies to maintain sessions. | ||||||
62 | digest => "Digest::SHA1", # Hash Digest to use | ||||||
63 | connection => 86400, # Maximum length of a authorized session. Default 24 hours | ||||||
64 | validation => 600, # Maximum amout of time for validation process. Default 10 minutes | ||||||
65 | idletime => 3600, # Amount of time you can be inactive before being logged out. Default 60 minutes | ||||||
66 | initcertretry => 5, # number of times to retry intitializing a session if the key is a duplicate | ||||||
67 | forgiverate => 86400, # Forgive bad login attempts after this much time or good login | ||||||
68 | maxconperip => 10, # Max connections/sessions per ip address | ||||||
69 | maxconperuser => 1, # Max connections/sessions per user name | ||||||
70 | maxbadpass => 5, # Max number of times a user can enter a bad password | ||||||
71 | compatmode => 0, # WARNING: THIS REDUCES SECURITY: Change to 1 to enable compatibility for non-javascript browsers. | ||||||
72 | locklength => [300,900,3600,86400,-1], # Amount of time a user is locked/banned for a rule violation | ||||||
73 | datamapping => \%DM, # Data Mapping to modify the fieldnames for the database. | ||||||
74 | }; | ||||||
75 | bless($self, $class); | ||||||
76 | $self->DebugAdd($PACKAGE."->new()::Initialized",3); | ||||||
77 | my($bitbucket) = $self->Put(%opts); | ||||||
78 | return $self; | ||||||
79 | } | ||||||
80 | |||||||
81 | sub Get{ | ||||||
82 | my($self,$opt1,$opt2,$opt3) = @_; | ||||||
83 | my $result; | ||||||
84 | $self->DebugAdd($PACKAGE."->Get($opt1,$opt2,$opt3)::Initialized",3); | ||||||
85 | |||||||
86 | $opt1 =~ s/[^\w]//g; | ||||||
87 | $opt1 = lc($opt1); | ||||||
88 | |||||||
89 | $opt2 =~ s/[^\w]//g; | ||||||
90 | $opt2 = lc($opt2); | ||||||
91 | |||||||
92 | $opt3 =~ s/[^\w]//g; | ||||||
93 | $opt3 = lc($opt3); | ||||||
94 | |||||||
95 | if(exists $self->{$opt1}){ | ||||||
96 | if($opt1 eq "datamapping"){ | ||||||
97 | if(exists $self->{datamapping}{$opt2}){ | ||||||
98 | if(exists $self->{$opt1}{$opt2}{$opt3}){ | ||||||
99 | return $self->{$opt1}{$opt2}{$opt3}; | ||||||
100 | }else{ | ||||||
101 | return $result; # no result | ||||||
102 | } | ||||||
103 | }else{ | ||||||
104 | return $result; # no result | ||||||
105 | } | ||||||
106 | }else{ | ||||||
107 | return $self->{$opt1}; | ||||||
108 | } | ||||||
109 | }else{ | ||||||
110 | return $result; # no result | ||||||
111 | } | ||||||
112 | } | ||||||
113 | sub Put{ | ||||||
114 | my($self,%opt) = @_; | ||||||
115 | my($result)= 0; | ||||||
116 | $self->DebugAdd($PACKAGE."->Put()::Initialized",3); | ||||||
117 | |||||||
118 | if(exists $opt{dbh}){ | ||||||
119 | $result++; $self->{dbh} = $opt{dbh}; | ||||||
120 | } | ||||||
121 | if(exists $opt{debug} && $self->SanitizeData($opt{debug}) && $opt{debug} >= 0 && $opt{debug} <= 3){ | ||||||
122 | $result++; $self->{debug} = $opt{debug}; | ||||||
123 | } | ||||||
124 | if(exists $opt{digest}){ | ||||||
125 | $result++; $self->{digest} = $opt{digest}; | ||||||
126 | } | ||||||
127 | if(exists $opt{cookiename} && $self->SanitizeData($opt{cookiename},1)){ | ||||||
128 | $result++; $self->{cookiename} = $opt{cookiename}; | ||||||
129 | } | ||||||
130 | if(exists $opt{domain} && $self->SanitizeData($opt{domain},4)){ | ||||||
131 | $result++; $self->{domain} = $opt{domain}; | ||||||
132 | } | ||||||
133 | if(exists $opt{usecookies} && ($opt{usecookies} == 0 || $opt{usecookies} == 1)){ | ||||||
134 | $result++; $self->{usecookies} = $opt{usecookies}; | ||||||
135 | } | ||||||
136 | if(exists $opt{connection} && $self->SanitizeData($opt{connection},3)){ | ||||||
137 | $result++; $self->{connection} = $opt{connection}; | ||||||
138 | } | ||||||
139 | if(exists $opt{validation} && $self->SanitizeData($opt{validation},3)){ | ||||||
140 | $result++; $self->{validation} = $opt{validation}; | ||||||
141 | } | ||||||
142 | if(exists $opt{idletime} && $self->SanitizeData($opt{idletime},3)){ | ||||||
143 | $result++; $self->{idletime} = $opt{idletime}; | ||||||
144 | } | ||||||
145 | if(exists $opt{initcertretry} && $self->SanitizeData($opt{initcertretry})){ | ||||||
146 | $result++; $self->{initcertretry} = $opt{initcertretry}; | ||||||
147 | } | ||||||
148 | if(exists $opt{forgiverate} && $self->SanitizeData($opt{forgiverate})){ | ||||||
149 | $result++; $self->{forgiverate} = $opt{forgiverate}; | ||||||
150 | } | ||||||
151 | if(exists $opt{maxconperip} && $self->SanitizeData($opt{maxconperip},3)){ | ||||||
152 | $result++; $self->{maxconperip} = $opt{maxconperip}; | ||||||
153 | } | ||||||
154 | if(exists $opt{maxconperuser} && $self->SanitizeData($opt{maxconperuser},3)){ | ||||||
155 | $result++; $self->{maxconperuser} = $opt{maxconperuser}; | ||||||
156 | } | ||||||
157 | if(exists $opt{maxbadpass} && $self->SanitizeData($opt{maxbadpass},3)){ | ||||||
158 | $result++; $self->{maxbadpass} = $opt{maxbadpass}; | ||||||
159 | } | ||||||
160 | if(exists $opt{compatmode} && $self->SanitizeData($opt{compatmode}) && ($opt{compatmode} == 1 || $opt{compatmode} == 0)){ | ||||||
161 | $result++; $self->{compatmode} = $opt{compatmode}; | ||||||
162 | } | ||||||
163 | if(exists $opt{locklength} && $self->SanitizeData($opt{locklength},3)){ | ||||||
164 | $result++; $self->{locklength} = $opt{locklength}; | ||||||
165 | } | ||||||
166 | if(exists $opt{datamapping}{session}{table} && $self->SanitizeData($opt{datamapping}{session}{table},2)){ | ||||||
167 | $result++; $self->{datamapping}{session}{table} = $opt{datamapping}{session}{table}; | ||||||
168 | } | ||||||
169 | if(exists $opt{datamapping}{session}{ip} && $self->SanitizeData($opt{datamapping}{session}{ip},2)){ | ||||||
170 | $result++; $self->{datamapping}{session}{ip} = $opt{datamapping}{session}{ip}; | ||||||
171 | } | ||||||
172 | if(exists $opt{datamapping}{session}{cert} && $self->SanitizeData($opt{datamapping}{session}{cert},2)){ | ||||||
173 | $result++; $self->{datamapping}{session}{cert} = $self->{datamapping}{session}{cert}; | ||||||
174 | } | ||||||
175 | if(exists $opt{datamapping}{session}{hash} && $self->SanitizeData($opt{datamapping}{session}{hash},2)){ | ||||||
176 | $result++; $self->{datamapping}{session}{hash} = $opt{datamapping}{session}{hash}; | ||||||
177 | } | ||||||
178 | if(exists $opt{datamapping}{session}{userid} && $self->SanitizeData($opt{datamapping}{session}{userid},2)){ | ||||||
179 | $result++; $self->{datamapping}{session}{userid} = $opt{datamapping}{session}{userid}; | ||||||
180 | } | ||||||
181 | if(exists $opt{datamapping}{session}{firstactive} && $self->SanitizeData($opt{datamapping}{session}{firstactive},2)){ | ||||||
182 | $result++; $self->{datamapping}{session}{firstactive} = $opt{datamapping}{session}{firstactive}; | ||||||
183 | } | ||||||
184 | if(exists $opt{datamapping}{session}{lastactive} && $self->SanitizeData($opt{datamapping}{session}{lastactive},2)){ | ||||||
185 | $result++; $self->{datamapping}{session}{lastactive} = $opt{datamapping}{session}{lastactive}; | ||||||
186 | } | ||||||
187 | if(exists $opt{datamapping}{sessionlocks}{table} && $self->SanitizeData($opt{datamapping}{sessionlocks}{table},2)){ | ||||||
188 | $result++; $self->{datamapping}{sessionlocks}{table} = $opt{datamapping}{sessionlocks}{table}; | ||||||
189 | } | ||||||
190 | if(exists $opt{datamapping}{sessionlocks}{ip} && $self->SanitizeData($opt{datamapping}{sessionlocks}{ip},2)){ | ||||||
191 | $result++; $self->{datamapping}{sessionlocks}{ip} = $opt{datamapping}{sessionlocks}{ip}; | ||||||
192 | } | ||||||
193 | if(exists $opt{datamapping}{sessionlocks}{stamp} && $self->SanitizeData($opt{datamapping}{sessionlocks}{stamp},2)){ | ||||||
194 | $result++; $self->{datamapping}{sessionlocks}{stamp} = $opt{datamapping}{sessionlocks}{stamp}; | ||||||
195 | } | ||||||
196 | if(exists $opt{datamapping}{sessionlocks}{cert} && $self->SanitizeData($opt{datamapping}{sessionlocks}{cert},2)){ | ||||||
197 | $result++; $self->{datamapping}{sessionlocks}{cert} = $opt{datamapping}{sessionlocks}{cert}; | ||||||
198 | } | ||||||
199 | if(exists $opt{datamapping}{sessionlocks}{hash} && $self->SanitizeData($opt{datamapping}{sessionlocks}{hash},2)){ | ||||||
200 | $result++; $self->{datamapping}{sessionlocks}{hash} = $opt{datamapping}{sessionlocks}{hash}; | ||||||
201 | } | ||||||
202 | if(exists $opt{datamapping}{sessionlocks}{userid} && $self->SanitizeData($opt{datamapping}{sessionlocks}{userid},2)){ | ||||||
203 | $result++; $self->{datamapping}{sessionlocks}{userid} = $opt{datamapping}{sessionlocks}{userid}; | ||||||
204 | } | ||||||
205 | if(exists $opt{datamapping}{sessionattempts}{table} && $self->SanitizeData($opt{datamapping}{sessionattempts}{table},2)){ | ||||||
206 | $result++; $self->{datamapping}{sessionattempts}{table} = $opt{datamapping}{sessionattempts}{table}; | ||||||
207 | } | ||||||
208 | if(exists $opt{datamapping}{sessionattempts}{ip} && $self->SanitizeData($opt{datamapping}{sessionattempts}{ip},2)){ | ||||||
209 | $result++; $self->{datamapping}{sessionattempts}{ip} = $self->{datamapping}{sessionattempts}{ip}; | ||||||
210 | } | ||||||
211 | if(exists $opt{datamapping}{sessionattempts}{stamp} && $self->SanitizeData($opt{datamapping}{sessionattempts}{stamp},2)){ | ||||||
212 | $result++; $self->{datamapping}{sessionattempts}{stamp} = $opt{datamapping}{sessionattempts}{stamp}; | ||||||
213 | } | ||||||
214 | if(exists $opt{datamapping}{sessionattempts}{cert} && $self->SanitizeData($opt{datamapping}{sessionattempts}{cert},2)){ | ||||||
215 | $result++; $self->{datamapping}{sessionattempts}{cert} = $opt{datamapping}{sessionattempts}{cert}; | ||||||
216 | } | ||||||
217 | if(exists $opt{datamapping}{sessionattempts}{hash} && $self->SanitizeData($opt{datamapping}{sessionattempts}{hash},2)){ | ||||||
218 | $result++; $self->{datamapping}{sessionattempts}{hash} = $opt{datamapping}{sessionattempts}{hash}; | ||||||
219 | } | ||||||
220 | if(exists $opt{datamapping}{sessionattempts}{userid} && $self->SanitizeData($opt{datamapping}{sessionattempts}{userid},2)){ | ||||||
221 | $result++; $self->{datamapping}{sessionattempts}{userid} = $opt{datamapping}{sessionattempts}{userid}; | ||||||
222 | } | ||||||
223 | if(exists $opt{datamapping}{sessionattempts}{password} && $self->SanitizeData($opt{datamapping}{sessionattempts}{password},2)){ | ||||||
224 | $result++; $self->{datamapping}{sessionattempts}{password} = $opt{datamapping}{sessionattempts}{password}; | ||||||
225 | } | ||||||
226 | if(exists $opt{datamapping}{user}{table} && $self->SanitizeData($opt{datamapping}{user}{table},2)){ | ||||||
227 | $result++; $self->{datamapping}{user}{table} = $opt{datamapping}{user}{table}; | ||||||
228 | } | ||||||
229 | if(exists $opt{datamapping}{user}{userid} && $self->SanitizeData($opt{datamapping}{user}{userid},2)){ | ||||||
230 | $result++; $self->{datamapping}{user}{userid} = $opt{datamapping}{user}{userid}; | ||||||
231 | } | ||||||
232 | if(exists $opt{datamapping}{user}{password} && $self->SanitizeData($opt{datamapping}{user}{password},2)){ | ||||||
233 | $result++; $self->{datamapping}{user}{password} = $opt{datamapping}{user}{password}; | ||||||
234 | } | ||||||
235 | |||||||
236 | return $result; | ||||||
237 | } | ||||||
238 | sub Keygen { | ||||||
239 | # Creates a somewhat random key of $QueKeyLength size using numbers | ||||||
240 | # and uppercase and lowercase letters based on $complexity. | ||||||
241 | my($self, | ||||||
242 | $QueKeyLength, | ||||||
243 | $complexity)=@_; | ||||||
244 | my(@keys); | ||||||
245 | my($key) = ""; | ||||||
246 | $self->DebugAdd($PACKAGE."->Keygen()::Initialized",3); | ||||||
247 | |||||||
248 | if($QueKeyLength < 1 || $QueKeyLength > 128 ){ $QueKeyLength = 10; } | ||||||
249 | if($complexity == 1){ | ||||||
250 | @keys = ('A'..'Z'); | ||||||
251 | }elsif($complexity == 2){ | ||||||
252 | @keys = ('A'..'Z','0'..'9'); | ||||||
253 | }else{ | ||||||
254 | @keys = ('A'..'Z','a'..'z','0'..'9'); | ||||||
255 | } | ||||||
256 | for(my($a)=1; $a <= $QueKeyLength; $a++){ $key .= $keys[ int( rand($#keys)) ]; } | ||||||
257 | return $key; | ||||||
258 | } | ||||||
259 | sub SanitizeData{ | ||||||
260 | # do a test to see if there are any special characters | ||||||
261 | my($self,$data1,$opt) = @_; | ||||||
262 | my($result)=0; | ||||||
263 | my($data2) = $data1; | ||||||
264 | if($opt == 1){ # letters and numbers with underscore "_" | ||||||
265 | $data2 =~ s/[^a-zA-Z0-9_]//g; | ||||||
266 | }elsif($opt == 2){ # only letters and numbers | ||||||
267 | $data2 =~ s/[^a-zA-Z0-9]//g; | ||||||
268 | }elsif($opt == 3){ # positive or neg numbers | ||||||
269 | $data2 =~ s/[^0-9\-]//g; | ||||||
270 | }elsif($opt == 4){ # lower case letters numbers and dots + dashes | ||||||
271 | $data2 =~ s/[^a-z0-9\.\-]//g; | ||||||
272 | }else{ # positive numbers only | ||||||
273 | $data2 =~ s/[^0-9]//g; | ||||||
274 | } | ||||||
275 | if($data1 eq $data2){ | ||||||
276 | $result++;} | ||||||
277 | return $result | ||||||
278 | } | ||||||
279 | sub AutoAuth{ | ||||||
280 | # Automatically Authorize the user. | ||||||
281 | my($self,%opts) = @_; | ||||||
282 | my($result)=0; | ||||||
283 | $self->DebugAdd($PACKAGE."->AutoAuth()::Initialized",3); | ||||||
284 | |||||||
285 | if( defined($self->{user}) && defined($self->{hash})){ | ||||||
286 | $result = "Authorize"; | ||||||
287 | # $self->Authorize(%opts); | ||||||
288 | |||||||
289 | }elsif( defined($opts{cert}) ){ | ||||||
290 | $result = "Validate"; | ||||||
291 | # $self->Validate(%opts); | ||||||
292 | |||||||
293 | }else{ | ||||||
294 | $result = "Initialize"; | ||||||
295 | # $self->Initialize(%opts); | ||||||
296 | |||||||
297 | } | ||||||
298 | |||||||
299 | return $result; | ||||||
300 | } | ||||||
301 | sub UserAdd{ | ||||||
302 | # insert data into user table for login credentials | ||||||
303 | my($self, %opts) = @_; | ||||||
304 | my($redflag) = 0; | ||||||
305 | my($result) = 0; | ||||||
306 | my($hits) = 0; | ||||||
307 | $self->DebugAdd($PACKAGE."->UserAdd()::Initialized",3); | ||||||
308 | |||||||
309 | if(! $self->SanitizeData($opts{user},1)){$redflag++;} | ||||||
310 | |||||||
311 | # Check for user in the system | ||||||
312 | # We have two methods to sanitize databases with. | ||||||
313 | # We are using DBI::quote since we want to keep this extensible. | ||||||
314 | # on the front end after the DBH is created if it is a SQL database it will be the | ||||||
315 | # programmers responisbility to first parse it with method no. 1. We will try to | ||||||
316 | # keep things neat using method no. 2. | ||||||
317 | # 1. mysql_real_escape_string(); | ||||||
318 | # 2. $self->{dbh}->quote(); | ||||||
319 | my($sql)='SELECT COUNT(*) AS HITS FROM ' | ||||||
320 | . $self->{datamapping}{user}{table} | ||||||
321 | . ' WHERE ' | ||||||
322 | . $self->{datamapping}{user}{userid} | ||||||
323 | . ' = ' | ||||||
324 | . $self->{dbh}->quote( $opts{user} ); | ||||||
325 | |||||||
326 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
327 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->UserAdd()::Check",$sql, $!),1); | ||||||
328 | while (my $ref = $sth->fetchrow_hashref()){ | ||||||
329 | $hits = $ref->{'HITS'}; | ||||||
330 | } | ||||||
331 | $sth->finish(); | ||||||
332 | |||||||
333 | # if user is not in the system, add them, otherwise fail gracefully | ||||||
334 | if($hits == 0){ | ||||||
335 | # create user, they are not in the system | ||||||
336 | my($sql)='INSERT INTO ' | ||||||
337 | . $self->{datamapping}{user}{table} | ||||||
338 | . ' (' | ||||||
339 | . $self->{datamapping}{user}{userid} | ||||||
340 | . ', ' | ||||||
341 | . $self->{datamapping}{user}{password} | ||||||
342 | . ') VALUES (' | ||||||
343 | . ' ' | ||||||
344 | . $self->{dbh}->quote($opts{user}) | ||||||
345 | . ', ' | ||||||
346 | . $self->{dbh}->quote($opts{password}) | ||||||
347 | . ')'; | ||||||
348 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
349 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->UserAdd()::Add",$sql, $!),1); | ||||||
350 | $sth->finish(); | ||||||
351 | $result=2; | ||||||
352 | }else{ | ||||||
353 | # user in the system already | ||||||
354 | $self->DebugAdd($PACKAGE."->UserAdd()::User Exists{".$opts{user}."}",2); | ||||||
355 | $result=1; | ||||||
356 | } | ||||||
357 | return $result; | ||||||
358 | } | ||||||
359 | |||||||
360 | sub Initialize{ | ||||||
361 | my($self) = @_; | ||||||
362 | my($result) = 0; | ||||||
363 | my($cert); | ||||||
364 | my($ip) = $ENV{'REMOTE_ADDR'}; | ||||||
365 | my($stamp) = time(); | ||||||
366 | |||||||
367 | $self->DebugAdd($PACKAGE."->Initialize()::Initialized",3); | ||||||
368 | # insert data into sessions table to establish a login session | ||||||
369 | |||||||
370 | my($login) = 0; # toggles to 1 when successfull | ||||||
371 | my($max) = 0; # max number of trys for system safety when testing | ||||||
372 | my($hits) = 0; | ||||||
373 | |||||||
374 | while ($login <= 0 && $max < $self->{initcertretry}){ # make sure it is a unique entry | ||||||
375 | |||||||
376 | $cert = $self->Keygen(10,2); | ||||||
377 | |||||||
378 | my($sql)="SELECT COUNT(*) AS HITS FROM " | ||||||
379 | . $self->{datamapping}{session}{table} | ||||||
380 | . " WHERE " | ||||||
381 | . $self->{datamapping}{session}{ip} | ||||||
382 | . " = " | ||||||
383 | . $self->{dbh}->quote($ip) | ||||||
384 | . " AND " | ||||||
385 | . $self->{datamapping}{session}{cert} | ||||||
386 | . " = " | ||||||
387 | . $self->{dbh}->quote($cert); | ||||||
388 | |||||||
389 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
390 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->Initialize()",$sql, $!),1); | ||||||
391 | while (my $ref = $sth->fetchrow_hashref()){ | ||||||
392 | $hits = $ref->{'HITS'}; | ||||||
393 | } | ||||||
394 | $sth->finish(); | ||||||
395 | if($hits == 0){ | ||||||
396 | $login++; | ||||||
397 | }else{ | ||||||
398 | $max++; | ||||||
399 | $self->DebugAdd($self->SQL_Die("Initialize()::CreateCert::CertCollision",$sql,"Debug"),2); | ||||||
400 | } | ||||||
401 | } | ||||||
402 | if($hits == 0){ | ||||||
403 | # initialize the session transaction. | ||||||
404 | my($sql) = "INSERT INTO " | ||||||
405 | . $self->{datamapping}{session}{table} | ||||||
406 | . " (" | ||||||
407 | . $self->{datamapping}{session}{cert} | ||||||
408 | . "," | ||||||
409 | . $self->{datamapping}{session}{ip} | ||||||
410 | . "," | ||||||
411 | . $self->{datamapping}{session}{firstactive} | ||||||
412 | . "," | ||||||
413 | . $self->{datamapping}{session}{lastactive} | ||||||
414 | . ") VALUES(" | ||||||
415 | . $self->{dbh}->quote($cert) | ||||||
416 | . "," | ||||||
417 | . $self->{dbh}->quote($ip) | ||||||
418 | . "," | ||||||
419 | . $self->{dbh}->quote($stamp) | ||||||
420 | . "," | ||||||
421 | . $self->{dbh}->quote($stamp) | ||||||
422 | . ")"; | ||||||
423 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
424 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->Initialize()",$sql, $!),1); | ||||||
425 | $sth->finish(); | ||||||
426 | $result++; | ||||||
427 | } | ||||||
428 | # temp measure cert, ip, stamp should not be global var's | ||||||
429 | # $self->{cert} = $cert; | ||||||
430 | # $self->{ip} = $ip | ||||||
431 | # $self->{stamp} = $stamp | ||||||
432 | return (cert => $cert, | ||||||
433 | ip => $ip, | ||||||
434 | stamp => $stamp); | ||||||
435 | } | ||||||
436 | |||||||
437 | sub Validate{ | ||||||
438 | # ops{userid, cert, hash, pass} | ||||||
439 | # userid, cert, (hash || password) required | ||||||
440 | # + use only hash when self->compatmode = 0 | ||||||
441 | # + use only pass when self->compatmode = 1 | ||||||
442 | |||||||
443 | my($self,%opts) = @_; | ||||||
444 | $self->DebugAdd($PACKAGE."->Validate()::Initialized",3); | ||||||
445 | |||||||
446 | my($hash); | ||||||
447 | my($cert); | ||||||
448 | my($ip) = $ENV{'REMOTE_ADDR'}; | ||||||
449 | my($stamp) = time(); | ||||||
450 | my($result) = 0; | ||||||
451 | my($hits) = 0; | ||||||
452 | my($cookiedata)=""; | ||||||
453 | |||||||
454 | # TODO: Need to build validation for this | ||||||
455 | |||||||
456 | # Find all matching record for the primary key (Key,IP Address) | ||||||
457 | my(%SQL_SESSION); | ||||||
458 | my($sql) = "SELECT * FROM " | ||||||
459 | . $self->{datamapping}{session}{table} | ||||||
460 | . " WHERE " | ||||||
461 | . $self->{datamapping}{session}{cert} | ||||||
462 | . " = " | ||||||
463 | . $self->{dbh}->quote($opts{cert}) | ||||||
464 | . " AND " | ||||||
465 | . $self->{datamapping}{session}{ip} | ||||||
466 | . " = " | ||||||
467 | . $self->{dbh}->quote($ip) | ||||||
468 | . " LIMIT 0,1"; | ||||||
469 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
470 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->Validate()",$sql, $!),1); | ||||||
471 | while (my $ref = $sth->fetchrow_hashref()){ | ||||||
472 | $SQL_SESSION{firstactive} = $ref->{$self->{datamapping}{session}{firstactive}}; | ||||||
473 | } | ||||||
474 | $sth->finish(); | ||||||
475 | |||||||
476 | if( ! $SQL_SESSION{firstactive} ){ | ||||||
477 | # no: stop / log attempt; (Key,IP Address) not found in sessions. Log to sessionattempts | ||||||
478 | # ops{user, cert, hash, pass} | ||||||
479 | $self->DebugAdd($PACKAGE."->Validate()::Active(Key,IP Address) Not Found",2); | ||||||
480 | my($sql) = "INSERT INTO " | ||||||
481 | . $self->{datamapping}{sessionattempt}{table} | ||||||
482 | . " (" | ||||||
483 | . $self->{datamapping}{sessionattempt}{cert} | ||||||
484 | . "," | ||||||
485 | . $self->{datamapping}{sessionattempt}{ip} | ||||||
486 | . "," | ||||||
487 | . $self->{datamapping}{sessionattempt}{stamp} | ||||||
488 | . "," | ||||||
489 | . $self->{datamapping}{sessionattempt}{userid} | ||||||
490 | . "," | ||||||
491 | . $self->{datamapping}{sessionattempt}{hash} | ||||||
492 | . "," | ||||||
493 | . $self->{datamapping}{sessionattempt}{password} | ||||||
494 | . ") VALUES(" | ||||||
495 | . $self->{dbh}->quote($opts{cert}) | ||||||
496 | . "," | ||||||
497 | . $self->{dbh}->quote($ip) | ||||||
498 | . "," | ||||||
499 | . $self->{dbh}->quote($stamp) | ||||||
500 | . "," | ||||||
501 | . $self->{dbh}->quote($opts{userid}) | ||||||
502 | . "," | ||||||
503 | . $self->{dbh}->quote($opts{hash}) | ||||||
504 | . "," | ||||||
505 | . $self->{dbh}->quote($opts{password}) | ||||||
506 | . ")"; | ||||||
507 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
508 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->Initialize()",$sql, $!),1); | ||||||
509 | $sth->finish(); | ||||||
510 | }else{ | ||||||
511 | # Yes: continue | ||||||
512 | # Get the specified Username given from the client from the user table | ||||||
513 | my(%SQL_USER); | ||||||
514 | my($sql) = "SELECT * FROM " | ||||||
515 | . $self->{datamapping}{user}{table} | ||||||
516 | . " WHERE " | ||||||
517 | . $self->{datamapping}{user}{userid} | ||||||
518 | . " = " | ||||||
519 | . $self->{dbh}->quote($opts{userid}); | ||||||
520 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
521 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->Validate()",$sql, $!),1); | ||||||
522 | while (my $ref = $sth->fetchrow_hashref()){ | ||||||
523 | $SQL_USER{password} = $ref->{$self->{datamapping}{user}{password}}; | ||||||
524 | $SQL_USER{userid} = $ref->{$self->{datamapping}{user}{userid}}; | ||||||
525 | } | ||||||
526 | $sth->finish(); | ||||||
527 | |||||||
528 | # if(Is username Found?){Yes: continue}else{no: stop} | ||||||
529 | # -----TODO | ||||||
530 | |||||||
531 | # Create a secure 1 way Hash of the Username, Key, and Password | ||||||
532 | |||||||
533 | my($digestdata) = ($opts{userid} . $opts{cert} . $SQL_USER{password} . $SQL_SESSION{firstactive} ); | ||||||
534 | |||||||
535 | $hash = $self->DigestMake(data => $digestdata); | ||||||
536 | |||||||
537 | # if compat mode, ignore hash arg and build the hash without javascript | ||||||
538 | if($self->{compatmode} != 0){ | ||||||
539 | $self->DebugAdd($PACKAGE."->Validate()::CompatMode=1",3); | ||||||
540 | my($digestdata2) = ($opts{userid} . $opts{cert} . $opts{password} . $SQL_SESSION{firstactive}); | ||||||
541 | $opts{hash} = $self->DigestMake(data => $digestdata); | ||||||
542 | } | ||||||
543 | |||||||
544 | |||||||
545 | |||||||
546 | # Test the hashes against eachother on a time sensitive manner | ||||||
547 | if( $hash eq $opts{hash} && | ||||||
548 | $stamp <= ($SQL_SESSION{firstactive} + $self->{validation}) | ||||||
549 | ){ | ||||||
550 | |||||||
551 | # -----TODO | ||||||
552 | # this deletes anything, but we have to make it match our prefrences for the max number of user logins | ||||||
553 | # we do need some sort of cleanup though here.. this SQL statement needs revision | ||||||
554 | # my($sql) = "DELETE * FROM " | ||||||
555 | # . $self->{datamapping}{session}{table} | ||||||
556 | # . " WHERE NOT " | ||||||
557 | # . $self->{datamapping}{session}{userid} | ||||||
558 | # . " = " | ||||||
559 | # . $self->{dbh}->quote($opts{userid}) | ||||||
560 | # . " AND " | ||||||
561 | # . $self->{datamapping}{session}{cert} | ||||||
562 | # . " = " | ||||||
563 | # . $self->{dbh}->quote($opts{cert}) | ||||||
564 | # . " AND " | ||||||
565 | # . $self->{datamapping}{session}{ip} | ||||||
566 | # . " = " | ||||||
567 | # . $self->{dbh}->quote($ip); | ||||||
568 | # print $self->SQL_Die("Validate()",$sql,"Debug"); | ||||||
569 | # # $self->DebugAdd( $self->SQL_Die("Validate()",$sql,"Debug") ); | ||||||
570 | # my($sth) = $self->{dbh}->prepare($sql); | ||||||
571 | # $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->Validate()",$sql, $!),1); | ||||||
572 | # $sth->finish(); | ||||||
573 | |||||||
574 | my($sql) = "UPDATE " | ||||||
575 | . $self->{datamapping}{session}{table} | ||||||
576 | . " SET " | ||||||
577 | . $self->{datamapping}{session}{lastactive} | ||||||
578 | . " = " | ||||||
579 | . $self->{dbh}->quote($stamp) | ||||||
580 | . ", " | ||||||
581 | . $self->{datamapping}{session}{hash} | ||||||
582 | . " = " | ||||||
583 | . $self->{dbh}->quote($hash) | ||||||
584 | . ", " | ||||||
585 | . $self->{datamapping}{session}{userid} | ||||||
586 | . " = " | ||||||
587 | . $self->{dbh}->quote($opts{userid}) | ||||||
588 | . " WHERE " | ||||||
589 | . $self->{datamapping}{session}{cert} | ||||||
590 | . " = " | ||||||
591 | . $self->{dbh}->quote($opts{cert}) | ||||||
592 | . " AND " | ||||||
593 | . $self->{datamapping}{session}{ip} | ||||||
594 | . " = " | ||||||
595 | . $self->{dbh}->quote($ip); | ||||||
596 | # $self->DebugAdd( $self->SQL_Die("Validate()",$sql,"Debug") ); | ||||||
597 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
598 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->Validate()",$sql, $!),1); | ||||||
599 | $sth->finish(); | ||||||
600 | # TODO: actions: | ||||||
601 | # delete all previous sessions for username (1 session per user) | ||||||
602 | |||||||
603 | $result = 1; | ||||||
604 | }else{ | ||||||
605 | # failed to validate | ||||||
606 | # print "'$hash' is ne '".$opts{hash}."' OR " .$stamp ." is not <= ". ($SQL_SESSION{firstactive} + $self->{validation})." "; |
||||||
607 | } | ||||||
608 | } | ||||||
609 | if($self->{usecookies}){ | ||||||
610 | $cookiedata = $self->CookieSet(data => "userid:".$opts{userid}.",hash:".$hash); | ||||||
611 | } | ||||||
612 | return (result => $result, | ||||||
613 | userid => $opts{userid}, | ||||||
614 | hash => $hash, | ||||||
615 | cookie => $cookiedata); | ||||||
616 | } | ||||||
617 | |||||||
618 | sub Authorize{ | ||||||
619 | my($self,%opts) = @_; | ||||||
620 | # ops{userid, hash} | ||||||
621 | |||||||
622 | my($ip) = $ENV{'REMOTE_ADDR'}; | ||||||
623 | my($stamp) = time(); | ||||||
624 | my($result) = 0; | ||||||
625 | my($hits) = 0; | ||||||
626 | $self->DebugAdd($PACKAGE."->Authorize()::Initialized",3); | ||||||
627 | |||||||
628 | # rules: | ||||||
629 | # CERT{hash} eq SQL.session{hash} | ||||||
630 | # CERT{userid} eq SQL.session{userid} | ||||||
631 | # Parsed{ip} eq SQL.session{ip} | ||||||
632 | # ($SQL_SESSION{firstactive} + $connection) = $stamp && | ||||||
633 | # ($SQL_SESSION{lastactive} + $idletime) >= $stamp | ||||||
634 | # actions: | ||||||
635 | # session{lastactive} = Parsed{time} | ||||||
636 | |||||||
637 | my(%SQL_SESSION); | ||||||
638 | my($sql)="SELECT * FROM " | ||||||
639 | . $self->{datamapping}{session}{table} | ||||||
640 | . " WHERE " | ||||||
641 | . $self->{datamapping}{session}{hash} | ||||||
642 | . " = " | ||||||
643 | . $self->{dbh}->quote($opts{hash}) | ||||||
644 | . " AND " | ||||||
645 | . $self->{datamapping}{session}{userid} | ||||||
646 | . " = " | ||||||
647 | . $self->{dbh}->quote($opts{userid}) | ||||||
648 | . " AND " | ||||||
649 | . $self->{datamapping}{session}{ip} | ||||||
650 | . " = " | ||||||
651 | . $self->{dbh}->quote($ip) | ||||||
652 | . " LIMIT 0,1"; | ||||||
653 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
654 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->Authorize()",$sql, $!),1); | ||||||
655 | while (my $ref = $sth->fetchrow_hashref()){ | ||||||
656 | $SQL_SESSION{firstactive} = $ref->{ $self->{datamapping}{session}{firstactive} }; | ||||||
657 | $SQL_SESSION{lastactive} = $ref->{ $self->{datamapping}{session}{lastactive} }; | ||||||
658 | } | ||||||
659 | $sth->finish(); | ||||||
660 | |||||||
661 | if( (($SQL_SESSION{firstactive} + $self->{connection}) >= $stamp) && | ||||||
662 | (($SQL_SESSION{lastactive} + $self->{idletime}) >= $stamp) | ||||||
663 | ){ | ||||||
664 | # Is the user session active valid? if it is update session table; | ||||||
665 | my($sql) = "UPDATE " | ||||||
666 | . $self->{datamapping}{session}{table} | ||||||
667 | . " SET " | ||||||
668 | . $self->{datamapping}{session}{lastactive} | ||||||
669 | . " = " | ||||||
670 | . $self->{dbh}->quote($stamp) | ||||||
671 | . " WHERE " | ||||||
672 | . $self->{datamapping}{session}{hash} | ||||||
673 | . " = " | ||||||
674 | . $self->{dbh}->quote($opts{hash}) | ||||||
675 | . " AND " | ||||||
676 | . $self->{datamapping}{session}{userid} | ||||||
677 | . " = " | ||||||
678 | . $self->{dbh}->quote($opts{userid}) | ||||||
679 | . " AND " | ||||||
680 | . $self->{datamapping}{session}{ip} | ||||||
681 | . " = " | ||||||
682 | . $self->{dbh}->quote($ip); | ||||||
683 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
684 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->Authorize()",$sql, $!),1); | ||||||
685 | $sth->finish(); | ||||||
686 | $result++; | ||||||
687 | }else{ | ||||||
688 | # Note the invalid attempt | ||||||
689 | } | ||||||
690 | return $result; | ||||||
691 | } | ||||||
692 | |||||||
693 | sub DigestMake{ | ||||||
694 | my($self,%opts) = @_; | ||||||
695 | $self->DebugAdd($PACKAGE."->Authorize()::DigestMake",3); | ||||||
696 | |||||||
697 | my($DIGEST); my($HASH); | ||||||
698 | |||||||
699 | if($self->{digest} eq "Digest::SHA1"){ | ||||||
700 | use Digest::SHA1; | ||||||
701 | $DIGEST = Digest::SHA1->new; | ||||||
702 | $DIGEST->add( $opts{data} ); | ||||||
703 | $HASH = $DIGEST->hexdigest; | ||||||
704 | }elsif($self->{digest} eq "MD5"){ | ||||||
705 | use Digest::MD5; | ||||||
706 | $DIGEST = Digest::MD5->new; | ||||||
707 | $DIGEST->add( $opts{data} ); | ||||||
708 | $HASH = $DIGEST->hexdigest; | ||||||
709 | }else{ | ||||||
710 | # Might do this way instead: | ||||||
711 | ################################################## | ||||||
712 | # use Package::Alias DIGESTNAME => $self->digest; | ||||||
713 | # use DIGESTNAME; | ||||||
714 | # $DIGEST = DIGESTNAME->new; | ||||||
715 | # $DIGEST->add($opts{data}); | ||||||
716 | # $HASH = $DIGEST->hexdigest; | ||||||
717 | ################################################## | ||||||
718 | |||||||
719 | eval ('use '.$self->digest); | ||||||
720 | eval ('$DIGEST = '.$self->digest.'->new'); | ||||||
721 | $DIGEST->add($opts{data}); | ||||||
722 | $HASH = $DIGEST->hexdigest; | ||||||
723 | } | ||||||
724 | return $HASH; | ||||||
725 | } | ||||||
726 | |||||||
727 | sub DeleteExpiredSessions { | ||||||
728 | # scrubs any expired sessions | ||||||
729 | my($self,%opts) = @_; | ||||||
730 | my($result) = 0; | ||||||
731 | |||||||
732 | return $result; | ||||||
733 | } | ||||||
734 | |||||||
735 | sub TableMake{ | ||||||
736 | my($self, %opts) = @_; | ||||||
737 | my($result) = 0; | ||||||
738 | $self->DebugAdd($PACKAGE."->TableMake()::Initialized",3); | ||||||
739 | |||||||
740 | if(defined($opts{'table'}) && (lc($opts{'table'}) eq 'all'|| lc($opts{'table'}) eq 'session')){ | ||||||
741 | $self->DebugAdd($PACKAGE."->TableMake()::CreatingTable::Session",3); | ||||||
742 | my($sql)= qq^CREATE TABLE IF NOT EXISTS ^ . $self->{datamapping}{session}{table} | ||||||
743 | . qq^ (^ . $self->{datamapping}{session}{ip} | ||||||
744 | . qq^ VARCHAR(15) NOT NULL, ^ . $self->{datamapping}{session}{cert} | ||||||
745 | . qq^ VARCHAR(10) NOT NULL, ^ . $self->{datamapping}{session}{hash} | ||||||
746 | . qq^ VARCHAR(45), ^ . $self->{datamapping}{session}{userid} | ||||||
747 | . qq^ VARCHAR(45), ^ . $self->{datamapping}{session}{firstactive} | ||||||
748 | . qq^ VARCHAR(45), ^ . $self->{datamapping}{session}{lastactive} | ||||||
749 | . qq^ VARCHAR(45), PRIMARY KEY(^ . $self->{datamapping}{session}{ip} | ||||||
750 | . qq^, ^ . $self->{datamapping}{session}{cert} | ||||||
751 | . qq^))^; | ||||||
752 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
753 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->TableMake(table => '".$opts{'table'}."')::Create Table::Session::Execute",$sql, $!),1); | ||||||
754 | $sth->finish(); | ||||||
755 | $result++; | ||||||
756 | } | ||||||
757 | |||||||
758 | if(defined($opts{'table'}) && (lc($opts{'table'}) eq 'all'|| lc($opts{'table'}) eq 'sessionattempts')){ | ||||||
759 | $self->DebugAdd($PACKAGE."->TableMake()::CreatingTable::SessionAttempts",3); | ||||||
760 | my($sql)= qq^CREATE TABLE IF NOT EXISTS ^.$self->{datamapping}{sessionattempts}{table} | ||||||
761 | .qq^ (^.$self->{datamapping}{sessionattempts}{ip} | ||||||
762 | .qq^ varchar(15) NOT NULL, ^.$self->{datamapping}{sessionattempts}{stamp} | ||||||
763 | .qq^ varchar(10) NOT NULL, ^.$self->{datamapping}{sessionattempts}{hash} | ||||||
764 | .qq^ varchar(45) default NULL, ^.$self->{datamapping}{sessionattempts}{userid} | ||||||
765 | .qq^ varchar(45) default NULL, ^.$self->{datamapping}{sessionattempts}{cert} | ||||||
766 | .qq^ varchar(45) default NULL, ^.$self->{datamapping}{sessionattempts}{password} | ||||||
767 | .qq^ varchar(45) default NULL, PRIMARY KEY(^.$self->{datamapping}{sessionattempts}{ip} | ||||||
768 | .qq^, ^.$self->{datamapping}{sessionattempts}{stamp} | ||||||
769 | .qq^))^; | ||||||
770 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
771 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->TableMake(table => '".$opts{'table'}."')::Create Table::SessionAttempts::Execute",$sql, $!),1); | ||||||
772 | $sth->finish(); | ||||||
773 | $result++; | ||||||
774 | } | ||||||
775 | |||||||
776 | if(defined($opts{'table'}) && (lc($opts{'table'}) eq 'all'|| lc($opts{'table'}) eq 'sessionlocks')){ | ||||||
777 | $self->DebugAdd($PACKAGE."->TableMake()::CreatingTable::SessionLocks",3); | ||||||
778 | my($sql)= qq^CREATE TABLE IF NOT EXISTS ^.$self->{datamapping}{sessionlocks}{table} | ||||||
779 | .qq^ (^.$self->{datamapping}{sessionlocks}{ip} | ||||||
780 | .qq^ varchar(15) NOT NULL, ^.$self->{datamapping}{sessionlocks}{stamp} | ||||||
781 | .qq^ varchar(10) NOT NULL, ^.$self->{datamapping}{sessionlocks}{hash} | ||||||
782 | .qq^ varchar(45) default NULL, ^.$self->{datamapping}{sessionlocks}{userid} | ||||||
783 | .qq^ varchar(45) default NULL, ^.$self->{datamapping}{sessionlocks}{cert} | ||||||
784 | .qq^ varchar(45) default NULL, PRIMARY KEY(^.$self->{datamapping}{sessionlocks}{ip} | ||||||
785 | .qq^,^.$self->{datamapping}{sessionlocks}{stamp} | ||||||
786 | .qq^))^; | ||||||
787 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
788 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->TableMake(table => '".$opts{'table'}."')::Create Table::SessionLocks::Execute",$sql, $!),1); | ||||||
789 | $sth->finish(); | ||||||
790 | $result++; | ||||||
791 | } | ||||||
792 | |||||||
793 | if(defined($opts{'table'}) && (lc($opts{'table'}) eq 'all'|| lc($opts{'table'}) eq 'user')){ | ||||||
794 | $self->DebugAdd($PACKAGE."->TableMake()::CreatingTable::User",3); | ||||||
795 | my($sql)= qq^CREATE TABLE IF NOT EXISTS ^.$self->{datamapping}{user}{table} | ||||||
796 | .qq^ (^.$self->{datamapping}{user}{userid} | ||||||
797 | .qq^ varchar(50) NOT NULL,^.$self->{datamapping}{user}{password} | ||||||
798 | .qq^ varchar(50) default NULL, PRIMARY KEY(^.$self->{datamapping}{user}{userid} | ||||||
799 | .qq^))^; | ||||||
800 | my($sth) = $self->{dbh}->prepare($sql); | ||||||
801 | $sth->execute() or $self->DebugShow($self->SQL_Die("Auth->TableMake(table => '".$opts{'table'}."')::Create Table::User::Execute",$sql, $!),1); | ||||||
802 | $sth->finish(); | ||||||
803 | $result++; | ||||||
804 | } | ||||||
805 | return $result; # Number of SQL statements processed successfully. | ||||||
806 | } | ||||||
807 | |||||||
808 | sub SQL_Die{ | ||||||
809 | # Deguging tool: Helps neatly print SQL statements out when module for debug messages. | ||||||
810 | my($self, $subroutine, $sql, $err) = @_; | ||||||
811 | my(@keys)=("FROM","WHERE","VALUES","SET","OR","AND","LIMIT","ORDER","BETWEEN","IN", "AS", "UNION", "INTO", "IF"); | ||||||
812 | my($cnt)= "\n"; |
||||||
813 | for(my($a) = 0; $a <= $#keys; $a++){ | ||||||
814 | my($b) = " " . $keys[$a] . " "; | ||||||
815 | my($c) = "\n" . $b; | ||||||
816 | $sql =~ s/$b/$c/gi; | ||||||
817 | } | ||||||
818 | $sql =~ s/, /,\n /g; | ||||||
819 | return ("\n \nCan not execute SQL statement $PACKAGE->". $subroutine ."". $cnt . $sql .";\n$err\n ");
|
||||||
820 | } | ||||||
821 | sub DebugAdd{ | ||||||
822 | # Deguging tool: Appends debugging information to the main module. | ||||||
823 | my($self,$data,$level) = @_; | ||||||
824 | if($self->{debug} >= $level){ | ||||||
825 | my($leveltext)=""; | ||||||
826 | if($level == 1){ | ||||||
827 | $leveltext = "Error"; | ||||||
828 | }elsif($level == 2){ | ||||||
829 | $leveltext = "Warning"; | ||||||
830 | }elsif($level == 3){ | ||||||
831 | $leveltext = "Infomation"; | ||||||
832 | }else{ | ||||||
833 | $leveltext = "Unknown"; | ||||||
834 | } | ||||||
835 | $self->{debuginfo} .= " ".$leveltext.": Time: " . localtime() . " [" . time() . "] " . $data; |
||||||
836 | } | ||||||
837 | } | ||||||
838 | sub DebugShow{ | ||||||
839 | my($self,$data,$level) = @_; | ||||||
840 | $self->DebugAdd($data,$level); | ||||||
841 | if($self->{debug} > 0){ | ||||||
842 | print $self->{debuginfo}; | ||||||
843 | } | ||||||
844 | } | ||||||
845 | |||||||
846 | sub CookieGet { | ||||||
847 | # move cookies to a hash | ||||||
848 | my($self,%opts) = @_; | ||||||
849 | $self->DebugAdd($PACKAGE."->CookieGet()::Initialized",3); | ||||||
850 | my(%result); | ||||||
851 | my($nm) = ( defined($opts{name}) )? $opts{name} : $self->{cookiename}; | ||||||
852 | my($query) = new CGI; | ||||||
853 | my(@cookies) = split(/;/, $query->cookie($nm)); | ||||||
854 | |||||||
855 | for (my($a)=0; $a <= $#cookies; $a++){ | ||||||
856 | my @pairs = split(/,/,$cookies[$a]); | ||||||
857 | for (my($b)=0; $b <= $#pairs; $b++){ | ||||||
858 | my($n,$v) = split(/:/, $pairs[$b]) ; | ||||||
859 | $result{$n} = $v; | ||||||
860 | } | ||||||
861 | last; | ||||||
862 | } | ||||||
863 | return (%result); | ||||||
864 | } | ||||||
865 | |||||||
866 | sub CookieSet { | ||||||
867 | # move data to a cookie | ||||||
868 | my($self,%opts) = @_; | ||||||
869 | $self->DebugAdd($PACKAGE."->CookieWrite()::Initialized",3); | ||||||
870 | |||||||
871 | my($query) = new CGI; | ||||||
872 | my($nm) = ( defined($opts{name}) )? $opts{name} : $self->{cookiename}; | ||||||
873 | my($domain)= ( defined($opts{domain}) )? $opts{domain} : $self->{domain}; | ||||||
874 | my($path) = ( defined($opts{path}) )? $opts{path} : "/"; | ||||||
875 | my($gmt) = ( defined($opts{gmt}) )? $opts{gmt} : gmtime(time() + $self->{idletime})." GMT;"; | ||||||
876 | my($cookie)= $query->cookie(-domain => $domain, | ||||||
877 | -name => $nm, | ||||||
878 | -value => $opts{data}, | ||||||
879 | -expires => $gmt, | ||||||
880 | -path => $path); | ||||||
881 | |||||||
882 | print "Set-Cookie: $cookie\n"; | ||||||
883 | $self->DebugAdd($PACKAGE."->CookieWrite()::Cookie Written".$cookie,3); | ||||||
884 | |||||||
885 | return $cookie; | ||||||
886 | } | ||||||
887 | |||||||
888 | sub WriteScript{ | ||||||
889 | # print a javascript | ||||||
890 | my($self,$script) = @_; | ||||||
891 | if($script eq undef){ $script = $self->JS_Digest(); } | ||||||
892 | my($result)= qq^\n\n^; | ||||||
893 | return $result; | ||||||
894 | } | ||||||
895 | |||||||
896 | sub JS_Digest{ | ||||||
897 | my($self,%opts) = @_; | ||||||
898 | |||||||
899 | if($self->{digest} eq "MD5"){ | ||||||
900 | |||||||
901 | return <<"ENDTAG" | ||||||
902 | /* | ||||||
903 | * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message | ||||||
904 | * Digest Algorithm, as defined in RFC 1321. | ||||||
905 | * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. | ||||||
906 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | ||||||
907 | * Distributed under the BSD License | ||||||
908 | * See http://pajhome.org.uk/crypt/md5 for more info. | ||||||
909 | */ | ||||||
910 | |||||||
911 | /* | ||||||
912 | * Configurable variables. You may need to tweak these to be compatible with | ||||||
913 | * the server-side, but the defaults work in most cases. | ||||||
914 | */ | ||||||
915 | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ | ||||||
916 | var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ | ||||||
917 | var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ | ||||||
918 | |||||||
919 | /* | ||||||
920 | * These are the functions you will usually want to call | ||||||
921 | * They take string arguments and return either hex or base-64 encoded strings | ||||||
922 | */ | ||||||
923 | function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));} | ||||||
924 | function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));} | ||||||
925 | function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));} | ||||||
926 | function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); } | ||||||
927 | function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); } | ||||||
928 | function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); } | ||||||
929 | |||||||
930 | /* | ||||||
931 | * Perform a simple self-test to see if the VM is working | ||||||
932 | */ | ||||||
933 | function md5_vm_test() | ||||||
934 | { | ||||||
935 | return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; | ||||||
936 | } | ||||||
937 | |||||||
938 | /* | ||||||
939 | * Calculate the MD5 of an array of little-endian words, and a bit length | ||||||
940 | */ | ||||||
941 | function core_md5(x, len) | ||||||
942 | { | ||||||
943 | /* append padding */ | ||||||
944 | x[len >> 5] |= 0x80 << ((len) % 32); | ||||||
945 | x[(((len + 64) >>> 9) << 4) + 14] = len; | ||||||
946 | |||||||
947 | var a = 1732584193; | ||||||
948 | var b = -271733879; | ||||||
949 | var c = -1732584194; | ||||||
950 | var d = 271733878; | ||||||
951 | |||||||
952 | for(var i = 0; i < x.length; i += 16) | ||||||
953 | { | ||||||
954 | var olda = a; | ||||||
955 | var oldb = b; | ||||||
956 | var oldc = c; | ||||||
957 | var oldd = d; | ||||||
958 | |||||||
959 | a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); | ||||||
960 | d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); | ||||||
961 | c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); | ||||||
962 | b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); | ||||||
963 | a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); | ||||||
964 | d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); | ||||||
965 | c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); | ||||||
966 | b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); | ||||||
967 | a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); | ||||||
968 | d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); | ||||||
969 | c = md5_ff(c, d, a, b, x[i+10], 17, -42063); | ||||||
970 | b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); | ||||||
971 | a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); | ||||||
972 | d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); | ||||||
973 | c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); | ||||||
974 | b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); | ||||||
975 | |||||||
976 | a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); | ||||||
977 | d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); | ||||||
978 | c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); | ||||||
979 | b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); | ||||||
980 | a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); | ||||||
981 | d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); | ||||||
982 | c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); | ||||||
983 | b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); | ||||||
984 | a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); | ||||||
985 | d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); | ||||||
986 | c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); | ||||||
987 | b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); | ||||||
988 | a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); | ||||||
989 | d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); | ||||||
990 | c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); | ||||||
991 | b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); | ||||||
992 | |||||||
993 | a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); | ||||||
994 | d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); | ||||||
995 | c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); | ||||||
996 | b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); | ||||||
997 | a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); | ||||||
998 | d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); | ||||||
999 | c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); | ||||||
1000 | b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); | ||||||
1001 | a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); | ||||||
1002 | d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); | ||||||
1003 | c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); | ||||||
1004 | b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); | ||||||
1005 | a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); | ||||||
1006 | d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); | ||||||
1007 | c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); | ||||||
1008 | b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); | ||||||
1009 | |||||||
1010 | a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); | ||||||
1011 | d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); | ||||||
1012 | c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); | ||||||
1013 | b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); | ||||||
1014 | a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); | ||||||
1015 | d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); | ||||||
1016 | c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); | ||||||
1017 | b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); | ||||||
1018 | a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); | ||||||
1019 | d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); | ||||||
1020 | c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); | ||||||
1021 | b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); | ||||||
1022 | a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); | ||||||
1023 | d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); | ||||||
1024 | c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); | ||||||
1025 | b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); | ||||||
1026 | |||||||
1027 | a = safe_add(a, olda); | ||||||
1028 | b = safe_add(b, oldb); | ||||||
1029 | c = safe_add(c, oldc); | ||||||
1030 | d = safe_add(d, oldd); | ||||||
1031 | } | ||||||
1032 | return Array(a, b, c, d); | ||||||
1033 | |||||||
1034 | } | ||||||
1035 | |||||||
1036 | /* | ||||||
1037 | * These functions implement the four basic operations the algorithm uses. | ||||||
1038 | */ | ||||||
1039 | function md5_cmn(q, a, b, x, s, t) | ||||||
1040 | { | ||||||
1041 | return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); | ||||||
1042 | } | ||||||
1043 | function md5_ff(a, b, c, d, x, s, t) | ||||||
1044 | { | ||||||
1045 | return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); | ||||||
1046 | } | ||||||
1047 | function md5_gg(a, b, c, d, x, s, t) | ||||||
1048 | { | ||||||
1049 | return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); | ||||||
1050 | } | ||||||
1051 | function md5_hh(a, b, c, d, x, s, t) | ||||||
1052 | { | ||||||
1053 | return md5_cmn(b ^ c ^ d, a, b, x, s, t); | ||||||
1054 | } | ||||||
1055 | function md5_ii(a, b, c, d, x, s, t) | ||||||
1056 | { | ||||||
1057 | return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); | ||||||
1058 | } | ||||||
1059 | |||||||
1060 | /* | ||||||
1061 | * Calculate the HMAC-MD5, of a key and some data | ||||||
1062 | */ | ||||||
1063 | function core_hmac_md5(key, data) | ||||||
1064 | { | ||||||
1065 | var bkey = str2binl(key); | ||||||
1066 | if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz); | ||||||
1067 | |||||||
1068 | var ipad = Array(16), opad = Array(16); | ||||||
1069 | for(var i = 0; i < 16; i++) | ||||||
1070 | { | ||||||
1071 | ipad[i] = bkey[i] ^ 0x36363636; | ||||||
1072 | opad[i] = bkey[i] ^ 0x5C5C5C5C; | ||||||
1073 | } | ||||||
1074 | |||||||
1075 | var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); | ||||||
1076 | return core_md5(opad.concat(hash), 512 + 128); | ||||||
1077 | } | ||||||
1078 | |||||||
1079 | /* | ||||||
1080 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally | ||||||
1081 | * to work around bugs in some JS interpreters. | ||||||
1082 | */ | ||||||
1083 | function safe_add(x, y) | ||||||
1084 | { | ||||||
1085 | var lsw = (x & 0xFFFF) + (y & 0xFFFF); | ||||||
1086 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16); | ||||||
1087 | return (msw << 16) | (lsw & 0xFFFF); | ||||||
1088 | } | ||||||
1089 | |||||||
1090 | /* | ||||||
1091 | * Bitwise rotate a 32-bit number to the left. | ||||||
1092 | */ | ||||||
1093 | function bit_rol(num, cnt) | ||||||
1094 | { | ||||||
1095 | return (num << cnt) | (num >>> (32 - cnt)); | ||||||
1096 | } | ||||||
1097 | |||||||
1098 | /* | ||||||
1099 | * Convert a string to an array of little-endian words | ||||||
1100 | * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. | ||||||
1101 | */ | ||||||
1102 | function str2binl(str) | ||||||
1103 | { | ||||||
1104 | var bin = Array(); | ||||||
1105 | var mask = (1 << chrsz) - 1; | ||||||
1106 | for(var i = 0; i < str.length * chrsz; i += chrsz) | ||||||
1107 | bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); | ||||||
1108 | return bin; | ||||||
1109 | } | ||||||
1110 | |||||||
1111 | /* | ||||||
1112 | * Convert an array of little-endian words to a string | ||||||
1113 | */ | ||||||
1114 | function binl2str(bin) | ||||||
1115 | { | ||||||
1116 | var str = ""; | ||||||
1117 | var mask = (1 << chrsz) - 1; | ||||||
1118 | for(var i = 0; i < bin.length * 32; i += chrsz) | ||||||
1119 | str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); | ||||||
1120 | return str; | ||||||
1121 | } | ||||||
1122 | |||||||
1123 | /* | ||||||
1124 | * Convert an array of little-endian words to a hex string. | ||||||
1125 | */ | ||||||
1126 | function binl2hex(binarray) | ||||||
1127 | { | ||||||
1128 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; | ||||||
1129 | var str = ""; | ||||||
1130 | for(var i = 0; i < binarray.length * 4; i++) | ||||||
1131 | { | ||||||
1132 | str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + | ||||||
1133 | hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF); | ||||||
1134 | } | ||||||
1135 | return str; | ||||||
1136 | } | ||||||
1137 | |||||||
1138 | /* | ||||||
1139 | * Convert an array of little-endian words to a base-64 string | ||||||
1140 | */ | ||||||
1141 | function binl2b64(binarray) | ||||||
1142 | { | ||||||
1143 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||||||
1144 | var str = ""; | ||||||
1145 | for(var i = 0; i < binarray.length * 4; i += 3) | ||||||
1146 | { | ||||||
1147 | var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16) | ||||||
1148 | | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) | ||||||
1149 | | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); | ||||||
1150 | for(var j = 0; j < 4; j++) | ||||||
1151 | { | ||||||
1152 | if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; | ||||||
1153 | else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); | ||||||
1154 | } | ||||||
1155 | } | ||||||
1156 | return str; | ||||||
1157 | } | ||||||
1158 | ENDTAG | ||||||
1159 | |||||||
1160 | #################################################################### | ||||||
1161 | }else{ # $self->{digest} eq "Digest::SHA1" | ||||||
1162 | #################################################################### | ||||||
1163 | |||||||
1164 | return <<"ENDTAG" | ||||||
1165 | /* | ||||||
1166 | * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined | ||||||
1167 | * in FIPS PUB 180-1 | ||||||
1168 | * Version 2.1a Copyright Paul Johnston 2000 - 2002. | ||||||
1169 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | ||||||
1170 | * Distributed under the BSD License | ||||||
1171 | * See http://pajhome.org.uk/crypt/md5 for details. | ||||||
1172 | */ | ||||||
1173 | |||||||
1174 | /* | ||||||
1175 | * Configurable variables. You may need to tweak these to be compatible with | ||||||
1176 | * the server-side, but the defaults work in most cases. | ||||||
1177 | */ | ||||||
1178 | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ | ||||||
1179 | var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ | ||||||
1180 | var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ | ||||||
1181 | |||||||
1182 | /* | ||||||
1183 | * These are the functions you will usually want to call | ||||||
1184 | * They take string arguments and return either hex or base-64 encoded strings | ||||||
1185 | */ | ||||||
1186 | function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} | ||||||
1187 | function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} | ||||||
1188 | function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} | ||||||
1189 | function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));} | ||||||
1190 | function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));} | ||||||
1191 | function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));} | ||||||
1192 | |||||||
1193 | /* | ||||||
1194 | * Perform a simple self-test to see if the VM is working | ||||||
1195 | */ | ||||||
1196 | function sha1_vm_test() | ||||||
1197 | { | ||||||
1198 | return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; | ||||||
1199 | } | ||||||
1200 | |||||||
1201 | /* | ||||||
1202 | * Calculate the SHA-1 of an array of big-endian words, and a bit length | ||||||
1203 | */ | ||||||
1204 | function core_sha1(x, len) | ||||||
1205 | { | ||||||
1206 | /* append padding */ | ||||||
1207 | x[len >> 5] |= 0x80 << (24 - len % 32); | ||||||
1208 | x[((len + 64 >> 9) << 4) + 15] = len; | ||||||
1209 | |||||||
1210 | var w = Array(80); | ||||||
1211 | var a = 1732584193; | ||||||
1212 | var b = -271733879; | ||||||
1213 | var c = -1732584194; | ||||||
1214 | var d = 271733878; | ||||||
1215 | var e = -1009589776; | ||||||
1216 | |||||||
1217 | for(var i = 0; i < x.length; i += 16) | ||||||
1218 | { | ||||||
1219 | var olda = a; | ||||||
1220 | var oldb = b; | ||||||
1221 | var oldc = c; | ||||||
1222 | var oldd = d; | ||||||
1223 | var olde = e; | ||||||
1224 | |||||||
1225 | for(var j = 0; j < 80; j++) | ||||||
1226 | { | ||||||
1227 | if(j < 16) w[j] = x[i + j]; | ||||||
1228 | else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); | ||||||
1229 | var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), | ||||||
1230 | safe_add(safe_add(e, w[j]), sha1_kt(j))); | ||||||
1231 | e = d; | ||||||
1232 | d = c; | ||||||
1233 | c = rol(b, 30); | ||||||
1234 | b = a; | ||||||
1235 | a = t; | ||||||
1236 | } | ||||||
1237 | |||||||
1238 | a = safe_add(a, olda); | ||||||
1239 | b = safe_add(b, oldb); | ||||||
1240 | c = safe_add(c, oldc); | ||||||
1241 | d = safe_add(d, oldd); | ||||||
1242 | e = safe_add(e, olde); | ||||||
1243 | } | ||||||
1244 | return Array(a, b, c, d, e); | ||||||
1245 | |||||||
1246 | } | ||||||
1247 | |||||||
1248 | /* | ||||||
1249 | * Perform the appropriate triplet combination function for the current | ||||||
1250 | * iteration | ||||||
1251 | */ | ||||||
1252 | function sha1_ft(t, b, c, d) | ||||||
1253 | { | ||||||
1254 | if(t < 20) return (b & c) | ((~b) & d); | ||||||
1255 | if(t < 40) return b ^ c ^ d; | ||||||
1256 | if(t < 60) return (b & c) | (b & d) | (c & d); | ||||||
1257 | return b ^ c ^ d; | ||||||
1258 | } | ||||||
1259 | |||||||
1260 | /* | ||||||
1261 | * Determine the appropriate additive constant for the current iteration | ||||||
1262 | */ | ||||||
1263 | function sha1_kt(t) | ||||||
1264 | { | ||||||
1265 | return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : | ||||||
1266 | (t < 60) ? -1894007588 : -899497514; | ||||||
1267 | } | ||||||
1268 | |||||||
1269 | /* | ||||||
1270 | * Calculate the HMAC-SHA1 of a key and some data | ||||||
1271 | */ | ||||||
1272 | function core_hmac_sha1(key, data) | ||||||
1273 | { | ||||||
1274 | var bkey = str2binb(key); | ||||||
1275 | if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz); | ||||||
1276 | |||||||
1277 | var ipad = Array(16), opad = Array(16); | ||||||
1278 | for(var i = 0; i < 16; i++) | ||||||
1279 | { | ||||||
1280 | ipad[i] = bkey[i] ^ 0x36363636; | ||||||
1281 | opad[i] = bkey[i] ^ 0x5C5C5C5C; | ||||||
1282 | } | ||||||
1283 | |||||||
1284 | var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); | ||||||
1285 | return core_sha1(opad.concat(hash), 512 + 160); | ||||||
1286 | } | ||||||
1287 | |||||||
1288 | /* | ||||||
1289 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally | ||||||
1290 | * to work around bugs in some JS interpreters. | ||||||
1291 | */ | ||||||
1292 | function safe_add(x, y) | ||||||
1293 | { | ||||||
1294 | var lsw = (x & 0xFFFF) + (y & 0xFFFF); | ||||||
1295 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16); | ||||||
1296 | return (msw << 16) | (lsw & 0xFFFF); | ||||||
1297 | } | ||||||
1298 | |||||||
1299 | /* | ||||||
1300 | * Bitwise rotate a 32-bit number to the left. | ||||||
1301 | */ | ||||||
1302 | function rol(num, cnt) | ||||||
1303 | { | ||||||
1304 | return (num << cnt) | (num >>> (32 - cnt)); | ||||||
1305 | } | ||||||
1306 | |||||||
1307 | /* | ||||||
1308 | * Convert an 8-bit or 16-bit string to an array of big-endian words | ||||||
1309 | * In 8-bit function, characters >255 have their hi-byte silently ignored. | ||||||
1310 | */ | ||||||
1311 | function str2binb(str) | ||||||
1312 | { | ||||||
1313 | var bin = Array(); | ||||||
1314 | var mask = (1 << chrsz) - 1; | ||||||
1315 | for(var i = 0; i < str.length * chrsz; i += chrsz) | ||||||
1316 | bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); | ||||||
1317 | return bin; | ||||||
1318 | } | ||||||
1319 | |||||||
1320 | /* | ||||||
1321 | * Convert an array of big-endian words to a string | ||||||
1322 | */ | ||||||
1323 | function binb2str(bin) | ||||||
1324 | { | ||||||
1325 | var str = ""; | ||||||
1326 | var mask = (1 << chrsz) - 1; | ||||||
1327 | for(var i = 0; i < bin.length * 32; i += chrsz) | ||||||
1328 | str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); | ||||||
1329 | return str; | ||||||
1330 | } | ||||||
1331 | |||||||
1332 | /* | ||||||
1333 | * Convert an array of big-endian words to a hex string. | ||||||
1334 | */ | ||||||
1335 | function binb2hex(binarray) | ||||||
1336 | { | ||||||
1337 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; | ||||||
1338 | var str = ""; | ||||||
1339 | for(var i = 0; i < binarray.length * 4; i++) | ||||||
1340 | { | ||||||
1341 | str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + | ||||||
1342 | hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); | ||||||
1343 | } | ||||||
1344 | return str; | ||||||
1345 | } | ||||||
1346 | |||||||
1347 | /* | ||||||
1348 | * Convert an array of big-endian words to a base-64 string | ||||||
1349 | */ | ||||||
1350 | function binb2b64(binarray) | ||||||
1351 | { | ||||||
1352 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||||||
1353 | var str = ""; | ||||||
1354 | for(var i = 0; i < binarray.length * 4; i += 3) | ||||||
1355 | { | ||||||
1356 | var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) | ||||||
1357 | | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) | ||||||
1358 | | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); | ||||||
1359 | for(var j = 0; j < 4; j++) | ||||||
1360 | { | ||||||
1361 | if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; | ||||||
1362 | else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); | ||||||
1363 | } | ||||||
1364 | } | ||||||
1365 | return str; | ||||||
1366 | } | ||||||
1367 | ENDTAG | ||||||
1368 | #################################################################### | ||||||
1369 | } | ||||||
1370 | #################################################################### | ||||||
1371 | } | ||||||
1372 | |||||||
1373 | 1; | ||||||
1374 | __END__ |