changeset 23042:2cd3fa4412dc

ssl: only use the dummy cert hack if using an Apple Python (issue4410) The hack for using certificate store in addition to the provided CAs resides in Apple's OpenSSL. Apple's own Pythons will use it, but other custom built Pythons might use a custom built OpenSSL without that hack and will fail when exposed to the dummy cacert introduced in d7f7f1860f00. There do not seem to be a simple way to check from Python if we are using a patched OpenSSL or if it is an Apple OpenSSL. Instead, check if the Python executable resides in /usr/bin/python* or in /System/Library/Frameworks/Python.framework/ and assume that all Pythons found there will be native Pythons using the patched OpenSSL. Custom built Pythons will not get the benefit of using the CAs from the certificate store.
author Mads Kiilerich <madski@unity3d.com>
date Fri, 17 Oct 2014 18:56:12 +0200
parents a36625ef1f35
children 244dbb646ab7
files mercurial/sslutil.py tests/test-https.t
diffstat 2 files changed, 17 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/sslutil.py	Wed Oct 15 05:08:56 2014 +0200
+++ b/mercurial/sslutil.py	Fri Oct 17 18:56:12 2014 +0200
@@ -88,6 +88,20 @@
 # We COMPLETELY ignore CERT_REQUIRED on Python <= 2.5, as it's totally
 # busted on those versions.
 
+def _plainapplepython():
+    """return true if this seems to be a pure Apple Python that
+    * is unfrozen and presumably has the whole mercurial module in the file
+      system
+    * presumably is an Apple Python that uses Apple OpenSSL which has patches
+      for using system certificate store CAs in addition to the provided
+      cacerts file
+    """
+    if sys.platform != 'darwin' or util.mainfrozen():
+        return False
+    exe = (sys.executable or '').lower()
+    return (exe.startswith('/usr/bin/python') or
+            exe.startswith('/system/library/frameworks/python.framework/'))
+
 def sslkwargs(ui, host):
     forcetls = ui.configbool('ui', 'tls', default=True)
     if forcetls:
@@ -104,7 +118,7 @@
         cacerts = util.expandpath(cacerts)
         if not os.path.exists(cacerts):
             raise util.Abort(_('could not find web.cacerts: %s') % cacerts)
-    elif cacerts is None and sys.platform == 'darwin' and not util.mainfrozen():
+    elif cacerts is None and _plainapplepython():
         dummycert = os.path.join(os.path.dirname(__file__), 'dummycert.pem')
         if os.path.exists(dummycert):
             ui.debug('using %s to enable OS X system CA\n' % dummycert)
--- a/tests/test-https.t	Wed Oct 15 05:08:56 2014 +0200
+++ b/tests/test-https.t	Fri Oct 17 18:56:12 2014 +0200
@@ -115,7 +115,8 @@
 #endif
   $ cd ..
 
-OS X has a dummy CA cert that enables use of the system CA store
+OS X has a dummy CA cert that enables use of the system CA store when using
+Apple's OpenSSL. This trick do not work with plain OpenSSL.
 
   $ DISABLEOSXDUMMYCERT=
 #if osx