##// END OF EJS Templates
url: check subjectAltName when verifying ssl certificate...
Yuya Nishihara -
r13249:75d0c38a stable
parent child Browse files
Show More
@@ -488,13 +488,26 b' class httphandler(keepalive.HTTPHandler)'
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':
@@ -503,11 +516,10 b' def _verifycert(cert, hostname):'
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):
@@ -25,6 +25,18 b" check(_verifycert(cert('*.example.com'),"
25 check(_verifycert(cert('*.example.com'), 'w.w.example.com'),
25 check(_verifycert(cert('*.example.com'), 'w.w.example.com'),
26 'certificate is for *.example.com')
26 'certificate is for *.example.com')
27
27
28 # Test subjectAltName
29 san_cert = {'subject': ((('commonName', 'example.com'),),),
30 'subjectAltName': (('DNS', '*.example.net'),
31 ('DNS', 'example.net'))}
32 check(_verifycert(san_cert, 'example.net'),
33 None)
34 check(_verifycert(san_cert, 'foo.example.net'),
35 None)
36 # subject is only checked when subjectAltName is empty
37 check(_verifycert(san_cert, 'example.com'),
38 'certificate is for *.example.net, example.net')
39
28 # Avoid some pitfalls
40 # Avoid some pitfalls
29 check(_verifycert(cert('*.foo'), 'foo'),
41 check(_verifycert(cert('*.foo'), 'foo'),
30 'certificate is for *.foo')
42 'certificate is for *.foo')
@@ -33,7 +45,7 b" check(_verifycert(cert('*o'), 'foo'),"
33
45
34 check(_verifycert({'subject': ()},
46 check(_verifycert({'subject': ()},
35 'example.com'),
47 'example.com'),
36 'no commonName found in certificate')
48 'no commonName or subjectAltName found in certificate')
37 check(_verifycert(None, 'example.com'),
49 check(_verifycert(None, 'example.com'),
38 'no certificate received')
50 'no certificate received')
39
51
General Comments 0
You need to be logged in to leave comments. Login now