CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

SPTUser.php
Go to the documentation of this file.
1 <?PHP
2
3 #
4 # FILE: SPT--SPTUser.php
5 #
6 # Part of the Collection Workflow Integration System (CWIS)
7 # Copyright 2004-2013 Edward Almasy and Internet Scout Research Group
8 # http://scout.wisc.edu/cwis/
9 #
10
11 class SPTUser extends CWUser
12 {
13
14 # ---- PUBLIC INTERFACE --------------------------------------------------
15
25 public static function GetCryptKey()
26 {
27 $DB = new Database();
28
29 # regenerate keys every day (24 * 60 * 60 = 86,400 seconds)
30 $KeyRegenInterval = 86400;
31
32 # oldest key we want to keep
33 $MaxKeyAge = 3 * $KeyRegenInterval;
34
35 # if the page cache was enabled, be sure to keep keys that were
36 # current (i.e. not expired) as of the oldest cache entry
37 if ($GLOBALS["AF"]->PageCacheEnabled())
38 {
39 $CacheInfo = $GLOBALS["AF"]->GetPageCacheInfo();
40 if ($CacheInfo["NumberOfEntries"]>0)
41 {
42 $MaxKeyAge += (time()-$CacheInfo["OldestTimestamp"]);
43 }
44 }
45
46 # NOTE: One can not simply subtract two TIMESTAMPs and expect
47 # a sane result from mysql. Using a TIMESTAMP in numeric
48 # context converts it to an int, but in YYYYMMDDHHMMSS format
49 # rather than as a UNIX time. Hence the use of
50 # TIMESTAMPDIFF() below.
51
52 # clear expired keys and replay protection tokens
53 $DB->Query("DELETE FROM UsedLoginTokens WHERE "
54 ."TIMESTAMPDIFF(SECOND, KeyCTime, NOW()) > ".$MaxKeyAge);
55
56 $DB->Query("LOCK TABLES LoginKeys WRITE");
57 $DB->Query("DELETE FROM LoginKeys WHERE "
58 ."TIMESTAMPDIFF(SECOND, CreationTime, NOW()) > ".$MaxKeyAge);
59
60 # get the most recently generated key
61 $DB->Query("SELECT TIMESTAMPDIFF(SECOND, CreationTime, NOW()) as Age,"
62 ."KeyPair FROM LoginKeys "
63 ."ORDER BY Age ASC LIMIT 1");
64 $Row = $DB->FetchRow();
65
66 # if there is no key in the database, or the key is too old
67 if ( ($Row===FALSE) || ($Row["Age"]>= $KeyRegenInterval) )
68 {
69 # generate a new OpenSSL format keypair
70 $KeyPair = openssl_pkey_new(
71 array(
72 'private_key_bits' => 512, # make this a Sysadmin pref later?
73 'private_key_type' => OPENSSL_KEYTYPE_RSA ));
74
75 # serialize it for storage
76 openssl_pkey_export($KeyPair, $KeyPairDBFormat);
77
78 # stick it into the database
79 $DB->Query("INSERT INTO LoginKeys "
80 ."(KeyPair, CreationTime) VALUES ("
81 ."\"".addslashes($KeyPairDBFormat)."\","
82 ."NOW())");
83 }
84 else
85 {
86 # if we do have a current key in the database,
87 # convert it to openssl format for usage
88 $KeyPair = openssl_pkey_get_private( $Row["KeyPair"] );
89 }
90 $DB->Query("UNLOCK TABLES");
91
92 return $KeyPair;
93 }
94
102 public static function ExtractPubKeyParameters($KeyPair)
103 {
104 # Export the keypair as an ASCII signing request (which contains the data we want)
105 openssl_csr_export(openssl_csr_new(array(), $KeyPair), $Export, FALSE);
106
107 $Modulus = "";
108 $Exponent = "";
109
110 // @codingStandardsIgnoreStart
111 $Patterns = array(
112 '/Modulus \([0-9]+ bit\):(.*)Exponent: [0-9]+ \(0x([0-9a-f]+)\)/ms',
113 '/Public-Key: \([0-9]+ bit\).*Modulus:(.*)Exponent: [0-9]+ \(0x([0-9a-f]+)\)/ms',
114 );
115 // @codingStandardsIgnoreEnd
116
117 foreach ($Patterns as $Pattern)
118 {
119 if (preg_match($Pattern, $Export, $Matches))
120 {
121 $Modulus = $Matches[1];
122 $Exponent = $Matches[2];
123 break;
124 }
125 }
126
127 # Clean newlines and whitespace out of the modulus
128 $Modulus = preg_replace("/[^0-9a-f]/", "", $Modulus);
129
130 # Return key material
131 return array( "Modulus" => $Modulus, "Exponent" => $Exponent );
132 }
133
141 public static function DecryptPassword($UserName, $EncryptedPassword)
142 {
143 $DB = new Database();
144 $DB->Query("SELECT CreationTime, KeyPair FROM LoginKeys");
145
146 # start off assuming that nothing will decrypt properly
147 $Password = FALSE;
148
149 # remove the base64 encoding sent on the cyphertext
150 $Cyphertext = base64_decode($EncryptedPassword);
151
152 # extract recently used login keys from the database
153 $Keys = $DB->FetchRows();
154
155 # iterate through them on the cyphertext, trying to decrypt it with
156 # each key. by default, 48 hr worth of keys are kept, and fresh keys
157 # are generated every 24 hr.
158 foreach ($Keys as $Key)
159 {
160 $KeyCTime = $Key["CreationTime"];
161 $DBFormatKeyPair = $Key["KeyPair"];
162 # extract the OpenSSL format private key from the database key format
163 $Keypair = openssl_pkey_get_private($DBFormatKeyPair);
164
165 # attempt to decrypt the cyphertext
166 if (openssl_private_decrypt($Cyphertext, $Cleartext, $Keypair))
167 {
168 # on success, extract the password portion and the random bytes
169 $Data = explode("\t", $Cleartext);
170
171 if (count($Data) == 2)
172 {
173 list($Password, $Token) = $Data;
174
175 # check to see if we've seen these particular bytes
176 # before for this user and this key
177 $DB->Query("SELECT * FROM UsedLoginTokens WHERE"
178 ." Token=\"".addslashes($Token)."\" AND"
179 ." KeyCTime=\"".$KeyCTime."\" AND"
180 ." UserName=\"".$UserName."\"");
181
182 if ($DB->NumRowsSelected() > 0)
183 {
184 # if so, this is a replay attack; fail the login
185 $Password = FALSE;
186 }
187 else
188 {
189 # otherwise, record these bytes as seen, and attempt to login
190 # with the plaintext password
191 $DB->Query("INSERT INTO UsedLoginTokens"
192 ." (Token, KeyCTime, UserName) VALUES ("
193 ."\"".addslashes($Token)."\","
194 ."\"".addslashes($KeyCTime)."\","
195 ."\"".addslashes($UserName)."\")");
196 }
197
198 # no need to try other keys when we've found one that
199 # works
200 break;
201 }
202 }
203 }
204
205 return $Password;
206 }
207 }
User\$DB
$DB
Definition: User.php:1079
Database
SQL database abstraction object with smart query caching.
Definition: Database.php:22
SPTUser\ExtractPubKeyParameters
static ExtractPubKeyParameters($KeyPair)
Extract the modulus and exponent of the public key from an OpenSSL format keypair to send in login fo...
Definition: SPTUser.php:102
PHP
PHP
Definition: RSSClient--Test.php:12
SPTUser
Definition: SPTUser.php:11
SPTUser\DecryptPassword
static DecryptPassword($UserName, $EncryptedPassword)
Decrypt an encrypted password.
Definition: SPTUser.php:141
SPTUser\GetCryptKey
static GetCryptKey()
Get/generate a cryptographic keypair for user login.
Definition: SPTUser.php:25
CWUser
CWIS-specific user class.
Definition: CWUser.php:13