BLOB streaming documentation
[phpmyadmin/crack.git] / libraries / auth / swekey / swekey.php
blobeb23f73ad59230704e311d92223b4c50e6f58500
1 <?php
2 /**
3 * Library that provides common functions that are used to help integrating Swekey Authentication in a PHP web site
4 * Version 1.0
5 *
6 * History:
7 * 1.2 Use curl (widely installed) to query the server
8 * Fixed a possible tempfile race attack
9 * Random token cache can now be disabled
10 * 1.1 Added Swekey_HttpGet function that support faulty servers
11 * Support for custom servers
12 * 1.0 First release
17 /**
18 * Errors codes
20 define ("SWEKEY_ERR_INVALID_DEV_STATUS",901); // The satus of the device is not SWEKEY_STATUS_OK
21 define ("SWEKEY_ERR_INTERNAL",902); // Should never occurd
22 define ("SWEKEY_ERR_OUTDATED_RND_TOKEN",910); // You random token is too old
23 define ("SWEKEY_ERR_INVALID_OTP",911); // The otp was not correct
25 /**
26 * Those errors are considered as an attack and your site will be blacklisted during one minute
27 * if you receive one of those errors
29 define ("SWEKEY_ERR_BADLY_ENCODED_REQUEST",920);
30 define ("SWEKEY_ERR_INVALID_RND_TOKEN",921);
31 define ("SWEKEY_ERR_DEV_NOT_FOUND",922);
33 /**
34 * The last error of an operation is alway put in this global var
37 global $gSwekeyLastError;
38 $gSwekeyLastError = 0;
40 global $gSwekeyLastResult;
41 $gSwekeyLastResult = "<not set>";
43 /**
44 * Servers addresses
45 * Use the Swekey_SetXxxServer($server) functions to set them
48 global $gSwekeyCheckServer;
49 if (! isset($gSwekeyCheckServer))
50 $gSwekeyCheckServer = 'http://auth-check.musbe.net';
52 global $gSwekeyRndTokenServer;
53 if (! isset($gSwekeyRndTokenServer))
54 $gSwekeyRndTokenServer = 'http://auth-rnd-gen.musbe.net';
56 global $gSwekeyStatusServer;
57 if (! isset($gSwekeyStatusServer))
58 $gSwekeyStatusServer = 'http://auth-status.musbe.net';
60 global $gSwekeyCA;
62 global $gSwekeyTokenCacheEnabled;
63 if (! isset($gSwekeyTokenCacheEnabled))
64 $gSwekeyTokenCacheEnabled = true;
66 /**
67 * Change the address of the Check server.
68 * If $server is empty the default value 'http://auth-check.musbe.net' will be used
70 * @param server The protocol and hostname to use
71 * @access public
73 function Swekey_SetCheckServer($server)
75 global $gSwekeyCheckServer;
76 if (empty($server))
77 $gSwekeyCheckServer = 'http://auth-check.musbe.net';
78 else
79 $gSwekeyCheckServer = $server;
82 /**
83 * Change the address of the Random Token Generator server.
84 * If $server is empty the default value 'http://auth-rnd-gen.musbe.net' will be used
86 * @param server The protocol and hostname to use
87 * @access public
89 function Swekey_SetRndTokenServer($server)
91 global $gSwekeyRndTokenServer;
92 if (empty($server))
93 $gSwekeyRndTokenServer = 'http://auth-rnd-gen.musbe.net';
94 else
95 $gSwekeyRndTokenServer = $server;
98 /**
99 * Change the address of the Satus server.
100 * If $server is empty the default value 'http://auth-status.musbe.net' will be used
102 * @param server The protocol and hostname to use
103 * @access public
105 function Swekey_SetStatusServer($server)
107 global $gSwekeyStatusServer;
108 if (empty($server))
109 $gSwekeyStatusServer = 'http://auth-status.musbe.net';
110 else
111 $gSwekeyStatusServer = $server;
115 * Change the certificat file in case of the the severs use https instead of http
117 * @param cafile The path of the crt file to use
118 * @access public
120 function Swekey_SetCAFile($cafile)
122 global $gSwekeyCA;
123 $gSwekeyCA = $cafile;
127 * Enable or disable the random token caching
128 * Because everybody has full access to the cache file, it can be a DOS vulnerability
129 * So disable it if you are running in a non secure enviromnement
131 * @param $enable
132 * @access public
134 function Swekey_EnableTokenCache($enable)
136 global $gSwekeyTokenCacheEnabled;
137 $gSwekeyTokenCacheEnabled = ! empty($enable);
142 * Return the last error.
144 * @return The Last Error
145 * @access public
147 function Swekey_GetLastError()
149 global $gSwekeyLastError;
150 return $gSwekeyLastError;
154 * Return the last result.
156 * @return The Last Error
157 * @access public
159 function Swekey_GetLastResult()
161 global $gSwekeyLastResult;
162 return $gSwekeyLastResult;
166 * Send a synchronous request to the server.
167 * This function manages timeout then will not block if one of the server is down
169 * @param url The url to get
170 * @param response_code The response code
171 * @return The body of the response or "" in case of error
172 * @access private
174 function Swekey_HttpGet($url, &$response_code)
176 global $gSwekeyLastError;
177 $gSwekeyLastError = 0;
178 global $gSwekeyLastResult;
179 $gSwekeyLastResult = "<not set>";
181 // use curl if available
182 if (function_exists('curl_init'))
184 $sess = curl_init($url);
185 if (substr($url, 0, 8) == "https://")
187 global $gSwekeyCA;
189 if (! empty($gSwekeyCA))
191 if (file_exists($gSwekeyCA))
193 if (! curl_setopt($sess, CURLOPT_CAINFO, $gSwekeyCA))
194 error_log("SWEKEY_ERROR:Could not set CA file : ".curl_error($sess));
195 else
196 $caFileOk = true;
198 else
199 error_log("SWEKEY_ERROR:Could not find CA file $gSwekeyCA getting $url");
202 curl_setopt($sess, CURLOPT_SSL_VERIFYHOST, '2');
203 curl_setopt($sess, CURLOPT_SSL_VERIFYPEER, '2');
204 curl_setopt($sess, CURLOPT_CONNECTTIMEOUT, '20');
205 curl_setopt($sess, CURLOPT_TIMEOUT, '20');
207 else
209 curl_setopt($sess, CURLOPT_CONNECTTIMEOUT, '3');
210 curl_setopt($sess, CURLOPT_TIMEOUT, '5');
213 curl_setopt($sess, CURLOPT_RETURNTRANSFER, '1');
214 $res=curl_exec($sess);
215 $response_code = curl_getinfo($sess, CURLINFO_HTTP_CODE);
216 $curlerr = curl_error($sess);
217 curl_close($sess);
219 if ($response_code == 200)
221 $gSwekeyLastResult = $res;
222 return $res;
225 if (! empty($response_code))
227 $gSwekeyLastError = $response_code;
228 error_log("SWEKEY_ERROR:Error $gSwekeyLastError ($curlerr) getting $url");
229 return "";
232 $response_code = 408; // Request Timeout
233 $gSwekeyLastError = $response_code;
234 error_log("SWEKEY_ERROR:Error $curlerr getting $url");
235 return "";
238 // use pecl_http if available
239 if (class_exists('HttpRequest'))
241 // retry if one of the server is down
242 for ($num=1; $num <= 3; $num++ )
244 $r = new HttpRequest($url);
245 $options = array('timeout' => '3');
247 if (substr($url,0, 6) == "https:")
249 $sslOptions = array();
250 $sslOptions['verifypeer'] = true;
251 $sslOptions['verifyhost'] = true;
253 $capath = __FILE__;
254 $name = strrchr($capath, '/');
255 if (empty($name)) // windows
256 $name = strrchr($capath, '\\');
257 $capath = substr($capath, 0, strlen($capath) - strlen($name) + 1).'musbe-ca.crt';
259 if (! empty($gSwekeyCA))
260 $sslOptions['cainfo'] = $gSwekeyCA;
262 $options['ssl'] = $sslOptions;
265 $r->setOptions($options);
267 // try
269 $reply = $r->send();
270 $res = $reply->getBody();
271 $info = $r->getResponseInfo();
272 $response_code = $info['response_code'];
273 if ($response_code != 200)
275 $gSwekeyLastError = $response_code;
276 error_log("SWEKEY_ERROR:Error ".$gSwekeyLastError." getting ".$url);
277 return "";
281 $gSwekeyLastResult = $res;
282 return $res;
284 // catch (HttpException $e)
285 // {
286 // error_log("SWEKEY_WARNING:HttpException ".$e." getting ".$url);
287 // }
290 $response_code = 408; // Request Timeout
291 $gSwekeyLastError = $response_code;
292 error_log("SWEKEY_ERROR:Error ".$gSwekeyLastError." getting ".$url);
293 return "";
296 global $http_response_header;
297 $res = @file_get_contents($url);
298 $response_code = substr($http_response_header[0], 9, 3); //HTTP/1.0
299 if ($response_code == 200)
301 $gSwekeyLastResult = $res;
302 return $res;
305 $gSwekeyLastError = $response_code;
306 error_log("SWEKEY_ERROR:Error ".$response_code." getting ".$url);
307 return "";
311 * Get a Random Token from a Token Server
312 * The RT is a 64 vhars hexadecimal value
313 * You should better use Swekey_GetFastRndToken() for performance
314 * @access public
316 function Swekey_GetRndToken()
318 global $gSwekeyRndTokenServer;
319 return Swekey_HttpGet($gSwekeyRndTokenServer.'/FULL-RND-TOKEN', $response_code);
323 * Get a Half Random Token from a Token Server
324 * The RT is a 64 vhars hexadecimal value
325 * Use this value if you want to make your own Swekey_GetFastRndToken()
326 * @access public
328 function Swekey_GetHalfRndToken()
330 global $gSwekeyRndTokenServer;
331 return Swekey_HttpGet($gSwekeyRndTokenServer.'/HALF-RND-TOKEN', $response_code);
335 * Get a Half Random Token
336 * The RT is a 64 vhars hexadecimal value
337 * This function get a new random token and reuse it.
338 * Token are refetched from the server only once every 30 seconds.
339 * You should always use this function to get half random token.
340 * @access public
342 function Swekey_GetFastHalfRndToken()
344 global $gSwekeyTokenCacheEnabled;
346 $res = "";
347 $cachefile = "";
349 // We check if we have a valid RT is the session
350 if (isset($_SESSION['rnd-token-date']))
351 if (time() - $_SESSION['rnd-token-date'] < 30)
352 $res = $_SESSION['rnd-token'];
354 // If not we try to get it from a temp file (PHP >= 5.2.1 only)
355 if (strlen($res) != 32 && $gSwekeyTokenCacheEnabled)
357 if (function_exists('sys_get_temp_dir'))
359 $tempdir = sys_get_temp_dir();
360 $cachefile = $tempdir."/swekey-rnd-token-".get_current_user();
361 $modif = filemtime($cachefile);
362 if ($modif != false)
363 if (time() - $modif < 30)
365 $res = @file_get_contents($cachefile);
366 if (strlen($res) != 32)
367 $res = "";
368 else
370 $_SESSION['rnd-token'] = $res;
371 $_SESSION['rnd-token-date'] = $modif;
377 // If we don't have a valid RT here we have to get it from the server
378 if (strlen($res) != 32)
380 $res = substr(Swekey_GetHalfRndToken(), 0, 32);
381 $_SESSION['rnd-token'] = $res;
382 $_SESSION['rnd-token-date'] = time();
383 if (! empty($cachefile))
385 // we unlink the file so no possible tempfile race attack (thanks Thijs)
386 unlink($cachefile);
387 $file = fopen($cachefile , "x");
388 if ($file != FALSE)
390 @fwrite($file, $res);
391 @fclose($file);
396 return $res."00000000000000000000000000000000";
400 * Get a Random Token
401 * The RT is a 64 vhars hexadecimal value
402 * This function generates a unique random token for each call but call the
403 * server only once every 30 seconds.
404 * You should always use this function to get random token.
405 * @access public
407 function Swekey_GetFastRndToken()
409 $res = Swekey_GetFastHalfRndToken();
410 if (strlen($res) == 64)
411 return substr($res, 0, 32).strtoupper(md5("Musbe Authentication Key" + mt_rand() + date(DATE_ATOM)));
413 return "";
418 * Checks that an OTP generated by a Swekey is valid
420 * @param id The id of the swekey
421 * @param rt The random token used to generate the otp
422 * @param otp The otp generated by the swekey
423 * @return true or false
424 * @access public
426 function Swekey_CheckOtp($id, $rt, $otp)
428 global $gSwekeyCheckServer;
429 $res = Swekey_HttpGet($gSwekeyCheckServer.'/CHECK-OTP/'.$id.'/'.$rt.'/'.$otp, $response_code);
430 return $response_code == 200 && $res == "OK";
434 * Values that are associated with a key.
435 * The following values can be returned by the Swekey_GetStatus() function
437 define ("SWEKEY_STATUS_OK",0);
438 define ("SWEKEY_STATUS_NOT_FOUND",1); // The key does not exist in the db
439 define ("SWEKEY_STATUS_INACTIVE",2); // The key has never been activated
440 define ("SWEKEY_STATUS_LOST",3); // The user has lost his key
441 define ("SWEKEY_STATUS_STOLEN",4); // The key was stolen
442 define ("SWEKEY_STATUS_FEE_DUE",5); // The annual fee was not paid
443 define ("SWEKEY_STATUS_OBSOLETE",6); // The hardware is no longer supported
444 define ("SWEKEY_STATUS_UNKOWN",201); // We could not connect to the authentication server
447 * Values that are associated with a key.
448 * The Javascript Api can also return the following values
450 define ("SWEKEY_STATUS_REPLACED",100); // This key has been replaced by a backup key
451 define ("SWEKEY_STATUS_BACKUP_KEY",101); // This key is a backup key that is not activated yet
452 define ("SWEKEY_STATUS_NOTPLUGGED",200); // This key is not plugged in the computer
456 * Return the text corresponding to the integer status of a key
458 * @param status The status
459 * @return The text corresponding to the status
460 * @access public
462 function Swekey_GetStatusStr($status)
464 switch($status)
466 case SWEKEY_STATUS_OK : return 'OK';
467 case SWEKEY_STATUS_NOT_FOUND : return 'Key does not exist in the db';
468 case SWEKEY_STATUS_INACTIVE : return 'Key not activated';
469 case SWEKEY_STATUS_LOST : return 'Key was lost';
470 case SWEKEY_STATUS_STOLEN : return 'Key was stolen';
471 case SWEKEY_STATUS_FEE_DUE : return 'The annual fee was not paid';
472 case SWEKEY_STATUS_OBSOLETE : return 'Key no longer supported';
473 case SWEKEY_STATUS_REPLACED : return 'This key has been replaced by a backup key';
474 case SWEKEY_STATUS_BACKUP_KEY : return 'This key is a backup key that is not activated yet';
475 case SWEKEY_STATUS_NOTPLUGGED : return 'This key is not plugged in the computer';
476 case SWEKEY_STATUS_UNKOWN : return 'Unknow Status, could not connect to the authentication server';
478 return 'unknown status '.$status;
482 * If your web site requires a key to login you should check that the key
483 * is still valid (has not been lost or stolen) before requiring it.
484 * A key can be authenticated only if its status is SWEKEY_STATUS_OK
485 * @param id The id of the swekey
486 * @return The status of the swekey
487 * @access public
489 function Swekey_GetStatus($id)
491 global $gSwekeyStatusServer;
492 $res = Swekey_HttpGet($gSwekeyStatusServer.'/GET-STATUS/'.$id, $response_code);
493 if ($response_code == 200)
494 return intval($res);
496 return SWEKEY_STATUS_UNKOWN;