gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / requests / packages / urllib3 / packages / ssl_match_hostname / _implementation.py @ 564
History | View | Annotate | Download (3.69 KB)
1 |
"""The match_hostname() function from Python 3.3.3, essential when using SSL."""
|
---|---|
2 |
|
3 |
# Note: This file is under the PSF license as the code comes from the python
|
4 |
# stdlib. http://docs.python.org/3/license.html
|
5 |
|
6 |
import re |
7 |
|
8 |
__version__ = '3.4.0.2'
|
9 |
|
10 |
class CertificateError(ValueError): |
11 |
pass
|
12 |
|
13 |
|
14 |
def _dnsname_match(dn, hostname, max_wildcards=1): |
15 |
"""Matching according to RFC 6125, section 6.4.3
|
16 |
|
17 |
http://tools.ietf.org/html/rfc6125#section-6.4.3
|
18 |
"""
|
19 |
pats = [] |
20 |
if not dn: |
21 |
return False |
22 |
|
23 |
# Ported from python3-syntax:
|
24 |
# leftmost, *remainder = dn.split(r'.')
|
25 |
parts = dn.split(r'.')
|
26 |
leftmost = parts[0]
|
27 |
remainder = parts[1:]
|
28 |
|
29 |
wildcards = leftmost.count('*')
|
30 |
if wildcards > max_wildcards:
|
31 |
# Issue #17980: avoid denials of service by refusing more
|
32 |
# than one wildcard per fragment. A survey of established
|
33 |
# policy among SSL implementations showed it to be a
|
34 |
# reasonable choice.
|
35 |
raise CertificateError(
|
36 |
"too many wildcards in certificate DNS name: " + repr(dn)) |
37 |
|
38 |
# speed up common case w/o wildcards
|
39 |
if not wildcards: |
40 |
return dn.lower() == hostname.lower()
|
41 |
|
42 |
# RFC 6125, section 6.4.3, subitem 1.
|
43 |
# The client SHOULD NOT attempt to match a presented identifier in which
|
44 |
# the wildcard character comprises a label other than the left-most label.
|
45 |
if leftmost == '*': |
46 |
# When '*' is a fragment by itself, it matches a non-empty dotless
|
47 |
# fragment.
|
48 |
pats.append('[^.]+')
|
49 |
elif leftmost.startswith('xn--') or hostname.startswith('xn--'): |
50 |
# RFC 6125, section 6.4.3, subitem 3.
|
51 |
# The client SHOULD NOT attempt to match a presented identifier
|
52 |
# where the wildcard character is embedded within an A-label or
|
53 |
# U-label of an internationalized domain name.
|
54 |
pats.append(re.escape(leftmost)) |
55 |
else:
|
56 |
# Otherwise, '*' matches any dotless string, e.g. www*
|
57 |
pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) |
58 |
|
59 |
# add the remaining fragments, ignore any wildcards
|
60 |
for frag in remainder: |
61 |
pats.append(re.escape(frag)) |
62 |
|
63 |
pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) |
64 |
return pat.match(hostname)
|
65 |
|
66 |
|
67 |
def match_hostname(cert, hostname): |
68 |
"""Verify that *cert* (in decoded format as returned by
|
69 |
SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125
|
70 |
rules are followed, but IP addresses are not accepted for *hostname*.
|
71 |
|
72 |
CertificateError is raised on failure. On success, the function
|
73 |
returns nothing.
|
74 |
"""
|
75 |
if not cert: |
76 |
raise ValueError("empty or no certificate") |
77 |
dnsnames = [] |
78 |
san = cert.get('subjectAltName', ())
|
79 |
for key, value in san: |
80 |
if key == 'DNS': |
81 |
if _dnsname_match(value, hostname):
|
82 |
return
|
83 |
dnsnames.append(value) |
84 |
if not dnsnames: |
85 |
# The subject is only checked when there is no dNSName entry
|
86 |
# in subjectAltName
|
87 |
for sub in cert.get('subject', ()): |
88 |
for key, value in sub: |
89 |
# XXX according to RFC 2818, the most specific Common Name
|
90 |
# must be used.
|
91 |
if key == 'commonName': |
92 |
if _dnsname_match(value, hostname):
|
93 |
return
|
94 |
dnsnames.append(value) |
95 |
if len(dnsnames) > 1: |
96 |
raise CertificateError("hostname %r " |
97 |
"doesn't match either of %s"
|
98 |
% (hostname, ', '.join(map(repr, dnsnames)))) |
99 |
elif len(dnsnames) == 1: |
100 |
raise CertificateError("hostname %r " |
101 |
"doesn't match %r"
|
102 |
% (hostname, dnsnames[0]))
|
103 |
else:
|
104 |
raise CertificateError("no appropriate commonName or " |
105 |
"subjectAltName fields were found")
|