Submitter | Mads Kiilerich |
---|---|
Date | Sept. 26, 2014, 12:20 a.m. |
Message ID | <afdbe4646db8f7a9d0d9.1411690858@localhost.localdomain> |
Download | mbox | patch |
Permalink | /patch/5988/ |
State | Accepted |
Headers | show |
Comments
On Fri, Sep 26, 2014 at 02:20:58AM +0200, Mads Kiilerich wrote: > # HG changeset patch > # User Mads Kiilerich <madski@unity3d.com> > # Date 1411690788 -7200 > # Fri Sep 26 02:19:48 2014 +0200 > # Node ID afdbe4646db8f7a9d0d9eaa623c021083f20a93a > # Parent 6e888ceda9e9b358e1bcb45eef2555ceb93e0874 > ssl: on OS X, use a dummy cert to trick Python/OpenSSL to use system CA certs LGTM, queued. (Will edit DISAPLE -> DISABLE.) > > This will give PKI-secure behaviour out of the box, without any configuration. > > Setting web.cacerts to any value or empty will disable this trick. > > This dummy cert trick only works on OS X 10.6+, but 10.5 had Python 2.5 which > didn't have certificate validation at all. > > diff --git a/mercurial/dummycert.pem b/mercurial/dummycert.pem > new file mode 100644 > --- /dev/null > +++ b/mercurial/dummycert.pem > @@ -0,0 +1,56 @@ > +A dummy certificate that will make OS X 10.6+ Python use the system CA > +certificate store: > + > +-----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 dummycert.pem -noout -text > + Certificate: > + Data: > + Version: 1 (0x0) > + Serial Number: 15629337334278746470 (0xd8e68f7f6c6f7166) > + Signature Algorithm: sha1WithRSAEncryption > + Issuer: CN=hg.example.com > + Validity > + Not Before: Aug 30 08:45:59 2014 GMT > + Not After : Aug 29 08:45:59 2014 GMT > + Subject: CN=hg.example.com > + Subject Public Key Info: > + Public Key Algorithm: rsaEncryption > + Public-Key: (512 bit) > + Modulus: > + 00:9a:1f:d9:c9:21:a5:72:ad:00:2c:d2:e6:03:58: > + 19:aa:de:b5:1e:bb:b2:c0:fa:d1:93:a5:b2:ac:b2: > + 51:82:df:97:ec:e3:fd:14:59:44:7e:5d:ad:cc:77: > + f3:aa:f9:8a:0a:d4:90:a0:f2:0d:58:e7:40:24:c7: > + a4:05:81:60:29 > + Exponent: 65537 (0x10001) > + Signature Algorithm: sha1WithRSAEncryption > + 17:d8:78:f4:b9:12:a8:9e:9a:22:5a:68:81:9b:94:1e:d8:a1: > + 5d:e2:99:06:c8:a4:b5:52:03:94:37:1c:62:c3:72:d1:14:a1: > + f5:7c:54:7e:19:3e:5c:c2:f0:f2:30:65:62:f7:25:b5:25:dd: > + 27:b5:9e:68:a7:50:45:e9:2e:31 > 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 _ > @@ -104,6 +104,13 @@ def sslkwargs(ui, host): > 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(): > + 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) > + ui.setconfig('web', 'cacerts', dummycert, 'dummy') > + cacerts = dummycert > + if cacerts: > kws.update({'ca_certs': cacerts, > 'cert_reqs': CERT_REQUIRED, > }) > diff --git a/setup.py b/setup.py > --- a/setup.py > +++ b/setup.py > @@ -481,7 +481,8 @@ class HackedMingw32CCompiler(cygwinccomp > cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler > > packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo', > - 'help/*.txt']} > + 'help/*.txt', > + 'dummycert.pem']} > > def ordinarypath(p): > return p and p[0] != '.' and p[-1] != '~' > diff --git a/tests/hghave.py b/tests/hghave.py > --- a/tests/hghave.py > +++ b/tests/hghave.py > @@ -332,6 +332,10 @@ def has_msys(): > def has_aix(): > return sys.platform.startswith("aix") > > +@check("osx", "OS X") > +def has_osx(): > + return sys.platform == 'darwin' > + > @check("absimport", "absolute_import in __future__") > def has_absimport(): > import __future__ > diff --git a/tests/test-https.t b/tests/test-https.t > --- a/tests/test-https.t > +++ b/tests/test-https.t > @@ -115,9 +115,20 @@ Test server address cannot be reused > #endif > $ cd .. > > +OS X has a dummy CA cert that enables use of the system CA store > + > + $ DISAPLEOSXDUMMYCERT= > +#if osx > + $ hg clone https://localhost:$HGPORT/ copy-pull > + abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob) > + [255] > + > + $ DISAPLEOSXDUMMYCERT="--config=web.cacerts=" > +#endif > + > clone via pull > > - $ hg clone https://localhost:$HGPORT/ copy-pull > + $ hg clone https://localhost:$HGPORT/ copy-pull $DISAPLEOSXDUMMYCERT > warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting) > requesting all changes > adding changesets > @@ -143,7 +154,7 @@ pull without cacert > $ cd copy-pull > $ echo '[hooks]' >> .hg/hgrc > $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup" >> .hg/hgrc > - $ hg pull > + $ hg pull $DISAPLEOSXDUMMYCERT > warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting) > pulling from https://localhost:$HGPORT/ > searching for changes > _______________________________________________ > Mercurial-devel mailing list > Mercurial-devel@selenic.com > http://selenic.com/mailman/listinfo/mercurial-devel
Patch
diff --git a/mercurial/dummycert.pem b/mercurial/dummycert.pem new file mode 100644 --- /dev/null +++ b/mercurial/dummycert.pem @@ -0,0 +1,56 @@ +A dummy certificate that will make OS X 10.6+ Python use the system CA +certificate store: + +-----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 dummycert.pem -noout -text + Certificate: + Data: + Version: 1 (0x0) + Serial Number: 15629337334278746470 (0xd8e68f7f6c6f7166) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hg.example.com + Validity + Not Before: Aug 30 08:45:59 2014 GMT + Not After : Aug 29 08:45:59 2014 GMT + Subject: CN=hg.example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (512 bit) + Modulus: + 00:9a:1f:d9:c9:21:a5:72:ad:00:2c:d2:e6:03:58: + 19:aa:de:b5:1e:bb:b2:c0:fa:d1:93:a5:b2:ac:b2: + 51:82:df:97:ec:e3:fd:14:59:44:7e:5d:ad:cc:77: + f3:aa:f9:8a:0a:d4:90:a0:f2:0d:58:e7:40:24:c7: + a4:05:81:60:29 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 17:d8:78:f4:b9:12:a8:9e:9a:22:5a:68:81:9b:94:1e:d8:a1: + 5d:e2:99:06:c8:a4:b5:52:03:94:37:1c:62:c3:72:d1:14:a1: + f5:7c:54:7e:19:3e:5c:c2:f0:f2:30:65:62:f7:25:b5:25:dd: + 27:b5:9e:68:a7:50:45:e9:2e:31 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 _ @@ -104,6 +104,13 @@ def sslkwargs(ui, host): 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(): + 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) + ui.setconfig('web', 'cacerts', dummycert, 'dummy') + cacerts = dummycert + if cacerts: kws.update({'ca_certs': cacerts, 'cert_reqs': CERT_REQUIRED, }) diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -481,7 +481,8 @@ class HackedMingw32CCompiler(cygwinccomp cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo', - 'help/*.txt']} + 'help/*.txt', + 'dummycert.pem']} def ordinarypath(p): return p and p[0] != '.' and p[-1] != '~' diff --git a/tests/hghave.py b/tests/hghave.py --- a/tests/hghave.py +++ b/tests/hghave.py @@ -332,6 +332,10 @@ def has_msys(): def has_aix(): return sys.platform.startswith("aix") +@check("osx", "OS X") +def has_osx(): + return sys.platform == 'darwin' + @check("absimport", "absolute_import in __future__") def has_absimport(): import __future__ diff --git a/tests/test-https.t b/tests/test-https.t --- a/tests/test-https.t +++ b/tests/test-https.t @@ -115,9 +115,20 @@ Test server address cannot be reused #endif $ cd .. +OS X has a dummy CA cert that enables use of the system CA store + + $ DISAPLEOSXDUMMYCERT= +#if osx + $ hg clone https://localhost:$HGPORT/ copy-pull + abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob) + [255] + + $ DISAPLEOSXDUMMYCERT="--config=web.cacerts=" +#endif + clone via pull - $ hg clone https://localhost:$HGPORT/ copy-pull + $ hg clone https://localhost:$HGPORT/ copy-pull $DISAPLEOSXDUMMYCERT warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting) requesting all changes adding changesets @@ -143,7 +154,7 @@ pull without cacert $ cd copy-pull $ echo '[hooks]' >> .hg/hgrc $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup" >> .hg/hgrc - $ hg pull + $ hg pull $DISAPLEOSXDUMMYCERT warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting) pulling from https://localhost:$HGPORT/ searching for changes