Patchwork [4,of,4] ssl: use included dummy cert on OS X to trigger use of the system CA storage

login
register
mail settings
Submitter Mads Kiilerich
Date Sept. 25, 2014, 1:33 a.m.
Message ID <5a2e3a66b5a93e17eb6a.1411608785@localhost.localdomain>
Download mbox | patch
Permalink /patch/5971/
State Superseded
Headers show

Comments

Mads Kiilerich - Sept. 25, 2014, 1:33 a.m.
# HG changeset patch
# User Mads Kiilerich <madski@unity3d.com>
# Date 1411608721 -7200
#      Thu Sep 25 03:32:01 2014 +0200
# Node ID 5a2e3a66b5a93e17eb6ab4ee2ee713e1dcfb39eb
# Parent  a2f00946b45a9dc002578c1782ab36b7cc659d14
ssl: use included dummy cert on OS X to trigger use of the system CA storage

This give pretty much sane behaviour out of the box without any configuration.
Augie Fackler - Sept. 25, 2014, 2:36 p.m.
On Thu, Sep 25, 2014 at 03:33:05AM +0200, Mads Kiilerich wrote:
> # HG changeset patch
> # User Mads Kiilerich <madski@unity3d.com>
> # Date 1411608721 -7200
> #      Thu Sep 25 03:32:01 2014 +0200
> # Node ID 5a2e3a66b5a93e17eb6ab4ee2ee713e1dcfb39eb
> # Parent  a2f00946b45a9dc002578c1782ab36b7cc659d14
> ssl: use included dummy cert on OS X to trigger use of the system CA storage
>
> This give pretty much sane behaviour out of the box without any configuration.
>
> diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
> --- a/mercurial/sslutil.py
> +++ b/mercurial/sslutil.py
> @@ -6,7 +6,7 @@
>  #
>  # This software may be used and distributed according to the terms of the
>  # GNU General Public License version 2 or any later version.
> -import os
> +import os, sys
>
>  from mercurial import util
>  from mercurial.i18n import _
> @@ -90,6 +90,11 @@ def _verifycert(cert, hostname):
>
>  def sslkwargs(ui, host):
>      cacerts = ui.config('web', 'cacerts')
> +    if not cacerts and sys.platform == 'darwin':
> +        # use certificate in this file that triggers use of system certs
> +        cacerts = __file__.rstrip('c')

Should also rstrip o in case someone uses -O?

> +        ui.debug('using dummy cert in %s to use OS X system store\n' % cacerts)
> +        ui.setconfig('web', 'cacerts', cacerts, 'dummy')
>      forcetls = ui.configbool('ui', 'tls', default=True)
>      if forcetls:
>          ssl_version = PROTOCOL_TLSv1
> @@ -168,3 +173,37 @@ class validator(object):
>                             'verified (check hostfingerprints or web.cacerts '
>                             'config setting)\n') %
>                           (host, nicefingerprint))
> +
> +
> +"""
> +A dummy certificate for OS X 10.6+:
> +
> +-----BEGIN CERTIFICATE-----
> +MIIBIzCBzgIJANjmj39sb3FmMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNVBAMTDmhn
> +LmV4YW1wbGUuY29tMB4XDTE0MDgzMDA4NDU1OVoXDTE0MDgyOTA4NDU1OVowGTEX
> +MBUGA1UEAxMOaGcuZXhhbXBsZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA
> +mh/ZySGlcq0ALNLmA1gZqt61HruywPrRk6WyrLJRgt+X7OP9FFlEfl2tzHfzqvmK
> +CtSQoPINWOdAJMekBYFgKQIDAQABMA0GCSqGSIb3DQEBBQUAA0EAF9h49LkSqJ6a
> +IlpogZuUHtihXeKZBsiktVIDlDccYsNy0RSh9XxUfhk+XMLw8jBlYvcltSXdJ7We
> +aKdQRekuMQ==
> +-----END CERTIFICATE-----

So, huh. You just inline the .pem and it works? I guess that makes
sense, but it's kind of kooky feeling.

> +
> +This certificate was generated to be syntactically valid but never be usable;
> +it expired before it became valid.
> +
> +Created as:
> +
> +  $ cat > cn.conf << EOT
> +  > [req]
> +  > distinguished_name = req_distinguished_name
> +  > [req_distinguished_name]
> +  > commonName = Common Name
> +  > commonName_default = no.example.com
> +  > EOT
> +  $ openssl req -nodes -new -x509 -keyout /dev/null \
> +  >   -out dummycert.pem -days -1 -config cn.conf -subj '/CN=hg.example.com'
> +
> +To verify the content of this certificate:
> +
> +  $ openssl x509 -in sslutil.py -noout -text
> +"""
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
Mads Kiilerich - Sept. 25, 2014, 3:53 p.m.
On 09/25/2014 04:36 PM, Augie Fackler wrote:
> On Thu, Sep 25, 2014 at 03:33:05AM +0200, Mads Kiilerich wrote:
>> # HG changeset patch
>> # User Mads Kiilerich <madski@unity3d.com>
>> # Date 1411608721 -7200
>> #      Thu Sep 25 03:32:01 2014 +0200
>> # Node ID 5a2e3a66b5a93e17eb6ab4ee2ee713e1dcfb39eb
>> # Parent  a2f00946b45a9dc002578c1782ab36b7cc659d14
>> ssl: use included dummy cert on OS X to trigger use of the system CA storage
>>
>> This give pretty much sane behaviour out of the box without any configuration.
>>
>> diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
>> --- a/mercurial/sslutil.py
>> +++ b/mercurial/sslutil.py
>> @@ -6,7 +6,7 @@
>>   #
>>   # This software may be used and distributed according to the terms of the
>>   # GNU General Public License version 2 or any later version.
>> -import os
>> +import os, sys
>>
>>   from mercurial import util
>>   from mercurial.i18n import _
>> @@ -90,6 +90,11 @@ def _verifycert(cert, hostname):
>>
>>   def sslkwargs(ui, host):
>>       cacerts = ui.config('web', 'cacerts')
>> +    if not cacerts and sys.platform == 'darwin':
>> +        # use certificate in this file that triggers use of system certs
>> +        cacerts = __file__.rstrip('c')
> Should also rstrip o in case someone uses -O?

