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): |
489 def _verifycert(cert, hostname): |
490 '''Verify that cert (in socket.getpeercert() format) matches hostname. |
490 '''Verify that cert (in socket.getpeercert() format) matches hostname. |
491 CRLs and subjectAltName are not handled. |
491 CRLs is not handled. |
492 |
492 |
493 Returns error message if any problems are found and None on success. |
493 Returns error message if any problems are found and None on success. |
494 ''' |
494 ''' |
495 if not cert: |
495 if not cert: |
496 return _('no certificate received') |
496 return _('no certificate received') |
497 dnsname = hostname.lower() |
497 dnsname = hostname.lower() |
|
498 def matchdnsname(certname): |
|
499 return (certname == dnsname or |
|
500 '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]) |
|
501 |
|
502 san = cert.get('subjectAltName', []) |
|
503 if san: |
|
504 certnames = [value.lower() for key, value in san if key == 'DNS'] |
|
505 for name in certnames: |
|
506 if matchdnsname(name): |
|
507 return None |
|
508 return _('certificate is for %s') % ', '.join(certnames) |
|
509 |
|
510 # subject is only checked when subjectAltName is empty |
498 for s in cert.get('subject', []): |
511 for s in cert.get('subject', []): |
499 key, value = s[0] |
512 key, value = s[0] |
500 if key == 'commonName': |
513 if key == 'commonName': |
501 try: |
514 try: |
502 # 'subject' entries are unicode |
515 # 'subject' entries are unicode |
503 certname = value.lower().encode('ascii') |
516 certname = value.lower().encode('ascii') |
504 except UnicodeEncodeError: |
517 except UnicodeEncodeError: |
505 return _('IDN in certificate not supported') |
518 return _('IDN in certificate not supported') |
506 if (certname == dnsname or |
519 if matchdnsname(certname): |
507 '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]): |
|
508 return None |
520 return None |
509 return _('certificate is for %s') % certname |
521 return _('certificate is for %s') % certname |
510 return _('no commonName found in certificate') |
522 return _('no commonName or subjectAltName found in certificate') |
511 |
523 |
512 if has_https: |
524 if has_https: |
513 class BetterHTTPS(httplib.HTTPSConnection): |
525 class BetterHTTPS(httplib.HTTPSConnection): |
514 send = keepalive.safesend |
526 send = keepalive.safesend |
515 |
527 |