Page MenuHomePhabricator

D10315.id24832.diff
No OneTemporary

D10315.id24832.diff

diff --git a/resources/ssl/README b/resources/ssl/README
--- a/resources/ssl/README
+++ b/resources/ssl/README
@@ -1,3 +1,23 @@
+This document describes how to set Certificate Authority information.
+Usually, you need to do this only if you're using a self-signed certificate.
+
+
+OSX after Yosemite
+==================
+
+If you're using a version of Mac OSX after Yosemite, you can not configure
+certificates from the command line. All libphutil and arcanist options
+related to CA configuration are ignored.
+
+Instead, you need to add them to the system keychain. The easiest way to do this
+is to visit the site in Safari and choose to permanently accept the certificate.
+
+You can also use `security add-trusted-cert` from the command line.
+
+
+All Other Systems
+=================
+
If "curl.cainfo" is not set (or you are using PHP older than 5.3.7, where the
option was introduced), libphutil uses the "default.pem" certificate authority
bundle when making HTTPS requests with cURL. This bundle is extracted from
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -57,6 +57,7 @@
'FutureProxy' => 'future/FutureProxy.php',
'HTTPFuture' => 'future/http/HTTPFuture.php',
'HTTPFutureCURLResponseStatus' => 'future/http/status/HTTPFutureCURLResponseStatus.php',
+ 'HTTPFutureCertificateResponseStatus' => 'future/http/status/HTTPFutureCertificateResponseStatus.php',
'HTTPFutureHTTPResponseStatus' => 'future/http/status/HTTPFutureHTTPResponseStatus.php',
'HTTPFutureParseResponseStatus' => 'future/http/status/HTTPFutureParseResponseStatus.php',
'HTTPFutureResponseStatus' => 'future/http/status/HTTPFutureResponseStatus.php',
@@ -161,6 +162,7 @@
'PhutilExcessiveServiceCallsDaemon' => 'daemon/torture/PhutilExcessiveServiceCallsDaemon.php',
'PhutilExecChannel' => 'channel/PhutilExecChannel.php',
'PhutilExecPassthru' => 'future/exec/PhutilExecPassthru.php',
+ 'PhutilExecutionEnvironment' => 'utils/PhutilExecutionEnvironment.php',
'PhutilExtensionsTestCase' => 'moduleutils/__tests__/PhutilExtensionsTestCase.php',
'PhutilFacebookAuthAdapter' => 'auth/PhutilFacebookAuthAdapter.php',
'PhutilFatalDaemon' => 'daemon/torture/PhutilFatalDaemon.php',
@@ -504,6 +506,7 @@
'FutureProxy' => 'Future',
'HTTPFuture' => 'BaseHTTPFuture',
'HTTPFutureCURLResponseStatus' => 'HTTPFutureResponseStatus',
+ 'HTTPFutureCertificateResponseStatus' => 'HTTPFutureResponseStatus',
'HTTPFutureHTTPResponseStatus' => 'HTTPFutureResponseStatus',
'HTTPFutureParseResponseStatus' => 'HTTPFutureResponseStatus',
'HTTPFutureResponseStatus' => 'Exception',
diff --git a/src/future/http/HTTPSFuture.php b/src/future/http/HTTPSFuture.php
--- a/src/future/http/HTTPSFuture.php
+++ b/src/future/http/HTTPSFuture.php
@@ -278,8 +278,15 @@
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
}
+ // We're going to try to set CAINFO below. This doesn't work at all on
+ // OSX around Yosemite (see T5913). On these systems, we'll use the
+ // system CA and then try to tell the user that their settings were
+ // ignored and how to fix things if we encounter a CA-related error.
+ // Assume we have custom CA settings to start with; we'll clear this
+ // flag if we read the default CA info below.
+
// Try some decent fallbacks here:
- // - First, check if a bundle is set explicit for this request, via
+ // - First, check if a bundle is set explicitly for this request, via
// `setCABundle()` or similar.
// - Then, check if a global bundle is set explicitly for all requests,
// via `setGlobalCABundle()` or similar.
@@ -308,7 +315,9 @@
}
}
- curl_setopt($curl, CURLOPT_CAINFO, $this->getCABundle());
+ if ($this->canSetCAInfo()) {
+ curl_setopt($curl, CURLOPT_CAINFO, $this->getCABundle());
+ }
$domain = id(new PhutilURI($uri))->getDomain();
if (!empty(self::$blindTrustDomains[$domain])) {
@@ -360,7 +369,14 @@
$err_code = $info['result'];
if ($err_code) {
- $status = new HTTPFutureCURLResponseStatus($err_code, $uri);
+ if (($err_code == CURLE_SSL_CACERT) && !$this->canSetCAInfo()) {
+ $status = new HTTPFutureCertificateResponseStatus(
+ HTTPFutureCertificateResponseStatus::ERROR_IMMUTABLE_CERTIFICATES,
+ $uri);
+ } else {
+ $status = new HTTPFutureCURLResponseStatus($err_code, $uri);
+ }
+
$body = null;
$headers = array();
$this->result = array($status, $body, $headers);
@@ -578,4 +594,21 @@
'request.'));
}
+
+ /**
+ * Determine whether CURLOPT_CAINFO is usable on this system.
+ */
+ private function canSetCAInfo() {
+ // We can not set CAInfo on OSX after Yosemite.
+
+ $osx_version = PhutilExecutionEnvironment::getOSXVersion();
+ if ($osx_version) {
+ if (version_compare($osx_version, 14, '>=')) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
}
diff --git a/src/future/http/status/HTTPFutureCertificateResponseStatus.php b/src/future/http/status/HTTPFutureCertificateResponseStatus.php
new file mode 100644
--- /dev/null
+++ b/src/future/http/status/HTTPFutureCertificateResponseStatus.php
@@ -0,0 +1,33 @@
+<?php
+
+final class HTTPFutureCertificateResponseStatus
+ extends HTTPFutureResponseStatus {
+
+ const ERROR_IMMUTABLE_CERTIFICATES = 1;
+
+ protected function getErrorCodeType($code) {
+ return 'Certificate';
+ }
+
+ public function isError() {
+ return true;
+ }
+
+ public function isTimeout() {
+ return false;
+ }
+
+ protected function getErrorCodeDescription($code) {
+ return pht(
+ "There was an error verifying the SSL Certificate Authority while ".
+ "negotating the SSL conncetion. This usually indicates you are ".
+ "using a self-signed certificate.\n\n".
+ "As of OSX Yosemite, certificates must be added to the OSX keychain. ".
+ "You can do this with `security add-trusted-cert` from the command ".
+ "line, or by visiting the site in Safari and choosing to trust the ".
+ "certificate permanently.\n\n".
+ 'For more information, see instructions in '.
+ '"libphutil/resources/ssl/README".');
+ }
+
+}
diff --git a/src/utils/PhutilExecutionEnvironment.php b/src/utils/PhutilExecutionEnvironment.php
new file mode 100644
--- /dev/null
+++ b/src/utils/PhutilExecutionEnvironment.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * Get information about the current execution environment.
+ */
+final class PhutilExecutionEnvironment {
+
+ public static function getOSXVersion() {
+ if (php_uname('s') != 'Darwin') {
+ return null;
+ }
+
+ return php_uname('r');
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 18, 6:25 AM (2 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6725370
Default Alt Text
D10315.id24832.diff (6 KB)

Event Timeline