Show More
@@ -506,22 +506,38 b' class httphandler(keepalive.HTTPHandler)' | |||
|
506 | 506 | |
|
507 | 507 | def _verifycert(cert, hostname): |
|
508 | 508 | '''Verify that cert (in socket.getpeercert() format) matches hostname. |
|
509 |
CRLs |
|
|
509 | CRLs is not handled. | |
|
510 | 510 | |
|
511 | 511 | Returns error message if any problems are found and None on success. |
|
512 | 512 | ''' |
|
513 | 513 | if not cert: |
|
514 | 514 | return _('no certificate received') |
|
515 | 515 | dnsname = hostname.lower() |
|
516 | def matchdnsname(certname): | |
|
517 | return (certname == dnsname or | |
|
518 | '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]) | |
|
519 | ||
|
520 | san = cert.get('subjectAltName', []) | |
|
521 | if san: | |
|
522 | certnames = [value.lower() for key, value in san if key == 'DNS'] | |
|
523 | for name in certnames: | |
|
524 | if matchdnsname(name): | |
|
525 | return None | |
|
526 | return _('certificate is for %s') % ', '.join(certnames) | |
|
527 | ||
|
528 | # subject is only checked when subjectAltName is empty | |
|
516 | 529 | for s in cert.get('subject', []): |
|
517 | 530 | key, value = s[0] |
|
518 | 531 | if key == 'commonName': |
|
519 | certname = value.lower() | |
|
520 | if (certname == dnsname or | |
|
521 | '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]): | |
|
532 | try: | |
|
533 | # 'subject' entries are unicode | |
|
534 | certname = value.lower().encode('ascii') | |
|
535 | except UnicodeEncodeError: | |
|
536 | return _('IDN in certificate not supported') | |
|
537 | if matchdnsname(certname): | |
|
522 | 538 | return None |
|
523 | 539 | return _('certificate is for %s') % certname |
|
524 | return _('no commonName found in certificate') | |
|
540 | return _('no commonName or subjectAltName found in certificate') | |
|
525 | 541 | |
|
526 | 542 | if has_https: |
|
527 | 543 | class BetterHTTPS(httplib.HTTPSConnection): |
@@ -25,6 +25,18 b" check(_verifycert(cert('*.example.com')," | |||
|
25 | 25 | check(_verifycert(cert('*.example.com'), 'w.w.example.com'), |
|
26 | 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 | 40 | # Avoid some pitfalls |
|
29 | 41 | check(_verifycert(cert('*.foo'), 'foo'), |
|
30 | 42 | 'certificate is for *.foo') |
@@ -33,6 +45,10 b" check(_verifycert(cert('*o'), 'foo')," | |||
|
33 | 45 | |
|
34 | 46 | check(_verifycert({'subject': ()}, |
|
35 | 47 | 'example.com'), |
|
36 | 'no commonName found in certificate') | |
|
48 | 'no commonName or subjectAltName found in certificate') | |
|
37 | 49 | check(_verifycert(None, 'example.com'), |
|
38 | 50 | 'no certificate received') |
|
51 | ||
|
52 | # Unicode (IDN) certname isn't supported | |
|
53 | check(_verifycert(cert(u'\u4f8b.jp'), 'example.jp'), | |
|
54 | 'IDN in certificate not supported') |
General Comments 0
You need to be logged in to leave comments.
Login now