Patchwork [4,of,4,V2] ssl: load CA certificates from system's store by default on Python 2.7.9

login
register
mail settings
Submitter Yuya Nishihara
Date March 12, 2015, 3:41 p.m.
Message ID <4a831146e17df61f3057.1426174917@mimosa>
Download mbox | patch
Permalink /patch/8024/
State Accepted
Commit 760a86865f806024af5f4ec45ab7b96e334122dc
Headers show

Comments

Yuya Nishihara - March 12, 2015, 3:41 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1424958853 -32400
#      Thu Feb 26 22:54:13 2015 +0900
# Node ID 4a831146e17df61f30573d852bba9062883791d6
# Parent  aa314d9b7beae9d6bdc9f939615edf5a18c17144
ssl: load CA certificates from system's store by default on Python 2.7.9

This will make it easy to manage in-house CA certificates, which are often
used in corporate environment and installed into the Windows' certs store.

Unlike Apple python, the dummycert trick isn't necessary on Python 2.7.9.
The default web.cacerts will be set as follows:

  environment    web.cacerts  behavior
  -------------  -----------  -----------------------------------------
  Apple Python   dummycert    fall back to system's store
  Python 2.7.8   '!'          never use CA certs (show warning instead)
  Python 2.7.9+  None         load CA certs from system's store
Matt Mackall - March 12, 2015, 10:30 p.m.
On Fri, 2015-03-13 at 00:41 +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1424958853 -32400
> #      Thu Feb 26 22:54:13 2015 +0900
> # Node ID 4a831146e17df61f30573d852bba9062883791d6
> # Parent  aa314d9b7beae9d6bdc9f939615edf5a18c17144
> ssl: load CA certificates from system's store by default on Python 2.7.9

These are queued for default, thanks.

Patch

diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -10,12 +10,16 @@  import os, sys
 
 from mercurial import util
 from mercurial.i18n import _
+
+_canloaddefaultcerts = False
 try:
     # avoid using deprecated/broken FakeSocket in python 2.6
     import ssl
     CERT_REQUIRED = ssl.CERT_REQUIRED
     try:
         ssl_context = ssl.SSLContext
+        _canloaddefaultcerts = util.safehasattr(ssl_context,
+                                                'load_default_certs')
 
         def ssl_wrap_socket(sock, keyfile, certfile, cert_reqs=ssl.CERT_NONE,
                             ca_certs=None, serverhostname=None):
@@ -35,6 +39,8 @@  try:
             sslcontext.verify_mode = cert_reqs
             if ca_certs is not None:
                 sslcontext.load_verify_locations(cafile=ca_certs)
+            elif _canloaddefaultcerts:
+                sslcontext.load_default_certs()
 
             sslsocket = sslcontext.wrap_socket(sock,
                                                server_hostname=serverhostname)
@@ -130,10 +136,13 @@  def _plainapplepython():
             exe.startswith('/system/library/frameworks/python.framework/'))
 
 def _defaultcacerts():
+    """return path to CA certificates; None for system's store; ! to disable"""
     if _plainapplepython():
         dummycert = os.path.join(os.path.dirname(__file__), 'dummycert.pem')
         if os.path.exists(dummycert):
             return dummycert
+    if _canloaddefaultcerts:
+        return None
     return '!'
 
 def sslkwargs(ui, host):