[PATCH 2 of 2] url: check server certificates when connecting through proxy (issue2407)

Thomas Arendsen Hein thomas at intevation.de
Mon Nov 1 14:56:30 CDT 2010


* Mads Kiilerich <mads at kiilerich.com> [20101101 12:01]:
> On 11/01/2010 11:12 AM, Thomas Arendsen Hein wrote:
>> * Mads Kiilerich<mads at kiilerich.com>  [20101101 02:16]:
>>> # HG changeset patch
>>> # User Mads Kiilerich<mads at kiilerich.com>
>>> # Date 1288573886 -3600
>>> # Branch stable
>>> # Node ID 391543217c1a222deb236d1fcc426e264921cd82
>>> # Parent  191f4f62a3ae7d9f27b3b16267c4f1400fd2451f
>>> url: check server certificates when connecting through proxy (issue2407)
>>
>> Does not help for me:
>>
>>> diff --git a/mercurial/url.py b/mercurial/url.py
>>> --- a/mercurial/url.py
>>> +++ b/mercurial/url.py
>>> @@ -540,8 +540,25 @@
>>>                   self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>>                   self.sock.connect((self.host, self.port))
>>>                   if _generic_proxytunnel(self):
>>> -                    self.sock = _ssl_wrap_socket(self.sock, self.key_file,
>>> -                            self.cert_file)
>>> +                    if hasattr(self, 'ui'):
>>> +                        cacerts = self.ui.config('web', 'cacerts')
>>> +                    else:
>>> +                        cacerts = None
>>> +
>>> +                    if cacerts:
>>> +                        self.sock = _ssl_wrap_socket(self.sock, self.key_file,
>>> +                                self.cert_file, cert_reqs=CERT_REQUIRED,
>>> +                                ca_certs=cacerts)
>>> +                        realhost = self.realhostport.rsplit(':', 1)[0]
>>> +                        msg = _verifycert(self.sock.getpeercert(), realhost)
>>> +                        if msg:
>>> +                            raise util.Abort(_('%s certificate error: %s') %
>>> +                                             (realhost, msg))
>>> +                        self.ui.debug('%s certificate successfully verified\n' %
>>> +                                      realhost)
>>> +                    else:
>>> +                        self.sock = _ssl_wrap_socket(self.sock, self.key_file,
>>> +                                self.cert_file)
>>>               else:
>>>                   BetterHTTPS.connect(self)
>>
>> This code path is not executed for me, but httpconnection.connect()
>> (url.py, line 140), which has no handling of cacerts.
>
> Line 338?

I wanted to write "line 340" for the socket.socket call, but yes,
338 (httpconnection.connect) is correct.

> Can you give a test case? Are you connecting to a https server through  
> proxy but using "http://"?

export http_proxy=http://proxy:8080/
./hg --config web.cacerts=Intevation-Root-CA-2010.crt in https://hg.intevation.de/mercurial/crew/

(CA file from https://ssl.intevation.de/Intevation-Root-CA-2010.crt)

> FWIW I don't understand why httpconnection.connect unconditionally wraps  
> in SSL if SSL is available and we are using proxy and we can CONNECT.  
> Shouldn't that only be done for https connections - which won't end up  
> in that code anyway? And what's the story behind the comment that we  
> don't support client x509 certificates?

What I just found out: Your patch works fine with Python 2.6, but
with Python 2.5 + ssl 1.15 it does not. Even test-https.t fails
in this case:

ERROR: /home/thomas/hg/repos/tah/tests/test-https.t output changed
--- /home/thomas/hg/repos/tah/tests/test-https.t 
+++ /home/thomas/hg/repos/tah/tests/test-https.t.err 
@@ -183,22 +183,20 @@
 Test verification of certificates when connecting with https through proxy
 
   $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True -R copy-pull pull
-  pulling from https://localhost:$HGPORT/
-  searching for changes
-  no changes found
+  abort: error: 
+  [255]
 
 Test using cacert through proxy
 
   $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True -R copy-pull pull --config web.cacerts=pub.pem
-  pulling from https://localhost:$HGPORT/
-  searching for changes
-  no changes found
+  abort: error: 
+  [255]
   $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True -R copy-pull pull --config web.cacerts=pub.pem https://127.0.0.1:$HGPORT/
-  abort: 127.0.0.1 certificate error: certificate is for localhost
+  abort: error: 
   [255]
   $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True -R copy-pull pull --config web.cacerts=pub-other.pem
-  abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
+  abort: error: 
   [255]
   $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True -R copy-pull pull --config web.cacerts=pub-expired.pem https://localhost:$HGPORT2/
-  abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
-  [255]
+  abort: error: 
+  [255]
!
Failed test-https.t: output changed
# Ran 1 tests, 0 skipped, 1 failed.


Regards,
Thomas

-- 
thomas at intevation.de - http://intevation.de/~thomas/ - OpenPGP key: 0x5816791A
Intevation GmbH, Neuer Graben 17, 49074 Osnabrueck - AG Osnabrueck, HR B 18998
Geschaeftsfuehrer: Frank Koormann, Bernhard Reiter, Dr. Jan-Oliver Wagner


More information about the Mercurial-devel mailing list