Right ... even though I kind of would expect that the pem parser would 
ignore all junk and find the string even in pyc and pyo. Apparently it 
doesn't.

I guess there also could be some "frozen" scenarios where __file__ is 
different ... but I doubt forzen ever is used on OS X?

Btw:  This trick only works on 10.6+ ... but IIRC 10.5 used Python 2.5 
where SSL support was very rudimental so I don't think we have to 
consider that.

>> +        ui.debug('using dummy cert in %s to use OS X system store\n' % cacerts)
>> +        ui.setconfig('web', 'cacerts', cacerts, 'dummy')
>>       forcetls = ui.configbool('ui', 'tls', default=True)
>>       if forcetls:
>>           ssl_version = PROTOCOL_TLSv1
>> @@ -168,3 +173,37 @@ class validator(object):
>>                              'verified (check hostfingerprints or web.cacerts '
>>                              'config setting)\n') %
>>                            (host, nicefingerprint))
>> +
>> +
>> +"""
>> +A dummy certificate for OS X 10.6+:
>> +
>> +-----BEGIN CERTIFICATE-----
>> +MIIBIzCBzgIJANjmj39sb3FmMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNVBAMTDmhn
>> +LmV4YW1wbGUuY29tMB4XDTE0MDgzMDA4NDU1OVoXDTE0MDgyOTA4NDU1OVowGTEX
>> +MBUGA1UEAxMOaGcuZXhhbXBsZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA
>> +mh/ZySGlcq0ALNLmA1gZqt61HruywPrRk6WyrLJRgt+X7OP9FFlEfl2tzHfzqvmK
>> +CtSQoPINWOdAJMekBYFgKQIDAQABMA0GCSqGSIb3DQEBBQUAA0EAF9h49LkSqJ6a
>> +IlpogZuUHtihXeKZBsiktVIDlDccYsNy0RSh9XxUfhk+XMLw8jBlYvcltSXdJ7We
>> +aKdQRekuMQ==
>> +-----END CERTIFICATE-----
> So, huh. You just inline the .pem and it works? I guess that makes
> sense, but it's kind of kooky feeling.

Yes. It is a workaround for deficiencies in code so I think it kind of 
make sense to do it code. We could of course also store the certificate 
in a data file somewhere next the source as we do with templates and 
help ... or my initial plan of just making it a config option in a hgrc 
file that we install by default.

/Mads
Augie Fackler - Sept. 25, 2014, 5:11 p.m.
On Thu, Sep 25, 2014 at 11:53 AM, Mads Kiilerich <mads@kiilerich.com> wrote:
> On 09/25/2014 04:36 PM, Augie Fackler wrote:
>>
>> On Thu, Sep 25, 2014 at 03:33:05AM +0200, Mads Kiilerich wrote:
>>>
>>> # HG changeset patch
>>> # User Mads Kiilerich <madski@unity3d.com>
>>> # Date 1411608721 -7200
>>> #      Thu Sep 25 03:32:01 2014 +0200
>>> # Node ID 5a2e3a66b5a93e17eb6ab4ee2ee713e1dcfb39eb
>>> # Parent  a2f00946b45a9dc002578c1782ab36b7cc659d14
>>> ssl: use included dummy cert on OS X to trigger use of the system CA
>>> storage
>>>
>>> This give pretty much sane behaviour out of the box without any
>>> configuration.
>>>
>>> diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
>>> --- a/mercurial/sslutil.py
>>> +++ b/mercurial/sslutil.py
>>> @@ -6,7 +6,7 @@
>>>   #
>>>   # This software may be used and distributed according to the terms of
>>> the
>>>   # GNU General Public License version 2 or any later version.
>>> -import os
>>> +import os, sys
>>>
>>>   from mercurial import util
>>>   from mercurial.i18n import _
>>> @@ -90,6 +90,11 @@ def _verifycert(cert, hostname):
>>>
>>>   def sslkwargs(ui, host):
>>>       cacerts = ui.config('web', 'cacerts')
>>> +    if not cacerts and sys.platform == 'darwin':
>>> +        # use certificate in this file that triggers use of system certs
>>> +        cacerts = __file__.rstrip('c')
>>
>> Should also rstrip o in case someone uses -O?
>
>
> Right ... even though I kind of would expect that the pem parser would
> ignore all junk and find the string even in pyc and pyo. Apparently it
> doesn't.
>
> I guess there also could be some "frozen" scenarios where __file__ is
> different ... but I doubt forzen ever is used on OS X?
>
> Btw:  This trick only works on 10.6+ ... but IIRC 10.5 used Python 2.5 where
> SSL support was very rudimental so I don't think we have to consider that.

Hm. We should probably sniff for Python 2.6+ as well as darwin then?

>
>
>>> +        ui.debug('using dummy cert in %s to use OS X system store\n' %
>>> cacerts)
>>> +        ui.setconfig('web', 'cacerts', cacerts, 'dummy')
>>>       forcetls = ui.configbool('ui', 'tls', default=True)
>>>       if forcetls:
>>>           ssl_version = PROTOCOL_TLSv1
>>> @@ -168,3 +173,37 @@ class validator(object):
>>>                              'verified (check hostfingerprints or
>>> web.cacerts '
>>>                              'config setting)\n') %
>>>                            (host, nicefingerprint))
>>> +
>>> +
>>> +"""
>>> +A dummy certificate for OS X 10.6+:
>>> +
>>> +-----BEGIN CERTIFICATE-----
>>> +MIIBIzCBzgIJANjmj39sb3FmMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNVBAMTDmhn
>>> +LmV4YW1wbGUuY29tMB4XDTE0MDgzMDA4NDU1OVoXDTE0MDgyOTA4NDU1OVowGTEX
>>> +MBUGA1UEAxMOaGcuZXhhbXBsZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA
>>> +mh/ZySGlcq0ALNLmA1gZqt61HruywPrRk6WyrLJRgt+X7OP9FFlEfl2tzHfzqvmK
>>> +CtSQoPINWOdAJMekBYFgKQIDAQABMA0GCSqGSIb3DQEBBQUAA0EAF9h49LkSqJ6a
>>> +IlpogZuUHtihXeKZBsiktVIDlDccYsNy0RSh9XxUfhk+XMLw8jBlYvcltSXdJ7We
>>> +aKdQRekuMQ==
>>> +-----END CERTIFICATE-----
>>
>> So, huh. You just inline the .pem and it works? I guess that makes
>> sense, but it's kind of kooky feeling.
>
>
> Yes. It is a workaround for deficiencies in code so I think it kind of make
> sense to do it code. We could of course also store the certificate in a data
> file somewhere next the source as we do with templates and help ... or my
> initial plan of just making it a config option in a hgrc file that we
> install by default.

