mercurial/url.py
branchstable
changeset 12592 f2937d6492c5
parent 12391 ca5fd84d62c6
child 12595 0f83a402faa0
child 12602 14198926975d
equal deleted inserted replaced
12576:1c9bb7e00f71 12592:f2937d6492c5
     5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
     5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
     6 #
     6 #
     7 # This software may be used and distributed according to the terms of the
     7 # This software may be used and distributed according to the terms of the
     8 # GNU General Public License version 2 or any later version.
     8 # GNU General Public License version 2 or any later version.
     9 
     9 
    10 import urllib, urllib2, urlparse, httplib, os, re, socket, cStringIO
    10 import urllib, urllib2, urlparse, httplib, os, re, socket, cStringIO, time
    11 from i18n import _
    11 from i18n import _
    12 import keepalive, util
    12 import keepalive, util
    13 
    13 
    14 def _urlunparse(scheme, netloc, path, params, query, fragment, url):
    14 def _urlunparse(scheme, netloc, path, params, query, fragment, url):
    15     '''Handle cases where urlunparse(urlparse(x://)) doesn't preserve the "//"'''
    15     '''Handle cases where urlunparse(urlparse(x://)) doesn't preserve the "//"'''
   467 
   467 
   468     def _start_transaction(self, h, req):
   468     def _start_transaction(self, h, req):
   469         _generic_start_transaction(self, h, req)
   469         _generic_start_transaction(self, h, req)
   470         return keepalive.HTTPHandler._start_transaction(self, h, req)
   470         return keepalive.HTTPHandler._start_transaction(self, h, req)
   471 
   471 
       
   472 def _verifycert(cert, hostname):
       
   473     '''Verify that cert (in socket.getpeercert() format) matches hostname and is 
       
   474     valid at this time. CRLs and subjectAltName are not handled.
       
   475     
       
   476     Returns error message if any problems are found and None on success.
       
   477     '''
       
   478     if not cert:
       
   479         return _('no certificate received')
       
   480     notafter = cert.get('notAfter')
       
   481     if notafter and time.time() > ssl.cert_time_to_seconds(notafter):
       
   482         return _('certificate expired %s') % notafter
       
   483     notbefore = cert.get('notBefore')
       
   484     if notbefore and time.time() < ssl.cert_time_to_seconds(notbefore):
       
   485         return _('certificate not valid before %s') % notbefore
       
   486     dnsname = hostname.lower()
       
   487     for s in cert.get('subject', []):
       
   488         key, value = s[0]
       
   489         if key == 'commonName':
       
   490             certname = value.lower()
       
   491             if (certname == dnsname or
       
   492                 '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]):
       
   493                 return None
       
   494             return _('certificate is for %s') % certname
       
   495     return _('no commonName found in certificate')
       
   496 
   472 if has_https:
   497 if has_https:
   473     class BetterHTTPS(httplib.HTTPSConnection):
   498     class BetterHTTPS(httplib.HTTPSConnection):
   474         send = keepalive.safesend
   499         send = keepalive.safesend
   475 
   500 
   476         def connect(self):
   501         def connect(self):
   482             if cacerts:
   507             if cacerts:
   483                 sock = _create_connection((self.host, self.port))
   508                 sock = _create_connection((self.host, self.port))
   484                 self.sock = _ssl_wrap_socket(sock, self.key_file,
   509                 self.sock = _ssl_wrap_socket(sock, self.key_file,
   485                         self.cert_file, cert_reqs=CERT_REQUIRED,
   510                         self.cert_file, cert_reqs=CERT_REQUIRED,
   486                         ca_certs=cacerts)
   511                         ca_certs=cacerts)
   487                 self.ui.debug(_('server identity verification succeeded\n'))
   512                 msg = _verifycert(self.sock.getpeercert(), self.host)
       
   513                 if msg:
       
   514                     raise util.Abort('%s certificate error: %s' % (self.host, msg))
       
   515                 self.ui.debug(_('%s certificate successfully verified\n') % 
       
   516                     self.host)
   488             else:
   517             else:
   489                 httplib.HTTPSConnection.connect(self)
   518                 httplib.HTTPSConnection.connect(self)
   490 
   519 
   491     class httpsconnection(BetterHTTPS):
   520     class httpsconnection(BetterHTTPS):
   492         response_class = keepalive.HTTPResponse
   521         response_class = keepalive.HTTPResponse