mirror of
https://github.com/Yubico/yubikey-val.git
synced 2025-01-20 10:52:15 +01:00
Merge branch 'master' of github.com:Yubico/yubikey-val-server-php
This commit is contained in:
commit
0f0a23694a
@ -47,7 +47,7 @@ function getHttpVal($key, $defaultVal) {
|
|||||||
return $v;
|
return $v;
|
||||||
}
|
}
|
||||||
|
|
||||||
function debug() {
|
function log_format() {
|
||||||
$str = "";
|
$str = "";
|
||||||
foreach (func_get_args() as $msg)
|
foreach (func_get_args() as $msg)
|
||||||
{
|
{
|
||||||
@ -59,8 +59,7 @@ function debug() {
|
|||||||
$str .= $msg . " ";
|
$str .= $msg . " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
global $ykval_common_log;
|
return $str;
|
||||||
$ykval_common_log->log(LOG_DEBUG, $str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return eg. 2008-11-21T06:11:55Z0711
|
// Return eg. 2008-11-21T06:11:55Z0711
|
||||||
@ -86,7 +85,7 @@ function UnixToDbTime($unix)
|
|||||||
|
|
||||||
// Sign a http query string in the array of key-value pairs
|
// Sign a http query string in the array of key-value pairs
|
||||||
// return b64 encoded hmac hash
|
// return b64 encoded hmac hash
|
||||||
function sign($a, $apiKey) {
|
function sign($a, $apiKey, $logger) {
|
||||||
ksort($a);
|
ksort($a);
|
||||||
$qs = urldecode(http_build_query($a));
|
$qs = urldecode(http_build_query($a));
|
||||||
|
|
||||||
@ -94,7 +93,7 @@ function sign($a, $apiKey) {
|
|||||||
$hmac = hash_hmac('sha1', utf8_encode($qs), $apiKey, true);
|
$hmac = hash_hmac('sha1', utf8_encode($qs), $apiKey, true);
|
||||||
$hmac = base64_encode($hmac);
|
$hmac = base64_encode($hmac);
|
||||||
|
|
||||||
debug('SIGN: ' . $qs . ' H=' . $hmac);
|
$logger->log(LOG_DEBUG, 'SIGN: ' . $qs . ' H=' . $hmac);
|
||||||
|
|
||||||
return $hmac;
|
return $hmac;
|
||||||
|
|
||||||
@ -117,18 +116,18 @@ function modhex2b64 ($modhex_str) {
|
|||||||
// long as one of the URLs given work, data will be returned. If all
|
// long as one of the URLs given work, data will be returned. If all
|
||||||
// URLs fail, data from some URL that did not match parameter $match
|
// URLs fail, data from some URL that did not match parameter $match
|
||||||
// (defaults to ^OK) is returned, or if all URLs failed, false.
|
// (defaults to ^OK) is returned, or if all URLs failed, false.
|
||||||
function retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False) {
|
function retrieveURLasync ($ident, $urls, $logger, $ans_req=1, $match="^OK", $returl=False, $timeout=10) {
|
||||||
$mh = curl_multi_init();
|
$mh = curl_multi_init();
|
||||||
|
|
||||||
$ch = array();
|
$ch = array();
|
||||||
foreach ($urls as $id => $url) {
|
foreach ($urls as $id => $url) {
|
||||||
$handle = curl_init();
|
$handle = curl_init();
|
||||||
debug("url is: " . $url);
|
$logger->log($ident . " adding URL : " . $url);
|
||||||
curl_setopt($handle, CURLOPT_URL, $url);
|
curl_setopt($handle, CURLOPT_URL, $url);
|
||||||
curl_setopt($handle, CURLOPT_USERAGENT, "YK-VAL");
|
curl_setopt($handle, CURLOPT_USERAGENT, "YK-VAL");
|
||||||
curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
|
curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
|
||||||
curl_setopt($handle, CURLOPT_FAILONERROR, true);
|
curl_setopt($handle, CURLOPT_FAILONERROR, true);
|
||||||
curl_setopt($handle, CURLOPT_TIMEOUT, 10);
|
curl_setopt($handle, CURLOPT_TIMEOUT, $timeout);
|
||||||
|
|
||||||
curl_multi_add_handle($mh, $handle);
|
curl_multi_add_handle($mh, $handle);
|
||||||
|
|
||||||
@ -144,17 +143,17 @@ function retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False) {
|
|||||||
;
|
;
|
||||||
|
|
||||||
while ($info = curl_multi_info_read($mh)) {
|
while ($info = curl_multi_info_read($mh)) {
|
||||||
debug ("YK-KSM multi", $info);
|
$logger->log($ident . " curl multi info : ", $info);
|
||||||
if ($info['result'] == CURLE_OK) {
|
if ($info['result'] == CURLE_OK) {
|
||||||
$str = curl_multi_getcontent($info['handle']);
|
$str = curl_multi_getcontent($info['handle']);
|
||||||
debug($str);
|
$logger->log($ident . " curl multi content : " . $str);
|
||||||
if (preg_match("/".$match."/", $str)) {
|
if (preg_match("/".$match."/", $str)) {
|
||||||
|
$logger->log($ident . " response matches " . $match);
|
||||||
$error = curl_error ($info['handle']);
|
$error = curl_error ($info['handle']);
|
||||||
$errno = curl_errno ($info['handle']);
|
$errno = curl_errno ($info['handle']);
|
||||||
$cinfo = curl_getinfo ($info['handle']);
|
$cinfo = curl_getinfo ($info['handle']);
|
||||||
debug("YK-KSM errno/error: " . $errno . "/" . $error, $cinfo);
|
$logger->log($ident . " errno/error: " . $errno . "/" . $error, $cinfo);
|
||||||
$ans_count++;
|
$ans_count++;
|
||||||
debug("found entry");
|
|
||||||
if ($returl) $ans_arr[]="url=" . $cinfo['url'] . "\n" . $str;
|
if ($returl) $ans_arr[]="url=" . $cinfo['url'] . "\n" . $str;
|
||||||
else $ans_arr[]=$str;
|
else $ans_arr[]=$str;
|
||||||
}
|
}
|
||||||
@ -166,8 +165,7 @@ function retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False) {
|
|||||||
}
|
}
|
||||||
curl_multi_close ($mh);
|
curl_multi_close ($mh);
|
||||||
|
|
||||||
if ($ans_count==1) return $ans_arr[0];
|
return $ans_arr;
|
||||||
else return $ans_arr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_multi_remove_handle ($mh, $info['handle']);
|
curl_multi_remove_handle ($mh, $info['handle']);
|
||||||
@ -185,6 +183,7 @@ function retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False) {
|
|||||||
}
|
}
|
||||||
curl_multi_close ($mh);
|
curl_multi_close ($mh);
|
||||||
|
|
||||||
|
if ($ans_count>0) return $ans_arr;
|
||||||
return $str;
|
return $str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,17 +197,20 @@ function retrieveURLsimple ($url, $match="^OK") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// $otp: A yubikey OTP
|
// $otp: A yubikey OTP
|
||||||
function KSMdecryptOTP($urls) {
|
function KSMdecryptOTP($urls, $logger) {
|
||||||
$ret = array();
|
$ret = array();
|
||||||
if (!is_array($urls)) {
|
if (!is_array($urls)) {
|
||||||
$response = retrieveURLsimple ($urls);
|
$response = retrieveURLsimple ($urls);
|
||||||
} elseif (count($urls) == 1) {
|
} elseif (count($urls) == 1) {
|
||||||
$response = retrieveURLsimple ($urls[0]);
|
$response = retrieveURLsimple ($urls[0]);
|
||||||
} else {
|
} else {
|
||||||
$response = retrieveURLasync ($urls);
|
$response = retrieveURLasync ("YK-KSM", $urls, $logger, $ans_req=1, $match="^OK", $returl=False, $timeout=10);
|
||||||
|
if (is_array($response)) {
|
||||||
|
$response = $response[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($response) {
|
if ($response) {
|
||||||
debug("YK-KSM response: " . $response);
|
$logger->log(LOG_DEBUG, log_format("YK-KSM response: ", $response));
|
||||||
}
|
}
|
||||||
if (sscanf ($response,
|
if (sscanf ($response,
|
||||||
"OK counter=%04x low=%04x high=%02x use=%02x",
|
"OK counter=%04x low=%04x high=%02x use=%02x",
|
||||||
@ -229,7 +231,7 @@ function sendResp($status, $logger, $apiKey = '', $extra = null) {
|
|||||||
if ($extra){
|
if ($extra){
|
||||||
foreach ($extra as $param => $value) $a[$param] = $value;
|
foreach ($extra as $param => $value) $a[$param] = $value;
|
||||||
}
|
}
|
||||||
$h = sign($a, $apiKey);
|
$h = sign($a, $apiKey, $logger);
|
||||||
|
|
||||||
$str = "h=" . $h . "\r\n";
|
$str = "h=" . $h . "\r\n";
|
||||||
$str .= "t=" . ($a['t']) . "\r\n";
|
$str .= "t=" . ($a['t']) . "\r\n";
|
||||||
|
@ -117,15 +117,6 @@ if (!$localParams) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($localParams['active'] != 1) {
|
|
||||||
/* The remote server has accepted an OTP from a YubiKey which we would not. We update our
|
|
||||||
* counters
|
|
||||||
*/
|
|
||||||
$myLog->log(LOG_WARNING, 'Received sync-request for de-activated Yubikey ' . $yk_publicname .
|
|
||||||
' - check database synchronization!!!');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Conditional update local database */
|
/* Conditional update local database */
|
||||||
$sync->updateDbCounters($syncParams);
|
$sync->updateDbCounters($syncParams);
|
||||||
|
|
||||||
@ -172,7 +163,15 @@ if ($sync->countersEqual($localParams, $syncParams)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($localParams['active'] != 1) {
|
||||||
|
/* The remote server has accepted an OTP from a YubiKey which we would not.
|
||||||
|
* We still needed to update our counters with the counters from the OTP though.
|
||||||
|
*/
|
||||||
|
$myLog->log(LOG_WARNING, 'Received sync-request for de-activated Yubikey ' . $yk_publicname .
|
||||||
|
' - check database synchronization!!!');
|
||||||
|
sendResp(S_BAD_OTP, $apiKey);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
$extra=array('modified'=>$localParams['modified'],
|
$extra=array('modified'=>$localParams['modified'],
|
||||||
'nonce'=>$localParams['nonce'],
|
'nonce'=>$localParams['nonce'],
|
||||||
|
@ -412,7 +412,7 @@ class SyncLib
|
|||||||
/*
|
/*
|
||||||
Send out requests
|
Send out requests
|
||||||
*/
|
*/
|
||||||
$ans_arr=$this->retrieveURLasync($urls, $ans_req, $timeout);
|
$ans_arr=$this->retrieveURLasync_wrap($urls, $ans_req, $timeout);
|
||||||
|
|
||||||
if (!is_array($ans_arr)) {
|
if (!is_array($ans_arr)) {
|
||||||
$this->log(LOG_WARNING, 'No responses from validation server pool');
|
$this->log(LOG_WARNING, 'No responses from validation server pool');
|
||||||
@ -516,84 +516,9 @@ class SyncLib
|
|||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function retrieveURLasync_wrap ($urls, $ans_req=1, $timeout=1.0)
|
||||||
/*
|
{
|
||||||
This function takes a list of URLs. It will return the content of
|
return retrieveURLasync("YK-VAL sync", $urls, $this->myLog, $ans_req, $match="status=OK", $returl=True, $timeout);
|
||||||
the first successfully retrieved URL, whose content matches ^OK.
|
|
||||||
The request are sent asynchronously. Some of the URLs can fail
|
|
||||||
with unknown host, connection errors, or network timeout, but as
|
|
||||||
long as one of the URLs given work, data will be returned. If all
|
|
||||||
URLs fail, data from some URL that did not match parameter $match
|
|
||||||
(defaults to ^OK) is returned, or if all URLs failed, false.
|
|
||||||
*/
|
|
||||||
function retrieveURLasync ($urls, $ans_req=1, $timeout=1.0) {
|
|
||||||
$mh = curl_multi_init();
|
|
||||||
|
|
||||||
$ch = array();
|
|
||||||
foreach ($urls as $id => $url) {
|
|
||||||
$this->log(LOG_DEBUG, "url in retrieveURLasync is " . $url);
|
|
||||||
$handle = curl_init();
|
|
||||||
|
|
||||||
curl_setopt($handle, CURLOPT_URL, $url);
|
|
||||||
curl_setopt($handle, CURLOPT_USERAGENT, "YK-VAL");
|
|
||||||
curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
|
|
||||||
curl_setopt($handle, CURLOPT_FAILONERROR, true);
|
|
||||||
curl_setopt($handle, CURLOPT_TIMEOUT, $timeout);
|
|
||||||
|
|
||||||
curl_multi_add_handle($mh, $handle);
|
|
||||||
|
|
||||||
$ch[$handle] = $handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
$str = false;
|
|
||||||
$ans_count = 0;
|
|
||||||
$ans_arr = array();
|
|
||||||
|
|
||||||
do {
|
|
||||||
while (($mrc = curl_multi_exec($mh, $active)) == CURLM_CALL_MULTI_PERFORM)
|
|
||||||
;
|
|
||||||
|
|
||||||
while ($info = curl_multi_info_read($mh)) {
|
|
||||||
debug ("YK-KSM multi", $info);
|
|
||||||
if ($info['result'] == CURLE_OK) {
|
|
||||||
$str = curl_multi_getcontent($info['handle']);
|
|
||||||
if (preg_match("/status=OK/", $str)) {
|
|
||||||
$error = curl_error ($info['handle']);
|
|
||||||
$errno = curl_errno ($info['handle']);
|
|
||||||
$cinfo = curl_getinfo ($info['handle']);
|
|
||||||
debug("YK-KSM errno/error: " . $errno . "/" . $error, $cinfo);
|
|
||||||
$ans_count++;
|
|
||||||
$ans_arr[]="url=" . $cinfo['url'] . "\n" . $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ans_count >= $ans_req) {
|
|
||||||
foreach ($ch as $h) {
|
|
||||||
curl_multi_remove_handle ($mh, $h);
|
|
||||||
curl_close ($h);
|
|
||||||
}
|
|
||||||
curl_multi_close ($mh);
|
|
||||||
|
|
||||||
return $ans_arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_multi_remove_handle ($mh, $info['handle']);
|
|
||||||
curl_close ($info['handle']);
|
|
||||||
unset ($ch[$info['handle']]);
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_multi_select ($mh);
|
|
||||||
}
|
|
||||||
} while($active);
|
|
||||||
|
|
||||||
|
|
||||||
foreach ($ch as $h) {
|
|
||||||
curl_multi_remove_handle ($mh, $h);
|
|
||||||
curl_close ($h);
|
|
||||||
}
|
|
||||||
curl_multi_close ($mh);
|
|
||||||
|
|
||||||
if ($ans_count>0) return $ans_arr;
|
|
||||||
else return $str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ if (preg_match("/\/wsapi\/([0-9]+)\.([0-9]+)\//", $_SERVER['REQUEST_URI'], $out)
|
|||||||
$protocol_version=1.0;
|
$protocol_version=1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$myLog->log(LOG_INFO, "found protocol version " . $protocol_version);
|
$myLog->log(LOG_DEBUG, "found protocol version " . $protocol_version);
|
||||||
|
|
||||||
/* Extract values from HTTP request
|
/* Extract values from HTTP request
|
||||||
*/
|
*/
|
||||||
@ -185,7 +185,7 @@ if ($h != '') {
|
|||||||
}
|
}
|
||||||
unset($a['h']);
|
unset($a['h']);
|
||||||
|
|
||||||
$hmac = sign($a, $apiKey);
|
$hmac = sign($a, $apiKey, $myLog);
|
||||||
// Compare it
|
// Compare it
|
||||||
if ($hmac != $h) {
|
if ($hmac != $h) {
|
||||||
$myLog->log(LOG_DEBUG, 'client hmac=' . $h . ', server hmac=' . $hmac);
|
$myLog->log(LOG_DEBUG, 'client hmac=' . $h . ', server hmac=' . $hmac);
|
||||||
@ -212,7 +212,7 @@ if (!is_array($urls)) {
|
|||||||
|
|
||||||
//// Decode OTP from input
|
//// Decode OTP from input
|
||||||
//
|
//
|
||||||
$otpinfo = KSMdecryptOTP($urls);
|
$otpinfo = KSMdecryptOTP($urls, $myLog);
|
||||||
if (!is_array($otpinfo)) {
|
if (!is_array($otpinfo)) {
|
||||||
sendResp(S_BAD_OTP, $myLog, $apiKey);
|
sendResp(S_BAD_OTP, $myLog, $apiKey);
|
||||||
exit;
|
exit;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user