I think I'd be a little happier installing it as we do the templates -
feels less likely to do something horrible if someone uses something
like freeze.

>
> /Mads
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
Mads Kiilerich - Sept. 25, 2014, 5:30 p.m.
On 09/25/2014 07:11 PM, Augie Fackler wrote:
> On Thu, Sep 25, 2014 at 11:53 AM, Mads Kiilerich <mads@kiilerich.com> wrote:
>> On 09/25/2014 04:36 PM, Augie Fackler wrote:
>>> On Thu, Sep 25, 2014 at 03:33:05AM +0200, Mads Kiilerich wrote:
>>>> # HG changeset patch
>>>> # User Mads Kiilerich <madski@unity3d.com>
>>>> # Date 1411608721 -7200
>>>> #      Thu Sep 25 03:32:01 2014 +0200
>>>> # Node ID 5a2e3a66b5a93e17eb6ab4ee2ee713e1dcfb39eb
>>>> # Parent  a2f00946b45a9dc002578c1782ab36b7cc659d14
>>>> ssl: use included dummy cert on OS X to trigger use of the system CA
>>>> storage
>>>>
>>>> This give pretty much sane behaviour out of the box without any
>>>> configuration.
>>>>
>>>> diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
>>>> --- a/mercurial/sslutil.py
>>>> +++ b/mercurial/sslutil.py
>>>> @@ -6,7 +6,7 @@
>>>>    #
>>>>    # This software may be used and distributed according to the terms of
>>>> the
>>>>    # GNU General Public License version 2 or any later version.
>>>> -import os
>>>> +import os, sys
>>>>
>>>>    from mercurial import util
>>>>    from mercurial.i18n import _
>>>> @@ -90,6 +90,11 @@ def _verifycert(cert, hostname):
>>>>
>>>>    def sslkwargs(ui, host):
>>>>        cacerts = ui.config('web', 'cacerts')
>>>> +    if not cacerts and sys.platform == 'darwin':
>>>> +        # use certificate in this file that triggers use of system certs
>>>> +        cacerts = __file__.rstrip('c')
>>> Should also rstrip o in case someone uses -O?
>>
>> Right ... even though I kind of would expect that the pem parser would
>> ignore all junk and find the string even in pyc and pyo. Apparently it
>> doesn't.
>>
>> I guess there also could be some "frozen" scenarios where __file__ is
>> different ... but I doubt forzen ever is used on OS X?
>>
>> Btw:  This trick only works on 10.6+ ... but IIRC 10.5 used Python 2.5 where
>> SSL support was very rudimental so I don't think we have to consider that.
> Hm. We should probably sniff for Python 2.6+ as well as darwin then?

