diff --git a/ykval-common.php b/ykval-common.php index 6f735f5..1c831e0 100644 --- a/ykval-common.php +++ b/ykval-common.php @@ -130,6 +130,63 @@ function modhex2b64 ($modhex_str) { return hex2b64($hex_str); } +function curl_settings($logger, $ident, $handle, $url, $timeout, $curlopts) { + //configure "hard" options + $logger->log(LOG_DEBUG, $ident . " adding URL : " . $url); + curl_setopt($handle, CURLOPT_URL, $url); + curl_setopt($handle, CURLOPT_TIMEOUT, $timeout); + curl_setopt($handle, CURLOPT_USERAGENT, "YK-VAL"); + curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($handle, CURLOPT_FAILONERROR, TRUE); + + if (!is_array($curlopts)) { + $logger->log(LOG_WARN, $ident . "curl options must be an array"); + return; + } + + //allowed configurable options in ykval-config.php + $allowed = array( + CURLOPT_PROTOCOLS, + CURLOPT_IPRESOLVE, + CURLOPT_SSLVERSION, + CURLOPT_SSL_VERIFYPEER, + CURLOPT_SSL_VERIFYHOST, + CURLOPT_CAINFO, + CURLOPT_CAPATH, + ); + + foreach($curlopts as $key => $val) { + if (in_array($key, $allowed) === FALSE) { + $logger->log(LOG_WARN, $ident . curl_opt_name($key) . " is not configurable"); + continue; + } + + if (curl_setopt($handle, $key, $val) === FALSE) { + $logger->log(LOG_WARN, $ident . " failed to set " . curl_opt_name($key)); + continue; + } + } +} + +//returns the string name of a curl constant, +// or "curl option" if constant not found. +// e.g. +// curl_opt_name(CURLOPT_URL) returns "CURLOPT_URL" +// curl_opt_name(CURLOPT_BLABLA) returns "curl option" +function curl_opt_name($opt) { + $consts = get_defined_constants(true); + $consts = $consts['curl']; + + $name = array_search($opt, $consts, TRUE); + + //array_search may return either on failure... + if ($name === FALSE || $name === NULL) { + return "curl option"; + } + + return $name; +} + // 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 @@ -137,18 +194,14 @@ function modhex2b64 ($modhex_str) { // long as one of the URLs given work, data will be returned. If all // URLs fail, data from some URL that did not match parameter $match // (defaults to ^OK) is returned, or if all URLs failed, false. -function retrieveURLasync ($ident, $urls, $logger, $ans_req=1, $match="^OK", $returl=False, $timeout=10) { +function retrieveURLasync ($ident, $urls, $logger, $ans_req=1, $match="^OK", $returl=False, $timeout=10, $curlopts) { $mh = curl_multi_init(); $ch = array(); foreach ($urls as $id => $url) { $handle = curl_init(); - $logger->log(LOG_DEBUG, $ident . " adding URL : " . $url); - curl_setopt($handle, CURLOPT_URL, $url); - curl_setopt($handle, CURLOPT_USERAGENT, "YK-VAL"); - curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($handle, CURLOPT_FAILONERROR, true); - curl_setopt($handle, CURLOPT_TIMEOUT, $timeout); + + curl_settings($logger, $ident, $handle, $url, $timeout, $curlopts); curl_multi_add_handle($mh, $handle); @@ -209,13 +262,13 @@ function retrieveURLasync ($ident, $urls, $logger, $ans_req=1, $match="^OK", $re } // $otp: A yubikey OTP -function KSMdecryptOTP($urls, $logger) { +function KSMdecryptOTP($urls, $logger, $curlopts) { $ret = array(); if (!is_array($urls)) { $urls = array($urls); } - $response = retrieveURLasync ("YK-KSM", $urls, $logger, $ans_req=1, $match="^OK", $returl=False, $timeout=10); + $response = retrieveURLasync ("YK-KSM", $urls, $logger, $ans_req=1, $match="^OK", $returl=False, $timeout=10, $curlopts); if (is_array($response)) { $response = $response[0]; } diff --git a/ykval-config.php b/ykval-config.php index 747cc74..d0bcf95 100644 --- a/ykval-config.php +++ b/ykval-config.php @@ -79,6 +79,40 @@ $baseParams['__YKVAL_SYNC_SECURE_LEVEL__'] = 40; $baseParams['__YKVAL_SYNC_DEFAULT_LEVEL__'] = 60; $baseParams['__YKVAL_SYNC_DEFAULT_TIMEOUT__'] = 1; +# A key -> value array with curl options to set +# when calling URLs defined in __YKVAL_SYNC_POOL__ +# +# Only the following options are configurable; +# CURLOPT_PROTOCOLS +# CURLOPT_IPRESOLVE +# CURLOPT_SSLVERSION +# CURLOPT_SSL_VERIFYPEER +# CURLOPT_SSL_VERIFYHOST +# CURLOPT_CAINFO +# CURLOPT_CAPATH +# +# Any other option is ignored and a warning is emitted. +$baseParams['__YKVAL_SYNC_CURL_OPTS__'] = array( + //CURLOPT_PROTOCOLS => CURLPROTO_HTTP, +); + +# A key -> value array with curl options to set +# when calling URLs returned by otp2ksmurls() +# +# Only the following options are configurable; +# CURLOPT_PROTOCOLS +# CURLOPT_IPRESOLVE +# CURLOPT_SSLVERSION +# CURLOPT_SSL_VERIFYPEER +# CURLOPT_SSL_VERIFYHOST +# CURLOPT_CAINFO +# CURLOPT_CAPATH +# +# Any other option is ignored and a warning is emitted. +$baseParams['__YKVAL_KSM_CURL_OPTS__'] = array( + //CURLOPT_PROTOCOLS => CURLPROTO_HTTP, +); + // otp2ksmurls: Return array of YK-KSM URLs for decrypting OTP for // CLIENT. The URLs must be fully qualified, i.e., contain the OTP // itself. diff --git a/ykval-synclib.php b/ykval-synclib.php index d0c6b8c..8777f09 100644 --- a/ykval-synclib.php +++ b/ykval-synclib.php @@ -430,10 +430,17 @@ class SyncLib "&" . $this->otpPartFromInfoString($row['info']); } + global $baseParams; + $curlopts = array(); + + if (array_key_exists('__YKVAL_SYNC_CURL_OPTS__', $baseParams)) { + $curlopts = $baseParams['__YKVAL_SYNC_CURL_OPTS__']; + } + /* Send out requests */ - $ans_arr=$this->retrieveURLasync_wrap($urls, $ans_req, $timeout); + $ans_arr=$this->retrieveURLasync_wrap($urls, $ans_req, $timeout, $curlopts); if (!is_array($ans_arr)) { $this->log(LOG_WARNING, 'No responses from validation server pool'); @@ -537,9 +544,9 @@ class SyncLib else return 0; } - function retrieveURLasync_wrap ($urls, $ans_req=1, $timeout=1.0) + function retrieveURLasync_wrap ($urls, $ans_req=1, $timeout=1.0, $curlopts) { - return retrieveURLasync("YK-VAL sync", $urls, $this->myLog, $ans_req, $match="status=OK", $returl=True, $timeout); + return retrieveURLasync("YK-VAL sync", $urls, $this->myLog, $ans_req, $match="status=OK", $returl=True, $timeout, $curlopts); } } diff --git a/ykval-verify.php b/ykval-verify.php index 77e402f..036f4b0 100644 --- a/ykval-verify.php +++ b/ykval-verify.php @@ -251,7 +251,11 @@ if (!is_array($urls)) { //// Decode OTP from input // -$otpinfo = KSMdecryptOTP($urls, $myLog); +$curlopts = array(); +if (array_key_exists('__YKVAL_KSM_CURL_OPTS__', $baseParams)) { + $curlopts = $baseParams['__YKVAL_KSM_CURL_OPTS__']; +} +$otpinfo = KSMdecryptOTP($urls, $myLog, $curlopts); if (!is_array($otpinfo)) { sendResp(S_BAD_OTP, $myLog, $apiKey); exit;