1 |
<?php
|
2 |
//$Header: /hl/cvsroots/gpl01/gpl01/webprojs/fboprime/sw/phplib/passwd.inc,v 1.4 2006/07/08 21:07:50 dashley Exp $
|
3 |
//********************************************************************************
|
4 |
//Copyright (C) 2006 David T. Ashley
|
5 |
//********************************************************************************
|
6 |
//This program or source file is free software; you can redistribute it and/or
|
7 |
//modify it under the terms of the GNU General Public License as published by
|
8 |
//the Free Software Foundation; either version 2 of the License, or (at your
|
9 |
//option) any later version.
|
10 |
//
|
11 |
//This program or source file is distributed in the hope that it will
|
12 |
//be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14 |
//GNU General Public License for more details.
|
15 |
//
|
16 |
//You may have received a copy of the GNU General Public License
|
17 |
//along with this program; if not, write to the Free Software
|
18 |
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19 |
//********************************************************************************
|
20 |
//Dave Ashley, 04/06
|
21 |
//
|
22 |
//This source file provides the code to deal with the manipulation of
|
23 |
//passwords.
|
24 |
//
|
25 |
require_once("sguid.inc"); //Necesssary to generate SGUIDs.
|
26 |
require_once("crhsh.inc");
|
27 |
//
|
28 |
//
|
29 |
//Characters allowed in a password.
|
30 |
define("PASSWD_ALLOWED_CHARS", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-");
|
31 |
//
|
32 |
//Characters that will be used when generating an automatic replacement password.
|
33 |
define("PASSWD_AUTOGEN_CHARS", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
|
34 |
//
|
35 |
//Minimum and maximum lengths for a password.
|
36 |
define("PASSWD_LEN_MIN", 4);
|
37 |
define("PASSWD_LEN_MAX", 22);
|
38 |
//
|
39 |
//
|
40 |
//--------------------------------------------------------------------------------
|
41 |
//Returns a random password suitable for use when e-mailing a user a replacement
|
42 |
//for a lost password.
|
43 |
//
|
44 |
//Unit-tested 20060408.
|
45 |
//
|
46 |
function PASSWD_random_password_gen()
|
47 |
{
|
48 |
//Assuming 12 chars, this will be about 62^10 = 3.2E21 possibilities.
|
49 |
//This will be adequate, although it is substantially less information
|
50 |
//than an MD5 (2^128 = 3.4E38). Strictly speaking, this appears to be
|
51 |
//the weak link. However, even guessing 1,000 passwords per second,
|
52 |
//expected value of solution time is 102 billion years.
|
53 |
//
|
54 |
$len = 12; //PASSWD_LEN_MAX;
|
55 |
$pwd = "";
|
56 |
|
57 |
for ($i=0; $i<$len; $i++)
|
58 |
{
|
59 |
$pos = rand(0, strlen(PASSWD_AUTOGEN_CHARS)-1);
|
60 |
$c = SubStr(PASSWD_AUTOGEN_CHARS, $pos, 1);
|
61 |
$pwd .= $c;
|
62 |
}
|
63 |
|
64 |
return($pwd);
|
65 |
}
|
66 |
//
|
67 |
//
|
68 |
//--------------------------------------------------------------------------------
|
69 |
//Given a password, returns the salt and the hash that should be stored in
|
70 |
//the database. The salt is an SGUID (32 characters), and the hash proper
|
71 |
//will be another 32 characters, giving a total of 64 characters.
|
72 |
//
|
73 |
//The password used isn't checked--that should have been done before
|
74 |
//this function is used.
|
75 |
//
|
76 |
//Unit-tested 20060408.
|
77 |
//
|
78 |
function PASSWD_stored_hash_gen($passwd)
|
79 |
{
|
80 |
$salt = SGUID_sguid();
|
81 |
$hash = CRHSH_hashva($salt, $passwd);
|
82 |
return(StrToUpper($salt . $hash));
|
83 |
}
|
84 |
//
|
85 |
//
|
86 |
//--------------------------------------------------------------------------------
|
87 |
//Authenticates a password against a 64-character stored salt/hash.
|
88 |
//Returns 0 for authentication failure or 1 for authentication success.
|
89 |
//
|
90 |
//Unit-tested 20060408.
|
91 |
//
|
92 |
function PASSWD_pwd_hash_auth($stored_hash, $passwd)
|
93 |
{
|
94 |
//We can only accept strings. Failure to provide
|
95 |
//two strings is authentication failure.
|
96 |
if ((! is_string($stored_hash)) || (! is_string($passwd)))
|
97 |
return(0);
|
98 |
|
99 |
//Stored hash must be of the right length.
|
100 |
if (strlen($stored_hash) != 64)
|
101 |
return(0);
|
102 |
|
103 |
//Extract the salt from the stored hash.
|
104 |
$salt = SubStr($stored_hash, 0, 32);
|
105 |
|
106 |
//The salt should be a properly formed SGUID. If not, failure.
|
107 |
if (! SGUID_is_syntactically_valid($salt))
|
108 |
return(0);
|
109 |
|
110 |
//The comparison hash is formed from the stored salt and the password.
|
111 |
$comparison_hash = StrToUpper(CRHSH_hashva($salt, $passwd));
|
112 |
|
113 |
//The full value that should be stored and that we compare against is
|
114 |
//the concatenation of the salt and the hash with upper-case letters.
|
115 |
$comparison_stored_hash = $salt . $comparison_hash;
|
116 |
|
117 |
//If the strings don't match, authentication failure.
|
118 |
if ($stored_hash != $comparison_stored_hash)
|
119 |
return(0);
|
120 |
|
121 |
//If we're here, authentication success.
|
122 |
return(1);
|
123 |
}
|
124 |
//
|
125 |
//
|
126 |
//--------------------------------------------------------------------------------
|
127 |
//Accepts as input a password that was either entered by a user either
|
128 |
//to authenticate or change passwords. Checks the password
|
129 |
//against design rules for passwords. Returns TRUE if the password
|
130 |
//is acceptable, or returns an array of complaints with HTML markup if not.
|
131 |
//
|
132 |
//Unit-tested 20060408.
|
133 |
//
|
134 |
function PASSWD_passwd_rules_check($passwd)
|
135 |
{
|
136 |
//Index into the complaints.
|
137 |
$i = 0;
|
138 |
|
139 |
//If we have been passed a non-string type, that is the ultimate complaint.
|
140 |
if (! is_string($passwd))
|
141 |
{
|
142 |
$complaints[0] = "A non-string password was supplied to software internals.";
|
143 |
return($complaints);
|
144 |
}
|
145 |
|
146 |
//Can't be too short.
|
147 |
if (strlen($passwd) < PASSWD_LEN_MIN)
|
148 |
{
|
149 |
$complaints[$i] = "The password supplied is too short. Passwords must be at least 4 characters long.";
|
150 |
$i++;
|
151 |
}
|
152 |
|
153 |
//Can't be too long.
|
154 |
if (strlen($passwd) > PASSWD_LEN_MAX)
|
155 |
{
|
156 |
$complaints[$i] = "The password supplied is too long. Passwords can be no longer than 20 characters.";
|
157 |
$i++;
|
158 |
}
|
159 |
|
160 |
//Can't contain illegal characters."
|
161 |
if (! STRFUNC_is_char_subset($passwd, PASSWD_ALLOWED_CHARS))
|
162 |
{
|
163 |
$complaints[$i] = "The password supplied contains illegal characters. Passwords may contain only " .
|
164 |
"characters from the set "" . PASSWD_ALLOWED_CHARS . "".";
|
165 |
$i++;
|
166 |
}
|
167 |
|
168 |
//If we've registered no complaints, return TRUE, else return the complaints.
|
169 |
if ($i)
|
170 |
{
|
171 |
return($complaints);
|
172 |
}
|
173 |
else
|
174 |
{
|
175 |
return(TRUE);
|
176 |
}
|
177 |
}
|
178 |
//--------------------------------------------------------------------------------
|
179 |
?>
|