diff --git a/ykval-checksum-clients b/ykval-checksum-clients index d15a244..0143daf 100755 --- a/ykval-checksum-clients +++ b/ykval-checksum-clients @@ -30,18 +30,18 @@ $verbose = 0; if (isset($argv[1])) { - if ($argv[1] == "-h" || $argv[1] == "--help") { - print "Usage: " . $argv[0] . " [-h|--help] [-v]\n"; - exit(1); - } + if ($argv[1] == "-h" || $argv[1] == "--help") { + print "Usage: " . $argv[0] . " [-h|--help] [-v]\n"; + exit(1); + } - if ($argv[1] && $argv[1] != "-v") { - print $argv[0] . ": invalid option -- '" . $argv[0] . "'\n"; - print "Try `" . $argv[0] . " --help' for more information.\n"; - exit(1); - } + if ($argv[1] && $argv[1] != "-v") { + print $argv[0] . ": invalid option -- '" . $argv[0] . "'\n"; + print "Try `" . $argv[0] . " --help' for more information.\n"; + exit(1); + } - $verbose = $argv[1] == "-v"; + $verbose = $argv[1] == "-v"; } set_include_path(implode(PATH_SEPARATOR, array( @@ -59,30 +59,30 @@ $myLog = new Log($logname); $db = Db::GetDatabaseHandle($baseParams, $logname); if (!$db->connect()) { - $myLog->log(LOG_WARNING, "Could not connect to database"); - exit(1); + $myLog->log(LOG_WARNING, "Could not connect to database"); + exit(1); } $everything = ""; $result=$db->customQuery("SELECT id, active, secret ". - "FROM clients ". - "ORDER BY id"); + "FROM clients ". + "ORDER BY id"); while($row = $db->fetchArray($result)) { - $active = $row['active']; - if ($active == "") { - # For some reason PostgreSQL returns empty strings for false values?! - $active = "0"; - } - $everything .= - $row['id'] . "\t" . $active . "\t" . - $row['secret'] . "\n"; + $active = $row['active']; + if ($active == "") { + # For some reason PostgreSQL returns empty strings for false values?! + $active = "0"; + } + $everything .= + $row['id'] . "\t" . $active . "\t" . + $row['secret'] . "\n"; } $db->closeCursor($result); $hash = sha1 ($everything); if ($verbose) { - print $everything; + print $everything; } print substr ($hash, 0, 10) . "\n"; diff --git a/ykval-checksum-deactivated b/ykval-checksum-deactivated index 1d7e1c4..f0ce06f 100755 --- a/ykval-checksum-deactivated +++ b/ykval-checksum-deactivated @@ -30,18 +30,18 @@ $verbose = 0; if (isset($argv[1])) { - if ($argv[1] == "-h" || $argv[1] == "--help") { - print "Usage: " . $argv[0] . " [-h|--help] [-v]\n"; - exit(1); - } + if ($argv[1] == "-h" || $argv[1] == "--help") { + print "Usage: " . $argv[0] . " [-h|--help] [-v]\n"; + exit(1); + } - if ($argv[1] && $argv[1] != "-v") { - print $argv[0] . ": invalid option -- '" . $argv[0] . "'\n"; - print "Try `" . $argv[0] . " --help' for more information.\n"; - exit(1); - } + if ($argv[1] && $argv[1] != "-v") { + print $argv[0] . ": invalid option -- '" . $argv[0] . "'\n"; + print "Try `" . $argv[0] . " --help' for more information.\n"; + exit(1); + } - $verbose = $argv[1] == "-v"; + $verbose = $argv[1] == "-v"; } set_include_path(implode(PATH_SEPARATOR, array( @@ -59,24 +59,24 @@ $myLog = new Log($logname); $db = Db::GetDatabaseHandle($baseParams, $logname); if (!$db->connect()) { - $myLog->log(LOG_WARNING, "Could not connect to database"); - exit(1); + $myLog->log(LOG_WARNING, "Could not connect to database"); + exit(1); } $everything = ""; $result=$db->customQuery("SELECT yk_publicname, yk_counter, yk_use ". - "FROM yubikeys WHERE active = false ". - "ORDER BY yk_publicname"); + "FROM yubikeys WHERE active = false ". + "ORDER BY yk_publicname"); while($row = $result->fetch(PDO::FETCH_ASSOC)) { - $everything .= - $row['yk_publicname'] . "\t" . $row['yk_counter'] . "\t" . $row['yk_use'] . - "\n"; + $everything .= + $row['yk_publicname'] . "\t" . $row['yk_counter'] . "\t" . $row['yk_use'] . + "\n"; } $hash = sha1 ($everything); if ($verbose) { - print $everything; + print $everything; } print substr ($hash, 0, 10) . "\n"; diff --git a/ykval-common.php b/ykval-common.php index 632f65e..b09c733 100644 --- a/ykval-common.php +++ b/ykval-common.php @@ -53,104 +53,104 @@ define('INT32_LEN', 10); function logdie ($logger, $str) { - $logger->log(LOG_INFO, $str); - die($str . "\n"); + $logger->log(LOG_INFO, $str); + die($str . "\n"); } function getHttpVal ($key, $default, $a) { - if (array_key_exists($key, $a)) - { - $val = $a[$key]; - } - else - { - $val = $default; - } + if (array_key_exists($key, $a)) + { + $val = $a[$key]; + } + else + { + $val = $default; + } - $val = trim($val); - $val = str_replace('\\', '', $val); + $val = trim($val); + $val = str_replace('\\', '', $val); - return $val; + return $val; } // Verifies if a given string is modhex function is_modhex($s) { - if (preg_match('/^[cbdefghijklnrtuv]+$/', $s) === 0) { - return false; - } else { - return true; - } + if (preg_match('/^[cbdefghijklnrtuv]+$/', $s) === 0) { + return false; + } else { + return true; + } } // Verifies if a given string is a valid OTP function is_otp($otp) { - if ($otp == "") { - return false; - } - $otp_len = strlen($otp); - return $otp_len >= TOKEN_LEN && $otp_len <= OTP_MAX_LEN && is_modhex($otp); + if ($otp == "") { + return false; + } + $otp_len = strlen($otp); + return $otp_len >= TOKEN_LEN && $otp_len <= OTP_MAX_LEN && is_modhex($otp); } // Verifies if a given string is a valid public id function is_pubid($id) { - $id_len = strlen($id); - return $id_len >= 0 && $id_len <= PUBID_MAX_LEN && is_modhex($id); + $id_len = strlen($id); + return $id_len >= 0 && $id_len <= PUBID_MAX_LEN && is_modhex($id); } // Verifies a given string is a valid nonce function is_nonce($nonce) { - return strlen($nonce) >= NONCE_MIN_LEN - && strlen($nonce) <= NONCE_MAX_LEN - && ctype_alnum($nonce); + return strlen($nonce) >= NONCE_MIN_LEN + && strlen($nonce) <= NONCE_MAX_LEN + && ctype_alnum($nonce); } // Verifies if a given string is a valid client id function is_clientid($id) { - if ($id == "0") { - return false; - } - return strlen($id) <= INT32_LEN && ctype_digit($id); + if ($id == "0") { + return false; + } + return strlen($id) <= INT32_LEN && ctype_digit($id); } // Sign a http query string in the array of key-value pairs // return b64 encoded hmac hash function sign($a, $apiKey, $logger) { - ksort($a); + ksort($a); - $qs = http_build_query($a); - $qs = urldecode($qs); - $qs = utf8_encode($qs); + $qs = http_build_query($a); + $qs = urldecode($qs); + $qs = utf8_encode($qs); - // base64 encoded binary digest - $hmac = hash_hmac('sha1', $qs, $apiKey, TRUE); - $hmac = base64_encode($hmac); + // base64 encoded binary digest + $hmac = hash_hmac('sha1', $qs, $apiKey, TRUE); + $hmac = base64_encode($hmac); - $logger->log(LOG_DEBUG, "SIGN: $qs H=$hmac"); + $logger->log(LOG_DEBUG, "SIGN: $qs H=$hmac"); - return $hmac; + return $hmac; } function curl_settings($logger, $ident, $ch, $url, $timeout, $opts) { - $logger->log(LOG_DEBUG, "$ident adding URL : $url"); + $logger->log(LOG_DEBUG, "$ident adding URL : $url"); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); - curl_setopt($ch, CURLOPT_USERAGENT, 'YK-VAL'); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - curl_setopt($ch, CURLOPT_FAILONERROR, TRUE); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); + curl_setopt($ch, CURLOPT_USERAGENT, 'YK-VAL'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($ch, CURLOPT_FAILONERROR, TRUE); - if (is_array($opts) === FALSE) - { - $logger->log(LOG_WARN, $ident . 'curl options must be an array'); - return; - } + if (is_array($opts) === FALSE) + { + $logger->log(LOG_WARN, $ident . 'curl options must be an array'); + return; + } - foreach ($opts as $key => $val) - if (curl_setopt($ch, $key, $val) === FALSE) - $logger->log(LOG_WARN, "$ident failed to set " . curl_opt_name($key)); + foreach ($opts as $key => $val) + if (curl_setopt($ch, $key, $val) === FALSE) + $logger->log(LOG_WARN, "$ident failed to set " . curl_opt_name($key)); } // returns the string name of a curl constant, @@ -160,16 +160,16 @@ function curl_settings($logger, $ident, $ch, $url, $timeout, $opts) // curl_opt_name(CURLOPT_BLABLA) returns "curl option" function curl_opt_name($opt) { - $consts = get_defined_constants(true); - $consts = $consts['curl']; + $consts = get_defined_constants(true); + $consts = $consts['curl']; - $name = array_search($opt, $consts, TRUE); + $name = array_search($opt, $consts, TRUE); - // array_search may return either on failure... - if ($name === FALSE || $name === NULL) - return 'curl option'; + // array_search may return either on failure... + if ($name === FALSE || $name === NULL) + return 'curl option'; - return $name; + return $name; } // This function takes a list of URLs. It will return the content of @@ -181,164 +181,164 @@ function curl_opt_name($opt) // (defaults to ^OK) is returned, or if all URLs failed, false. function retrieveURLasync($ident, $urls, $logger, $ans_req=1, $match="^OK", $returl=False, $timeout=10, $curlopts) { - $mh = curl_multi_init(); - $ch = array(); + $mh = curl_multi_init(); + $ch = array(); - foreach ($urls as $url) - { - $handle = curl_init(); - curl_settings($logger, $ident, $handle, $url, $timeout, $curlopts); - curl_multi_add_handle($mh, $handle); - $ch[(int) $handle] = $handle; - } + foreach ($urls as $url) + { + $handle = curl_init(); + curl_settings($logger, $ident, $handle, $url, $timeout, $curlopts); + curl_multi_add_handle($mh, $handle); + $ch[(int) $handle] = $handle; + } - $ans_arr = array(); + $ans_arr = array(); - do - { - while (curl_multi_exec($mh, $active) == CURLM_CALL_MULTI_PERFORM); + do + { + while (curl_multi_exec($mh, $active) == CURLM_CALL_MULTI_PERFORM); - while ($info = curl_multi_info_read($mh)) - { - $logger->log(LOG_DEBUG, "$ident curl multi info : ", $info); + while ($info = curl_multi_info_read($mh)) + { + $logger->log(LOG_DEBUG, "$ident curl multi info : ", $info); - if ($info['result'] == CURLE_OK) - { - $str = curl_multi_getcontent($info['handle']); + if ($info['result'] == CURLE_OK) + { + $str = curl_multi_getcontent($info['handle']); - $logger->log(LOG_DEBUG, "$ident curl multi content : $str"); + $logger->log(LOG_DEBUG, "$ident curl multi content : $str"); - if (preg_match("/$match/", $str)) - { - $logger->log(LOG_DEBUG, "$ident response matches $match"); - $error = curl_error($info['handle']); - $errno = curl_errno($info['handle']); - $cinfo = curl_getinfo($info['handle']); - $logger->log(LOG_INFO, "$ident errno/error: $errno/$error", $cinfo); + if (preg_match("/$match/", $str)) + { + $logger->log(LOG_DEBUG, "$ident response matches $match"); + $error = curl_error($info['handle']); + $errno = curl_errno($info['handle']); + $cinfo = curl_getinfo($info['handle']); + $logger->log(LOG_INFO, "$ident errno/error: $errno/$error", $cinfo); - if ($returl) - $ans_arr[] = "url=" . $cinfo['url'] . "\n" . $str; - else - $ans_arr[] = $str; - } + if ($returl) + $ans_arr[] = "url=" . $cinfo['url'] . "\n" . $str; + else + $ans_arr[] = $str; + } - if (count($ans_arr) >= $ans_req) - { - foreach ($ch as $h) - { - curl_multi_remove_handle($mh, $h); - curl_close($h); - } - curl_multi_close($mh); + if (count($ans_arr) >= $ans_req) + { + foreach ($ch as $h) + { + curl_multi_remove_handle($mh, $h); + curl_close($h); + } + curl_multi_close($mh); - return $ans_arr; - } + return $ans_arr; + } - curl_multi_remove_handle($mh, $info['handle']); - curl_close($info['handle']); - unset($ch[(int) $info['handle']]); - } + curl_multi_remove_handle($mh, $info['handle']); + curl_close($info['handle']); + unset($ch[(int) $info['handle']]); + } - curl_multi_select($mh); - } - } - while($active); + curl_multi_select($mh); + } + } + while($active); - foreach ($ch as $h) - { - curl_multi_remove_handle($mh, $h); - curl_close($h); - } - curl_multi_close($mh); + foreach ($ch as $h) + { + curl_multi_remove_handle($mh, $h); + curl_close($h); + } + curl_multi_close($mh); - if (count($ans_arr) > 0) - return $ans_arr; + if (count($ans_arr) > 0) + return $ans_arr; - return false; + return false; } function KSMdecryptOTP($urls, $logger, $curlopts) { - $response = retrieveURLasync('YK-KSM', $urls, $logger, $ans_req=1, $match='^OK', $returl=False, $timeout=10, $curlopts); + $response = retrieveURLasync('YK-KSM', $urls, $logger, $ans_req=1, $match='^OK', $returl=False, $timeout=10, $curlopts); - if ($response === FALSE) - return false; + if ($response === FALSE) + return false; - $response = array_shift($response); + $response = array_shift($response); - $logger->log(LOG_DEBUG, "YK-KSM response: $response"); + $logger->log(LOG_DEBUG, "YK-KSM response: $response"); - $ret = array(); + $ret = array(); - if (sscanf($response, - 'OK counter=%04x low=%04x high=%02x use=%02x', - $ret['session_counter'], - $ret['low'], - $ret['high'], - $ret['session_use']) !== 4) - { - return false; - } + if (sscanf($response, + 'OK counter=%04x low=%04x high=%02x use=%02x', + $ret['session_counter'], + $ret['low'], + $ret['high'], + $ret['session_use']) !== 4) + { + return false; + } - return $ret; + return $ret; } function sendResp($status, $logger, $apiKey = '', $extra = null) { - if ($logger->request !== NULL) - $logger->request->set('status', $status); + if ($logger->request !== NULL) + $logger->request->set('status', $status); - $a['status'] = $status; + $a['status'] = $status; - // 2008-11-21T06:11:55Z0711 - $t = substr(microtime(false), 2, 3); - $t = gmdate('Y-m-d\TH:i:s\Z0') . $t; + // 2008-11-21T06:11:55Z0711 + $t = substr(microtime(false), 2, 3); + $t = gmdate('Y-m-d\TH:i:s\Z0') . $t; - $a['t'] = $t; + $a['t'] = $t; - if ($extra) - foreach ($extra as $param => $value) - $a[$param] = $value; + if ($extra) + foreach ($extra as $param => $value) + $a[$param] = $value; - $h = sign($a, $apiKey, $logger); + $h = sign($a, $apiKey, $logger); - $str = ""; - $str .= "h=" . $h . "\r\n"; - $str .= "t=" . $a['t'] . "\r\n"; + $str = ""; + $str .= "h=" . $h . "\r\n"; + $str .= "t=" . $a['t'] . "\r\n"; - if ($extra) - foreach ($extra as $param => $value) - $str .= $param . "=" . $value . "\r\n"; + if ($extra) + foreach ($extra as $param => $value) + $str .= $param . "=" . $value . "\r\n"; - $str .= "status=" . $a['status'] . "\r\n"; - $str .= "\r\n"; + $str .= "status=" . $a['status'] . "\r\n"; + $str .= "\r\n"; - $logger->log(LOG_INFO, "Response: " . $str . " (at " . gmdate("c") . " " . microtime() . ")"); + $logger->log(LOG_INFO, "Response: " . $str . " (at " . gmdate("c") . " " . microtime() . ")"); - if ($logger->request !== NULL) - $logger->request->write(); + if ($logger->request !== NULL) + $logger->request->write(); - echo $str; - exit; + echo $str; + exit; } // backport from PHP 5.6 if (function_exists('hash_equals') === FALSE) { - function hash_equals($a, $b) - { - // hashes are a (known) fixed length, - // so this doesn't leak anything. - if (strlen($a) != strlen($b)) - return false; + function hash_equals($a, $b) + { + // hashes are a (known) fixed length, + // so this doesn't leak anything. + if (strlen($a) != strlen($b)) + return false; - $result = 0; + $result = 0; - for ($i = 0; $i < strlen($a); $i++) - $result |= ord($a[$i]) ^ ord($b[$i]); + for ($i = 0; $i < strlen($a); $i++) + $result |= ord($a[$i]) ^ ord($b[$i]); - return (0 === $result); - } + return (0 === $result); + } } /** @@ -349,33 +349,33 @@ if (function_exists('hash_equals') === FALSE) */ function total_time ($url) { - $opts = array( - CURLOPT_URL => $url, - CURLOPT_TIMEOUT => 3, - CURLOPT_FORBID_REUSE => TRUE, - CURLOPT_FRESH_CONNECT => TRUE, - CURLOPT_RETURNTRANSFER => TRUE, - CURLOPT_USERAGENT => 'ykval-munin-vallatency/1.0', - ); + $opts = array( + CURLOPT_URL => $url, + CURLOPT_TIMEOUT => 3, + CURLOPT_FORBID_REUSE => TRUE, + CURLOPT_FRESH_CONNECT => TRUE, + CURLOPT_RETURNTRANSFER => TRUE, + CURLOPT_USERAGENT => 'ykval-munin-vallatency/1.0', + ); - if (($ch = curl_init()) === FALSE) - return false; + if (($ch = curl_init()) === FALSE) + return false; - if (curl_setopt_array($ch, $opts) === FALSE) - return false; + if (curl_setopt_array($ch, $opts) === FALSE) + return false; - // we don't care about the actual response - if (curl_exec($ch) === FALSE) - return false; + // we don't care about the actual response + if (curl_exec($ch) === FALSE) + return false; - $total_time = curl_getinfo($ch, CURLINFO_TOTAL_TIME); + $total_time = curl_getinfo($ch, CURLINFO_TOTAL_TIME); - curl_close($ch); + curl_close($ch); - if (is_float($total_time) === FALSE) - return false; + if (is_float($total_time) === FALSE) + return false; - return $total_time; + return $total_time; } /** @@ -386,38 +386,38 @@ function total_time ($url) */ function endpoints ($urls) { - $endpoints = array(); + $endpoints = array(); - foreach ($urls as $url) - { - // internal munin name must be a-zA-Z0-9_, - // so sha1 hex should be fine. - // - // munin also truncates at some length, - // so we just take the first few characters of the hashsum. - $internal = substr(sha1($url), 0, 20); + foreach ($urls as $url) + { + // internal munin name must be a-zA-Z0-9_, + // so sha1 hex should be fine. + // + // munin also truncates at some length, + // so we just take the first few characters of the hashsum. + $internal = substr(sha1($url), 0, 20); - // actual label name shown for graph values - if (($label = hostport($url)) === FALSE) - { - return false; - } + // actual label name shown for graph values + if (($label = hostport($url)) === FALSE) + { + return false; + } - $endpoints[] = array($internal, $label, $url); - } + $endpoints[] = array($internal, $label, $url); + } - // check for truncated sha1 collisions (or actual duplicate URLs!) - $internal = array(); + // check for truncated sha1 collisions (or actual duplicate URLs!) + $internal = array(); - foreach($endpoints as $endpoint) - { - $internal[] = $endpoint[0]; - } + foreach($endpoints as $endpoint) + { + $internal[] = $endpoint[0]; + } - if (count(array_unique($internal)) !== count($endpoints)) - return false; + if (count(array_unique($internal)) !== count($endpoints)) + return false; - return $endpoints; + return $endpoints; } /** @@ -430,22 +430,22 @@ function endpoints ($urls) */ function hostport ($url) { - if (($url = parse_url($url)) === FALSE) - return false; + if (($url = parse_url($url)) === FALSE) + return false; - if (array_key_exists('host', $url) === FALSE || $url['host'] === NULL) - return false; + if (array_key_exists('host', $url) === FALSE || $url['host'] === NULL) + return false; - if (array_key_exists('port', $url) === TRUE && $url['port'] !== NULL) - return $url['host'].':'.$url['port']; + if (array_key_exists('port', $url) === TRUE && $url['port'] !== NULL) + return $url['host'].':'.$url['port']; - if (array_key_exists('scheme', $url) === TRUE - && strtolower($url['scheme']) === 'http') - return $url['host'].':80'; + if (array_key_exists('scheme', $url) === TRUE + && strtolower($url['scheme']) === 'http') + return $url['host'].':80'; - if (array_key_exists('scheme', $url) === TRUE - && strtolower($url['scheme']) === 'https') - return $url['host'].':443'; + if (array_key_exists('scheme', $url) === TRUE + && strtolower($url['scheme']) === 'https') + return $url['host'].':443'; - return $url['host']; + return $url['host']; } diff --git a/ykval-config.php b/ykval-config.php index 5052f17..5c369f8 100644 --- a/ykval-config.php +++ b/ykval-config.php @@ -36,17 +36,17 @@ $dbfile = '/etc/yubico/val/config-db.php'; if (file_exists($dbfile) && @is_readable($dbfile)) { - require_once $dbfile; + require_once $dbfile; } else { - // FIXME hostname - // FIXME port - // 'oci:oracledb' for Oracle DB (with OCI library) - $dbtype = 'mysql'; - $dbuser = 'ykval_verifier'; - $dbpass = 'yourpassword'; - $dbname = 'ykval'; + // FIXME hostname + // FIXME port + // 'oci:oracledb' for Oracle DB (with OCI library) + $dbtype = 'mysql'; + $dbuser = 'ykval_verifier'; + $dbpass = 'yourpassword'; + $dbname = 'ykval'; } // for the validation interface. @@ -58,9 +58,9 @@ $baseParams['__YKVAL_DB_OPTIONS__'] = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EX // for the validation server sync $baseParams['__YKVAL_SYNC_POOL__'] = array( - // "https://api2.example.com/wsapi/2.0/sync", - // "https://api3.example.com/wsapi/2.0/sync", - // "https://api4.example.com/wsapi/2.0/sync", + // "https://api2.example.com/wsapi/2.0/sync", + // "https://api3.example.com/wsapi/2.0/sync", + // "https://api4.example.com/wsapi/2.0/sync", ); /** @@ -70,12 +70,12 @@ $baseParams['__YKVAL_SYNC_POOL__'] = array( * Both IPv4 and IPv6 are supported. */ $baseParams['__YKVAL_ALLOWED_SYNC_POOL__'] = array( - // "1.2.3.4", - // "2.3.4.5", - // "3.4.5.6", - // "fc00:aaaa::", - // "fc00:bbbb::", - // "fc00:cccc::", + // "1.2.3.4", + // "2.3.4.5", + // "3.4.5.6", + // "fc00:aaaa::", + // "fc00:bbbb::", + // "fc00:cccc::", ); // An array of IP addresses allowed to issue YubiKey activation/deactivation @@ -103,33 +103,33 @@ $baseParams['__YKVAL_SYNC_DEFAULT_TIMEOUT__'] = 1; // A key -> value array with curl options to set // when calling URLs defined in __YKVAL_SYNC_POOL__ $baseParams['__YKVAL_SYNC_CURL_OPTS__'] = array( - //CURLOPT_PROTOCOLS => CURLPROTO_HTTP, + //CURLOPT_PROTOCOLS => CURLPROTO_HTTP, ); // A key -> value array with curl options to set // when calling URLs returned by otp2ksmurls() $baseParams['__YKVAL_KSM_CURL_OPTS__'] = array( - //CURLOPT_PROTOCOLS => CURLPROTO_HTTP, + //CURLOPT_PROTOCOLS => CURLPROTO_HTTP, ); // Returns an array of YK-KSM URLs for decrypting $otp for $client. // The URLs must be fully qualified, i.e., containing the OTP itself. function otp2ksmurls ($otp, $client) { - //if ($client == 42) { - // return array("https://another-ykksm.example.com/wsapi/decrypt?otp=$otp"); - //} + //if ($client == 42) { + // return array("https://another-ykksm.example.com/wsapi/decrypt?otp=$otp"); + //} - //if (preg_match("/^dteffujehknh/", $otp)) { - // return array("https://different-ykksm.example.com/wsapi/decrypt?otp=$otp"); - //} + //if (preg_match("/^dteffujehknh/", $otp)) { + // return array("https://different-ykksm.example.com/wsapi/decrypt?otp=$otp"); + //} - return array( - // "https://ykksm1.example.com/wsapi/decrypt?otp=$otp", - // "https://ykksm2.example.com/wsapi/decrypt?otp=$otp", - "http://127.0.0.1:80/wsapi/decrypt?otp=$otp", - "http://127.0.0.1:8002/wsapi/decrypt?otp=$otp", - ); + return array( + // "https://ykksm1.example.com/wsapi/decrypt?otp=$otp", + // "https://ykksm2.example.com/wsapi/decrypt?otp=$otp", + "http://127.0.0.1:80/wsapi/decrypt?otp=$otp", + "http://127.0.0.1:8002/wsapi/decrypt?otp=$otp", + ); } /** diff --git a/ykval-db-oci.php b/ykval-db-oci.php index ea97f06..1c5c82b 100644 --- a/ykval-db-oci.php +++ b/ykval-db-oci.php @@ -36,224 +36,224 @@ require_once('ykval-db.php'); class DbImpl extends Db { - /** - * Constructor - * - * @param string $host Database host - * @param string $user Database user - * @param string $pwd Database password - * @param string $name Database table name - * @return void - * - */ - public function __construct($db_dsn, $db_username, $db_password, $db_options, $name='ykval-db') - { - $this->db_dsn=$db_dsn; - $this->db_username=$db_username; - $this->db_password=$db_password; - $this->db_options=$db_options; + /** + * Constructor + * + * @param string $host Database host + * @param string $user Database user + * @param string $pwd Database password + * @param string $name Database table name + * @return void + * + */ + public function __construct($db_dsn, $db_username, $db_password, $db_options, $name='ykval-db') + { + $this->db_dsn=$db_dsn; + $this->db_username=$db_username; + $this->db_password=$db_password; + $this->db_options=$db_options; - if(substr($db_dsn, 0, 4) == 'oci:') { - # "oci:" prefix needs to be removed before passing db_dsn to OCI - $this->db_dsn = substr($this->db_dsn, 4); - } - - $this->myLog=new Log($name); - } - - /** - * function to connect to database defined in config.php - * - * @return boolean True on success, otherwise false. - * - */ - public function connect(){ - $this->dbh = oci_connect($this->db_username, $this->db_password, $this->db_dsn); - if (!$this->dbh) { - $error = oci_error(); - $this->myLog->log(LOG_CRIT, "Database connection error: " . $error["message"]); - $this->dbh=Null; - return false; - } - return true; - } - - protected function query($query, $returnresult=false) { - if(!$this->isConnected()) { - $this->connect(); - } - if($this->isConnected()) { - $this->myLog->log(LOG_DEBUG, 'DB query is: ' . $query); - # OCI mode - $result = oci_parse($this->dbh, $query); - if(!oci_execute($result)) { - $this->myLog->log(LOG_INFO, 'Database query error: ' . preg_replace('/\n/',' ',print_r(oci_error($result), true))); - $this->dbh = Null; - return false; - } - $this->result = $result; - if ($returnresult) return $this->result; - else return true; - } else { - $this->myLog->log(LOG_CRIT, 'No database connection'); - return false; - } - } - - /** - * function to get a row from the query result - * Once all rows have been fetch, function closeCursor needs to be called - * - * @param object $result Query result object or null to use the current one - * @return array a query row - * - */ - public function fetchArray($result=null){ - if(!$result) $result = $this->result; - if(!$result) return null; - - $res = oci_fetch_array($result, OCI_ASSOC); - return array_change_key_case($res, CASE_LOWER); - } - - /** - * function to close the cursor after having fetched rows - * - * @param object $result Query result object or null to use the current one - * - */ - public function closeCursor($result=null){ - } - - /** - * main function used to get rows by multiple key=>value pairs from Db table. - * - * @param string $table Database table to update row in - * @param array $where Array with column=>values to select rows by - * @param int $nr Number of rows to collect. NULL=>inifinity. Default=NULL. - * @param int $rev rev=1 indicates order should be reversed. Default=NULL. - * @param string distinct Select rows with distinct columns, Default=NULL - * @return mixed Array with values from Db row or 2d-array with multiple rows - * - */ - public function findByMultiple($table, $where, $nr=null, $rev=null, $distinct=null) - { - $value=""; /* quiet the PHP Notice */ - $match=null; /* quiet the PHP Notice */ - $query="SELECT"; - - if($nr!=null){ - # LIMIT doesn't exist in Oracle, so we encapsulate the query to be - # able to filter a given number of rows afterwars (after ordering) - $query.= " * FROM (SELECT"; - } - - if ($distinct!=null) { - $query.= " DISTINCT " . $distinct; - } else { - $query.= " *"; - } - $query.= " FROM " . $table; - if ($where!=null){ - foreach ($where as $key=>$value) { - if ($key != 'server' && !(ctype_alnum($value) || is_null($value))) - { - $this->myLog->log(LOG_WARNING, "findByMultiple: attempted to use non-alphanumeric in WHERE: " . $table . "." . $key . " = " . $value); - return false; + if(substr($db_dsn, 0, 4) == 'oci:') { + # "oci:" prefix needs to be removed before passing db_dsn to OCI + $this->db_dsn = substr($this->db_dsn, 4); } - elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) - { - $this->myLog->log(LOG_WARNING, "findByMultiple: attempted use invalid URL in WHERE: " . $table . "." . $key . " = " . $value); - return false; + + $this->myLog=new Log($name); + } + + /** + * function to connect to database defined in config.php + * + * @return boolean True on success, otherwise false. + * + */ + public function connect(){ + $this->dbh = oci_connect($this->db_username, $this->db_password, $this->db_dsn); + if (!$this->dbh) { + $error = oci_error(); + $this->myLog->log(LOG_CRIT, "Database connection error: " . $error["message"]); + $this->dbh=Null; + return false; } - if ($key!=null) { - if ($value!=null) $match.= " ". $key . " = '" . $value . "' and"; - else $match.= " ". $key . " is NULL and"; + return true; + } + + protected function query($query, $returnresult=false) { + if(!$this->isConnected()) { + $this->connect(); } - } - if ($match!=null) $query .= " WHERE" . $match; - $query=rtrim($query, "and"); - $query=rtrim($query); - } - if ($rev==1) $query.= " ORDER BY id DESC"; - if ($nr!=null) { - $query .= ") WHERE rownum < " . ($nr+1); - } - - $result = $this->query($query, true); - if (!$result) return false; - - if ($nr==1) { - $row = $this->fetchArray($result); - $this->closeCursor($result); - return $row; - } - else { - $collection=array(); - while($row = $this->fetchArray($result)){ - $collection[]=$row; - } - $this->closeCursor($result); - return $collection; - } - } - - /** - * main function used to delete rows by multiple key=>value pairs from Db table. - * - * @param string $table Database table to delete row in - * @param array $where Array with column=>values to select rows by - * @param int $nr Number of rows to collect. NULL=>inifinity. Default=NULL. - * @param int $rev rev=1 indicates order should be reversed. Default=NULL. - * @param string distinct Select rows with distinct columns, Default=NULL - * @return boolean True on success, otherwise false. - * - */ - public function deleteByMultiple($table, $where, $nr=null, $rev=null) - { - $query="DELETE"; - $query.= " FROM " . $table; - $query .= " WHERE id IN (SELECT id FROM " . $table; - if ($where!=null){ - $query.= " WHERE"; - foreach ($where as $key=>$value) { - if ($key != 'server' && !ctype_alnum($value)) - { - $this->myLog->log(LOG_WARNING, "deleteByMultiple: attempted to write non-alphanumeric to the database: " . $value); - return false; + if($this->isConnected()) { + $this->myLog->log(LOG_DEBUG, 'DB query is: ' . $query); + # OCI mode + $result = oci_parse($this->dbh, $query); + if(!oci_execute($result)) { + $this->myLog->log(LOG_INFO, 'Database query error: ' . preg_replace('/\n/',' ',print_r(oci_error($result), true))); + $this->dbh = Null; + return false; + } + $this->result = $result; + if ($returnresult) return $this->result; + else return true; + } else { + $this->myLog->log(LOG_CRIT, 'No database connection'); + return false; } - elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) - { - $this->myLog->log(LOG_WARNING, "deleteByMultiple: attempted to write invalid URL to the database: " . $value); - return false; + } + + /** + * function to get a row from the query result + * Once all rows have been fetch, function closeCursor needs to be called + * + * @param object $result Query result object or null to use the current one + * @return array a query row + * + */ + public function fetchArray($result=null){ + if(!$result) $result = $this->result; + if(!$result) return null; + + $res = oci_fetch_array($result, OCI_ASSOC); + return array_change_key_case($res, CASE_LOWER); + } + + /** + * Function to close the cursor after having fetched rows + * + * @param object $result Query result object or null to use the current one + * + */ + public function closeCursor($result=null){ + } + + /** + * main function used to get rows by multiple key=>value pairs from Db table. + * + * @param string $table Database table to update row in + * @param array $where Array with column=>values to select rows by + * @param int $nr Number of rows to collect. NULL=>inifinity. Default=NULL. + * @param int $rev rev=1 indicates order should be reversed. Default=NULL. + * @param string distinct Select rows with distinct columns, Default=NULL + * @return mixed Array with values from Db row or 2d-array with multiple rows + * + */ + public function findByMultiple($table, $where, $nr=null, $rev=null, $distinct=null) + { + $value=""; /* quiet the PHP Notice */ + $match=null; /* quiet the PHP Notice */ + $query="SELECT"; + + if($nr!=null){ + # LIMIT doesn't exist in Oracle, so we encapsulate the query to be + # able to filter a given number of rows afterwars (after ordering) + $query.= " * FROM (SELECT"; + } + + if ($distinct!=null) { + $query.= " DISTINCT " . $distinct; + } else { + $query.= " *"; + } + $query.= " FROM " . $table; + if ($where!=null){ + foreach ($where as $key=>$value) { + if ($key != 'server' && !(ctype_alnum($value) || is_null($value))) + { + $this->myLog->log(LOG_WARNING, "findByMultiple: attempted to use non-alphanumeric in WHERE: " . $table . "." . $key . " = " . $value); + return false; + } + elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) + { + $this->myLog->log(LOG_WARNING, "findByMultiple: attempted use invalid URL in WHERE: " . $table . "." . $key . " = " . $value); + return false; + } + if ($key!=null) { + if ($value!=null) $match.= " ". $key . " = '" . $value . "' and"; + else $match.= " ". $key . " is NULL and"; + } + } + if ($match!=null) $query .= " WHERE" . $match; + $query=rtrim($query, "and"); + $query=rtrim($query); + } + if ($rev==1) $query.= " ORDER BY id DESC"; + if ($nr!=null) { + $query .= ") WHERE rownum < " . ($nr+1); + } + + $result = $this->query($query, true); + if (!$result) return false; + + if ($nr==1) { + $row = $this->fetchArray($result); + $this->closeCursor($result); + return $row; + } + else { + $collection=array(); + while($row = $this->fetchArray($result)){ + $collection[]=$row; + } + $this->closeCursor($result); + return $collection; } - $query.= " ". $key . " = '" . $value . "' and"; - } - $query=rtrim($query, "and"); - $query=rtrim($query); } - if ($rev==1) $query.= " ORDER BY id DESC"; - $query .= ")"; - if ($nr!=null) $query.= " and rownum < " . ($nr+1); + /** + * main function used to delete rows by multiple key=>value pairs from Db table. + * + * @param string $table Database table to delete row in + * @param array $where Array with column=>values to select rows by + * @param int $nr Number of rows to collect. NULL=>inifinity. Default=NULL. + * @param int $rev rev=1 indicates order should be reversed. Default=NULL. + * @param string distinct Select rows with distinct columns, Default=NULL + * @return boolean True on success, otherwise false. + * + */ + public function deleteByMultiple($table, $where, $nr=null, $rev=null) + { + $query="DELETE"; + $query.= " FROM " . $table; + $query .= " WHERE id IN (SELECT id FROM " . $table; + if ($where!=null){ + $query.= " WHERE"; + foreach ($where as $key=>$value) { + if ($key != 'server' && !ctype_alnum($value)) + { + $this->myLog->log(LOG_WARNING, "deleteByMultiple: attempted to write non-alphanumeric to the database: " . $value); + return false; + } + elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) + { + $this->myLog->log(LOG_WARNING, "deleteByMultiple: attempted to write invalid URL to the database: " . $value); + return false; + } + $query.= " ". $key . " = '" . $value . "' and"; + } + $query=rtrim($query, "and"); + $query=rtrim($query); + } + if ($rev==1) $query.= " ORDER BY id DESC"; - return $this->query($query, false); - } + $query .= ")"; + if ($nr!=null) $query.= " and rownum < " . ($nr+1); - /** - * Function to get the number of rows - * - * @param object $result Query result object or null to use the current one - * @return int number of rows affected by last statement or 0 if database connection is not functional. - * - */ - public function rowCount($result=null) - { - if(!$result) $result = $this->result; - if($result) { - return oci_num_rows($result); - } else { - return 0; + return $this->query($query, false); + } + + /** + * Function to get the number of rows + * + * @param object $result Query result object or null to use the current one + * @return int number of rows affected by last statement or 0 if database connection is not functional. + * + */ + public function rowCount($result=null) + { + if(!$result) $result = $this->result; + if($result) { + return oci_num_rows($result); + } else { + return 0; + } } - } } diff --git a/ykval-db-pdo.php b/ykval-db-pdo.php index 969372a..0fee1cb 100644 --- a/ykval-db-pdo.php +++ b/ykval-db-pdo.php @@ -36,231 +36,228 @@ require_once('ykval-db.php'); class DbImpl extends Db { + /** + * Constructor + * + * @param string $host Database host + * @param string $user Database user + * @param string $pwd Database password + * @param string $name Database table name + * @return void + * + */ + public function __construct($db_dsn, $db_username, $db_password, $db_options, $name='ykval-db') + { + $this->db_dsn=$db_dsn; + $this->db_username=$db_username; + $this->db_password=$db_password; + $this->db_options=$db_options; + $this->result = null; - - /** - * Constructor - * - * @param string $host Database host - * @param string $user Database user - * @param string $pwd Database password - * @param string $name Database table name - * @return void - * - */ - public function __construct($db_dsn, $db_username, $db_password, $db_options, $name='ykval-db') - { - $this->db_dsn=$db_dsn; - $this->db_username=$db_username; - $this->db_password=$db_password; - $this->db_options=$db_options; - $this->result = null; - - $this->myLog=new Log($name); - } - - /** - * function to connect to database defined in config.php - * - * @return boolean True on success, otherwise false. - * - */ - public function connect(){ - - try { - $this->dbh = new PDO($this->db_dsn, $this->db_username, $this->db_password, $this->db_options); - } catch (PDOException $e) { - $this->myLog->log(LOG_CRIT, "Database connection error: " . $e->getMessage()); - $this->dbh=Null; - return false; + $this->myLog=new Log($name); } - return true; - } - protected function query($query, $returnresult=false) { - if(!$this->isConnected()) { - $this->connect(); + /** + * function to connect to database defined in config.php + * + * @return boolean True on success, otherwise false. + * + */ + public function connect(){ + + try { + $this->dbh = new PDO($this->db_dsn, $this->db_username, $this->db_password, $this->db_options); + } catch (PDOException $e) { + $this->myLog->log(LOG_CRIT, "Database connection error: " . $e->getMessage()); + $this->dbh=Null; + return false; + } + return true; } - if($this->isConnected()) { - $this->myLog->log(LOG_DEBUG, 'DB query is: ' . $query); - try { - $this->result = $this->dbh->query($query); - } catch (PDOException $e) { - $this->myLog->log(LOG_INFO, 'Database query error: ' . preg_replace('/\n/',' ',print_r($this->dbh->errorInfo(), true))); - $this->dbh = Null; - return false; - } - if ($returnresult) return $this->result; - else return true; - } else { - $this->myLog->log(LOG_CRIT, 'No database connection'); - return false; + protected function query($query, $returnresult=false) { + if(!$this->isConnected()) { + $this->connect(); + } + if($this->isConnected()) { + $this->myLog->log(LOG_DEBUG, 'DB query is: ' . $query); + + try { + $this->result = $this->dbh->query($query); + } catch (PDOException $e) { + $this->myLog->log(LOG_INFO, 'Database query error: ' . preg_replace('/\n/',' ',print_r($this->dbh->errorInfo(), true))); + $this->dbh = Null; + return false; + } + if ($returnresult) return $this->result; + else return true; + } else { + $this->myLog->log(LOG_CRIT, 'No database connection'); + return false; + } } - } + /** + * function to get a row from the query result + * Once all rows have been fetch, function closeCursor needs to be called + * + * @param object $result Query result object or null to use the current one + * @return array a query row + * + */ + public function fetchArray($result=null){ + if(!$result) $result = $this->result; + if(!$result) return null; - /** - * function to get a row from the query result - * Once all rows have been fetch, function closeCursor needs to be called - * - * @param object $result Query result object or null to use the current one - * @return array a query row - * - */ - public function fetchArray($result=null){ - if(!$result) $result = $this->result; - if(!$result) return null; + return $result->fetch(PDO::FETCH_ASSOC); + } - return $result->fetch(PDO::FETCH_ASSOC); - } + /** + * function to close the cursor after having fetched rows + * + * @param object $result Query result object or null to use the current one + * + */ + public function closeCursor($result=null){ + if(!$result) $result = $this->result; + if($result) $result->closeCursor(); + } - /** - * function to close the cursor after having fetched rows - * - * @param object $result Query result object or null to use the current one - * - */ - public function closeCursor($result=null){ - if(!$result) $result = $this->result; - if($result) $result->closeCursor(); - } + /** + * Main function used to get rows by multiple key=>value pairs from Db table. + * + * @param string $table Database table to update row in + * @param array $where Array with column=>values to select rows by + * @param int $nr Number of rows to collect. NULL=>inifinity. Default=NULL. + * @param int $rev rev=1 indicates order should be reversed. Default=NULL. + * @param string distinct Select rows with distinct columns, Default=NULL + * + * @return mixed Array with values from Db row or 2d-array with multiple rows + */ + public function findByMultiple($table, $where, $nr=NULL, $rev=NULL, $distinct=NULL) + { + $value = ''; + $match = NULL; + $query = 'SELECT'; - /** - * Main function used to get rows by multiple key=>value pairs from Db table. - * - * @param string $table Database table to update row in - * @param array $where Array with column=>values to select rows by - * @param int $nr Number of rows to collect. NULL=>inifinity. Default=NULL. - * @param int $rev rev=1 indicates order should be reversed. Default=NULL. - * @param string distinct Select rows with distinct columns, Default=NULL - * - * @return mixed Array with values from Db row or 2d-array with multiple rows - */ - public function findByMultiple($table, $where, $nr=NULL, $rev=NULL, $distinct=NULL) - { - $value = ''; - $match = NULL; - $query = 'SELECT'; + if ($distinct != NULL) + $query.= " DISTINCT " . $distinct; + else + $query.= " *"; - if ($distinct != NULL) - $query.= " DISTINCT " . $distinct; - else - $query.= " *"; + $query.= " FROM " . $table; - $query.= " FROM " . $table; - - if ($where != NULL) - { - foreach ($where as $key => $value) - { - if ($key != 'server' && !(ctype_alnum($value) || is_null($value))) + if ($where != NULL) { - $this->myLog->log(LOG_WARNING, "findByMultiple: attempted to use non-alphanumeric in WHERE: " . $table . "." . $key . " = " . $value); - return false; + foreach ($where as $key => $value) + { + if ($key != 'server' && !(ctype_alnum($value) || is_null($value))) + { + $this->myLog->log(LOG_WARNING, "findByMultiple: attempted to use non-alphanumeric in WHERE: " . $table . "." . $key . " = " . $value); + return false; + } + elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) + { + $this->myLog->log(LOG_WARNING, "findByMultiple: attempted to use invalid URL in WHERE: " . $table . "." . $key . " = " . $value); + return false; + } + if ($key != NULL) + { + if ($value != NULL) + $match .= " ". $key . " = '" . $value . "' and"; + else + $match .= " ". $key . " is NULL and"; + } + } + + if ($match != NULL) + $query .= " WHERE" . $match; + + $query = rtrim($query, "and"); + $query = rtrim($query); } - elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) + + if ($rev == 1) + $query.= " ORDER BY id DESC"; + + if ($nr != NULL) + $query.= " LIMIT " . $nr; + + $result = $this->query($query, true); + + if (!$result) + return false; + + if ($nr == 1) { - $this->myLog->log(LOG_WARNING, "findByMultiple: attempted to use invalid URL in WHERE: " . $table . "." . $key . " = " . $value); - return false; + $row = $this->fetchArray($result); + $this->closeCursor($result); + return $row; } - if ($key != NULL) - { - if ($value != NULL) - $match .= " ". $key . " = '" . $value . "' and"; - else - $match .= " ". $key . " is NULL and"; - } - } - if ($match != NULL) - $query .= " WHERE" . $match; + $collection = array(); - $query = rtrim($query, "and"); - $query = rtrim($query); - } + while($row = $this->fetchArray($result)) + $collection[] = $row; - if ($rev == 1) - $query.= " ORDER BY id DESC"; + $this->closeCursor($result); - if ($nr != NULL) - $query.= " LIMIT " . $nr; - - $result = $this->query($query, true); - - if (!$result) - return false; - - if ($nr == 1) - { - $row = $this->fetchArray($result); - $this->closeCursor($result); - return $row; - } - - $collection = array(); - - while($row = $this->fetchArray($result)) - $collection[] = $row; - - $this->closeCursor($result); - - return $collection; - } - - /** - * main function used to delete rows by multiple key=>value pairs from Db table. - * - * @param string $table Database table to delete row in - * @param array $where Array with column=>values to select rows by - * @param int $nr Number of rows to collect. NULL=>inifinity. Default=NULL. - * @param int $rev rev=1 indicates order should be reversed. Default=NULL. - * @param string distinct Select rows with distinct columns, Default=NULL - * @return boolean True on success, otherwise false. - * - */ - public function deleteByMultiple($table, $where, $nr=null, $rev=null) - { - $query="DELETE"; - $query.= " FROM " . $table; - if ($where!=null){ - $query.= " WHERE"; - foreach ($where as $key=>$value) { - if ($key != 'server' && !ctype_alnum($value)) { - $this->myLog->log(LOG_WARNING, "deleteByMultiple: attempted to write non-alphanumeric to the database: " . $value); - return false; - } - elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) - { - $this->myLog->log(LOG_WARNING, "deleteByMultiple: attempted to write invalid URL to the database: " . $value); - return false; - } - $query.= " ". $key . " = '" . $value . "' and"; - } - $query=rtrim($query, "and"); - $query=rtrim($query); + return $collection; } - if ($rev==1) $query.= " ORDER BY id DESC"; - if ($nr!=null) $query.= " LIMIT " . $nr; - return $this->query($query, false); - } - /** - * Function to get the number of rows - * - * @param object $result Query result object or null to use the current one - * @return int number of rows affected by last statement or 0 if database connection is not functional. - * - */ - public function rowCount($result=null) - { - if(!$result) $result = $this->result; - if($result) { - $count=$result->rowCount(); - $result->closeCursor(); - return $count; - } else { - return 0; + /** + * main function used to delete rows by multiple key=>value pairs from Db table. + * + * @param string $table Database table to delete row in + * @param array $where Array with column=>values to select rows by + * @param int $nr Number of rows to collect. NULL=>inifinity. Default=NULL. + * @param int $rev rev=1 indicates order should be reversed. Default=NULL. + * @param string distinct Select rows with distinct columns, Default=NULL + * @return boolean True on success, otherwise false. + * + */ + public function deleteByMultiple($table, $where, $nr=null, $rev=null) + { + $query="DELETE"; + $query.= " FROM " . $table; + if ($where!=null){ + $query.= " WHERE"; + foreach ($where as $key=>$value) { + if ($key != 'server' && !ctype_alnum($value)) { + $this->myLog->log(LOG_WARNING, "deleteByMultiple: attempted to write non-alphanumeric to the database: " . $value); + return false; + } + elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) + { + $this->myLog->log(LOG_WARNING, "deleteByMultiple: attempted to write invalid URL to the database: " . $value); + return false; + } + $query.= " ". $key . " = '" . $value . "' and"; + } + $query=rtrim($query, "and"); + $query=rtrim($query); + } + if ($rev==1) $query.= " ORDER BY id DESC"; + if ($nr!=null) $query.= " LIMIT " . $nr; + return $this->query($query, false); + } + + /** + * Function to get the number of rows + * + * @param object $result Query result object or null to use the current one + * @return int number of rows affected by last statement or 0 if database connection is not functional. + * + */ + public function rowCount($result=null) + { + if(!$result) $result = $this->result; + if($result) { + $count=$result->rowCount(); + $result->closeCursor(); + return $count; + } else { + return 0; + } } - } } diff --git a/ykval-db.php b/ykval-db.php index 4ab359e..4c1296e 100644 --- a/ykval-db.php +++ b/ykval-db.php @@ -35,276 +35,274 @@ require_once('ykval-log.php'); abstract class Db { - /** - * static function to determine database type and instantiate the correct subclass - * - * */ - public static function GetDatabaseHandle($baseParams, $logname) - { - if(substr($baseParams['__YKVAL_DB_DSN__'], 0, 3) == 'oci') { - require_once 'ykval-db-oci.php'; - } else { - require_once 'ykval-db-pdo.php'; - } - return new DbImpl($baseParams['__YKVAL_DB_DSN__'], + /** + * static function to determine database type and instantiate the correct subclass + * + * */ + public static function GetDatabaseHandle($baseParams, $logname) + { + if(substr($baseParams['__YKVAL_DB_DSN__'], 0, 3) == 'oci') { + require_once 'ykval-db-oci.php'; + } else { + require_once 'ykval-db-pdo.php'; + } + return new DbImpl($baseParams['__YKVAL_DB_DSN__'], $baseParams['__YKVAL_DB_USER__'], $baseParams['__YKVAL_DB_PW__'], $baseParams['__YKVAL_DB_OPTIONS__'], $logname . ':db'); - } - - function addField($name, $value) - { - $this->myLog->addField($name, $value); - } - - /** - * function to convert Db timestamps to unixtime(s) - * - * @param string $updated Database timestamp - * @return int Timestamp in unixtime format - * - */ - public function timestampToTime($updated) - { - $stamp=strptime($updated, '%F %H:%M:%S'); - return mktime($stamp[tm_hour], $stamp[tm_min], $stamp[tm_sec], $stamp[tm_mon]+1, $stamp[tm_mday], $stamp[tm_year]); - - } - - /** - * function to compute delta (s) between 2 Db timestamps - * - * @param string $first Database timestamp 1 - * @param string $second Database timestamp 2 - * @return int Deltatime (s) - * - */ - public function timestampDeltaTime($first, $second) - { - return Db::timestampToTime($second) - Db::timestampToTime($first); - } - - /** - * function to disconnect from database - * - * @return boolean True on success, otherwise false. - * - */ - public function disconnect() - { - $this->dbh=NULL; - } - - /** - * function to check if database is connected - * - * @return boolean True if connected, otherwise false. - * - */ - public function isConnected() - { - if ($this->dbh!=NULL) return True; - else return False; - } - - /** - * function to update row in database by a where condition - * - * @param string $table Database table to update row in - * @param int $id Id on row to update - * @param array $values Array with key=>values to update - * @return boolean True on success, otherwise false. - * - */ - public function updateBy($table, $k, $v, $values) - { - if (!ctype_alnum($v) && !filter_var($v, FILTER_VALIDATE_URL)) { - $this->myLog->log(LOG_WARNING, "updateBy: attempted to use an invalid value: " . $v); - return false; - } - $query = ""; - - foreach ($values as $key=>$value) { - if ($key != 'server' && !(ctype_alnum($value) || is_null($value))) { - $this->myLog->log(LOG_WARNING, "updateBy: attempted to write non-alphanumeric to the database: " . $table . "." . $key . " <= " . $value); - return false; - } - elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) - { - $this->myLog->log(LOG_WARNING, "updateBy: attempted to write invalid URL to the database: " . $table . "." . $key . " <= " . $value); - return false; - } - if (!is_null($value)) $query .= ' ' . $key . "='" . $value . "',"; - else $query .= ' ' . $key . '=NULL,'; - } - if (! $query) { - $this->myLog->log(LOG_DEBUG, "no values to set in query. Not updating DB"); - return true; } - $query = rtrim($query, ",") . " WHERE " . $k . " = '" . $v . "'"; - // Insert UPDATE statement at beginning - $query = "UPDATE " . $table . " SET " . $query; - - return $this->query($query, false); - } - - - /** - * function to update row in database - * - * @param string $table Database table to update row in - * @param int $id Id on row to update - * @param array $values Array with key=>values to update - * @return boolean True on success, otherwise false. - * - */ - public function update($table, $id, $values) - { - return $this->updateBy($table, 'id', $id, $values); - } - - /** - * function to update row in database based on a condition - * - * @param string $table Database table to update row in - * @param string $k Column to select row on - * @param string $v Value to select row on - * @param array $values Array with key=>values to update - * @param string $condition conditional statement - * @return boolean True on success, otherwise false. - * - */ - public function conditionalUpdateBy($table, $k, $v, $values, $condition) - { - if (!ctype_alnum($v) || preg_match('/^[a-zA-Z0-9><=()_ ]*$/', $condition) == 0) + function addField($name, $value) { - $this->myLog->log(LOG_WARNING, "conditionalUpdateBy: attempted to use non-alphanumeric value: " . $v . " - " . $condition); - return false; - } - $query = ""; /* quiet the PHP Notice */ - - foreach ($values as $key=>$value){ - if ($key != 'server' && !is_int($value) && !ctype_alnum($value)) { - $this->myLog->log(LOG_WARNING, "conditionalUpdateBy: attempted to write non-alphanumeric to the database: " . $value); - return false; - } - elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) - { - $this->myLog->log(LOG_WARNING, "conditionalUpdateBy: attempted to write invalid URL to the database: " . $value); - return false; - } - $query = $query . " " . $key . "='" . $value . "',"; - } - if (! $query) { - $this->myLog->log(LOG_DEBUG, "no values to set in query. Not updating DB"); - return true; + $this->myLog->addField($name, $value); } - $query = rtrim($query, ",") . " WHERE " . $k . " = '" . $v . "' and " . $condition; - // Insert UPDATE statement at beginning - $query = "UPDATE " . $table . " SET " . $query; + /** + * function to convert Db timestamps to unixtime(s) + * + * @param string $updated Database timestamp + * @return int Timestamp in unixtime format + * + */ + public function timestampToTime($updated) + { + $stamp=strptime($updated, '%F %H:%M:%S'); + return mktime($stamp[tm_hour], $stamp[tm_min], $stamp[tm_sec], $stamp[tm_mon]+1, $stamp[tm_mday], $stamp[tm_year]); - return $this->query($query, false); - } + } + /** + * function to compute delta (s) between 2 Db timestamps + * + * @param string $first Database timestamp 1 + * @param string $second Database timestamp 2 + * @return int Deltatime (s) + * + */ + public function timestampDeltaTime($first, $second) + { + return Db::timestampToTime($second) - Db::timestampToTime($first); + } - /** - * Function to update row in database based on a condition. - * An ID value is passed to select the appropriate column - * - * @param string $table Database table to update row in - * @param int $id Id on row to update - * @param array $values Array with key=>values to update - * @param string $condition conditional statement - * @return boolean True on success, otherwise false. - * - */ - public function conditionalUpdate($table, $id, $values, $condition) - { - return $this->conditionalUpdateBy($table, 'id', $id, $values, $condition); - } + /** + * function to disconnect from database + * + * @return boolean True on success, otherwise false. + * + */ + public function disconnect() + { + $this->dbh=NULL; + } - /** - * function to insert new row in database - * - * @param string $table Database table to update row in - * @param array $values Array with key=>values to update - * @return boolean True on success, otherwise false. - * - */ - public function save($table, $values) - { - $query= 'INSERT INTO ' . $table . " ("; - foreach ($values as $key=>$value){ - if ($key == 'server') { - $v = filter_var($value, FILTER_VALIDATE_URL); - if (!$v) { - $this->myLog->log(LOG_WARNING, "save: bad server URL provided: " . $value); - return false; + /** + * function to check if database is connected + * + * @return boolean True if connected, otherwise false. + * + */ + public function isConnected() + { + if ($this->dbh!=NULL) return True; + else return False; + } + + /** + * function to update row in database by a where condition + * + * @param string $table Database table to update row in + * @param int $id Id on row to update + * @param array $values Array with key=>values to update + * @return boolean True on success, otherwise false. + * + */ + public function updateBy($table, $k, $v, $values) + { + if (!ctype_alnum($v) && !filter_var($v, FILTER_VALIDATE_URL)) { + $this->myLog->log(LOG_WARNING, "updateBy: attempted to use an invalid value: " . $v); + return false; } - $value = $v; - } else if ($key == 'info') { - if (preg_match('/[a-zA-Z0-9&_=,]+/', $value) == 0) { - $this->myLog->log(LOG_WARNING, "save: bad info string provided: " . $value); - return false; - } - } else { - if ($value != '' && !is_int($value) && !ctype_alnum($value)) { - $this->myLog->log(LOG_WARNING, "save: attempted to write non-alphanumeric to the database: " . $value); - return false; - } - } - if (!is_null($value)) $query = $query . $key . ","; - } - $query = rtrim($query, ",") . ') VALUES ('; - foreach ($values as $key=>$value){ - if (!is_null($value)) $query = $query . "'" . $value . "',"; - } - $query = rtrim($query, ","); - $query = $query . ")"; - return $this->query($query, false); - } - /** - * helper function to collect last row[s] in database - * - * @param string $table Database table to update row in - * @param int $nr Number of rows to collect. NULL=>inifinity. DEFAULT=1. - * @return mixed Array with values from Db row or 2d-array with multiple rows -or false on failure. - * - */ - public function last($table, $nr=1) - { - return Db::findBy($table, null, null, $nr, 1); - } + $query = ""; - /** - * main function used to get rows from Db table. - * - * @param string $table Database table to update row in - * @param string $key Column to select rows by - * @param string $value Value to select rows by - * @param int $nr Number of rows to collect. NULL=>inifinity. Default=NULL. - * @param int $rev rev=1 indicates order should be reversed. Default=NULL. - * @return mixed Array with values from Db row or 2d-array with multiple rows - * - */ - public function findBy($table, $key, $value, $nr=null, $rev=null) - { - return $this->findByMultiple($table, array($key=>$value), $nr, $rev); - } + foreach ($values as $key=>$value) { + if ($key != 'server' && !(ctype_alnum($value) || is_null($value))) { + $this->myLog->log(LOG_WARNING, "updateBy: attempted to write non-alphanumeric to the database: " . $table . "." . $key . " <= " . $value); + return false; + } + elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) + { + $this->myLog->log(LOG_WARNING, "updateBy: attempted to write invalid URL to the database: " . $table . "." . $key . " <= " . $value); + return false; + } + if (!is_null($value)) $query .= ' ' . $key . "='" . $value . "',"; + else $query .= ' ' . $key . '=NULL,'; + } + if (! $query) { + $this->myLog->log(LOG_DEBUG, "no values to set in query. Not updating DB"); + return true; + } - /** - * Function to do a custom query on database connection - * - * @param string $query Database query - * @return mixed - * - */ - public function customQuery($query) - { - return $this->query($query, true); - } + $query = rtrim($query, ",") . " WHERE " . $k . " = '" . $v . "'"; + // Insert UPDATE statement at beginning + $query = "UPDATE " . $table . " SET " . $query; + + return $this->query($query, false); + } + + /** + * function to update row in database + * + * @param string $table Database table to update row in + * @param int $id Id on row to update + * @param array $values Array with key=>values to update + * @return boolean True on success, otherwise false. + * + */ + public function update($table, $id, $values) + { + return $this->updateBy($table, 'id', $id, $values); + } + + /** + * function to update row in database based on a condition + * + * @param string $table Database table to update row in + * @param string $k Column to select row on + * @param string $v Value to select row on + * @param array $values Array with key=>values to update + * @param string $condition conditional statement + * @return boolean True on success, otherwise false. + * + */ + public function conditionalUpdateBy($table, $k, $v, $values, $condition) + { + if (!ctype_alnum($v) || preg_match('/^[a-zA-Z0-9><=()_ ]*$/', $condition) == 0) + { + $this->myLog->log(LOG_WARNING, "conditionalUpdateBy: attempted to use non-alphanumeric value: " . $v . " - " . $condition); + return false; + } + $query = ""; /* quiet the PHP Notice */ + + foreach ($values as $key=>$value){ + if ($key != 'server' && !is_int($value) && !ctype_alnum($value)) { + $this->myLog->log(LOG_WARNING, "conditionalUpdateBy: attempted to write non-alphanumeric to the database: " . $value); + return false; + } + elseif ($key == 'server' && !filter_var($value, FILTER_VALIDATE_URL)) + { + $this->myLog->log(LOG_WARNING, "conditionalUpdateBy: attempted to write invalid URL to the database: " . $value); + return false; + } + $query = $query . " " . $key . "='" . $value . "',"; + } + if (! $query) { + $this->myLog->log(LOG_DEBUG, "no values to set in query. Not updating DB"); + return true; + } + + $query = rtrim($query, ",") . " WHERE " . $k . " = '" . $v . "' and " . $condition; + // Insert UPDATE statement at beginning + $query = "UPDATE " . $table . " SET " . $query; + + return $this->query($query, false); + } + + /** + * Function to update row in database based on a condition. + * An ID value is passed to select the appropriate column + * + * @param string $table Database table to update row in + * @param int $id Id on row to update + * @param array $values Array with key=>values to update + * @param string $condition conditional statement + * @return boolean True on success, otherwise false. + * + */ + public function conditionalUpdate($table, $id, $values, $condition) + { + return $this->conditionalUpdateBy($table, 'id', $id, $values, $condition); + } + + /** + * function to insert new row in database + * + * @param string $table Database table to update row in + * @param array $values Array with key=>values to update + * @return boolean True on success, otherwise false. + * + */ + public function save($table, $values) + { + $query= 'INSERT INTO ' . $table . " ("; + foreach ($values as $key=>$value){ + if ($key == 'server') { + $v = filter_var($value, FILTER_VALIDATE_URL); + if (!$v) { + $this->myLog->log(LOG_WARNING, "save: bad server URL provided: " . $value); + return false; + } + $value = $v; + } else if ($key == 'info') { + if (preg_match('/[a-zA-Z0-9&_=,]+/', $value) == 0) { + $this->myLog->log(LOG_WARNING, "save: bad info string provided: " . $value); + return false; + } + } else { + if ($value != '' && !is_int($value) && !ctype_alnum($value)) { + $this->myLog->log(LOG_WARNING, "save: attempted to write non-alphanumeric to the database: " . $value); + return false; + } + } + if (!is_null($value)) $query = $query . $key . ","; + } + $query = rtrim($query, ",") . ') VALUES ('; + foreach ($values as $key=>$value){ + if (!is_null($value)) $query = $query . "'" . $value . "',"; + } + $query = rtrim($query, ","); + $query = $query . ")"; + return $this->query($query, false); + } + /** + * helper function to collect last row[s] in database + * + * @param string $table Database table to update row in + * @param int $nr Number of rows to collect. NULL=>inifinity. DEFAULT=1. + * @return mixed Array with values from Db row or 2d-array with multiple rows + or false on failure. + * + */ + public function last($table, $nr=1) + { + return Db::findBy($table, null, null, $nr, 1); + } + + /** + * main function used to get rows from Db table. + * + * @param string $table Database table to update row in + * @param string $key Column to select rows by + * @param string $value Value to select rows by + * @param int $nr Number of rows to collect. NULL=>inifinity. Default=NULL. + * @param int $rev rev=1 indicates order should be reversed. Default=NULL. + * @return mixed Array with values from Db row or 2d-array with multiple rows + * + */ + public function findBy($table, $key, $value, $nr=null, $rev=null) + { + return $this->findByMultiple($table, array($key=>$value), $nr, $rev); + } + + /** + * Function to do a custom query on database connection + * + * @param string $query Database query + * @return mixed + * + */ + public function customQuery($query) + { + return $this->query($query, true); + } } diff --git a/ykval-export b/ykval-export index 8c941f4..7ad5dbb 100755 --- a/ykval-export +++ b/ykval-export @@ -29,9 +29,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set_include_path(implode(PATH_SEPARATOR, array( - get_include_path(), - '/usr/share/yubikey-val', - '/etc/yubico/val', + get_include_path(), + '/usr/share/yubikey-val', + '/etc/yubico/val', ))); require_once 'ykval-config.php'; @@ -44,24 +44,24 @@ $myLog = new Log($logname); $db = Db::GetDatabaseHandle($baseParams, $logname); if (!$db->connect()) { - $myLog->log(LOG_WARNING, "Could not connect to database"); - exit(1); - } + $myLog->log(LOG_WARNING, "Could not connect to database"); + exit(1); +} $result=$db->customQuery("SELECT active, created, modified, yk_publicname, yk_counter, yk_use, yk_low, yk_high, nonce, notes FROM yubikeys ORDER BY yk_publicname"); while($row = $db->fetchArray($result)){ - echo (int)$row['active'] . - "," . $row['created'] . - "," . $row['modified'] . - "," . $row['yk_publicname'] . - "," . $row['yk_counter'] . - "," . $row['yk_use'] . - "," . $row['yk_low'] . - "," . $row['yk_high'] . - "," . $row['nonce'] . - "," . $row['notes'] . - "\n"; - } + echo (int)$row['active'] . + "," . $row['created'] . + "," . $row['modified'] . + "," . $row['yk_publicname'] . + "," . $row['yk_counter'] . + "," . $row['yk_use'] . + "," . $row['yk_low'] . + "," . $row['yk_high'] . + "," . $row['nonce'] . + "," . $row['notes'] . + "\n"; +} $db->closeCursor($result); $db->disconnect(); diff --git a/ykval-export-clients b/ykval-export-clients index a65f200..7860b12 100755 --- a/ykval-export-clients +++ b/ykval-export-clients @@ -44,20 +44,20 @@ $myLog = new Log($logname); $db = Db::GetDatabaseHandle($baseParams, $logname); if (!$db->connect()) { - $myLog->log(LOG_WARNING, "Could not connect to database"); - exit(1); - } + $myLog->log(LOG_WARNING, "Could not connect to database"); + exit(1); +} $result = $db->customQuery("select id, active, created, secret, email, notes, otp from clients order by id"); while($row = $db->fetchArray($result)) { - echo $row['id'] . - "," . (int)$row['active'] . - "," . $row['created'] . - "," . $row['secret'] . - "," . $row['email'] . - "," . $row['notes'] . - "," . $row['otp'] . - "\n"; + echo $row['id'] . + "," . (int)$row['active'] . + "," . $row['created'] . + "," . $row['secret'] . + "," . $row['email'] . + "," . $row['notes'] . + "," . $row['otp'] . + "\n"; } $db->closeCursor($result); diff --git a/ykval-gen-clients b/ykval-gen-clients index 039a36d..071e29b 100755 --- a/ykval-gen-clients +++ b/ykval-gen-clients @@ -37,18 +37,18 @@ set_include_path(implode(PATH_SEPARATOR, array( $options = getopt("h", array("help", "email::", "notes::", "otp::", "urandom")); if(array_key_exists('h', $options) || array_key_exists('help', $options)) { - echo "Usage: ".$argv[0]." [ OPTIONS ] [ num_clients ]\n"; - echo " Unless num_clients is defined, one client will be generated.\n\n"; - echo "Options supported by ".$argv[0]."\n"; - echo " --urandom\n"; - echo " Use /dev/urandom instead of /dev/random as entropy source\n"; - echo " --email=EMAIL\n"; - echo " Sets the e-mail field of the created clients\n"; - echo " --notes=NOTES\n"; - echo " Sets the notes field of the created clients\n"; - echo " --otp=OTP\n"; - echo " Sets the otp field of the created clients\n"; - exit(1); + echo "Usage: ".$argv[0]." [ OPTIONS ] [ num_clients ]\n"; + echo " Unless num_clients is defined, one client will be generated.\n\n"; + echo "Options supported by ".$argv[0]."\n"; + echo " --urandom\n"; + echo " Use /dev/urandom instead of /dev/random as entropy source\n"; + echo " --email=EMAIL\n"; + echo " Sets the e-mail field of the created clients\n"; + echo " --notes=NOTES\n"; + echo " Sets the notes field of the created clients\n"; + echo " --otp=OTP\n"; + echo " Sets the otp field of the created clients\n"; + exit(1); } require_once 'ykval-config.php'; @@ -60,65 +60,65 @@ $myLog = new Log($logname); $db = Db::GetDatabaseHandle($baseParams, $logname); if(!$db->connect()) { - $myLog->log(LOG_WARNING, "Could not connect to database"); - error_log("Could not connect to database"); - exit(1); + $myLog->log(LOG_WARNING, "Could not connect to database"); + error_log("Could not connect to database"); + exit(1); } $count=1; if($last_arg = intval(array_pop($argv))) { - $count = $last_arg; + $count = $last_arg; } $result = $db->customQuery("SELECT id FROM clients ORDER BY id DESC LIMIT 1"); $row = $db->fetchArray($result); $db->closeCursor($result); if($row) { - $next_id = $row['id']+1; + $next_id = $row['id']+1; } else { - $next_id = 1; + $next_id = 1; } $random = array_key_exists('urandom', $options) ? "/dev/urandom" : "/dev/random"; $fh = fopen($random, "r"); if(!$fh) { - die("cannot open ".$random); + die("cannot open ".$random); } for ($i=0; $i<$count; $i++) { - $client_id = $next_id++; - if (!($rnd = fread ($fh, 20))) { - die("cannot read from ".$random); - } - $secret = base64_encode($rnd); + $client_id = $next_id++; + if (!($rnd = fread ($fh, 20))) { + die("cannot read from ".$random); + } + $secret = base64_encode($rnd); - $params = array( - "id" => $client_id, - "active" => 1, - "created" => time(), - "secret" => $secret, - "email" => array_key_exists('email', $options) ? $options['email'] : '', - "notes" => array_key_exists('notes', $options) ? $options['notes'] : '', - "otp" => array_key_exists('otp', $options) ? $options['otp'] : '' - ); + $params = array( + "id" => $client_id, + "active" => 1, + "created" => time(), + "secret" => $secret, + "email" => array_key_exists('email', $options) ? $options['email'] : '', + "notes" => array_key_exists('notes', $options) ? $options['notes'] : '', + "otp" => array_key_exists('otp', $options) ? $options['otp'] : '' + ); - $query="INSERT INTO clients " . - "(id,active,created,secret,email,notes,otp) VALUES " . - "('" . $params["id"] . "', " . - "'" . $params["active"] . "', " . - "'" . $params['created'] . "'," . - "'" . $params['secret'] . "'," . - "'" . $params['email'] . "'," . - "'" . $params['notes'] . "'," . - "'" . $params['otp'] . "')"; + $query="INSERT INTO clients " . + "(id,active,created,secret,email,notes,otp) VALUES " . + "('" . $params["id"] . "', " . + "'" . $params["active"] . "', " . + "'" . $params['created'] . "'," . + "'" . $params['secret'] . "'," . + "'" . $params['email'] . "'," . + "'" . $params['notes'] . "'," . + "'" . $params['otp'] . "')"; - if(!$db->customQuery($query)){ - $myLog->log(LOG_ERR, "Failed to insert new client with query " . $query); - error_log("Failed to insert new client with query " . $query); - exit(1); - } + if(!$db->customQuery($query)){ + $myLog->log(LOG_ERR, "Failed to insert new client with query " . $query); + error_log("Failed to insert new client with query " . $query); + exit(1); + } - echo $client_id.",".$secret."\n"; + echo $client_id.",".$secret."\n"; } fclose($fh); diff --git a/ykval-import b/ykval-import index abebdac..9d03b4c 100755 --- a/ykval-import +++ b/ykval-import @@ -44,80 +44,80 @@ $myLog = new Log($logname); $db = Db::GetDatabaseHandle($baseParams, $logname); if (!$db->connect()) { - $myLog->log(LOG_WARNING, "Could not connect to database"); - error_log("Could not connect to database"); - exit(1); + $myLog->log(LOG_WARNING, "Could not connect to database"); + error_log("Could not connect to database"); + exit(1); } while ($res=fgetcsv(STDIN, 0, ",")) { - if ($res[0]===null || strpos($res[0], '#')===0) - continue; + if ($res[0]===null || strpos($res[0], '#')===0) + continue; - $params=array( - "active"=>$res[0], - "created"=>$res[1], - "modified"=>$res[2], - "yk_publicname"=>$res[3], - "yk_counter"=>$res[4], - "yk_use"=>$res[5], - "yk_low"=>$res[6], - "yk_high"=>$res[7], - "nonce"=>$res[8], - "notes"=>$res[9] - ); + $params=array( + "active"=>$res[0], + "created"=>$res[1], + "modified"=>$res[2], + "yk_publicname"=>$res[3], + "yk_counter"=>$res[4], + "yk_use"=>$res[5], + "yk_low"=>$res[6], + "yk_high"=>$res[7], + "nonce"=>$res[8], + "notes"=>$res[9] + ); - # FIXME - # INSERT first, if duplicate error, UPDATE. + # FIXME + # INSERT first, if duplicate error, UPDATE. - $query="SELECT * FROM yubikeys WHERE yk_publicname='" . $params['yk_publicname'] . "'"; - $result=$db->customQuery($query); + $query="SELECT * FROM yubikeys WHERE yk_publicname='" . $params['yk_publicname'] . "'"; + $result=$db->customQuery($query); - if ($db->rowCount($result)) { - $query="UPDATE yubikeys SET " . - "active='" . $params["active"] . "' " . - ",created='" . $params["created"] . "' " . - ",modified='" . $params["modified"] . "' " . - ",yk_counter='" . $params["yk_counter"] . "' " . - ",yk_use='" . $params["yk_use"] . "' " . - ",yk_low='" . $params["yk_low"] . "' " . - ",yk_high='" . $params["yk_high"] . "' " . - ",nonce='" . $params["nonce"] . "' " . - ",notes='" . $params["notes"] . "' " . - "WHERE yk_publicname='" . $params['yk_publicname'] . "' AND " . - "(".$params['yk_counter'].">yk_counter or (".$params['yk_counter']."=yk_counter and " . - $params['yk_use'] . ">yk_use))"; + if ($db->rowCount($result)) { + $query="UPDATE yubikeys SET " . + "active='" . $params["active"] . "' " . + ",created='" . $params["created"] . "' " . + ",modified='" . $params["modified"] . "' " . + ",yk_counter='" . $params["yk_counter"] . "' " . + ",yk_use='" . $params["yk_use"] . "' " . + ",yk_low='" . $params["yk_low"] . "' " . + ",yk_high='" . $params["yk_high"] . "' " . + ",nonce='" . $params["nonce"] . "' " . + ",notes='" . $params["notes"] . "' " . + "WHERE yk_publicname='" . $params['yk_publicname'] . "' AND " . + "(".$params['yk_counter'].">yk_counter or (".$params['yk_counter']."=yk_counter and " . + $params['yk_use'] . ">yk_use))"; - if(!$db->customQuery($query)) { - $myLog->log(LOG_ERR, "Failed to update yk_publicname with query " . $query); - error_log("Failed to update yk_publicname with query " . $query); - exit(1); + if(!$db->customQuery($query)) { + $myLog->log(LOG_ERR, "Failed to update yk_publicname with query " . $query); + error_log("Failed to update yk_publicname with query " . $query); + exit(1); + } } - } - else { - // We didn't have the yk_publicname in database so we need to do insert instead - $query="INSERT INTO yubikeys " . - "(active,created,modified,yk_publicname,yk_counter,yk_use,yk_low,yk_high,nonce,notes) VALUES " . - "('" . $params["active"] . "', " . - "'" . $params['created'] . "'," . - "'" . $params['modified'] . "'," . - "'" . $params['yk_publicname'] . "'," . - "'" . $params['yk_counter'] . "'," . - "'" . $params['yk_use'] . "'," . - "'" . $params['yk_low'] . "'," . - "'" . $params['yk_high'] . "'," . - "'" . $params['nonce'] . "'," . - "'" . $params['notes'] . "')"; + else { + // We didn't have the yk_publicname in database so we need to do insert instead + $query="INSERT INTO yubikeys " . + "(active,created,modified,yk_publicname,yk_counter,yk_use,yk_low,yk_high,nonce,notes) VALUES " . + "('" . $params["active"] . "', " . + "'" . $params['created'] . "'," . + "'" . $params['modified'] . "'," . + "'" . $params['yk_publicname'] . "'," . + "'" . $params['yk_counter'] . "'," . + "'" . $params['yk_use'] . "'," . + "'" . $params['yk_low'] . "'," . + "'" . $params['yk_high'] . "'," . + "'" . $params['nonce'] . "'," . + "'" . $params['notes'] . "')"; - if (!$db->customQuery($query)) { - $myLog->log(LOG_ERR, "Failed to insert new yk_publicname with query " . $query); - error_log("Failed to insert new yk_publicname with query " . $query); - exit(1); + if (!$db->customQuery($query)) { + $myLog->log(LOG_ERR, "Failed to insert new yk_publicname with query " . $query); + error_log("Failed to insert new yk_publicname with query " . $query); + exit(1); + } } - } - $db->closeCursor($result); + $db->closeCursor($result); } $myLog->log(LOG_NOTICE, "Successfully imported yubikeys to database"); diff --git a/ykval-import-clients b/ykval-import-clients index cd224b6..f79027f 100755 --- a/ykval-import-clients +++ b/ykval-import-clients @@ -44,46 +44,46 @@ $myLog = new Log($logname); $db = Db::GetDatabaseHandle($baseParams, $logname); if (!$db->connect()) { - $myLog->log(LOG_WARNING, "Could not connect to database"); - error_log("Could not connect to database"); - exit(1); - } + $myLog->log(LOG_WARNING, "Could not connect to database"); + error_log("Could not connect to database"); + exit(1); +} while ($res=fgetcsv(STDIN, 0, ",")) { - if($res[0]===null || strpos($res[0], '#')===0) continue; + if($res[0]===null || strpos($res[0], '#')===0) continue; - $params=array("id"=>$res[0], - "active"=>$res[1], - "created"=>$res[2], - "secret"=>$res[3], - "email"=>$res[4], - "notes"=>$res[5], - "otp"=>$res[6]); + $params=array("id"=>$res[0], + "active"=>$res[1], + "created"=>$res[2], + "secret"=>$res[3], + "email"=>$res[4], + "notes"=>$res[5], + "otp"=>$res[6]); - $query="SELECT * FROM clients WHERE id='" . $params['id'] . "'"; - $result=$db->customQuery($query); - if($db->rowCount($result) == 0) { - // We didn't have the id in database so we need to do insert instead - $query="INSERT INTO clients " . - "(id,active,created,secret,email,notes,otp) VALUES " . - "('" . $params["id"] . "', " . - "'" . $params["active"] . "', " . - "'" . $params['created'] . "'," . - "'" . $params['secret'] . "'," . - "'" . $params['email'] . "'," . - "'" . $params['notes'] . "'," . - "'" . $params['otp'] . "')"; + $query="SELECT * FROM clients WHERE id='" . $params['id'] . "'"; + $result=$db->customQuery($query); + if($db->rowCount($result) == 0) { + // We didn't have the id in database so we need to do insert instead + $query="INSERT INTO clients " . + "(id,active,created,secret,email,notes,otp) VALUES " . + "('" . $params["id"] . "', " . + "'" . $params["active"] . "', " . + "'" . $params['created'] . "'," . + "'" . $params['secret'] . "'," . + "'" . $params['email'] . "'," . + "'" . $params['notes'] . "'," . + "'" . $params['otp'] . "')"; - if(!$db->customQuery($query)){ - $myLog->log(LOG_ERR, "Failed to insert new client with query " . $query); - error_log("Failed to insert new client with query " . $query); - exit(1); + if(!$db->customQuery($query)){ + $myLog->log(LOG_ERR, "Failed to insert new client with query " . $query); + error_log("Failed to insert new client with query " . $query); + exit(1); + } } - } - $db->closeCursor($result); - } + $db->closeCursor($result); +} $myLog->log(LOG_NOTICE, "Successfully imported clients to database"); diff --git a/ykval-log-verify.php b/ykval-log-verify.php index 927bc4d..9fec5ba 100644 --- a/ykval-log-verify.php +++ b/ykval-log-verify.php @@ -31,153 +31,153 @@ require_once 'ykval-common.php'; class LogVerify { - public $format = NULL; + public $format = NULL; - private $fields = array( - 'time_start' => NULL, - 'time_end' => NULL, - 'time_taken' => NULL, - 'ip' => NULL, - 'client' => NULL, - 'public_id' => NULL, - 'otp' => NULL, - 'status' => NULL, - 'nonce' => NULL, - 'signed' => NULL, - 'counter' => NULL, - 'low' => NULL, - 'high' => NULL, - 'use' => NULL, - 'tls' => NULL, - 'protocol' => NULL, - 'sl' => NULL, - 'timeout' => NULL, - ); + private $fields = array( + 'time_start' => NULL, + 'time_end' => NULL, + 'time_taken' => NULL, + 'ip' => NULL, + 'client' => NULL, + 'public_id' => NULL, + 'otp' => NULL, + 'status' => NULL, + 'nonce' => NULL, + 'signed' => NULL, + 'counter' => NULL, + 'low' => NULL, + 'high' => NULL, + 'use' => NULL, + 'tls' => NULL, + 'protocol' => NULL, + 'sl' => NULL, + 'timeout' => NULL, + ); - /** - * Set field value. - * - * @param $name string - * @param $value mixed - * @return bool - */ - public function set($name, $value) - { - // not settable from outside - if ($name === 'time_end' || $name === 'time_taken') - return false; + /** + * Set field value. + * + * @param $name string + * @param $value mixed + * @return bool + */ + public function set($name, $value) + { + // not settable from outside + if ($name === 'time_end' || $name === 'time_taken') + return false; - if (array_key_exists($name, $this->fields) === FALSE) - return false; + if (array_key_exists($name, $this->fields) === FALSE) + return false; - $this->fields[$name] = $value; - return true; - } + $this->fields[$name] = $value; + return true; + } - /** - * Write verify request log line to syslog. - * - * @return bool - */ - public function write() - { - if ($this->format === NULL) - return false; + /** + * Write verify request log line to syslog. + * + * @return bool + */ + public function write() + { + if ($this->format === NULL) + return false; - $values = array(); - foreach ($this->sanitized() as $key => $val) - { - $values['%'.$key.'%'] = $val; - } + $values = array(); + foreach ($this->sanitized() as $key => $val) + { + $values['%'.$key.'%'] = $val; + } - $message = strtr($this->format, $values); + $message = strtr($this->format, $values); - if (!is_string($message)) - return false; + if (!is_string($message)) + return false; - return syslog(LOG_INFO, $message); - } + return syslog(LOG_INFO, $message); + } - /** - * Sanitize untrusted values from clients before writing them to syslog. - * - * P.S. signed, status, time_start, tls are assumed safe, - * since they are set internally. - * - * @return array sanitized $this->fields - */ - private function sanitized() - { - $a = $this->fields; + /** + * Sanitize untrusted values from clients before writing them to syslog. + * + * P.S. signed, status, time_start, tls are assumed safe, + * since they are set internally. + * + * @return array sanitized $this->fields + */ + private function sanitized() + { + $a = $this->fields; - if (preg_match('/^[cbdefghijklnrtuv]+$/', $a['public_id']) !== 1 - || strlen($a['public_id']) < 1 - || strlen($a['public_id']) > (OTP_MAX_LEN - TOKEN_LEN)) - { - $a['public_id'] = '-'; - } + if (preg_match('/^[cbdefghijklnrtuv]+$/', $a['public_id']) !== 1 + || strlen($a['public_id']) < 1 + || strlen($a['public_id']) > (OTP_MAX_LEN - TOKEN_LEN)) + { + $a['public_id'] = '-'; + } - if (preg_match('/^[cbdefghijklnrtuv]+$/', $a['otp']) !== 1 - || strlen($a['otp']) < TOKEN_LEN - || strlen($a['otp']) > OTP_MAX_LEN) - { - $a['otp'] = '-'; - } + if (preg_match('/^[cbdefghijklnrtuv]+$/', $a['otp']) !== 1 + || strlen($a['otp']) < TOKEN_LEN + || strlen($a['otp']) > OTP_MAX_LEN) + { + $a['otp'] = '-'; + } - if (preg_match('/^[0-9]+$/', $a['client']) !== 1) - $a['client'] = '-'; + if (preg_match('/^[0-9]+$/', $a['client']) !== 1) + $a['client'] = '-'; - if (filter_var($a['ip'], FILTER_VALIDATE_IP) === FALSE) - $a['ip'] = '-'; + if (filter_var($a['ip'], FILTER_VALIDATE_IP) === FALSE) + $a['ip'] = '-'; - if (is_int($a['counter']) === FALSE) - $a['counter'] = '-'; + if (is_int($a['counter']) === FALSE) + $a['counter'] = '-'; - if (is_int($a['low']) === FALSE) - $a['low'] = '-'; + if (is_int($a['low']) === FALSE) + $a['low'] = '-'; - if (is_int($a['high']) === FALSE) - $a['high'] = '-'; + if (is_int($a['high']) === FALSE) + $a['high'] = '-'; - if (is_int($a['use']) === FALSE) - $a['use'] = '-'; + if (is_int($a['use']) === FALSE) + $a['use'] = '-'; - if (preg_match('/^[a-zA-Z0-9]{16,40}$/', $a['nonce']) !== 1) - $a['nonce'] = '-'; + if (preg_match('/^[a-zA-Z0-9]{16,40}$/', $a['nonce']) !== 1) + $a['nonce'] = '-'; - if (is_float($a['protocol']) === TRUE) - $a['protocol'] = sprintf('%.1f', $a['protocol']); - else - $a['protocol'] = '-'; + if (is_float($a['protocol']) === TRUE) + $a['protocol'] = sprintf('%.1f', $a['protocol']); + else + $a['protocol'] = '-'; - if ( $a['sl'] !== 'fast' - && $a['sl'] !== 'secure' - && (preg_match('/^[0-9]{1,3}$/', $a['sl']) !== 1 || (((int) $a['sl']) > 100))) - { - $a['sl'] = '-'; - } + if ( $a['sl'] !== 'fast' + && $a['sl'] !== 'secure' + && (preg_match('/^[0-9]{1,3}$/', $a['sl']) !== 1 || (((int) $a['sl']) > 100))) + { + $a['sl'] = '-'; + } - if (preg_match('/^[0-9]+$/', $a['timeout']) !== 1) - $a['timeout'] = '-'; + if (preg_match('/^[0-9]+$/', $a['timeout']) !== 1) + $a['timeout'] = '-'; - $start = explode(' ', $a['time_start']); - $start_msec = $start[0]; - $start_sec = $start[1]; - $start = bcadd($start_sec, $start_msec, 8); - unset($start_sec, $start_msec); + $start = explode(' ', $a['time_start']); + $start_msec = $start[0]; + $start_sec = $start[1]; + $start = bcadd($start_sec, $start_msec, 8); + unset($start_sec, $start_msec); - $end = explode(' ', microtime()); - $end_msec = $end[0]; - $end_sec = $end[1]; - $end = bcadd($end_sec, $end_msec, 8); - unset($end_sec, $end_msec); + $end = explode(' ', microtime()); + $end_msec = $end[0]; + $end_sec = $end[1]; + $end = bcadd($end_sec, $end_msec, 8); + unset($end_sec, $end_msec); - $taken = bcsub($end, $start, 8); + $taken = bcsub($end, $start, 8); - $a['time_start'] = $start; - $a['time_end'] = $end; - $a['time_taken'] = $taken; + $a['time_start'] = $start; + $a['time_end'] = $end; + $a['time_taken'] = $taken; - return $a; - } + return $a; + } } diff --git a/ykval-log.php b/ykval-log.php index 20502f3..0c81565 100644 --- a/ykval-log.php +++ b/ykval-log.php @@ -29,58 +29,58 @@ class Log { - // request logger object - public $request = NULL; + // request logger object + public $request = NULL; - private $log_levels = array( - LOG_EMERG => 'LOG_EMERG', - LOG_ALERT => 'LOG_ALERT', - LOG_CRIT => 'LOG_CRIT', - LOG_ERR => 'LOG_ERR', - LOG_WARNING => 'LOG_WARNING', - LOG_NOTICE => 'LOG_NOTICE', - LOG_INFO => 'LOG_INFO', - LOG_DEBUG => 'LOG_DEBUG', - ); + private $log_levels = array( + LOG_EMERG => 'LOG_EMERG', + LOG_ALERT => 'LOG_ALERT', + LOG_CRIT => 'LOG_CRIT', + LOG_ERR => 'LOG_ERR', + LOG_WARNING => 'LOG_WARNING', + LOG_NOTICE => 'LOG_NOTICE', + LOG_INFO => 'LOG_INFO', + LOG_DEBUG => 'LOG_DEBUG', + ); - private $fields = array(); + private $fields = array(); - public function __construct ($name = 'ykval') - { - $this->name = $name; + public function __construct ($name = 'ykval') + { + $this->name = $name; - openlog('ykval', LOG_PID, LOG_LOCAL0); - } + openlog('ykval', LOG_PID, LOG_LOCAL0); + } - public function addField ($name, $value) - { - $this->fields[$name] = $value; - } + public function addField ($name, $value) + { + $this->fields[$name] = $value; + } - public function log ($priority, $message, $extra = NULL) - { - $prefix = ''; - foreach ($this->fields as $val) - $prefix .= "[$val] "; + public function log ($priority, $message, $extra = NULL) + { + $prefix = ''; + foreach ($this->fields as $val) + $prefix .= "[$val] "; - $suffix = ''; - if (is_array($extra)) { - foreach($extra as $key => $value) { - if (is_array($value)) { - $value = implode(':', $value); - } - $suffix .= " $key=$value "; - } - } + $suffix = ''; + if (is_array($extra)) { + foreach($extra as $key => $value) { + if (is_array($value)) { + $value = implode(':', $value); + } + $suffix .= " $key=$value "; + } + } - $message = $prefix . $message . $suffix; + $message = $prefix . $message . $suffix; - $message = implode(':', array( - $this->log_levels[$priority], - $this->name, - $message - )); + $message = implode(':', array( + $this->log_levels[$priority], + $this->name, + $message + )); - syslog($priority, $message); - } + syslog($priority, $message); + } } diff --git a/ykval-munin-ksmlatency.php b/ykval-munin-ksmlatency.php index 450121c..adf3a47 100755 --- a/ykval-munin-ksmlatency.php +++ b/ykval-munin-ksmlatency.php @@ -1,6 +1,5 @@ #!/usr/bin/php 0) - { - echo "yes\n"; - exit(0); - } + if (is_array($urls) && count($urls) > 0) + { + echo "yes\n"; + exit(0); + } - echo "no (sync pool not configured)\n"; - exit(0); + echo "no (sync pool not configured)\n"; + exit(0); } if (($endpoints = endpoints($urls)) === FALSE) { - echo "Cannot parse URLs from sync pool list\n"; - exit(1); + echo "Cannot parse URLs from sync pool list\n"; + exit(1); } if ($argc == 2 && strcmp($argv[1], 'config') == 0) { - echo "graph_title YK-VAL queue size\n"; - echo "graph_vlabel sync requests in queue\n"; - echo "graph_category ykval\n"; + echo "graph_title YK-VAL queue size\n"; + echo "graph_vlabel sync requests in queue\n"; + echo "graph_category ykval\n"; - foreach ($endpoints as $endpoint) - { - list ($internal, $label, $url) = $endpoint; + foreach ($endpoints as $endpoint) + { + list ($internal, $label, $url) = $endpoint; - echo "${internal}_queuelength.label sync ${label}\n"; - echo "${internal}_queuelength.draw AREASTACK\n"; - echo "${internal}_queuelength.type GAUGE\n"; - } + echo "${internal}_queuelength.label sync ${label}\n"; + echo "${internal}_queuelength.draw AREASTACK\n"; + echo "${internal}_queuelength.type GAUGE\n"; + } - exit(0); + exit(0); } $sync = new SyncLib('ykval-synclib:munin'); @@ -82,14 +81,14 @@ $queuelength = $sync->getQueueLengthByServer(); foreach ($endpoints as $endpoint) { - list ($internal, $label, $url) = $endpoint; + list ($internal, $label, $url) = $endpoint; - $count = 0; + $count = 0; - if (array_key_exists($url, $queuelength)) - $count = $queuelength[$url]; + if (array_key_exists($url, $queuelength)) + $count = $queuelength[$url]; - echo "${internal}_queuelength.value $count\n"; + echo "${internal}_queuelength.value $count\n"; } exit(0); diff --git a/ykval-munin-vallatency.php b/ykval-munin-vallatency.php index 7de0abe..2d4c273 100755 --- a/ykval-munin-vallatency.php +++ b/ykval-munin-vallatency.php @@ -29,67 +29,66 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set_include_path(implode(PATH_SEPARATOR, array( - get_include_path(), - '/usr/share/yubikey-val', - '/etc/yubico/val', + get_include_path(), + '/usr/share/yubikey-val', + '/etc/yubico/val', ))); require_once 'ykval-config.php'; require_once 'ykval-common.php'; - $urls = $baseParams['__YKVAL_SYNC_POOL__']; if ($argc == 2 && strcmp($argv[1], 'autoconf') == 0) { - if (is_array($urls) && count($urls) > 0) - { - echo "yes\n"; - exit(0); - } + if (is_array($urls) && count($urls) > 0) + { + echo "yes\n"; + exit(0); + } - echo "no (sync pool not configured)\n"; - exit(0); + echo "no (sync pool not configured)\n"; + exit(0); } if (($endpoints = endpoints($urls)) === FALSE) { - echo "Cannot parse URLs from sync pool list\n"; - exit(1); + echo "Cannot parse URLs from sync pool list\n"; + exit(1); } if ($argc == 2 && strcmp($argv[1], 'config') == 0) { - echo "multigraph ykval_vallatency\n"; - echo "graph_title VAL latency\n"; - echo "graph_vlabel Average VAL Latency (seconds)\n"; - echo "graph_category ykval\n"; - echo "graph_width 400\n"; + echo "multigraph ykval_vallatency\n"; + echo "graph_title VAL latency\n"; + echo "graph_vlabel Average VAL Latency (seconds)\n"; + echo "graph_category ykval\n"; + echo "graph_width 400\n"; - foreach ($endpoints as $endpoint) - { - list($internal, $label, $url) = $endpoint; + foreach ($endpoints as $endpoint) + { + list($internal, $label, $url) = $endpoint; - echo "${internal}_avgwait.label ${label}\n"; - echo "${internal}_avgwait.type GAUGE\n"; - echo "${internal}_avgwait.info Average VAL round-trip latency\n"; - echo "${internal}_avgwait.min 0\n"; - echo "${internal}_avgwait.draw LINE1\n"; - } + echo "${internal}_avgwait.label ${label}\n"; + echo "${internal}_avgwait.type GAUGE\n"; + echo "${internal}_avgwait.info Average VAL round-trip latency\n"; + echo "${internal}_avgwait.min 0\n"; + echo "${internal}_avgwait.draw LINE1\n"; + } - exit(0); + exit(0); } echo "multigraph ykval_vallatency\n"; foreach ($endpoints as $endpoint) { - list ($internal, $label, $url) = $endpoint; + list ($internal, $label, $url) = $endpoint; - if (($total_time = total_time($url)) === FALSE) - $total_time = 'error'; + if (($total_time = total_time($url)) === FALSE) + $total_time = 'error'; - echo "${internal}_avgwait.value ${total_time}\n"; + echo "${internal}_avgwait.value ${total_time}\n"; } exit(0); diff --git a/ykval-munin-yubikeystats.php b/ykval-munin-yubikeystats.php index 0d0a76a..214b512 100755 --- a/ykval-munin-yubikeystats.php +++ b/ykval-munin-yubikeystats.php @@ -29,9 +29,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set_include_path(implode(PATH_SEPARATOR, array( - get_include_path(), - '/usr/share/yubikey-val', - '/etc/yubico/val', + get_include_path(), + '/usr/share/yubikey-val', + '/etc/yubico/val', ))); require_once 'ykval-config.php'; @@ -39,62 +39,62 @@ require_once 'ykval-db.php'; if ($argc == 2 && strcmp($argv[1], "autoconf") == 0) { - print "yes\n"; - exit(0); + print "yes\n"; + exit(0); } if ($argc == 2 && strcmp($argv[1], "config") == 0) { - echo "graph_title YK-VAL YubiKey stats\n"; - echo "graph_vlabel Known YubiKeys\n"; - echo "graph_category ykval\n"; + echo "graph_title YK-VAL YubiKey stats\n"; + echo "graph_vlabel Known YubiKeys\n"; + echo "graph_category ykval\n"; - echo "yubikeys_enabled.label Enabled YubiKeys\n"; - echo "yubikeys_enabled.draw AREA\n"; + echo "yubikeys_enabled.label Enabled YubiKeys\n"; + echo "yubikeys_enabled.draw AREA\n"; - echo "yubikeys_disabled.label Disabled YubiKeys\n"; - echo "yubikeys_disabled.draw STACK\n"; + echo "yubikeys_disabled.label Disabled YubiKeys\n"; + echo "yubikeys_disabled.draw STACK\n"; - echo "yubikeys_1month.label YubiKeys seen last month\n"; - echo "yubikeys_1month.draw LINE2\n"; + echo "yubikeys_1month.label YubiKeys seen last month\n"; + echo "yubikeys_1month.draw LINE2\n"; - echo "clients_enabled.label Enabled validation clients\n"; - echo "clients_enabled.draw LINE2\n"; + echo "clients_enabled.label Enabled validation clients\n"; + echo "clients_enabled.draw LINE2\n"; - echo "clients_disabled.label Disabled validation clients\n"; - echo "clients_disabled.draw LINE2\n"; + echo "clients_disabled.label Disabled validation clients\n"; + echo "clients_disabled.draw LINE2\n"; - exit(0); + exit(0); } $db = Db::GetDatabaseHandle($baseParams, 'ykval-munin-yubikeystats'); if (!$db->connect()) - logdie($myLog, 'ERROR Database connect error (1)'); + logdie($myLog, 'ERROR Database connect error (1)'); function get_count($db, $table, $conditions) { - $res = $db->customQuery("SELECT count(1) as count FROM $table WHERE $conditions"); + $res = $db->customQuery("SELECT count(1) as count FROM $table WHERE $conditions"); - if ($res) - { - $r = $res->fetch(PDO::FETCH_ASSOC); - return $r['count']; - } + if ($res) + { + $r = $res->fetch(PDO::FETCH_ASSOC); + return $r['count']; + } - return Null; + return Null; } if ($count = get_count($db, 'yubikeys', 'active=true')) - echo "yubikeys_enabled.value $count\n"; + echo "yubikeys_enabled.value $count\n"; if ($count = get_count($db, 'yubikeys', 'active=false')) - echo "yubikeys_disabled.value $count\n"; + echo "yubikeys_disabled.value $count\n"; if ($count = get_count($db, 'yubikeys', 'modified >= ' . (time() - (31 * 86400)))) - echo "yubikeys_1month.value $count\n"; + echo "yubikeys_1month.value $count\n"; if ($count = get_count($db, 'clients', 'active=true')) - echo "clients_enabled.value $count\n"; + echo "clients_enabled.value $count\n"; if ($count = get_count($db, 'clients', 'active=false')) - echo "clients_disabled.value $count\n"; + echo "clients_disabled.value $count\n"; diff --git a/ykval-nagios-queuelength.php b/ykval-nagios-queuelength.php index 4f12c6f..dac8fea 100755 --- a/ykval-nagios-queuelength.php +++ b/ykval-nagios-queuelength.php @@ -29,9 +29,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set_include_path(implode(PATH_SEPARATOR, array( - get_include_path(), - '/usr/share/yubikey-val', - '/etc/yubico/val', + get_include_path(), + '/usr/share/yubikey-val', + '/etc/yubico/val', ))); require_once 'ykval-synclib.php'; @@ -39,8 +39,8 @@ require_once 'ykval-config.php'; require_once 'ykval-log.php'; if ($argc != 3) { - print "warning and critical levels have to be given on commandline\n"; - exit (3); + print "warning and critical levels have to be given on commandline\n"; + exit (3); } $warning = $argv[1]; @@ -53,12 +53,12 @@ $len = $sync->getQueueLength (); $message = "Queue length is $len"; if($len > $critical) { - print("CRITICAL: $message\n"); - exit (2); + print("CRITICAL: $message\n"); + exit (2); } elseif($len > $warning) { - print("WARNING: $message\n"); - exit (1); + print("WARNING: $message\n"); + exit (1); } else { - print("OK: $message\n"); - exit (0); + print("OK: $message\n"); + exit (0); } diff --git a/ykval-queue b/ykval-queue index d1a2fb3..fa3dc1c 100755 --- a/ykval-queue +++ b/ykval-queue @@ -56,7 +56,7 @@ if ($sl->getNumberOfServers() === 0 && $sl->getQueueLength() === 0) do { $start = time(); $sl->reSync($baseParams['__YKVAL_SYNC_OLD_LIMIT__'], - $baseParams['__YKVAL_SYNC_RESYNC_TIMEOUT__']); + $baseParams['__YKVAL_SYNC_RESYNC_TIMEOUT__']); $duration = time() - $start; $sleep_time = max($baseParams['__YKVAL_SYNC_INTERVAL__'] - $duration, 0); } while(sleep($sleep_time)==0); diff --git a/ykval-resync.php b/ykval-resync.php index 6b5cbca..a806140 100644 --- a/ykval-resync.php +++ b/ykval-resync.php @@ -39,39 +39,39 @@ $myLog = new Log('ykval-resync'); $myLog->addField('ip', $_SERVER['REMOTE_ADDR']); if (!in_array ($_SERVER["REMOTE_ADDR"], $baseParams['__YKRESYNC_IPS__'])) { - logdie($myLog, "ERROR Authorization failed (logged ". $_SERVER["REMOTE_ADDR"] .")"); + logdie($myLog, "ERROR Authorization failed (logged ". $_SERVER["REMOTE_ADDR"] .")"); } # Parse input $yk = $_REQUEST["yk"]; if (!$yk) { - logdie($myLog, "ERROR Missing parameter"); + logdie($myLog, "ERROR Missing parameter"); } if (!($yk == "all" || is_pubid($yk))) { - logdie($myLog, "ERROR Unknown yk value: $yk"); + logdie($myLog, "ERROR Unknown yk value: $yk"); } $myLog->addField('yk', $yk); # Connect to db $db = Db::GetDatabaseHandle($baseParams, 'ykval-resync'); if (!$db->connect()) { - logdie($myLog, 'ERROR Database connect error (1)'); + logdie($myLog, 'ERROR Database connect error (1)'); } if($yk == "all") { - # Get all keys - $res = $db->customQuery("SELECT yk_publicname FROM yubikeys WHERE active = true"); - while($r = $db->fetchArray($res)) { - $yubikeys[] = $r['yk_publicname']; - } - $db->closeCursor($res); + # Get all keys + $res = $db->customQuery("SELECT yk_publicname FROM yubikeys WHERE active = true"); + while($r = $db->fetchArray($res)) { + $yubikeys[] = $r['yk_publicname']; + } + $db->closeCursor($res); } else { - # Check if key exists - $r = $db->findBy('yubikeys', 'yk_publicname', $yk, 1); - if (!$r) { - logdie($myLog, "ERROR Unknown yubikey: $yk"); - } - $yubikeys = array($yk); + # Check if key exists + $r = $db->findBy('yubikeys', 'yk_publicname', $yk, 1); + if (!$r) { + logdie($myLog, "ERROR Unknown yubikey: $yk"); + } + $yubikeys = array($yk); } /* Initialize the sync library. */ @@ -80,21 +80,21 @@ $sync->addField('ip', $_SERVER['REMOTE_ADDR']); $sync->addField('yk', $yk); if (! $sync->isConnected()) { - logdie($myLog, 'ERROR Database connect error (2)'); + logdie($myLog, 'ERROR Database connect error (2)'); } foreach($yubikeys as $key) { - if (($localParams = $sync->getLocalParams($key)) === FALSE) { - logdie($myLog, 'ERROR Invalid Yubikey ' . $key); - } + if (($localParams = $sync->getLocalParams($key)) === FALSE) { + logdie($myLog, 'ERROR Invalid Yubikey ' . $key); + } - $localParams['otp'] = $key . str_repeat('c', 32); // Fake an OTP, only used for logging. - $myLog->log(LOG_DEBUG, "Auth data:", $localParams); + $localParams['otp'] = $key . str_repeat('c', 32); // Fake an OTP, only used for logging. + $myLog->log(LOG_DEBUG, "Auth data:", $localParams); - /* Queue sync request */ - if (!$sync->queue($localParams, $localParams)) { - logdie($myLog, 'ERROR Failed resync'); - } + /* Queue sync request */ + if (!$sync->queue($localParams, $localParams)) { + logdie($myLog, 'ERROR Failed resync'); + } } # We are done diff --git a/ykval-revoke.php b/ykval-revoke.php index 6cd77f7..84cbaed 100644 --- a/ykval-revoke.php +++ b/ykval-revoke.php @@ -38,38 +38,38 @@ $myLog = new Log('ykval-revoke'); $myLog->addField('ip', $_SERVER['REMOTE_ADDR']); if (!in_array ($_SERVER["REMOTE_ADDR"], $baseParams['__YKREV_IPS__'])) { - logdie($myLog, "ERROR Authorization failed (logged ". $_SERVER["REMOTE_ADDR"] .")"); + logdie($myLog, "ERROR Authorization failed (logged ". $_SERVER["REMOTE_ADDR"] .")"); } # Parse input $yk = $_REQUEST["yk"]; $do = $_REQUEST["do"]; if (!$yk || !$do) { - logdie($myLog, "ERROR Missing parameter"); + logdie($myLog, "ERROR Missing parameter"); } if (!is_pubid($yk)) { - logdie($myLog, "ERROR Unknown yk value: $yk"); + logdie($myLog, "ERROR Unknown yk value: $yk"); } if ($do != "enable" && $do != "disable") { - logdie($myLog, "ERROR Unknown do value: $do"); + logdie($myLog, "ERROR Unknown do value: $do"); } # Connect to db $db = Db::GetDatabaseHandle($baseParams, 'ykval-revoke'); if (!$db->connect()) { - logdie($myLog, "ERROR Database connect error"); + logdie($myLog, "ERROR Database connect error"); } # Check if key exists $r = $db->findBy('yubikeys', 'yk_publicname', $yk, 1); if (!$r) { - logdie($myLog, "ERROR Unknown yubikey: $yk"); + logdie($myLog, "ERROR Unknown yubikey: $yk"); } # Enable/Disable the yubikey if (!$db->updateBy('yubikeys', 'yk_publicname', $yk, - array('active'=>($do == "enable" ? "1" : "0")))) { - logdie($myLog, "ERROR Could not $do for $yk"); + array('active'=>($do == "enable" ? "1" : "0")))) { + logdie($myLog, "ERROR Could not $do for $yk"); } # We are done diff --git a/ykval-sync.php b/ykval-sync.php index 8cf2b03..987e496 100644 --- a/ykval-sync.php +++ b/ykval-sync.php @@ -43,43 +43,43 @@ $myLog->log(LOG_DEBUG, "Received request from $ipaddr"); if (empty($_SERVER['QUERY_STRING'])) { - sendResp(S_MISSING_PARAMETER, $myLog); + sendResp(S_MISSING_PARAMETER, $myLog); } // verify request sent by whitelisted address if (in_array($ipaddr, $allowed, TRUE) === FALSE) { - $myLog->log(LOG_NOTICE, "Operation not allowed from IP $ipaddr"); - $myLog->log(LOG_DEBUG, "Remote IP $ipaddr not listed in allowed sync pool : " . implode(', ', $allowed)); - sendResp(S_OPERATION_NOT_ALLOWED, $myLog); + $myLog->log(LOG_NOTICE, "Operation not allowed from IP $ipaddr"); + $myLog->log(LOG_DEBUG, "Remote IP $ipaddr not listed in allowed sync pool : " . implode(', ', $allowed)); + sendResp(S_OPERATION_NOT_ALLOWED, $myLog); } // define requirements on protocol $syncParams = array( - 'modified' => NULL, - 'otp' => NULL, - 'nonce' => NULL, - 'yk_publicname' => NULL, - 'yk_counter' => NULL, - 'yk_use' => NULL, - 'yk_high' => NULL, - 'yk_low' => NULL + 'modified' => NULL, + 'otp' => NULL, + 'nonce' => NULL, + 'yk_publicname' => NULL, + 'yk_counter' => NULL, + 'yk_use' => NULL, + 'yk_high' => NULL, + 'yk_low' => NULL ); // extract values from HTTP request $tmp_log = 'Received '; foreach ($syncParams as $param => $value) { - $value = getHttpVal($param, NULL, $_GET); + $value = getHttpVal($param, NULL, $_GET); - if ($value == NULL) - { - $myLog->log(LOG_NOTICE, "Received request with parameter[s] ($param) missing value"); - sendResp(S_MISSING_PARAMETER, $myLog); - } + if ($value == NULL) + { + $myLog->log(LOG_NOTICE, "Received request with parameter[s] ($param) missing value"); + sendResp(S_MISSING_PARAMETER, $myLog); + } - $syncParams[$param] = $value; - $tmp_log .= "$param=$value "; + $syncParams[$param] = $value; + $tmp_log .= "$param=$value "; } $myLog->log(LOG_INFO, $tmp_log); @@ -89,7 +89,7 @@ $sync->addField('ip', $ipaddr); if (! $sync->isConnected()) { - sendResp(S_BACKEND_ERROR, $myLog); + sendResp(S_BACKEND_ERROR, $myLog); } // at this point we should have the otp so let's add it to the logging module @@ -98,34 +98,34 @@ $myLog->addField('otp', $syncParams['otp']); // Verify correctness of numeric input parameters foreach (array('modified','yk_counter', 'yk_use', 'yk_high', 'yk_low') as $param) { - // -1 is valid except for modified - if ($param !== 'modified' && $syncParams[$param] === '-1') - continue; + // -1 is valid except for modified + if ($param !== 'modified' && $syncParams[$param] === '-1') + continue; - // [0-9]+ - if ($syncParams[$param] !== '' && ctype_digit($syncParams[$param])) - continue; + // [0-9]+ + if ($syncParams[$param] !== '' && ctype_digit($syncParams[$param])) + continue; - $myLog->log(LOG_NOTICE, "Input parameters $param not correct"); - sendResp(S_MISSING_PARAMETER, $myLog); + $myLog->log(LOG_NOTICE, "Input parameters $param not correct"); + sendResp(S_MISSING_PARAMETER, $myLog); } // Verify correctness of OTP input if (!is_otp($syncParams['otp'])) { - $myLog->log(LOG_NOTICE, "Input parameter " . $syncParams['otp'] . " not correct"); - sendResp(S_MISSING_PARAMETER, $myLog); + $myLog->log(LOG_NOTICE, "Input parameter " . $syncParams['otp'] . " not correct"); + sendResp(S_MISSING_PARAMETER, $myLog); } // Verify correctness of pubid input if (!is_pubid($syncParams['yk_publicname'])) { - $myLog->log(LOG_NOTICE, "Input parameter " . $syncParams['yk_publicname'] . " not correct"); - sendResp(S_MISSING_PARAMETER, $myLog); + $myLog->log(LOG_NOTICE, "Input parameter " . $syncParams['yk_publicname'] . " not correct"); + sendResp(S_MISSING_PARAMETER, $myLog); } // Verify correctness of nonce input if (!is_nonce($syncParams['nonce'])) { - $myLog->log(LOG_NOTICE, "Input parameter " . $syncParams['nonce'] . " not correct"); - sendResp(S_MISSING_PARAMETER, $myLog); + $myLog->log(LOG_NOTICE, "Input parameter " . $syncParams['nonce'] . " not correct"); + sendResp(S_MISSING_PARAMETER, $myLog); } // get local counter data @@ -133,8 +133,8 @@ $sync->addField('otp', $syncParams['otp']); $yk_publicname = $syncParams['yk_publicname']; if (($localParams = $sync->getLocalParams($yk_publicname)) === FALSE) { - $myLog->log(LOG_NOTICE, "Invalid Yubikey $yk_publicname"); - sendResp(S_BACKEND_ERROR, $myLog); + $myLog->log(LOG_NOTICE, "Invalid Yubikey $yk_publicname"); + sendResp(S_BACKEND_ERROR, $myLog); } // conditional update local database @@ -145,60 +145,60 @@ $myLog->log(LOG_DEBUG, 'Sync request params ', $syncParams); if ($sync->countersHigherThan($localParams, $syncParams)) { - $myLog->log(LOG_WARNING, 'Remote server out of sync.'); + $myLog->log(LOG_WARNING, 'Remote server out of sync.'); } if ($sync->countersEqual($localParams, $syncParams)) { - if ($syncParams['modified'] == $localParams['modified'] - && $syncParams['nonce'] == $localParams['nonce']) - { - /** - * This is not an error. When the remote server received an OTP to verify, it would - * have sent out sync requests immediately. When the required number of responses had - * been received, the current implementation discards all additional responses (to - * return the result to the client as soon as possible). If our response sent last - * time was discarded, we will end up here when the background ykval-queue processes - * the sync request again. - */ - $myLog->log(LOG_INFO, 'Sync request unnecessarily sent'); - } + if ($syncParams['modified'] == $localParams['modified'] + && $syncParams['nonce'] == $localParams['nonce']) + { + /** + * This is not an error. When the remote server received an OTP to verify, it would + * have sent out sync requests immediately. When the required number of responses had + * been received, the current implementation discards all additional responses (to + * return the result to the client as soon as possible). If our response sent last + * time was discarded, we will end up here when the background ykval-queue processes + * the sync request again. + */ + $myLog->log(LOG_INFO, 'Sync request unnecessarily sent'); + } - if ($syncParams['modified'] != $localParams['modified'] - && $syncParams['nonce'] == $localParams['nonce']) - { - $deltaModified = $syncParams['modified'] - $localParams['modified']; + if ($syncParams['modified'] != $localParams['modified'] + && $syncParams['nonce'] == $localParams['nonce']) + { + $deltaModified = $syncParams['modified'] - $localParams['modified']; - if ($deltaModified < -1 || $deltaModified > 1) - { - $myLog->log(LOG_WARNING, "We might have a replay. 2 events at different times have generated the same counters. The time difference is $deltaModified seconds"); - } - } + if ($deltaModified < -1 || $deltaModified > 1) + { + $myLog->log(LOG_WARNING, "We might have a replay. 2 events at different times have generated the same counters. The time difference is $deltaModified seconds"); + } + } - if ($syncParams['nonce'] != $localParams['nonce']) - { - $myLog->log(LOG_WARNING, 'Remote server has received a request to validate an already validated OTP'); - } + if ($syncParams['nonce'] != $localParams['nonce']) + { + $myLog->log(LOG_WARNING, 'Remote server has received a request to validate an already validated OTP'); + } } 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, $myLog); + /** + * 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, $myLog); } $extra = array( - 'modified' => $localParams['modified'], - 'nonce' => $localParams['nonce'], - 'yk_publicname' => $yk_publicname, - 'yk_counter' => $localParams['yk_counter'], - 'yk_use' => $localParams['yk_use'], - 'yk_high' => $localParams['yk_high'], - 'yk_low' => $localParams['yk_low'] + 'modified' => $localParams['modified'], + 'nonce' => $localParams['nonce'], + 'yk_publicname' => $yk_publicname, + 'yk_counter' => $localParams['yk_counter'], + 'yk_use' => $localParams['yk_use'], + 'yk_high' => $localParams['yk_high'], + 'yk_low' => $localParams['yk_low'] ); sendResp(S_OK, $myLog, '', $extra); diff --git a/ykval-synchronize b/ykval-synchronize index fff81ac..ce93c03 100755 --- a/ykval-synchronize +++ b/ykval-synchronize @@ -29,23 +29,23 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. if($argc != 3 || !( $argv[2] == 'all' || preg_match('/^[cbdefghijklnrtuv]{0,16}$/', $argv[2]))) { - echo "Usage: ".$argv[0]." URL KEY\n\n"; - echo "URL: URL of resync service.\n\n"; - echo "KEY: Public identifier of a YubiKey to sync, or \"all\".\n\n"; - echo "Usage example:\n\n"; - echo $argv[0]." http://example.com/wsapi/2.0/resync ccccccccccdn\n"; - exit(1); + echo "Usage: ".$argv[0]." URL KEY\n\n"; + echo "URL: URL of resync service.\n\n"; + echo "KEY: Public identifier of a YubiKey to sync, or \"all\".\n\n"; + echo "Usage example:\n\n"; + echo $argv[0]." http://example.com/wsapi/2.0/resync ccccccccccdn\n"; + exit(1); } $host = $argv[1]; $yk = $argv[2]; if(!preg_match('~^https?://~', $host)) { - #Allow just an IP or host - if(strpos($host, "/") == False) { - $host = $host."/wsapi/2.0/resync"; - } - $host = "http://".$host; + #Allow just an IP or host + if(strpos($host, "/") == False) { + $host = $host."/wsapi/2.0/resync"; + } + $host = "http://".$host; } $url = $host."?yk=".$yk; @@ -59,7 +59,7 @@ curl_setopt($ch, CURLOPT_FAILONERROR, true); $response = curl_exec($ch); if($response == False) { - die("error"); + die("error"); } echo $response; diff --git a/ykval-synclib.php b/ykval-synclib.php index 412ec61..9dcddee 100644 --- a/ykval-synclib.php +++ b/ykval-synclib.php @@ -33,651 +33,651 @@ require_once 'ykval-db.php'; require_once 'ykval-log.php'; function _get($arr, $key) { - return array_key_exists($key, $arr) ? $arr[$key] : "?"; + return array_key_exists($key, $arr) ? $arr[$key] : "?"; } class SyncLib { - public $syncServers = array(); - public $dbConn = null; - public $curlopts = array(); - - public function __construct($logname='ykval-synclib') - { - $this->myLog = new Log($logname); - global $baseParams; - $this->syncServers = $baseParams['__YKVAL_SYNC_POOL__']; - $this->db = Db::GetDatabaseHandle($baseParams, $logname); - $this->isConnected=$this->db->connect(); - $this->server_nonce=md5(uniqid(rand())); - - if (array_key_exists('__YKVAL_SYNC_CURL_OPTS__', $baseParams)) - { - $this->curlopts = $baseParams['__YKVAL_SYNC_CURL_OPTS__']; - } - } - - public function addField($name, $value) - { - $this->myLog->addField($name, $value); - $this->db->addField($name, $value); - } - - public function isConnected() - { - return $this->isConnected; - } - - public function getNumberOfServers() - { - return count($this->syncServers); - } - - public function getNumberOfValidAnswers() - { - if (isset($this->valid_answers)) - return $this->valid_answers; - - return 0; - } - - public function getNumberOfAnswers() - { - if (isset($this->answers)) - return $this->answers; - - return 0; - } - - public function getClientData($client) - { - $res = $this->db->customQuery("SELECT id, secret FROM clients WHERE active='1' AND id='" . $client . "'"); - $r = $this->db->fetchArray($res); - $this->db->closeCursor($res); - - if ($r) - return $r; - - return false; - } - - public function getQueueLength() - { - return count($this->db->findBy('queue', null, null, null)); - } - - public function getQueueLengthByServer() - { - $counters = array(); - - foreach ($this->syncServers as $server) - { - $counters[$server] = 0; - } - - $result = $this->db->customQuery('SELECT server, COUNT(server) as count FROM queue GROUP BY server'); - - while ($row = $this->db->fetchArray($result)) - { - $counters[$row['server']] = $row['count']; - } - - $this->db->closeCursor($result); - - return $counters; - } - - public function queue($otpParams, $localParams) - { - $info = $this->createInfoString($otpParams, $localParams); - $this->otpParams = $otpParams; - $this->localParams = $localParams; - - $queued = time(); - $result = true; - - foreach ($this->syncServers as $server) - { - $arr = array( - 'queued' => $queued, - 'modified' => $otpParams['modified'], - 'otp' => $otpParams['otp'], - 'server' => $server, - 'server_nonce' => $this->server_nonce, - 'info' => $info - ); - - if (! $this->db->save('queue', $arr)) - $result = false; - } - - return $result; - } - - public function log($priority, $msg, $params=NULL) - { - if ($params) - $msg .= ' modified=' . _get($params, 'modified') . - ' nonce=' . _get($params, 'nonce') . - ' yk_publicname=' . _get($params, 'yk_publicname') . - ' yk_counter=' . _get($params, 'yk_counter') . - ' yk_use=' . _get($params, 'yk_use') . - ' yk_high=' . _get($params, 'yk_high') . - ' yk_low=' . _get($params, 'yk_low'); - - if ($this->myLog) - $this->myLog->log($priority, $msg); - else - error_log("Warning: myLog uninitialized in ykval-synclib.php. Message is " . $msg); - } - - public function getLocalParams($yk_publicname) - { - $this->log(LOG_DEBUG, "searching for yk_publicname $yk_publicname in local db"); - - $res = $this->db->findBy('yubikeys', 'yk_publicname', $yk_publicname, 1); - - if (!$res) - { - $this->log(LOG_NOTICE, "Discovered new identity $yk_publicname"); - - $this->db->save('yubikeys', array( - 'active' => 1, - 'created' => time(), - 'modified' => -1, - 'yk_publicname' => $yk_publicname, - 'yk_counter' => -1, - 'yk_use' => -1, - 'yk_low' => -1, - 'yk_high' => -1, - 'nonce' => '0000000000000000', - 'notes' => '' - )); - - $res = $this->db->findBy('yubikeys', 'yk_publicname', $yk_publicname, 1); - } - - if ($res) - { - $localParams = array( - 'modified' => $res['modified'], - 'nonce' => $res['nonce'], - 'active' => $res['active'], - 'yk_publicname' => $yk_publicname, - 'yk_counter' => $res['yk_counter'], - 'yk_use' => $res['yk_use'], - 'yk_high' => $res['yk_high'], - 'yk_low' => $res['yk_low'] - ); - - $this->log(LOG_INFO, "yubikey found in db ", $localParams); - return $localParams; - } - - $this->log(LOG_NOTICE, "params for yk_publicname $yk_publicname not found in database"); - return false; - } - - public function updateDbCounters($params) - { - if (!isset($params['yk_publicname'])) - return false; - - $arr = array( - 'modified' => $params['modified'], - 'yk_counter' => $params['yk_counter'], - 'yk_use' => $params['yk_use'], - 'yk_low' => $params['yk_low'], - 'yk_high' => $params['yk_high'], - 'nonce' => $params['nonce'] - ); - - $condition = '('.$params['yk_counter'].'>yk_counter or ('.$params['yk_counter'].'=yk_counter and ' . $params['yk_use'] . '>yk_use))'; - - if (! $this->db->conditionalUpdateBy('yubikeys', 'yk_publicname', $params['yk_publicname'], $arr, $condition)) - { - $this->log(LOG_CRIT, 'failed to update internal DB with new counters'); - return false; - } - - if ($this->db->rowCount() > 0) - $this->log(LOG_INFO, 'updated database ', $params); - else - $this->log(LOG_INFO, 'database not updated', $params); - - return true; - } - - public function countersHigherThan($p1, $p2) - { - if ($p1['yk_counter'] > $p2['yk_counter']) - return true; - - if ($p1['yk_counter'] == $p2['yk_counter'] && $p1['yk_use'] > $p2['yk_use']) - return true; - - return false; - } - - public function countersHigherThanOrEqual($p1, $p2) - { - if ($p1['yk_counter'] > $p2['yk_counter']) - return true; - - if ($p1['yk_counter'] == $p2['yk_counter'] && $p1['yk_use'] >= $p2['yk_use']) - return true; - - return false; - } - - public function countersEqual($p1, $p2) - { - return ($p1['yk_counter'] == $p2['yk_counter'] && $p1['yk_use'] == $p2['yk_use']); - } - - // queue daemon - public function reSync($older_than, $timeout) - { - $this->log(LOG_DEBUG, 'starting resync'); - - /* Loop over all unique servers in queue */ - $queued_limit = time()-$older_than; - $server_res = $this->db->customQuery("select distinct server from queue WHERE queued < " . $queued_limit . " or queued is null"); - $server_list = array(); - $mh = curl_multi_init(); - $ch = array(); - $entries = array(); - $handles = 0; - $num_per_server = 4; - $curlopts = $this->curlopts; - - while ($my_server = $this->db->fetchArray($server_res)) - { - $server = $my_server['server']; - $this->log(LOG_DEBUG, "Processing queue for server " . $server); - - $res = $this->db->customQuery("select * from queue WHERE (queued < " . $queued_limit . " or queued is null) and server='" . $server . "' LIMIT 1000"); - - $list = array(); - - while ($entry = $this->db->fetchArray($res)) - { - $list[] = $entry; - } - $server_list[$server] = $list; - - $this->db->closeCursor($res); - } - $this->db->closeCursor($server_res); - - /* add up to n entries for each server we're going to sync */ - foreach ($server_list as $server) { - $items = array_slice($server, 0, $num_per_server); - $counter = 0; - foreach ($items as $entry) { - $label = "{$entry['server']}:$counter"; - $handle = curl_init(); - $ch[$label] = $handle; - $counter++; - $this->log(LOG_INFO, "server=" . $entry['server'] . ", server_nonce=" . $entry['server_nonce'] . ", info=" . $entry['info']); - - $url = $this->buildSyncUrl($entry); - - $curlopts[CURLOPT_PRIVATE] = $label; - - curl_settings($this, 'YK-VAL resync', $handle, $url, $timeout, $curlopts); - $entries[$label] = $entry; - curl_multi_add_handle($mh, $handle); - $handles++; - } - $empty = array(); - array_splice($server, 0, $num_per_server, $empty); - if(count($server) == 0) { - unset($server_list[$entry['server']]); - } - } - - while($handles > 0) { - while (curl_multi_exec($mh, $active) == CURLM_CALL_MULTI_PERFORM); - - while ($info = curl_multi_info_read($mh)) { - $handle = $info['handle']; - $server = strtok(curl_getinfo($handle, CURLINFO_EFFECTIVE_URL), "?"); - $label = curl_getinfo($handle, CURLINFO_PRIVATE); - $entry = $entries[$label]; - $this->log(LOG_DEBUG, "handle indicated to be for $server."); - curl_multi_remove_handle($mh, $handle); - $handles--; - if ($info['result'] === CURLE_OK) { - $response = curl_multi_getcontent($handle); - if (preg_match('/status=OK/', $response)) - { - $resParams = $this->parseParamsFromMultiLineString($response); - $this->log(LOG_DEBUG, 'response contains ', $resParams); - - /* Update database counters */ - $this->updateDbCounters($resParams); - - /* Retrieve info from entry info string */ - - /* This is the counter values we had in our database *before* processing the current OTP. */ - $validationParams = $this->localParamsFromInfoString($entry['info']); - - /* This is the data from the current OTP. */ - $otpParams = $this->otpParamsFromInfoString($entry['info']); - - /* Fetch current information from our database */ - $localParams = $this->getLocalParams($otpParams['yk_publicname']); - - $this->log(LOG_DEBUG, 'validation params: ', $validationParams); - $this->log(LOG_DEBUG, 'OTP params: ', $otpParams); - - /* Check for warnings */ - - if ($this->countersHigherThan($validationParams, $resParams)) - { - $this->log(LOG_NOTICE, 'Remote server out of sync compared to counters at validation request time. '); - } - - if ($this->countersHigherThan($resParams, $validationParams)) - { - if ($this->countersEqual($resParams, $otpParams)) - { - $this->log(LOG_INFO, 'Remote server had received the current counter values already. '); - } - else - { - $this->log(LOG_NOTICE, 'Local server out of sync compared to counters at validation request time. '); - } - } - - if ($this->countersHigherThan($localParams, $resParams)) - { - $this->log(LOG_WARNING, 'Remote server out of sync compared to current local counters. '); - } - - if ($this->countersHigherThan($resParams, $localParams)) - { - $this->log(LOG_WARNING, 'Local server out of sync compared to current local counters. Local server updated. '); - } - - if ($this->countersHigherThan($resParams, $otpParams)) - { - $this->log(LOG_ERR, 'Remote server has higher counters than OTP. This response would have marked the OTP as invalid. '); - } - elseif ($this->countersEqual($resParams, $otpParams) && $resParams['nonce'] != $otpParams['nonce']) - { - $this->log(LOG_ERR, 'Remote server has equal counters as OTP and nonce differs. This response would have marked the OTP as invalid.'); - } - - /* Deletion */ - $this->log(LOG_DEBUG, 'deleting queue entry with modified=' . $entry['modified'] . - ' server_nonce=' . $entry['server_nonce'] . - ' server=' . $entry['server']); - - $this->db->deleteByMultiple('queue', array( - 'modified' => $entry['modified'], - 'server_nonce' => $entry['server_nonce'], - 'server' => $entry['server'] - )); - - } - else if (preg_match('/status=BAD_OTP/', $response)) - { - $this->log(LOG_WARNING, 'Remote server says BAD_OTP, pointless to try again, removing from queue.'); - $this->db->deleteByMultiple('queue', array( - 'modified' => $entry['modified'], - 'server_nonce' => $entry['server_nonce'], - 'server' => $entry['server'] - )); - } - else - { - $this->log(LOG_ERR, 'Remote server refused our sync request. Check remote server logs.'); - } - - if (array_key_exists($server, $server_list)) { - $entry = array_shift($server_list[$server]); - if(count($server_list[$server]) == 0) { - $this->log(LOG_DEBUG, "All entries for $server synced."); - unset($server_list[$server]); - } - $this->log(LOG_INFO, "server=" . $entry['server'] . ", server_nonce=" . $entry['server_nonce'] . ", info=" . $entry['info']); - - $url = $this->buildSyncUrl($entry); - - $curlopts[CURLOPT_PRIVATE] = $label; - curl_settings($this, 'YK-VAL resync', $handle, $url, $timeout, $curlopts); - $entries[$label] = $entry; - curl_multi_add_handle($mh, $handle); - $handles++; - } - } else { - $this->log(LOG_NOTICE, 'Timeout. Stopping queue resync for server ' . $entry['server']); - unset($server_list[$server]); - } - } - } - - foreach ($ch as $handle) { - curl_close($handle); - } - - curl_multi_close($mh); - - return true; - } - - // blocks verify requests - public function sync($ans_req, $timeout=1) - { - // construct URLs - $urls = array(); - $res = $this->db->findByMultiple('queue', array( - 'modified' => $this->otpParams['modified'], - 'server_nonce' => $this->server_nonce - )); - foreach ($res as $row) - { - $urls[] = $this->buildSyncUrl($row); - } - - // send out requests - $ans_arr = retrieveURLasync('YK-VAL sync', $urls, $this->myLog, $ans_req, $match='status=OK', $returl=True, $timeout, $this->curlopts); - - if ($ans_arr === FALSE) - { - $this->log(LOG_WARNING, 'No responses from validation server pool'); - $ans_arr = array(); - } - - // parse responses - $localParams = $this->localParams; - - $this->answers = count($ans_arr); - $this->valid_answers = 0; - - foreach ($ans_arr as $answer) - { - // parse out parameters from each response - $resParams=$this->parseParamsFromMultiLineString($answer); - $this->log(LOG_DEBUG, 'local db contains ', $localParams); - $this->log(LOG_DEBUG, 'response contains ', $resParams); - $this->log(LOG_DEBUG, 'OTP contains ', $this->otpParams); - - // update internal DB (conditional) - $this->updateDbCounters($resParams); - - /** - * Check for warnings - * - * See https://developers.yubico.com/yubikey-val/doc/ServerReplicationProtocol.html - * - * NOTE: We use localParams for validationParams comparison since they are actually the - * same in this situation and we have them at hand. - */ - - if ($this->countersHigherThan($localParams, $resParams)) - { - $this->log(LOG_NOTICE, 'Remote server out of sync'); - } - - if ($this->countersHigherThan($resParams, $localParams)) - { - $this->log(LOG_NOTICE, 'Local server out of sync'); - } - - if ($this->countersEqual($resParams, $localParams) && $resParams['nonce'] != $localParams['nonce']) - { - $this->log(LOG_NOTICE, 'Servers out of sync. Nonce differs. '); - } - - if ($this->countersEqual($resParams, $localParams) && $resParams['modified'] != $localParams['modified']) - { - $this->log(LOG_NOTICE, 'Servers out of sync. Modified differs. '); - } - - if ($this->countersHigherThan($resParams, $this->otpParams)) - { - $this->log(LOG_WARNING, 'OTP is replayed. Sync response counters higher than OTP counters.'); - } - elseif ($this->countersEqual($resParams, $this->otpParams) && $resParams['nonce'] != $this->otpParams['nonce']) - { - $this->log(LOG_WARNING, 'OTP is replayed. Sync response counters equal to OTP counters and nonce differs.'); - } - else - { - // the answer is ok since a REPLAY was not indicated - $this->valid_answers++; - } - - // delete entry from table - $this->deleteQueueEntry($answer); - } - - /** - * NULL queued_time for remaining entries in queue, to allow - * daemon to take care of them as soon as possible. - */ - $this->db->updateBy('queue', 'server_nonce', $this->server_nonce, array('queued'=>NULL)); - - /** - * Return true if valid answers equals required answers. - * Since we only obtain the required amount of answers from - * retrieveAsync this indicates that all answers were actually valid. - * Otherwise, return false. - */ - if ($this->valid_answers == $ans_req) - return true; - - return false; - } - - private function createInfoString($otpParams, $localParams) - { - # FIXME &local_counter - return 'yk_publicname=' . $otpParams['yk_publicname'] . - '&yk_counter=' . $otpParams['yk_counter'] . - '&yk_use=' . $otpParams['yk_use'] . - '&yk_high=' . $otpParams['yk_high'] . - '&yk_low=' . $otpParams['yk_low'] . - '&nonce=' . $otpParams['nonce'] . - ',local_counter=' . $localParams['yk_counter'] . - '&local_use=' . $localParams['yk_use']; - } - - private function otpParamsFromInfoString($info) - { - $out = explode(',', $info); - parse_str($out[0], $params); - return $params; - } - - private function otpPartFromInfoString($info) - { - $out = explode(',', $info); - return $out[0]; - } - - private function localParamsFromInfoString($info) - { - $out = explode(',', $info); - parse_str($out[1], $params); - - return array( - 'yk_counter' => $params['local_counter'], - 'yk_use' => $params['local_use'] - ); - } - - private function parseParamsFromMultiLineString($str) - { - $i = preg_match("/^modified=(-1|[0-9]+)/m", $str, $out); - if ($i != 1) { - $this->log(LOG_ALERT, "cannot parse modified value: $str"); - } - $resParams['modified']=$out[1]; - - $i = preg_match("/^yk_publicname=([cbdefghijklnrtuv]+)/m", $str, $out); - if ($i != 1) { - $this->log(LOG_ALERT, "cannot parse publicname value: $str"); - } - $resParams['yk_publicname']=$out[1]; - - $i = preg_match("/^yk_counter=(-1|[0-9]+)/m", $str, $out); - if ($i != 1) { - $this->log(LOG_ALERT, "cannot parse counter value: $str"); - } - $resParams['yk_counter']=$out[1]; - - $i = preg_match("/^yk_use=(-1|[0-9]+)/m", $str, $out); - if ($i != 1) { - $this->log(LOG_ALERT, "cannot parse use value: $str"); - } - $resParams['yk_use']=$out[1]; - - $i = preg_match("/^yk_high=(-1|[0-9]+)/m", $str, $out); - if ($i != 1) { - $this->log(LOG_ALERT, "cannot parse high value: $str"); - } - $resParams['yk_high']=$out[1]; - - $i = preg_match("/^yk_low=(-1|[0-9]+)/m", $str, $out); - if ($i != 1) { - $this->log(LOG_ALERT, "cannot parse low value: $str"); - } - $resParams['yk_low']=$out[1]; - - $i = preg_match("/^nonce=([[:alnum:]]+)/m", $str, $out); - if ($i != 1) { - $this->log(LOG_ALERT, "cannot parse nonce value: $str"); - } - $resParams['nonce']=$out[1]; - - return $resParams; - } - - private function deleteQueueEntry($answer) - { - preg_match('/url=(.*)\?/', $answer, $out); - $server = $out[1]; - - $this->log(LOG_INFO, "deleting server=" . $server . - " modified=" . $this->otpParams['modified'] . - " server_nonce=" . $this->server_nonce); - - $this->db->deleteByMultiple('queue', array( - 'modified' => $this->otpParams['modified'], - 'server_nonce' => $this->server_nonce, - 'server' => $server - )); - } - - private function buildSyncUrl($entry) - { - return $entry['server'] . - "?otp=" . $entry['otp'] . - "&modified=" . $entry['modified'] . - "&" . $this->otpPartFromInfoString($entry['info']); - } + public $syncServers = array(); + public $dbConn = null; + public $curlopts = array(); + + public function __construct($logname='ykval-synclib') + { + $this->myLog = new Log($logname); + global $baseParams; + $this->syncServers = $baseParams['__YKVAL_SYNC_POOL__']; + $this->db = Db::GetDatabaseHandle($baseParams, $logname); + $this->isConnected=$this->db->connect(); + $this->server_nonce=md5(uniqid(rand())); + + if (array_key_exists('__YKVAL_SYNC_CURL_OPTS__', $baseParams)) + { + $this->curlopts = $baseParams['__YKVAL_SYNC_CURL_OPTS__']; + } + } + + public function addField($name, $value) + { + $this->myLog->addField($name, $value); + $this->db->addField($name, $value); + } + + public function isConnected() + { + return $this->isConnected; + } + + public function getNumberOfServers() + { + return count($this->syncServers); + } + + public function getNumberOfValidAnswers() + { + if (isset($this->valid_answers)) + return $this->valid_answers; + + return 0; + } + + public function getNumberOfAnswers() + { + if (isset($this->answers)) + return $this->answers; + + return 0; + } + + public function getClientData($client) + { + $res = $this->db->customQuery("SELECT id, secret FROM clients WHERE active='1' AND id='" . $client . "'"); + $r = $this->db->fetchArray($res); + $this->db->closeCursor($res); + + if ($r) + return $r; + + return false; + } + + public function getQueueLength() + { + return count($this->db->findBy('queue', null, null, null)); + } + + public function getQueueLengthByServer() + { + $counters = array(); + + foreach ($this->syncServers as $server) + { + $counters[$server] = 0; + } + + $result = $this->db->customQuery('SELECT server, COUNT(server) as count FROM queue GROUP BY server'); + + while ($row = $this->db->fetchArray($result)) + { + $counters[$row['server']] = $row['count']; + } + + $this->db->closeCursor($result); + + return $counters; + } + + public function queue($otpParams, $localParams) + { + $info = $this->createInfoString($otpParams, $localParams); + $this->otpParams = $otpParams; + $this->localParams = $localParams; + + $queued = time(); + $result = true; + + foreach ($this->syncServers as $server) + { + $arr = array( + 'queued' => $queued, + 'modified' => $otpParams['modified'], + 'otp' => $otpParams['otp'], + 'server' => $server, + 'server_nonce' => $this->server_nonce, + 'info' => $info + ); + + if (! $this->db->save('queue', $arr)) + $result = false; + } + + return $result; + } + + public function log($priority, $msg, $params=NULL) + { + if ($params) + $msg .= ' modified=' . _get($params, 'modified') . + ' nonce=' . _get($params, 'nonce') . + ' yk_publicname=' . _get($params, 'yk_publicname') . + ' yk_counter=' . _get($params, 'yk_counter') . + ' yk_use=' . _get($params, 'yk_use') . + ' yk_high=' . _get($params, 'yk_high') . + ' yk_low=' . _get($params, 'yk_low'); + + if ($this->myLog) + $this->myLog->log($priority, $msg); + else + error_log("Warning: myLog uninitialized in ykval-synclib.php. Message is " . $msg); + } + + public function getLocalParams($yk_publicname) + { + $this->log(LOG_DEBUG, "searching for yk_publicname $yk_publicname in local db"); + + $res = $this->db->findBy('yubikeys', 'yk_publicname', $yk_publicname, 1); + + if (!$res) + { + $this->log(LOG_NOTICE, "Discovered new identity $yk_publicname"); + + $this->db->save('yubikeys', array( + 'active' => 1, + 'created' => time(), + 'modified' => -1, + 'yk_publicname' => $yk_publicname, + 'yk_counter' => -1, + 'yk_use' => -1, + 'yk_low' => -1, + 'yk_high' => -1, + 'nonce' => '0000000000000000', + 'notes' => '' + )); + + $res = $this->db->findBy('yubikeys', 'yk_publicname', $yk_publicname, 1); + } + + if ($res) + { + $localParams = array( + 'modified' => $res['modified'], + 'nonce' => $res['nonce'], + 'active' => $res['active'], + 'yk_publicname' => $yk_publicname, + 'yk_counter' => $res['yk_counter'], + 'yk_use' => $res['yk_use'], + 'yk_high' => $res['yk_high'], + 'yk_low' => $res['yk_low'] + ); + + $this->log(LOG_INFO, "yubikey found in db ", $localParams); + return $localParams; + } + + $this->log(LOG_NOTICE, "params for yk_publicname $yk_publicname not found in database"); + return false; + } + + public function updateDbCounters($params) + { + if (!isset($params['yk_publicname'])) + return false; + + $arr = array( + 'modified' => $params['modified'], + 'yk_counter' => $params['yk_counter'], + 'yk_use' => $params['yk_use'], + 'yk_low' => $params['yk_low'], + 'yk_high' => $params['yk_high'], + 'nonce' => $params['nonce'] + ); + + $condition = '('.$params['yk_counter'].'>yk_counter or ('.$params['yk_counter'].'=yk_counter and ' . $params['yk_use'] . '>yk_use))'; + + if (! $this->db->conditionalUpdateBy('yubikeys', 'yk_publicname', $params['yk_publicname'], $arr, $condition)) + { + $this->log(LOG_CRIT, 'failed to update internal DB with new counters'); + return false; + } + + if ($this->db->rowCount() > 0) + $this->log(LOG_INFO, 'updated database ', $params); + else + $this->log(LOG_INFO, 'database not updated', $params); + + return true; + } + + public function countersHigherThan($p1, $p2) + { + if ($p1['yk_counter'] > $p2['yk_counter']) + return true; + + if ($p1['yk_counter'] == $p2['yk_counter'] && $p1['yk_use'] > $p2['yk_use']) + return true; + + return false; + } + + public function countersHigherThanOrEqual($p1, $p2) + { + if ($p1['yk_counter'] > $p2['yk_counter']) + return true; + + if ($p1['yk_counter'] == $p2['yk_counter'] && $p1['yk_use'] >= $p2['yk_use']) + return true; + + return false; + } + + public function countersEqual($p1, $p2) + { + return ($p1['yk_counter'] == $p2['yk_counter'] && $p1['yk_use'] == $p2['yk_use']); + } + + // queue daemon + public function reSync($older_than, $timeout) + { + $this->log(LOG_DEBUG, 'starting resync'); + + /* Loop over all unique servers in queue */ + $queued_limit = time()-$older_than; + $server_res = $this->db->customQuery("select distinct server from queue WHERE queued < " . $queued_limit . " or queued is null"); + $server_list = array(); + $mh = curl_multi_init(); + $ch = array(); + $entries = array(); + $handles = 0; + $num_per_server = 4; + $curlopts = $this->curlopts; + + while ($my_server = $this->db->fetchArray($server_res)) + { + $server = $my_server['server']; + $this->log(LOG_DEBUG, "Processing queue for server " . $server); + + $res = $this->db->customQuery("select * from queue WHERE (queued < " . $queued_limit . " or queued is null) and server='" . $server . "' LIMIT 1000"); + + $list = array(); + + while ($entry = $this->db->fetchArray($res)) + { + $list[] = $entry; + } + $server_list[$server] = $list; + + $this->db->closeCursor($res); + } + $this->db->closeCursor($server_res); + + /* add up to n entries for each server we're going to sync */ + foreach ($server_list as $server) { + $items = array_slice($server, 0, $num_per_server); + $counter = 0; + foreach ($items as $entry) { + $label = "{$entry['server']}:$counter"; + $handle = curl_init(); + $ch[$label] = $handle; + $counter++; + $this->log(LOG_INFO, "server=" . $entry['server'] . ", server_nonce=" . $entry['server_nonce'] . ", info=" . $entry['info']); + + $url = $this->buildSyncUrl($entry); + + $curlopts[CURLOPT_PRIVATE] = $label; + + curl_settings($this, 'YK-VAL resync', $handle, $url, $timeout, $curlopts); + $entries[$label] = $entry; + curl_multi_add_handle($mh, $handle); + $handles++; + } + $empty = array(); + array_splice($server, 0, $num_per_server, $empty); + if(count($server) == 0) { + unset($server_list[$entry['server']]); + } + } + + while($handles > 0) { + while (curl_multi_exec($mh, $active) == CURLM_CALL_MULTI_PERFORM); + + while ($info = curl_multi_info_read($mh)) { + $handle = $info['handle']; + $server = strtok(curl_getinfo($handle, CURLINFO_EFFECTIVE_URL), "?"); + $label = curl_getinfo($handle, CURLINFO_PRIVATE); + $entry = $entries[$label]; + $this->log(LOG_DEBUG, "handle indicated to be for $server."); + curl_multi_remove_handle($mh, $handle); + $handles--; + if ($info['result'] === CURLE_OK) { + $response = curl_multi_getcontent($handle); + if (preg_match('/status=OK/', $response)) + { + $resParams = $this->parseParamsFromMultiLineString($response); + $this->log(LOG_DEBUG, 'response contains ', $resParams); + + /* Update database counters */ + $this->updateDbCounters($resParams); + + /* Retrieve info from entry info string */ + + /* This is the counter values we had in our database *before* processing the current OTP. */ + $validationParams = $this->localParamsFromInfoString($entry['info']); + + /* This is the data from the current OTP. */ + $otpParams = $this->otpParamsFromInfoString($entry['info']); + + /* Fetch current information from our database */ + $localParams = $this->getLocalParams($otpParams['yk_publicname']); + + $this->log(LOG_DEBUG, 'validation params: ', $validationParams); + $this->log(LOG_DEBUG, 'OTP params: ', $otpParams); + + /* Check for warnings */ + + if ($this->countersHigherThan($validationParams, $resParams)) + { + $this->log(LOG_NOTICE, 'Remote server out of sync compared to counters at validation request time. '); + } + + if ($this->countersHigherThan($resParams, $validationParams)) + { + if ($this->countersEqual($resParams, $otpParams)) + { + $this->log(LOG_INFO, 'Remote server had received the current counter values already. '); + } + else + { + $this->log(LOG_NOTICE, 'Local server out of sync compared to counters at validation request time. '); + } + } + + if ($this->countersHigherThan($localParams, $resParams)) + { + $this->log(LOG_WARNING, 'Remote server out of sync compared to current local counters. '); + } + + if ($this->countersHigherThan($resParams, $localParams)) + { + $this->log(LOG_WARNING, 'Local server out of sync compared to current local counters. Local server updated. '); + } + + if ($this->countersHigherThan($resParams, $otpParams)) + { + $this->log(LOG_ERR, 'Remote server has higher counters than OTP. This response would have marked the OTP as invalid. '); + } + elseif ($this->countersEqual($resParams, $otpParams) && $resParams['nonce'] != $otpParams['nonce']) + { + $this->log(LOG_ERR, 'Remote server has equal counters as OTP and nonce differs. This response would have marked the OTP as invalid.'); + } + + /* Deletion */ + $this->log(LOG_DEBUG, 'deleting queue entry with modified=' . $entry['modified'] . + ' server_nonce=' . $entry['server_nonce'] . + ' server=' . $entry['server']); + + $this->db->deleteByMultiple('queue', array( + 'modified' => $entry['modified'], + 'server_nonce' => $entry['server_nonce'], + 'server' => $entry['server'] + )); + + } + else if (preg_match('/status=BAD_OTP/', $response)) + { + $this->log(LOG_WARNING, 'Remote server says BAD_OTP, pointless to try again, removing from queue.'); + $this->db->deleteByMultiple('queue', array( + 'modified' => $entry['modified'], + 'server_nonce' => $entry['server_nonce'], + 'server' => $entry['server'] + )); + } + else + { + $this->log(LOG_ERR, 'Remote server refused our sync request. Check remote server logs.'); + } + + if (array_key_exists($server, $server_list)) { + $entry = array_shift($server_list[$server]); + if(count($server_list[$server]) == 0) { + $this->log(LOG_DEBUG, "All entries for $server synced."); + unset($server_list[$server]); + } + $this->log(LOG_INFO, "server=" . $entry['server'] . ", server_nonce=" . $entry['server_nonce'] . ", info=" . $entry['info']); + + $url = $this->buildSyncUrl($entry); + + $curlopts[CURLOPT_PRIVATE] = $label; + curl_settings($this, 'YK-VAL resync', $handle, $url, $timeout, $curlopts); + $entries[$label] = $entry; + curl_multi_add_handle($mh, $handle); + $handles++; + } + } else { + $this->log(LOG_NOTICE, 'Timeout. Stopping queue resync for server ' . $entry['server']); + unset($server_list[$server]); + } + } + } + + foreach ($ch as $handle) { + curl_close($handle); + } + + curl_multi_close($mh); + + return true; + } + + // blocks verify requests + public function sync($ans_req, $timeout=1) + { + // construct URLs + $urls = array(); + $res = $this->db->findByMultiple('queue', array( + 'modified' => $this->otpParams['modified'], + 'server_nonce' => $this->server_nonce + )); + foreach ($res as $row) + { + $urls[] = $this->buildSyncUrl($row); + } + + // send out requests + $ans_arr = retrieveURLasync('YK-VAL sync', $urls, $this->myLog, $ans_req, $match='status=OK', $returl=True, $timeout, $this->curlopts); + + if ($ans_arr === FALSE) + { + $this->log(LOG_WARNING, 'No responses from validation server pool'); + $ans_arr = array(); + } + + // parse responses + $localParams = $this->localParams; + + $this->answers = count($ans_arr); + $this->valid_answers = 0; + + foreach ($ans_arr as $answer) + { + // parse out parameters from each response + $resParams=$this->parseParamsFromMultiLineString($answer); + $this->log(LOG_DEBUG, 'local db contains ', $localParams); + $this->log(LOG_DEBUG, 'response contains ', $resParams); + $this->log(LOG_DEBUG, 'OTP contains ', $this->otpParams); + + // update internal DB (conditional) + $this->updateDbCounters($resParams); + + /** + * Check for warnings + * + * See https://developers.yubico.com/yubikey-val/doc/ServerReplicationProtocol.html + * + * NOTE: We use localParams for validationParams comparison since they are actually the + * same in this situation and we have them at hand. + */ + + if ($this->countersHigherThan($localParams, $resParams)) + { + $this->log(LOG_NOTICE, 'Remote server out of sync'); + } + + if ($this->countersHigherThan($resParams, $localParams)) + { + $this->log(LOG_NOTICE, 'Local server out of sync'); + } + + if ($this->countersEqual($resParams, $localParams) && $resParams['nonce'] != $localParams['nonce']) + { + $this->log(LOG_NOTICE, 'Servers out of sync. Nonce differs. '); + } + + if ($this->countersEqual($resParams, $localParams) && $resParams['modified'] != $localParams['modified']) + { + $this->log(LOG_NOTICE, 'Servers out of sync. Modified differs. '); + } + + if ($this->countersHigherThan($resParams, $this->otpParams)) + { + $this->log(LOG_WARNING, 'OTP is replayed. Sync response counters higher than OTP counters.'); + } + elseif ($this->countersEqual($resParams, $this->otpParams) && $resParams['nonce'] != $this->otpParams['nonce']) + { + $this->log(LOG_WARNING, 'OTP is replayed. Sync response counters equal to OTP counters and nonce differs.'); + } + else + { + // the answer is ok since a REPLAY was not indicated + $this->valid_answers++; + } + + // delete entry from table + $this->deleteQueueEntry($answer); + } + + /** + * NULL queued_time for remaining entries in queue, to allow + * daemon to take care of them as soon as possible. + */ + $this->db->updateBy('queue', 'server_nonce', $this->server_nonce, array('queued'=>NULL)); + + /** + * Return true if valid answers equals required answers. + * Since we only obtain the required amount of answers from + * retrieveAsync this indicates that all answers were actually valid. + * Otherwise, return false. + */ + if ($this->valid_answers == $ans_req) + return true; + + return false; + } + + private function createInfoString($otpParams, $localParams) + { + # FIXME &local_counter + return 'yk_publicname=' . $otpParams['yk_publicname'] . + '&yk_counter=' . $otpParams['yk_counter'] . + '&yk_use=' . $otpParams['yk_use'] . + '&yk_high=' . $otpParams['yk_high'] . + '&yk_low=' . $otpParams['yk_low'] . + '&nonce=' . $otpParams['nonce'] . + ',local_counter=' . $localParams['yk_counter'] . + '&local_use=' . $localParams['yk_use']; + } + + private function otpParamsFromInfoString($info) + { + $out = explode(',', $info); + parse_str($out[0], $params); + return $params; + } + + private function otpPartFromInfoString($info) + { + $out = explode(',', $info); + return $out[0]; + } + + private function localParamsFromInfoString($info) + { + $out = explode(',', $info); + parse_str($out[1], $params); + + return array( + 'yk_counter' => $params['local_counter'], + 'yk_use' => $params['local_use'] + ); + } + + private function parseParamsFromMultiLineString($str) + { + $i = preg_match("/^modified=(-1|[0-9]+)/m", $str, $out); + if ($i != 1) { + $this->log(LOG_ALERT, "cannot parse modified value: $str"); + } + $resParams['modified']=$out[1]; + + $i = preg_match("/^yk_publicname=([cbdefghijklnrtuv]+)/m", $str, $out); + if ($i != 1) { + $this->log(LOG_ALERT, "cannot parse publicname value: $str"); + } + $resParams['yk_publicname']=$out[1]; + + $i = preg_match("/^yk_counter=(-1|[0-9]+)/m", $str, $out); + if ($i != 1) { + $this->log(LOG_ALERT, "cannot parse counter value: $str"); + } + $resParams['yk_counter']=$out[1]; + + $i = preg_match("/^yk_use=(-1|[0-9]+)/m", $str, $out); + if ($i != 1) { + $this->log(LOG_ALERT, "cannot parse use value: $str"); + } + $resParams['yk_use']=$out[1]; + + $i = preg_match("/^yk_high=(-1|[0-9]+)/m", $str, $out); + if ($i != 1) { + $this->log(LOG_ALERT, "cannot parse high value: $str"); + } + $resParams['yk_high']=$out[1]; + + $i = preg_match("/^yk_low=(-1|[0-9]+)/m", $str, $out); + if ($i != 1) { + $this->log(LOG_ALERT, "cannot parse low value: $str"); + } + $resParams['yk_low']=$out[1]; + + $i = preg_match("/^nonce=([[:alnum:]]+)/m", $str, $out); + if ($i != 1) { + $this->log(LOG_ALERT, "cannot parse nonce value: $str"); + } + $resParams['nonce']=$out[1]; + + return $resParams; + } + + private function deleteQueueEntry($answer) + { + preg_match('/url=(.*)\?/', $answer, $out); + $server = $out[1]; + + $this->log(LOG_INFO, "deleting server=" . $server . + " modified=" . $this->otpParams['modified'] . + " server_nonce=" . $this->server_nonce); + + $this->db->deleteByMultiple('queue', array( + 'modified' => $this->otpParams['modified'], + 'server_nonce' => $this->server_nonce, + 'server' => $server + )); + } + + private function buildSyncUrl($entry) + { + return $entry['server'] . + "?otp=" . $entry['otp'] . + "&modified=" . $entry['modified'] . + "&" . $this->otpPartFromInfoString($entry['info']); + } } diff --git a/ykval-verify.php b/ykval-verify.php index b66cd4f..d1db9ed 100644 --- a/ykval-verify.php +++ b/ykval-verify.php @@ -39,7 +39,7 @@ header('content-type: text/plain'); $ipaddr = $_SERVER['REMOTE_ADDR']; $https = (array_key_exists('HTTPS', $_SERVER) === TRUE - && strtolower($_SERVER['HTTPS']) !== 'off' ? TRUE : FALSE); + && strtolower($_SERVER['HTTPS']) !== 'off' ? TRUE : FALSE); $myLog = new Log('ykval-verify'); $myLog->addField('ip', $ipaddr); @@ -47,9 +47,9 @@ $myLog->addField('ip', $ipaddr); $myLog->request = new LogVerify(); if (array_key_exists('__YKVAL_VERIFY_LOGFORMAT__', $baseParams) - && is_string($baseParams['__YKVAL_VERIFY_LOGFORMAT__'])) + && is_string($baseParams['__YKVAL_VERIFY_LOGFORMAT__'])) { - $myLog->request->format = $baseParams['__YKVAL_VERIFY_LOGFORMAT__']; + $myLog->request->format = $baseParams['__YKVAL_VERIFY_LOGFORMAT__']; } $myLog->request->set('ip', $ipaddr); @@ -60,24 +60,24 @@ unset($time_start); if ($_GET) { - $request = $_GET; - $message = 'Request: ' . $_SERVER['QUERY_STRING']; + $request = $_GET; + $message = 'Request: ' . $_SERVER['QUERY_STRING']; } else if ($_POST) { - $request = $_POST; - $kv = array(); - foreach ($request as $key => $value) - { - $kv[] = "$key=$value"; - } - $message = 'POST: ' . join('&', $kv); - unset($kv); + $request = $_POST; + $kv = array(); + foreach ($request as $key => $value) + { + $kv[] = "$key=$value"; + } + $message = 'POST: ' . join('&', $kv); + unset($kv); } else { - $request = array(); - $message = ''; + $request = array(); + $message = ''; } $message .= ' (at ' . date('c') . ' ' . microtime() . ') HTTP' . ($https ? 'S' : ''); $myLog->log(LOG_INFO, $message); @@ -87,11 +87,11 @@ unset($message); /* Detect protocol version */ if (preg_match('/\/wsapi\/([0-9]+)\.([0-9]+)\//', $_SERVER['REQUEST_URI'], $out)) { - $protocol_version = $out[1] + $out[2] * 0.1; + $protocol_version = $out[1] + $out[2] * 0.1; } else { - $protocol_version = 1.0; + $protocol_version = 1.0; } $myLog->request->set('protocol', $protocol_version); @@ -108,10 +108,10 @@ $otp = getHttpVal('otp', '', $request); $otp = strtolower($otp); if (preg_match('/^[jxe.uidchtnbpygk]+$/', $otp)) { - $new_otp = strtr($otp, 'jxe.uidchtnbpygk', 'cbdefghijklnrtuv'); - $myLog->log(LOG_INFO, "Dvorak OTP converting $otp to $new_otp"); - $otp = $new_otp; - unset($new_otp); + $new_otp = strtr($otp, 'jxe.uidchtnbpygk', 'cbdefghijklnrtuv'); + $myLog->log(LOG_INFO, "Dvorak OTP converting $otp to $new_otp"); + $otp = $new_otp; + unset($new_otp); } $myLog->request->set('signed', ($h === '' ? '-' : 'signed')); @@ -126,7 +126,7 @@ $extra = array(); if ($protocol_version >= 2.0) { - $extra['otp'] = $otp; + $extra['otp'] = $otp; } /** @@ -137,23 +137,23 @@ $myLog->addField('otp', $otp); if ($protocol_version >= 2.0) { - $sl = getHttpVal('sl', '', $request); - $timeout = getHttpVal('timeout', '', $request); - $nonce = getHttpVal('nonce', '', $request); + $sl = getHttpVal('sl', '', $request); + $timeout = getHttpVal('timeout', '', $request); + $nonce = getHttpVal('nonce', '', $request); - $myLog->request->set('sl', $sl); - $myLog->request->set('timeout', $timeout); - $myLog->request->set('nonce', $nonce); + $myLog->request->set('sl', $sl); + $myLog->request->set('timeout', $timeout); + $myLog->request->set('nonce', $nonce); - /* Nonce is required from protocol 2.0 */ - if (!$nonce) - { - $myLog->log(LOG_NOTICE, 'Nonce is missing and protocol version >= 2.0'); - sendResp(S_MISSING_PARAMETER, $myLog); - } + /* Nonce is required from protocol 2.0 */ + if (!$nonce) + { + $myLog->log(LOG_NOTICE, 'Nonce is missing and protocol version >= 2.0'); + sendResp(S_MISSING_PARAMETER, $myLog); + } - /* Add nonce to response parameters */ - $extra['nonce'] = $nonce; + /* Add nonce to response parameters */ + $extra['nonce'] = $nonce; } @@ -176,10 +176,10 @@ if (isset($sl) && $sl != '') { } else if (strcasecmp($sl, 'secure') == 0) { $sl = $baseParams['__YKVAL_SYNC_SECURE_LEVEL__']; } else { - $sl = intval($sl); // non-numbers return zero - if ($sl < 1) { - $myLog->log(LOG_NOTICE, 'SL is provided but not correct'); - sendResp(S_MISSING_PARAMETER, $myLog); + $sl = intval($sl); // non-numbers return zero + if ($sl < 1) { + $myLog->log(LOG_NOTICE, 'SL is provided but not correct'); + sendResp(S_MISSING_PARAMETER, $myLog); } } } else { @@ -187,28 +187,28 @@ if (isset($sl) && $sl != '') { } if (!isset($timeout) || $timeout == '') { - $timeout = $baseParams['__YKVAL_SYNC_DEFAULT_TIMEOUT__']; + $timeout = $baseParams['__YKVAL_SYNC_DEFAULT_TIMEOUT__']; } else if (!ctype_digit($timeout)) { - $myLog->log(LOG_NOTICE, 'timeout is provided but not correct'); - sendResp(S_MISSING_PARAMETER, $myLog); + $myLog->log(LOG_NOTICE, 'timeout is provided but not correct'); + sendResp(S_MISSING_PARAMETER, $myLog); } if (!is_otp($otp)) { - $myLog->log(LOG_NOTICE, "Invalid OTP: $otp"); - sendResp(S_BAD_OTP, $myLog); + $myLog->log(LOG_NOTICE, "Invalid OTP: $otp"); + sendResp(S_BAD_OTP, $myLog); } if (!is_clientid($client)) { - $myLog->log(LOG_NOTICE, 'Client ID is missing or invalid'); - sendResp(S_MISSING_PARAMETER, $myLog); + $myLog->log(LOG_NOTICE, 'Client ID is missing or invalid'); + sendResp(S_MISSING_PARAMETER, $myLog); } if (isset($nonce) && !is_nonce($nonce)) { - $myLog->log(LOG_NOTICE, 'NONCE is provided but not correct'); - sendResp(S_MISSING_PARAMETER, $myLog); + $myLog->log(LOG_NOTICE, 'NONCE is provided but not correct'); + sendResp(S_MISSING_PARAMETER, $myLog); } /** @@ -227,13 +227,13 @@ $sync->addField('otp', $otp); if (! $sync->isConnected()) { - sendResp(S_BACKEND_ERROR, $myLog); + sendResp(S_BACKEND_ERROR, $myLog); } if (($cd = $sync->getClientData($client)) === FALSE) { - $myLog->log(LOG_NOTICE, "Invalid client id $client"); - sendResp(S_NO_SUCH_CLIENT, $myLog); + $myLog->log(LOG_NOTICE, "Invalid client id $client"); + sendResp(S_NO_SUCH_CLIENT, $myLog); } $myLog->log(LOG_DEBUG, 'Client data:', $cd); @@ -247,16 +247,16 @@ unset($cd); if ($h != '') { - // Create the signature using the API key - unset($request['h']); + // Create the signature using the API key + unset($request['h']); - $hmac = sign($request, $apiKey, $myLog); + $hmac = sign($request, $apiKey, $myLog); - if (hash_equals($hmac, $h) === FALSE) - { - $myLog->log(LOG_DEBUG, "client hmac=$h, server hmac=$hmac"); - sendResp(S_BAD_SIGNATURE, $myLog, $apiKey); - } + if (hash_equals($hmac, $h) === FALSE) + { + $myLog->log(LOG_DEBUG, "client hmac=$h, server hmac=$hmac"); + sendResp(S_BAD_SIGNATURE, $myLog, $apiKey); + } } /** @@ -265,33 +265,33 @@ if ($h != '') */ if ($protocol_version < 2.0) { - // we need to create a nonce manually here - $nonce = md5(uniqid(rand())); - $myLog->log(LOG_INFO, "protocol version below 2.0. Created nonce $nonce"); + // we need to create a nonce manually here + $nonce = md5(uniqid(rand())); + $myLog->log(LOG_INFO, "protocol version below 2.0. Created nonce $nonce"); } // which YK-KSM should we talk to? $urls = otp2ksmurls($otp, $client); if (!is_array($urls)) { - sendResp(S_BACKEND_ERROR, $myLog, $apiKey); + sendResp(S_BACKEND_ERROR, $myLog, $apiKey); } // decode OTP from input $curlopts = array(); if (array_key_exists('__YKVAL_KSM_CURL_OPTS__', $baseParams)) { - $curlopts = $baseParams['__YKVAL_KSM_CURL_OPTS__']; + $curlopts = $baseParams['__YKVAL_KSM_CURL_OPTS__']; } if (($otpinfo = KSMdecryptOTP($urls, $myLog, $curlopts)) === FALSE) { - /** - * FIXME - * - * Return S_BACKEND_ERROR if there are connection issues, - * e.g. misconfigured otp2ksmurls. - */ - sendResp(S_BAD_OTP, $myLog, $apiKey); + /** + * FIXME + * + * Return S_BACKEND_ERROR if there are connection issues, + * e.g. misconfigured otp2ksmurls. + */ + sendResp(S_BAD_OTP, $myLog, $apiKey); } $myLog->request->set('counter', $otpinfo['session_counter']); $myLog->request->set('use', $otpinfo['session_use']); @@ -304,28 +304,28 @@ $public_id = substr($otp, 0, strlen ($otp) - TOKEN_LEN); $myLog->request->set('public_id', $public_id); if (($localParams = $sync->getLocalParams($public_id)) === FALSE) { - $myLog->log(LOG_NOTICE, "Invalid Yubikey $public_id"); - sendResp(S_BACKEND_ERROR, $myLog, $apiKey); + $myLog->log(LOG_NOTICE, "Invalid Yubikey $public_id"); + sendResp(S_BACKEND_ERROR, $myLog, $apiKey); } $myLog->log(LOG_DEBUG, 'Auth data:', $localParams); if ($localParams['active'] != 1) { - $myLog->log(LOG_NOTICE, "De-activated Yubikey $public_id"); - sendResp(S_BAD_OTP, $myLog, $apiKey); + $myLog->log(LOG_NOTICE, "De-activated Yubikey $public_id"); + sendResp(S_BAD_OTP, $myLog, $apiKey); } /* Build OTP params */ $otpParams = array( - 'modified' => time(), - 'otp' => $otp, - 'nonce' => $nonce, - 'yk_publicname' => $public_id, - 'yk_counter' => $otpinfo['session_counter'], - 'yk_use' => $otpinfo['session_use'], - 'yk_high' => $otpinfo['high'], - 'yk_low' => $otpinfo['low'] + 'modified' => time(), + 'otp' => $otp, + 'nonce' => $nonce, + 'yk_publicname' => $public_id, + 'yk_counter' => $otpinfo['session_counter'], + 'yk_use' => $otpinfo['session_use'], + 'yk_high' => $otpinfo['high'], + 'yk_low' => $otpinfo['low'] ); unset($otpinfo); @@ -333,117 +333,117 @@ unset($otpinfo); /* First check if OTP is seen with the same nonce, in such case we have an replayed request */ if ($sync->countersEqual($localParams, $otpParams) && $localParams['nonce'] == $otpParams['nonce']) { - $myLog->log(LOG_WARNING, 'Replayed request'); - sendResp(S_REPLAYED_REQUEST, $myLog, $apiKey, $extra); + $myLog->log(LOG_WARNING, 'Replayed request'); + sendResp(S_REPLAYED_REQUEST, $myLog, $apiKey, $extra); } /* Check the OTP counters against local db */ if ($sync->countersHigherThanOrEqual($localParams, $otpParams)) { - $sync->log(LOG_WARNING, 'replayed OTP: Local counters higher'); - $sync->log(LOG_WARNING, 'replayed OTP: Local counters ', $localParams); - $sync->log(LOG_WARNING, 'replayed OTP: Otp counters ', $otpParams); - sendResp(S_REPLAYED_OTP, $myLog, $apiKey, $extra); + $sync->log(LOG_WARNING, 'replayed OTP: Local counters higher'); + $sync->log(LOG_WARNING, 'replayed OTP: Local counters ', $localParams); + $sync->log(LOG_WARNING, 'replayed OTP: Otp counters ', $otpParams); + sendResp(S_REPLAYED_OTP, $myLog, $apiKey, $extra); } /* Valid OTP, update database. */ if (!$sync->updateDbCounters($otpParams)) { - $myLog->log(LOG_CRIT, 'Failed to update yubikey counters in database'); - sendResp(S_BACKEND_ERROR, $myLog, $apiKey); + $myLog->log(LOG_CRIT, 'Failed to update yubikey counters in database'); + sendResp(S_BACKEND_ERROR, $myLog, $apiKey); } /* Queue sync requests */ if (!$sync->queue($otpParams, $localParams)) { - $myLog->log(LOG_CRIT, 'failed to queue sync requests'); - sendResp(S_BACKEND_ERROR, $myLog, $apiKey); + $myLog->log(LOG_CRIT, 'failed to queue sync requests'); + sendResp(S_BACKEND_ERROR, $myLog, $apiKey); } $nr_servers = $sync->getNumberOfServers(); $req_answers = ceil($nr_servers * $sl / 100.0); if ($req_answers > 0) { - $syncres = $sync->sync($req_answers, $timeout); - $nr_answers = $sync->getNumberOfAnswers(); - $nr_valid_answers = $sync->getNumberOfValidAnswers(); - $sl_success_rate = floor(100.0 * $nr_valid_answers / $nr_servers); + $syncres = $sync->sync($req_answers, $timeout); + $nr_answers = $sync->getNumberOfAnswers(); + $nr_valid_answers = $sync->getNumberOfValidAnswers(); + $sl_success_rate = floor(100.0 * $nr_valid_answers / $nr_servers); } else { - $syncres = true; - $nr_answers = 0; - $nr_valid_answers = 0; - $sl_success_rate = 0; + $syncres = true; + $nr_answers = 0; + $nr_valid_answers = 0; + $sl_success_rate = 0; } $myLog->log(LOG_INFO, '', array( - 'synclevel' => $sl, - 'nr servers' => $nr_servers, - 'req answers' => $req_answers, - 'answers' => $nr_answers, - 'valid answers' => $nr_valid_answers, - 'sl success rate' => $sl_success_rate, - 'timeout' => $timeout, + 'synclevel' => $sl, + 'nr servers' => $nr_servers, + 'req answers' => $req_answers, + 'answers' => $nr_answers, + 'valid answers' => $nr_valid_answers, + 'sl success rate' => $sl_success_rate, + 'timeout' => $timeout, )); if ($syncres == False) { - /* sync returned false, indicating that - either at least 1 answer marked OTP as invalid or - there were not enough answers */ - $myLog->log(LOG_WARNING, 'Sync failed'); + /* sync returned false, indicating that + either at least 1 answer marked OTP as invalid or + there were not enough answers */ + $myLog->log(LOG_WARNING, 'Sync failed'); - if ($nr_valid_answers != $nr_answers) - sendResp(S_REPLAYED_OTP, $myLog, $apiKey, $extra); + if ($nr_valid_answers != $nr_answers) + sendResp(S_REPLAYED_OTP, $myLog, $apiKey, $extra); - $extra['sl'] = $sl_success_rate; - sendResp(S_NOT_ENOUGH_ANSWERS, $myLog, $apiKey, $extra); + $extra['sl'] = $sl_success_rate; + sendResp(S_NOT_ENOUGH_ANSWERS, $myLog, $apiKey, $extra); } if ($otpParams['yk_counter'] == $localParams['yk_counter'] && $otpParams['yk_use'] > $localParams['yk_use']) { - $ts = ($otpParams['yk_high'] << 16) + $otpParams['yk_low']; - $seenTs = ($localParams['yk_high'] << 16) + $localParams['yk_low']; - $tsDiff = $ts - $seenTs; - $tsDelta = $tsDiff * TS_SEC; + $ts = ($otpParams['yk_high'] << 16) + $otpParams['yk_low']; + $seenTs = ($localParams['yk_high'] << 16) + $localParams['yk_low']; + $tsDiff = $ts - $seenTs; + $tsDelta = $tsDiff * TS_SEC; - $now = time(); - $elapsed = $now - $localParams['modified']; - $deviation = abs($elapsed - $tsDelta); + $now = time(); + $elapsed = $now - $localParams['modified']; + $deviation = abs($elapsed - $tsDelta); - // Time delta server might verify multiple OTPS in a row. In such case validation server doesn't - // have time to tick a whole second and we need to avoid division by zero. - if ($elapsed != 0) - { - $percent = $deviation/$elapsed; - } - else - { - $percent = 1; - } + // Time delta server might verify multiple OTPS in a row. In such case validation server doesn't + // have time to tick a whole second and we need to avoid division by zero. + if ($elapsed != 0) + { + $percent = $deviation/$elapsed; + } + else + { + $percent = 1; + } - $myLog->log(LOG_INFO, 'Timestamp', array( - 'seen' => $seenTs, - 'this' => $ts, - 'delta' => $tsDiff, - 'secs' => $tsDelta, - 'accessed' => sprintf('%s (%s)', $localParams['modified'], date('Y-m-d H:i:s', $localParams['modified'])), - 'now' => sprintf('%s (%s)', $now, date('Y-m-d H:i:s', $now)), - 'elapsed' => $elapsed, - 'deviation' => sprintf('%s secs or %s%%', $deviation, round(100 * $percent)), - )); + $myLog->log(LOG_INFO, 'Timestamp', array( + 'seen' => $seenTs, + 'this' => $ts, + 'delta' => $tsDiff, + 'secs' => $tsDelta, + 'accessed' => sprintf('%s (%s)', $localParams['modified'], date('Y-m-d H:i:s', $localParams['modified'])), + 'now' => sprintf('%s (%s)', $now, date('Y-m-d H:i:s', $now)), + 'elapsed' => $elapsed, + 'deviation' => sprintf('%s secs or %s%%', $deviation, round(100 * $percent)), + )); - if ($deviation > TS_ABS_TOLERANCE && $percent > TS_REL_TOLERANCE) - { - $myLog->log(LOG_NOTICE, 'OTP failed phishing test'); + if ($deviation > TS_ABS_TOLERANCE && $percent > TS_REL_TOLERANCE) + { + $myLog->log(LOG_NOTICE, 'OTP failed phishing test'); - // FIXME - // This was wrapped around if (0). should we nuke or enable? - // sendResp(S_DELAYED_OTP, $myLog, $apiKey, $extra); - } + // FIXME + // This was wrapped around if (0). should we nuke or enable? + // sendResp(S_DELAYED_OTP, $myLog, $apiKey, $extra); + } } /** @@ -452,14 +452,14 @@ if ($otpParams['yk_counter'] == $localParams['yk_counter'] && $otpParams['yk_use if ($protocol_version >= 2.0) { - $extra['sl'] = $sl_success_rate; + $extra['sl'] = $sl_success_rate; } if ($timestamp == 1) { - $extra['timestamp'] = ($otpParams['yk_high'] << 16) + $otpParams['yk_low']; - $extra['sessioncounter'] = $otpParams['yk_counter']; - $extra['sessionuse'] = $otpParams['yk_use']; + $extra['timestamp'] = ($otpParams['yk_high'] << 16) + $otpParams['yk_low']; + $extra['sessioncounter'] = $otpParams['yk_counter']; + $extra['sessionuse'] = $otpParams['yk_use']; } sendResp(S_OK, $myLog, $apiKey, $extra);