mercurial/url.py
changeset 12595 0f83a402faa0
parent 12394 9d45f78c465b
parent 12592 f2937d6492c5
child 12607 1393a81b3bdc
equal deleted inserted replaced
12591:4b9f23885a55 12595:0f83a402faa0
     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 import __builtin__
    11 import __builtin__
    12 from i18n import _
    12 from i18n import _
    13 import keepalive, util
    13 import keepalive, util
    14 
    14 
    15 def _urlunparse(scheme, netloc, path, params, query, fragment, url):
    15 def _urlunparse(scheme, netloc, path, params, query, fragment, url):
   484 
   484 
   485     def _start_transaction(self, h, req):
   485     def _start_transaction(self, h, req):
   486         _generic_start_transaction(self, h, req)
   486         _generic_start_transaction(self, h, req)
   487         return keepalive.HTTPHandler._start_transaction(self, h, req)
   487         return keepalive.HTTPHandler._start_transaction(self, h, req)
   488 
   488 
       
   489 def _verifycert(cert, hostname):
       
   490     '''Verify that cert (in socket.getpeercert() format) matches hostname and is 
       
   491     valid at this time. CRLs and subjectAltName are not handled.
       
   492     
       
   493     Returns error message if any problems are found and None on success.
       
   494     '''
       
   495     if not cert:
       
   496         return _('no certificate received')
       
   497     notafter = cert.get('notAfter')
       
   498     if notafter and time.time() > ssl.cert_time_to_seconds(notafter):
       
   499         return _('certificate expired %s') % notafter
       
   500     notbefore = cert.get('notBefore')
       
   501     if notbefore and time.time() < ssl.cert_time_to_seconds(notbefore):
       
   502         return _('certificate not valid before %s') % notbefore
       
   503     dnsname = hostname.lower()
       
   504     for s in cert.get('subject', []):
       
   505         key, value = s[0]
       
   506         if key == 'commonName':
       
   507             certname = value.lower()
       
   508             if (certname == dnsname or
       
   509                 '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]):
       
   510                 return None
       
   511             return _('certificate is for %s') % certname
       
   512     return _('no commonName found in certificate')
       
   513 
   489 if has_https:
   514 if has_https:
   490     class BetterHTTPS(httplib.HTTPSConnection):
   515     class BetterHTTPS(httplib.HTTPSConnection):
   491         send = keepalive.safesend
   516         send = keepalive.safesend
   492 
   517 
   493         def connect(self):
   518         def connect(self):
   499             if cacerts:
   524             if cacerts:
   500                 sock = _create_connection((self.host, self.port))
   525                 sock = _create_connection((self.host, self.port))
   501                 self.sock = _ssl_wrap_socket(sock, self.key_file,
   526                 self.sock = _ssl_wrap_socket(sock, self.key_file,
   502                         self.cert_file, cert_reqs=CERT_REQUIRED,
   527                         self.cert_file, cert_reqs=CERT_REQUIRED,
   503                         ca_certs=cacerts)
   528                         ca_certs=cacerts)
   504                 self.ui.debug(_('server identity verification succeeded\n'))
   529                 msg = _verifycert(self.sock.getpeercert(), self.host)
       
   530                 if msg:
       
   531                     raise util.Abort('%s certificate error: %s' % (self.host, msg))
       
   532                 self.ui.debug(_('%s certificate successfully verified\n') % 
       
   533                     self.host)
   505             else:
   534             else:
   506                 httplib.HTTPSConnection.connect(self)
   535                 httplib.HTTPSConnection.connect(self)
   507 
   536 
   508     class httpsconnection(BetterHTTPS):
   537     class httpsconnection(BetterHTTPS):
   509         response_class = keepalive.HTTPResponse
   538         response_class = keepalive.HTTPResponse