mirror of
https://github.com/Yubico/yubikey-val.git
synced 2024-11-29 09:24:12 +01:00
Support parallel queries to multiple KSMs.
This commit is contained in:
parent
4c6c078a7e
commit
6c25b66ccd
113
common.php
113
common.php
@ -32,10 +32,10 @@ function getHttpVal($key, $defaultVal) {
|
||||
}
|
||||
|
||||
function query($conn, $q) {
|
||||
debug('Query: '.$q);
|
||||
debug('SQL query: ' . $q);
|
||||
$result = mysql_query($q, $conn);
|
||||
if (!$result) {
|
||||
die("Query error: " . mysql_error());
|
||||
die("SQL query error: " . mysql_error());
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
@ -44,15 +44,18 @@ function mysql_quote($value) {
|
||||
return "'" . mysql_real_escape_string($value) . "'";
|
||||
}
|
||||
|
||||
function debug($msg) {
|
||||
if (is_array($msg)) {
|
||||
$str = "";
|
||||
foreach($msg as $key => $value){
|
||||
$str .= "$key=$value ";
|
||||
function debug() {
|
||||
$str = "";
|
||||
foreach (func_get_args() as $msg)
|
||||
{
|
||||
if (is_array($msg)) {
|
||||
foreach($msg as $key => $value){
|
||||
$str .= "$key=$value ";
|
||||
}
|
||||
} else {
|
||||
$str .= $msg . " ";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$str = $msg;
|
||||
}
|
||||
error_log($str);
|
||||
}
|
||||
|
||||
@ -98,22 +101,82 @@ function modhex2b64 ($modhex_str) {
|
||||
return hex2b64($hex_str);
|
||||
}
|
||||
|
||||
// $otp: A yubikey OTP
|
||||
function decryptOTP($otp, $base_url) {
|
||||
$url = $base_url . $otp;
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, "YK-VAL");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
|
||||
$response = curl_exec($ch);
|
||||
$error = curl_error ($ch);
|
||||
$errno = curl_errno ($ch);
|
||||
debug("YK-KSM response: $response errno: " . $errno . " error: " . $error);
|
||||
$info = curl_getinfo ($ch);
|
||||
debug($info);
|
||||
curl_close($ch);
|
||||
// This function takes a list of URLs. It will return the content of
|
||||
// the first successfully retrieved URL, whose content matches ^OK.
|
||||
// The request are sent asynchronously. Some of the URLs can fail
|
||||
// with unknown host, connection errors, or network timeout, but as
|
||||
// long as one of the URLs given work, data will be returned. If all
|
||||
// URLs fail, data from some URL that did not match ^OK is returned,
|
||||
// or if all URLs failed, false.
|
||||
function retrieveURLasync ($urls) {
|
||||
$mh = curl_multi_init();
|
||||
|
||||
$ch = array();
|
||||
foreach ($urls as $id => $url) {
|
||||
$handle = curl_init();
|
||||
|
||||
curl_setopt($handle, CURLOPT_URL, $url);
|
||||
curl_setopt($handle, CURLOPT_USERAGENT, "YK-VAL");
|
||||
curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($handle, CURLOPT_FAILONERROR, true);
|
||||
curl_setopt($handle, CURLOPT_TIMEOUT, 10);
|
||||
|
||||
curl_multi_add_handle($mh, $handle);
|
||||
|
||||
$ch[$handle] = $handle;
|
||||
}
|
||||
|
||||
$str = false;
|
||||
|
||||
do {
|
||||
while (($mrc = curl_multi_exec($mh, $active)) == CURLM_CALL_MULTI_PERFORM)
|
||||
;
|
||||
|
||||
while ($info = curl_multi_info_read($mh)) {
|
||||
debug ("YK-KSM multi", $info);
|
||||
if ($info['result'] == CURL_OK) {
|
||||
$str = curl_multi_getcontent($info['handle']);
|
||||
|
||||
if (preg_match("/^OK/", $str)) {
|
||||
$error = curl_error ($info['handle']);
|
||||
$errno = curl_errno ($info['handle']);
|
||||
$info = curl_getinfo ($info['handle']);
|
||||
debug("YK-KSM errno/error: " . $errno . "/" . $error, $info);
|
||||
|
||||
foreach ($ch as $h) {
|
||||
curl_multi_remove_handle ($mh, $h);
|
||||
curl_close ($h);
|
||||
}
|
||||
curl_multi_close ($mh);
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
curl_multi_remove_handle ($mh, $info['handle']);
|
||||
curl_close ($info['handle']);
|
||||
unset ($ch[$info['handle']]);
|
||||
}
|
||||
|
||||
curl_multi_select ($mh);
|
||||
}
|
||||
} while($active);
|
||||
|
||||
foreach ($ch as $h) {
|
||||
curl_multi_remove_handle ($mh, $h);
|
||||
curl_close ($h);
|
||||
}
|
||||
curl_multi_close ($mh);
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
// $otp: A yubikey OTP
|
||||
function KSMdecryptOTP($urls) {
|
||||
$ret = array();
|
||||
$response = retrieveURLasync ($urls);
|
||||
if ($response) {
|
||||
debug("YK-KSM response: " . $response);
|
||||
}
|
||||
if (sscanf ($response,
|
||||
"OK counter=%04x low=%04x high=%02x use=%02x",
|
||||
$ret["session_counter"], $ret["low"], $ret["high"],
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php # -*- php -*-
|
||||
|
||||
//// DB
|
||||
//
|
||||
@ -7,6 +7,23 @@ $baseParams['__DB_HOST__'] = 'localhost';
|
||||
$baseParams['__DB_USER__'] = 'username';
|
||||
$baseParams['__DB_PW__'] = 'password';
|
||||
$baseParams['__DB_NAME__'] = 'yubico';
|
||||
$baseParams['__YKKMS_URL__'] = "http://ykkms.example.com/wsapi/decrypt/?otp=";
|
||||
|
||||
// otp2ksmurls: Return array of YK-KSM URLs for decrypting OTP for
|
||||
// CLIENT. The URLs must be fully qualified, i.e., contain the OTP
|
||||
// itself.
|
||||
function otp2ksmurls ($otp, $client) {
|
||||
if ($client == 42) {
|
||||
return array("http://another-ykkms.example.com/wsapi/decrypt/?otp=$otp");
|
||||
}
|
||||
|
||||
if (preg_match ("/^dteffujehknh/", $otp)) {
|
||||
return array("http://different-ykkms.example.com/wsapi/decrypt/?otp=$otp");
|
||||
}
|
||||
|
||||
return array(
|
||||
"http://ykkms1.example.com/wsapi/decrypt/?otp=$otp",
|
||||
"http://ykkms2.example.com/wsapi/decrypt/?otp=$otp",
|
||||
);
|
||||
}
|
||||
|
||||
?>
|
||||
|
22
test-multi.php
Normal file
22
test-multi.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
include 'common.php';
|
||||
|
||||
$data = array(
|
||||
#'http://ykksm.example.com/wsapi/decrypt/?otp=dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh', # Valid response
|
||||
'http://www.google.com:4711', # Connection times out
|
||||
'http://smtp1.google.com', # Connection refused
|
||||
'http://www.google.com/unknown', # 404
|
||||
'http://josefsson.org/key.txt', # incorrect data, but takes some time to load
|
||||
'http://klcxkljsdfiojsafjiosaiojd.org/', # No such domain
|
||||
);
|
||||
echo '<pre>';
|
||||
|
||||
$r = retrieveURLasync($data);
|
||||
if ($r) {
|
||||
print "ok $r";
|
||||
} else {
|
||||
print "err";
|
||||
}
|
||||
|
||||
?>
|
16
verify.php
16
verify.php
@ -40,7 +40,7 @@ if ($cd == null) {
|
||||
sendResp(S_NO_SUCH_CLIENT);
|
||||
exit;
|
||||
}
|
||||
debug($cd);
|
||||
debug("Client data:", $cd);
|
||||
|
||||
//// Check client signature
|
||||
//
|
||||
@ -69,14 +69,22 @@ if (strlen($otp) <= TOKEN_LEN) {
|
||||
exit;
|
||||
}
|
||||
|
||||
//// Which YK-KSM should we talk to?
|
||||
//
|
||||
$urls = otp2ksmurls ($otp, $client);
|
||||
if (!is_array($urls)) {
|
||||
sendResp(S_BACKEND_ERROR);
|
||||
exit;
|
||||
}
|
||||
|
||||
//// Decode OTP from input
|
||||
//
|
||||
$otpinfo = decryptOTP($otp, $baseParams['__YKKMS_URL__']);
|
||||
$otpinfo = KSMdecryptOTP($urls);
|
||||
if (!is_array($otpinfo)) {
|
||||
sendResp(S_BACKEND_ERROR);
|
||||
exit;
|
||||
}
|
||||
debug($otpinfo);
|
||||
debug("Decrypted OTP:", $otpinfo);
|
||||
|
||||
//// Get Yubikey from DB
|
||||
//
|
||||
@ -92,7 +100,7 @@ if (!is_array($ad)) {
|
||||
exit;
|
||||
}
|
||||
}
|
||||
debug($ad);
|
||||
debug("Auth data:", $ad);
|
||||
if ($ad['active'] != 1) {
|
||||
debug('De-activated Yubikey ' . $devId);
|
||||
sendResp(S_BAD_OTP);
|
||||
|
Loading…
Reference in New Issue
Block a user