"; /** * Servers addresses * Use the Swekey_SetXxxServer($server) functions to set them */ global $gSwekeyCheckServer; if (! isset($gSwekeyCheckServer)) $gSwekeyCheckServer = 'http://auth-check.musbe.net'; global $gSwekeyRndTokenServer; if (! isset($gSwekeyRndTokenServer)) $gSwekeyRndTokenServer = 'http://auth-rnd-gen.musbe.net'; global $gSwekeyStatusServer; if (! isset($gSwekeyStatusServer)) $gSwekeyStatusServer = 'http://auth-status.musbe.net'; global $gSwekeyCA; global $gSwekeyTokenCacheEnabled; if (! isset($gSwekeyTokenCacheEnabled)) $gSwekeyTokenCacheEnabled = true; /** * Change the address of the Check server. * If $server is empty the default value 'http://auth-check.musbe.net' will be used * * @param server The protocol and hostname to use * @access public */ function Swekey_SetCheckServer($server) { global $gSwekeyCheckServer; if (empty($server)) $gSwekeyCheckServer = 'http://auth-check.musbe.net'; else $gSwekeyCheckServer = $server; } /** * Change the address of the Random Token Generator server. * If $server is empty the default value 'http://auth-rnd-gen.musbe.net' will be used * * @param server The protocol and hostname to use * @access public */ function Swekey_SetRndTokenServer($server) { global $gSwekeyRndTokenServer; if (empty($server)) $gSwekeyRndTokenServer = 'http://auth-rnd-gen.musbe.net'; else $gSwekeyRndTokenServer = $server; } /** * Change the address of the Satus server. * If $server is empty the default value 'http://auth-status.musbe.net' will be used * * @param server The protocol and hostname to use * @access public */ function Swekey_SetStatusServer($server) { global $gSwekeyStatusServer; if (empty($server)) $gSwekeyStatusServer = 'http://auth-status.musbe.net'; else $gSwekeyStatusServer = $server; } /** * Change the certificat file in case of the the severs use https instead of http * * @param cafile The path of the crt file to use * @access public */ function Swekey_SetCAFile($cafile) { global $gSwekeyCA; $gSwekeyCA = $cafile; } /** * Enable or disable the random token caching * Because everybody has full access to the cache file, it can be a DOS vulnerability * So disable it if you are running in a non secure enviromnement * * @param $enable * @access public */ function Swekey_EnableTokenCache($enable) { global $gSwekeyTokenCacheEnabled; $gSwekeyTokenCacheEnabled = ! empty($enable); } /** * Return the last error. * * @return The Last Error * @access public */ function Swekey_GetLastError() { global $gSwekeyLastError; return $gSwekeyLastError; } /** * Return the last result. * * @return The Last Error * @access public */ function Swekey_GetLastResult() { global $gSwekeyLastResult; return $gSwekeyLastResult; } /** * Send a synchronous request to the server. * This function manages timeout then will not block if one of the server is down * * @param url The url to get * @param response_code The response code * @return The body of the response or "" in case of error * @access private */ function Swekey_HttpGet($url, &$response_code) { global $gSwekeyLastError; $gSwekeyLastError = 0; global $gSwekeyLastResult; $gSwekeyLastResult = ""; // use curl if available if (function_exists('curl_init')) { $sess = curl_init($url); if (substr($url, 0, 8) == "https://") { global $gSwekeyCA; if (! empty($gSwekeyCA)) { if (file_exists($gSwekeyCA)) { if (! curl_setopt($sess, CURLOPT_CAINFO, $gSwekeyCA)) error_log("SWEKEY_ERROR:Could not set CA file : ".curl_error($sess)); else $caFileOk = true; } else error_log("SWEKEY_ERROR:Could not find CA file $gSwekeyCA getting $url"); } curl_setopt($sess, CURLOPT_SSL_VERIFYHOST, '2'); curl_setopt($sess, CURLOPT_SSL_VERIFYPEER, '2'); curl_setopt($sess, CURLOPT_CONNECTTIMEOUT, '20'); curl_setopt($sess, CURLOPT_TIMEOUT, '20'); } else { curl_setopt($sess, CURLOPT_CONNECTTIMEOUT, '3'); curl_setopt($sess, CURLOPT_TIMEOUT, '5'); } curl_setopt($sess, CURLOPT_RETURNTRANSFER, '1'); $res=curl_exec($sess); $response_code = curl_getinfo($sess, CURLINFO_HTTP_CODE); $curlerr = curl_error($sess); curl_close($sess); if ($response_code == 200) { $gSwekeyLastResult = $res; return $res; } if (! empty($response_code)) { $gSwekeyLastError = $response_code; error_log("SWEKEY_ERROR:Error $gSwekeyLastError ($curlerr) getting $url"); return ""; } $response_code = 408; // Request Timeout $gSwekeyLastError = $response_code; error_log("SWEKEY_ERROR:Error $curlerr getting $url"); return ""; } // use pecl_http if available if (class_exists('HttpRequest')) { // retry if one of the server is down for ($num=1; $num <= 3; $num++ ) { $r = new HttpRequest($url); $options = array('timeout' => '3'); if (substr($url,0, 6) == "https:") { $sslOptions = array(); $sslOptions['verifypeer'] = true; $sslOptions['verifyhost'] = true; $capath = __FILE__; $name = strrchr($capath, '/'); if (empty($name)) // windows $name = strrchr($capath, '\\'); $capath = substr($capath, 0, strlen($capath) - strlen($name) + 1).'musbe-ca.crt'; if (! empty($gSwekeyCA)) $sslOptions['cainfo'] = $gSwekeyCA; $options['ssl'] = $sslOptions; } $r->setOptions($options); // try { $reply = $r->send(); $res = $reply->getBody(); $info = $r->getResponseInfo(); $response_code = $info['response_code']; if ($response_code != 200) { $gSwekeyLastError = $response_code; error_log("SWEKEY_ERROR:Error ".$gSwekeyLastError." getting ".$url); return ""; } $gSwekeyLastResult = $res; return $res; } // catch (HttpException $e) // { // error_log("SWEKEY_WARNING:HttpException ".$e." getting ".$url); // } } $response_code = 408; // Request Timeout $gSwekeyLastError = $response_code; error_log("SWEKEY_ERROR:Error ".$gSwekeyLastError." getting ".$url); return ""; } global $http_response_header; $res = @file_get_contents($url); $response_code = substr($http_response_header[0], 9, 3); //HTTP/1.0 if ($response_code == 200) { $gSwekeyLastResult = $res; return $res; } $gSwekeyLastError = $response_code; error_log("SWEKEY_ERROR:Error ".$response_code." getting ".$url); return ""; } /** * Get a Random Token from a Token Server * The RT is a 64 vhars hexadecimal value * You should better use Swekey_GetFastRndToken() for performance * @access public */ function Swekey_GetRndToken() { global $gSwekeyRndTokenServer; return Swekey_HttpGet($gSwekeyRndTokenServer.'/FULL-RND-TOKEN', $response_code); } /** * Get a Half Random Token from a Token Server * The RT is a 64 vhars hexadecimal value * Use this value if you want to make your own Swekey_GetFastRndToken() * @access public */ function Swekey_GetHalfRndToken() { global $gSwekeyRndTokenServer; return Swekey_HttpGet($gSwekeyRndTokenServer.'/HALF-RND-TOKEN', $response_code); } /** * Get a Half Random Token * The RT is a 64 vhars hexadecimal value * This function get a new random token and reuse it. * Token are refetched from the server only once every 30 seconds. * You should always use this function to get half random token. * @access public */ function Swekey_GetFastHalfRndToken() { global $gSwekeyTokenCacheEnabled; $res = ""; $cachefile = ""; // We check if we have a valid RT is the session if (isset($_SESSION['rnd-token-date'])) if (time() - $_SESSION['rnd-token-date'] < 30) $res = $_SESSION['rnd-token']; // If not we try to get it from a temp file (PHP >= 5.2.1 only) if (strlen($res) != 32 && $gSwekeyTokenCacheEnabled) { if (function_exists('sys_get_temp_dir')) { $tempdir = sys_get_temp_dir(); $cachefile = $tempdir."/swekey-rnd-token-".get_current_user(); $modif = filemtime($cachefile); if ($modif != false) if (time() - $modif < 30) { $res = @file_get_contents($cachefile); if (strlen($res) != 32) $res = ""; else { $_SESSION['rnd-token'] = $res; $_SESSION['rnd-token-date'] = $modif; } } } } // If we don't have a valid RT here we have to get it from the server if (strlen($res) != 32) { $res = substr(Swekey_GetHalfRndToken(), 0, 32); $_SESSION['rnd-token'] = $res; $_SESSION['rnd-token-date'] = time(); if (! empty($cachefile)) { // we unlink the file so no possible tempfile race attack (thanks Thijs) unlink($cachefile); $file = fopen($cachefile , "x"); if ($file != FALSE) { @fwrite($file, $res); @fclose($file); } } } return $res."00000000000000000000000000000000"; } /** * Get a Random Token * The RT is a 64 vhars hexadecimal value * This function generates a unique random token for each call but call the * server only once every 30 seconds. * You should always use this function to get random token. * @access public */ function Swekey_GetFastRndToken() { $res = Swekey_GetFastHalfRndToken(); if (strlen($res) == 64) return substr($res, 0, 32).strtoupper(md5("Musbe Authentication Key" + mt_rand() + date(DATE_ATOM))); return ""; } /** * Checks that an OTP generated by a Swekey is valid * * @param id The id of the swekey * @param rt The random token used to generate the otp * @param otp The otp generated by the swekey * @return true or false * @access public */ function Swekey_CheckOtp($id, $rt, $otp) { global $gSwekeyCheckServer; $res = Swekey_HttpGet($gSwekeyCheckServer.'/CHECK-OTP/'.$id.'/'.$rt.'/'.$otp, $response_code); return $response_code == 200 && $res == "OK"; } /** * Values that are associated with a key. * The following values can be returned by the Swekey_GetStatus() function */ define ("SWEKEY_STATUS_OK",0); define ("SWEKEY_STATUS_NOT_FOUND",1); // The key does not exist in the db define ("SWEKEY_STATUS_INACTIVE",2); // The key has never been activated define ("SWEKEY_STATUS_LOST",3); // The user has lost his key define ("SWEKEY_STATUS_STOLEN",4); // The key was stolen define ("SWEKEY_STATUS_FEE_DUE",5); // The annual fee was not paid define ("SWEKEY_STATUS_OBSOLETE",6); // The hardware is no longer supported define ("SWEKEY_STATUS_UNKOWN",201); // We could not connect to the authentication server /** * Values that are associated with a key. * The Javascript Api can also return the following values */ define ("SWEKEY_STATUS_REPLACED",100); // This key has been replaced by a backup key define ("SWEKEY_STATUS_BACKUP_KEY",101); // This key is a backup key that is not activated yet define ("SWEKEY_STATUS_NOTPLUGGED",200); // This key is not plugged in the computer /** * Return the text corresponding to the integer status of a key * * @param status The status * @return The text corresponding to the status * @access public */ function Swekey_GetStatusStr($status) { switch($status) { case SWEKEY_STATUS_OK : return 'OK'; case SWEKEY_STATUS_NOT_FOUND : return 'Key does not exist in the db'; case SWEKEY_STATUS_INACTIVE : return 'Key not activated'; case SWEKEY_STATUS_LOST : return 'Key was lost'; case SWEKEY_STATUS_STOLEN : return 'Key was stolen'; case SWEKEY_STATUS_FEE_DUE : return 'The annual fee was not paid'; case SWEKEY_STATUS_OBSOLETE : return 'Key no longer supported'; case SWEKEY_STATUS_REPLACED : return 'This key has been replaced by a backup key'; case SWEKEY_STATUS_BACKUP_KEY : return 'This key is a backup key that is not activated yet'; case SWEKEY_STATUS_NOTPLUGGED : return 'This key is not plugged in the computer'; case SWEKEY_STATUS_UNKOWN : return 'Unknow Status, could not connect to the authentication server'; } return 'unknown status '.$status; } /** * If your web site requires a key to login you should check that the key * is still valid (has not been lost or stolen) before requiring it. * A key can be authenticated only if its status is SWEKEY_STATUS_OK * @param id The id of the swekey * @return The status of the swekey * @access public */ function Swekey_GetStatus($id) { global $gSwekeyStatusServer; $res = Swekey_HttpGet($gSwekeyStatusServer.'/GET-STATUS/'.$id, $response_code); if ($response_code == 200) return intval($res); return SWEKEY_STATUS_UNKOWN; } ?>