We already have

    # CERT_REQUIRED means fetch the cert from the server all the time AND
    # validate it against the CA store provided in web.cacerts.
    #
    # We COMPLETELY ignore CERT_REQUIRED on Python <= 2.5, as it's totally
    # busted on those versions.


so I think we should be home free.

/Mads

Patch

diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -6,7 +6,7 @@ 
 #
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
-import os
+import os, sys
 
 from mercurial import util
 from mercurial.i18n import _
@@ -90,6 +90,11 @@  def _verifycert(cert, hostname):
 
 def sslkwargs(ui, host):
     cacerts = ui.config('web', 'cacerts')
+    if not cacerts and sys.platform == 'darwin':
+        # use certificate in this file that triggers use of system certs
+        cacerts = __file__.rstrip('c')
+        ui.debug('using dummy cert in %s to use OS X system store\n' % cacerts)
+        ui.setconfig('web', 'cacerts', cacerts, 'dummy')
     forcetls = ui.configbool('ui', 'tls', default=True)
     if forcetls:
         ssl_version = PROTOCOL_TLSv1
@@ -168,3 +173,37 @@  class validator(object):
                            'verified (check hostfingerprints or web.cacerts '
                            'config setting)\n') %
                          (host, nicefingerprint))
+
+
+"""
+A dummy certificate for OS X 10.6+:
+
+-----BEGIN CERTIFICATE-----
+MIIBIzCBzgIJANjmj39sb3FmMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNVBAMTDmhn
+LmV4YW1wbGUuY29tMB4XDTE0MDgzMDA4NDU1OVoXDTE0MDgyOTA4NDU1OVowGTEX
+MBUGA1UEAxMOaGcuZXhhbXBsZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA
+mh/ZySGlcq0ALNLmA1gZqt61HruywPrRk6WyrLJRgt+X7OP9FFlEfl2tzHfzqvmK
+CtSQoPINWOdAJMekBYFgKQIDAQABMA0GCSqGSIb3DQEBBQUAA0EAF9h49LkSqJ6a
+IlpogZuUHtihXeKZBsiktVIDlDccYsNy0RSh9XxUfhk+XMLw8jBlYvcltSXdJ7We
+aKdQRekuMQ==
+-----END CERTIFICATE-----
+
+This certificate was generated to be syntactically valid but never be usable;
+it expired before it became valid.
+
+Created as:
+
+  $ cat > cn.conf << EOT
+  > [req]
+  > distinguished_name = req_distinguished_name
+  > [req_distinguished_name]
+  > commonName = Common Name
+  > commonName_default = no.example.com
+  > EOT
+  $ openssl req -nodes -new -x509 -keyout /dev/null \
+  >   -out dummycert.pem -days -1 -config cn.conf -subj '/CN=hg.example.com'
+
+To verify the content of this certificate:
+
+  $ openssl x509 -in sslutil.py -noout -text
+"""