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
103
common.php
103
common.php
@ -32,10 +32,10 @@ function getHttpVal($key, $defaultVal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function query($conn, $q) {
|
function query($conn, $q) {
|
||||||
debug('Query: '.$q);
|
debug('SQL query: ' . $q);
|
||||||
$result = mysql_query($q, $conn);
|
$result = mysql_query($q, $conn);
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
die("Query error: " . mysql_error());
|
die("SQL query error: " . mysql_error());
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
@ -44,14 +44,17 @@ function mysql_quote($value) {
|
|||||||
return "'" . mysql_real_escape_string($value) . "'";
|
return "'" . mysql_real_escape_string($value) . "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
function debug($msg) {
|
function debug() {
|
||||||
if (is_array($msg)) {
|
|
||||||
$str = "";
|
$str = "";
|
||||||
|
foreach (func_get_args() as $msg)
|
||||||
|
{
|
||||||
|
if (is_array($msg)) {
|
||||||
foreach($msg as $key => $value){
|
foreach($msg as $key => $value){
|
||||||
$str .= "$key=$value ";
|
$str .= "$key=$value ";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$str = $msg;
|
$str .= $msg . " ";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
error_log($str);
|
error_log($str);
|
||||||
}
|
}
|
||||||
@ -98,22 +101,82 @@ function modhex2b64 ($modhex_str) {
|
|||||||
return hex2b64($hex_str);
|
return hex2b64($hex_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// $otp: A yubikey OTP
|
// This function takes a list of URLs. It will return the content of
|
||||||
function decryptOTP($otp, $base_url) {
|
// the first successfully retrieved URL, whose content matches ^OK.
|
||||||
$url = $base_url . $otp;
|
// The request are sent asynchronously. Some of the URLs can fail
|
||||||
$ch = curl_init($url);
|
// with unknown host, connection errors, or network timeout, but as
|
||||||
curl_setopt($ch, CURLOPT_USERAGENT, "YK-VAL");
|
// long as one of the URLs given work, data will be returned. If all
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
// URLs fail, data from some URL that did not match ^OK is returned,
|
||||||
curl_setopt($ch, CURLOPT_FAILONERROR, true);
|
// or if all URLs failed, false.
|
||||||
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
|
function retrieveURLasync ($urls) {
|
||||||
$response = curl_exec($ch);
|
$mh = curl_multi_init();
|
||||||
$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);
|
|
||||||
|
|
||||||
|
$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,
|
if (sscanf ($response,
|
||||||
"OK counter=%04x low=%04x high=%02x use=%02x",
|
"OK counter=%04x low=%04x high=%02x use=%02x",
|
||||||
$ret["session_counter"], $ret["low"], $ret["high"],
|
$ret["session_counter"], $ret["low"], $ret["high"],
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?php
|
<?php # -*- php -*-
|
||||||
|
|
||||||
//// DB
|
//// DB
|
||||||
//
|
//
|
||||||
@ -7,6 +7,23 @@ $baseParams['__DB_HOST__'] = 'localhost';
|
|||||||
$baseParams['__DB_USER__'] = 'username';
|
$baseParams['__DB_USER__'] = 'username';
|
||||||
$baseParams['__DB_PW__'] = 'password';
|
$baseParams['__DB_PW__'] = 'password';
|
||||||
$baseParams['__DB_NAME__'] = 'yubico';
|
$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);
|
sendResp(S_NO_SUCH_CLIENT);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
debug($cd);
|
debug("Client data:", $cd);
|
||||||
|
|
||||||
//// Check client signature
|
//// Check client signature
|
||||||
//
|
//
|
||||||
@ -69,14 +69,22 @@ if (strlen($otp) <= TOKEN_LEN) {
|
|||||||
exit;
|
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
|
//// Decode OTP from input
|
||||||
//
|
//
|
||||||
$otpinfo = decryptOTP($otp, $baseParams['__YKKMS_URL__']);
|
$otpinfo = KSMdecryptOTP($urls);
|
||||||
if (!is_array($otpinfo)) {
|
if (!is_array($otpinfo)) {
|
||||||
sendResp(S_BACKEND_ERROR);
|
sendResp(S_BACKEND_ERROR);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
debug($otpinfo);
|
debug("Decrypted OTP:", $otpinfo);
|
||||||
|
|
||||||
//// Get Yubikey from DB
|
//// Get Yubikey from DB
|
||||||
//
|
//
|
||||||
@ -92,7 +100,7 @@ if (!is_array($ad)) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug($ad);
|
debug("Auth data:", $ad);
|
||||||
if ($ad['active'] != 1) {
|
if ($ad['active'] != 1) {
|
||||||
debug('De-activated Yubikey ' . $devId);
|
debug('De-activated Yubikey ' . $devId);
|
||||||
sendResp(S_BAD_OTP);
|
sendResp(S_BAD_OTP);
|
||||||
|
Loading…
Reference in New Issue
Block a user