From 0fe0be9980d0e81696f477965f2eb873bd36b335 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 14 Jun 2012 13:30:04 +0200 Subject: [PATCH 01/11] Restore responding BAD_OTP if YubiKey is disabled. It seems that we might get into problems if responding OK - the other sync client validation server would think we approved of the OTP. --- ykval-sync.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/ykval-sync.php b/ykval-sync.php index ddf40fe..c94f9e7 100644 --- a/ykval-sync.php +++ b/ykval-sync.php @@ -116,15 +116,6 @@ if (!$localParams) { 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 */ $sync->updateDbCounters($syncParams); @@ -169,7 +160,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'], 'nonce'=>$localParams['nonce'], From 658ddef8227de0976dfecc60b29217de3189c636 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 14 Jun 2012 14:25:33 +0200 Subject: [PATCH 02/11] Move de-arraying out of retrieveURLasync. --- ykval-common.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ykval-common.php b/ykval-common.php index 50bb2e0..59b9bca 100644 --- a/ykval-common.php +++ b/ykval-common.php @@ -166,8 +166,7 @@ function retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False) { } curl_multi_close ($mh); - if ($ans_count==1) return $ans_arr[0]; - else return $ans_arr; + return $ans_arr; } curl_multi_remove_handle ($mh, $info['handle']); @@ -205,7 +204,10 @@ function KSMdecryptOTP($urls) { } elseif (count($urls) == 1) { $response = retrieveURLsimple ($urls[0]); } else { - $response = retrieveURLasync ($urls); + $response = retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False); + if (is_array($response)) { + $response = $response[0]; + } } if ($response) { debug("YK-KSM response: " . $response); From df71d3a5a8437a2dded7552d3443c3ecd6f5df6d Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 14 Jun 2012 14:34:07 +0200 Subject: [PATCH 03/11] retrieveURLasync: make timeout an argument --- ykval-common.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ykval-common.php b/ykval-common.php index 59b9bca..74c4034 100644 --- a/ykval-common.php +++ b/ykval-common.php @@ -117,7 +117,7 @@ function modhex2b64 ($modhex_str) { // 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, $match="^OK", $returl=False) { +function retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False, $timeout=10) { $mh = curl_multi_init(); $ch = array(); @@ -128,7 +128,7 @@ function retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False) { curl_setopt($handle, CURLOPT_USERAGENT, "YK-VAL"); curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1); curl_setopt($handle, CURLOPT_FAILONERROR, true); - curl_setopt($handle, CURLOPT_TIMEOUT, 10); + curl_setopt($handle, CURLOPT_TIMEOUT, $timeout); curl_multi_add_handle($mh, $handle); @@ -204,7 +204,7 @@ function KSMdecryptOTP($urls) { } elseif (count($urls) == 1) { $response = retrieveURLsimple ($urls[0]); } else { - $response = retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False); + $response = retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False, $timeout=10); if (is_array($response)) { $response = $response[0]; } From 41f1e15a43a921da26022f63ce95559bfac27dce Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 14 Jun 2012 14:49:37 +0200 Subject: [PATCH 04/11] retrieveURLasync: cater for the last need in ykval-synclib. --- ykval-common.php | 1 + 1 file changed, 1 insertion(+) diff --git a/ykval-common.php b/ykval-common.php index 74c4034..efbb8e1 100644 --- a/ykval-common.php +++ b/ykval-common.php @@ -184,6 +184,7 @@ function retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False, $time } curl_multi_close ($mh); + if ($ans_count>0) return $ans_arr; return $str; } From 201416b15adfc5c735f0bb645d2455253b4a2636 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 14 Jun 2012 14:54:12 +0200 Subject: [PATCH 05/11] retrieveURLasync: logging using ident string --- ykval-common.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ykval-common.php b/ykval-common.php index efbb8e1..0c7d5d7 100644 --- a/ykval-common.php +++ b/ykval-common.php @@ -117,13 +117,13 @@ function modhex2b64 ($modhex_str) { // 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, $match="^OK", $returl=False, $timeout=10) { +function retrieveURLasync ($ident, $urls, $ans_req=1, $match="^OK", $returl=False, $timeout=10) { $mh = curl_multi_init(); $ch = array(); foreach ($urls as $id => $url) { $handle = curl_init(); - debug("url is: " . $url); + debug($ident . " adding URL : " . $url); curl_setopt($handle, CURLOPT_URL, $url); curl_setopt($handle, CURLOPT_USERAGENT, "YK-VAL"); curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1); @@ -144,17 +144,17 @@ function retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False, $time ; while ($info = curl_multi_info_read($mh)) { - debug ("YK-KSM multi", $info); + debug ($ident . " curl multi info : ", $info); if ($info['result'] == CURLE_OK) { $str = curl_multi_getcontent($info['handle']); debug($str); if (preg_match("/".$match."/", $str)) { + debug($ident . "response matches " . $match); $error = curl_error ($info['handle']); $errno = curl_errno ($info['handle']); $cinfo = curl_getinfo ($info['handle']); - debug("YK-KSM errno/error: " . $errno . "/" . $error, $cinfo); + debug($ident . " errno/error: " . $errno . "/" . $error, $cinfo); $ans_count++; - debug("found entry"); if ($returl) $ans_arr[]="url=" . $cinfo['url'] . "\n" . $str; else $ans_arr[]=$str; } @@ -205,7 +205,7 @@ function KSMdecryptOTP($urls) { } elseif (count($urls) == 1) { $response = retrieveURLsimple ($urls[0]); } else { - $response = retrieveURLasync ($urls, $ans_req=1, $match="^OK", $returl=False, $timeout=10); + $response = retrieveURLasync ("YK-KSM", $urls, $ans_req=1, $match="^OK", $returl=False, $timeout=10); if (is_array($response)) { $response = $response[0]; } From 32c94e92566faa681a1751751673211cbd855fb9 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 14 Jun 2012 14:55:07 +0200 Subject: [PATCH 06/11] Use retrieveURLasync in ykval-common instead. --- ykval-synclib.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ykval-synclib.php b/ykval-synclib.php index 2627b20..6c96317 100644 --- a/ykval-synclib.php +++ b/ykval-synclib.php @@ -406,7 +406,7 @@ class SyncLib /* 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)) { $this->log(LOG_WARNING, 'No responses from validation server pool'); @@ -510,6 +510,10 @@ class SyncLib else return 0; } + function retrieveURLasync_wrap ($urls, $ans_req=1, $timeout=1.0) + { + return retrieveURLasync("YK-VAL sync", $urls, $ans_req, $match="status=OK", $returl=True, $timeout); + } /* This function takes a list of URLs. It will return the content of @@ -520,7 +524,7 @@ class SyncLib 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) { + function retrieveURLasync_old ($urls, $ans_req=1, $timeout=1.0) { $mh = curl_multi_init(); $ch = array(); From 60bfa8ff1ab025ac84a3cb18cf28e21dbb1e3bb7 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 14 Jun 2012 15:10:44 +0200 Subject: [PATCH 07/11] minor debug log fixes --- ykval-common.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ykval-common.php b/ykval-common.php index 6e849a1..0809861 100644 --- a/ykval-common.php +++ b/ykval-common.php @@ -147,9 +147,9 @@ function retrieveURLasync ($ident, $urls, $ans_req=1, $match="^OK", $returl=Fals debug ($ident . " curl multi info : ", $info); if ($info['result'] == CURLE_OK) { $str = curl_multi_getcontent($info['handle']); - debug($str); + debug($ident . " curl multi content : " . $str); if (preg_match("/".$match."/", $str)) { - debug($ident . "response matches " . $match); + debug($ident . " response matches " . $match); $error = curl_error ($info['handle']); $errno = curl_errno ($info['handle']); $cinfo = curl_getinfo ($info['handle']); From c8e9eb828f85e0a5a54727bc99560cea5aafa381 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 14 Jun 2012 15:19:04 +0200 Subject: [PATCH 08/11] Pass logger object to retrieveURLasync() --- ykval-common.php | 33 ++++++++++++++++++++++++--------- ykval-synclib.php | 2 +- ykval-verify.php | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/ykval-common.php b/ykval-common.php index 0809861..98ce99a 100644 --- a/ykval-common.php +++ b/ykval-common.php @@ -63,6 +63,21 @@ function debug() { $ykval_common_log->log(LOG_DEBUG, $str); } +function log_format() { + $str = ""; + foreach (func_get_args() as $msg) + { + if (is_array($msg)) { + foreach($msg as $key => $value){ + $str .= "$key=$value "; + } + } else { + $str .= $msg . " "; + } + } + return $str; +} + // Return eg. 2008-11-21T06:11:55Z0711 // function getUTCTimeStamp() { @@ -117,13 +132,13 @@ function modhex2b64 ($modhex_str) { // 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 ($ident, $urls, $ans_req=1, $match="^OK", $returl=False, $timeout=10) { +function retrieveURLasync ($ident, $urls, $logger, $ans_req=1, $match="^OK", $returl=False, $timeout=10) { $mh = curl_multi_init(); $ch = array(); foreach ($urls as $id => $url) { $handle = curl_init(); - debug($ident . " adding URL : " . $url); + $logger->log($ident . " adding URL : " . $url); curl_setopt($handle, CURLOPT_URL, $url); curl_setopt($handle, CURLOPT_USERAGENT, "YK-VAL"); curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1); @@ -144,16 +159,16 @@ function retrieveURLasync ($ident, $urls, $ans_req=1, $match="^OK", $returl=Fals ; while ($info = curl_multi_info_read($mh)) { - debug ($ident . " curl multi info : ", $info); + $logger->log($ident . " curl multi info : ", $info); if ($info['result'] == CURLE_OK) { $str = curl_multi_getcontent($info['handle']); - debug($ident . " curl multi content : " . $str); + $logger->log($ident . " curl multi content : " . $str); if (preg_match("/".$match."/", $str)) { - debug($ident . " response matches " . $match); + $logger->log($ident . " response matches " . $match); $error = curl_error ($info['handle']); $errno = curl_errno ($info['handle']); $cinfo = curl_getinfo ($info['handle']); - debug($ident . " errno/error: " . $errno . "/" . $error, $cinfo); + $logger->log($ident . " errno/error: " . $errno . "/" . $error, $cinfo); $ans_count++; if ($returl) $ans_arr[]="url=" . $cinfo['url'] . "\n" . $str; else $ans_arr[]=$str; @@ -198,20 +213,20 @@ function retrieveURLsimple ($url, $match="^OK") { } // $otp: A yubikey OTP -function KSMdecryptOTP($urls) { +function KSMdecryptOTP($urls, $logger) { $ret = array(); if (!is_array($urls)) { $response = retrieveURLsimple ($urls); } elseif (count($urls) == 1) { $response = retrieveURLsimple ($urls[0]); } else { - $response = retrieveURLasync ("YK-KSM", $urls, $ans_req=1, $match="^OK", $returl=False, $timeout=10); + $response = retrieveURLasync ("YK-KSM", $urls, $logger, $ans_req=1, $match="^OK", $returl=False, $timeout=10); if (is_array($response)) { $response = $response[0]; } } if ($response) { - debug("YK-KSM response: " . $response); + $logger->log(LOG_DEBUG, log_format("YK-KSM response: ", $response)); } if (sscanf ($response, "OK counter=%04x low=%04x high=%02x use=%02x", diff --git a/ykval-synclib.php b/ykval-synclib.php index 29ece23..7822d04 100644 --- a/ykval-synclib.php +++ b/ykval-synclib.php @@ -518,7 +518,7 @@ class SyncLib function retrieveURLasync_wrap ($urls, $ans_req=1, $timeout=1.0) { - return retrieveURLasync("YK-VAL sync", $urls, $ans_req, $match="status=OK", $returl=True, $timeout); + return retrieveURLasync("YK-VAL sync", $urls, $this->myLog, $ans_req, $match="status=OK", $returl=True, $timeout); } /* diff --git a/ykval-verify.php b/ykval-verify.php index a5a5944..6743840 100644 --- a/ykval-verify.php +++ b/ykval-verify.php @@ -213,7 +213,7 @@ if (!is_array($urls)) { //// Decode OTP from input // -$otpinfo = KSMdecryptOTP($urls); +$otpinfo = KSMdecryptOTP($urls, $myLog); if (!is_array($otpinfo)) { sendResp(S_BAD_OTP, $context, $apiKey); exit; From b8d18af10c77f7b0a7fcedf737a7bb00ec67b8d9 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 14 Jun 2012 15:22:38 +0200 Subject: [PATCH 09/11] Remove now unused retrieveURLasync_old() --- ykval-synclib.php | 79 ----------------------------------------------- 1 file changed, 79 deletions(-) diff --git a/ykval-synclib.php b/ykval-synclib.php index 7822d04..f96e2d9 100644 --- a/ykval-synclib.php +++ b/ykval-synclib.php @@ -521,85 +521,6 @@ class SyncLib return retrieveURLasync("YK-VAL sync", $urls, $this->myLog, $ans_req, $match="status=OK", $returl=True, $timeout); } - /* - This function takes a list of URLs. It will return the content of - 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_old ($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; - } - } ?> From 6c80f761027630f17c6d318bae000b493be94a2e Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 14 Jun 2012 15:22:55 +0200 Subject: [PATCH 10/11] Get rid of debug() - use log_format() for the formatting part. --- ykval-common.php | 22 +++------------------- ykval-verify.php | 2 +- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/ykval-common.php b/ykval-common.php index 929465f..6e7395e 100644 --- a/ykval-common.php +++ b/ykval-common.php @@ -47,22 +47,6 @@ function getHttpVal($key, $defaultVal) { return $v; } -function debug() { - $str = ""; - foreach (func_get_args() as $msg) - { - if (is_array($msg)) { - foreach($msg as $key => $value){ - $str .= "$key=$value "; - } - } else { - $str .= $msg . " "; - } - } - global $ykval_common_log; - $ykval_common_log->log(LOG_DEBUG, $str); -} - function log_format() { $str = ""; foreach (func_get_args() as $msg) @@ -101,7 +85,7 @@ function UnixToDbTime($unix) // Sign a http query string in the array of key-value pairs // return b64 encoded hmac hash -function sign($a, $apiKey) { +function sign($a, $apiKey, $logger) { ksort($a); $qs = urldecode(http_build_query($a)); @@ -109,7 +93,7 @@ function sign($a, $apiKey) { $hmac = hash_hmac('sha1', utf8_encode($qs), $apiKey, true); $hmac = base64_encode($hmac); - debug('SIGN: ' . $qs . ' H=' . $hmac); + $logger->log(LOG_DEBUG, 'SIGN: ' . $qs . ' H=' . $hmac); return $hmac; @@ -247,7 +231,7 @@ function sendResp($status, $logger, $apiKey = '', $extra = null) { if ($extra){ foreach ($extra as $param => $value) $a[$param] = $value; } - $h = sign($a, $apiKey); + $h = sign($a, $apiKey, $logger); $str = "h=" . $h . "\r\n"; $str .= "t=" . ($a['t']) . "\r\n"; diff --git a/ykval-verify.php b/ykval-verify.php index 1ddf140..9f39fe8 100644 --- a/ykval-verify.php +++ b/ykval-verify.php @@ -185,7 +185,7 @@ if ($h != '') { } unset($a['h']); - $hmac = sign($a, $apiKey); + $hmac = sign($a, $apiKey, $myLog); // Compare it if ($hmac != $h) { $myLog->log(LOG_DEBUG, 'client hmac=' . $h . ', server hmac=' . $hmac); From 499377fd2f2101b7588545c80ca57a29fe9829e1 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 14 Jun 2012 15:54:51 +0200 Subject: [PATCH 11/11] Change protocol version logging to 'debug'. --- ykval-verify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ykval-verify.php b/ykval-verify.php index 9f39fe8..e466190 100644 --- a/ykval-verify.php +++ b/ykval-verify.php @@ -20,7 +20,7 @@ if (preg_match("/\/wsapi\/([0-9]+)\.([0-9]+)\//", $_SERVER['REQUEST_URI'], $out) $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 */