From b76b9c4065bb98c8d9ff9bed3660cc70eeb026d7 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 14 May 2020 08:58:27 -0700 Subject: [PATCH] Add "HTTPSFuture->addCurlOption()" for raw access to "curl_setopt()" Summary: Fixes T13533. This is a narrow, fragile API for a particular Kerberos use case on one install. Test Plan: - Set a non-scalar key, got an exception. - Set <"duck", "quack">, got an exception from cURL that the value was invalid. - Set a bunch of made-up options to arbitrary values, no errors. cURL accepts anything so there's nothing we can do about this. - Set `CURLOPT_NOBODY` and saw the request behavior change, demonstrating that the call can produce effects. Maniphest Tasks: T13533 Differential Revision: https://secure.phabricator.com/D21251 --- src/future/http/HTTPSFuture.php | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/future/http/HTTPSFuture.php b/src/future/http/HTTPSFuture.php index 5b9dd7b0..e1f37cce 100644 --- a/src/future/http/HTTPSFuture.php +++ b/src/future/http/HTTPSFuture.php @@ -27,6 +27,8 @@ final class HTTPSFuture extends BaseHTTPFuture { private $parser; private $progressSink; + private $curlOptions = array(); + /** * Create a temp file containing an SSL cert, and use it for this session. * @@ -164,6 +166,22 @@ final class HTTPSFuture extends BaseHTTPFuture { return $this->progressSink; } + /** + * See T13533. This supports an install-specific Kerberos workflow. + */ + public function addCURLOption($option_key, $option_value) { + if (!is_scalar($option_key)) { + throw new Exception( + pht( + 'Expected option key passed to "addCurlOption(, ...)" to be '. + 'a scalar, got "%s".', + phutil_describe_type($option_key))); + } + + $this->curlOptions[] = array($option_key, $option_value); + return $this; + } + /** * Attach a file to the request. * @@ -409,6 +427,24 @@ final class HTTPSFuture extends BaseHTTPFuture { curl_setopt($curl, CURLOPT_PROXY, (string)$proxy); } + foreach ($this->curlOptions as $curl_option) { + list($curl_key, $curl_value) = $curl_option; + try { + $ok = curl_setopt($curl, $curl_key, $curl_value); + if (!$ok) { + throw new Exception( + pht( + 'Call to "curl_setopt(...)" returned "false".')); + } + } catch (Exception $ex) { + throw new PhutilProxyException( + pht( + 'Call to "curl_setopt(...) failed for option key "%s".', + $curl_key), + $ex); + } + } + if ($is_download) { $this->downloadHandle = @fopen($this->downloadPath, 'wb+'); if (!$this->downloadHandle) {