diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2015-02-15 17:12:20 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2015-02-15 17:12:20 (GMT) |
commit | c481bfb3f62787e9ef0947785df7383a173a23c3 (patch) | |
tree | c7d6b4745a46c9d535ce3f413c4dd0f69f488f84 /Lib/ssl.py | |
parent | 2d07b855855c13814c2050f2f062aadf936fa886 (diff) | |
download | cpython-c481bfb3f62787e9ef0947785df7383a173a23c3.zip cpython-c481bfb3f62787e9ef0947785df7383a173a23c3.tar.gz cpython-c481bfb3f62787e9ef0947785df7383a173a23c3.tar.bz2 |
Issue #23239: ssl.match_hostname() now supports matching of IP addresses.
Diffstat (limited to 'Lib/ssl.py')
-rw-r--r-- | Lib/ssl.py | 23 |
1 files changed, 22 insertions, 1 deletions
@@ -87,6 +87,7 @@ ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY """ +import ipaddress import textwrap import re import sys @@ -242,6 +243,17 @@ def _dnsname_match(dn, hostname, max_wildcards=1): return pat.match(hostname) +def _ipaddress_match(ipname, host_ip): + """Exact matching of IP addresses. + + RFC 6125 explicitly doesn't define an algorithm for this + (section 1.7.2 - "Out of Scope"). + """ + # OpenSSL may add a trailing newline to a subjectAltName's IP address + ip = ipaddress.ip_address(ipname.rstrip()) + return ip == host_ip + + def match_hostname(cert, hostname): """Verify that *cert* (in decoded format as returned by SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 @@ -254,11 +266,20 @@ def match_hostname(cert, hostname): raise ValueError("empty or no certificate, match_hostname needs a " "SSL socket or SSL context with either " "CERT_OPTIONAL or CERT_REQUIRED") + try: + host_ip = ipaddress.ip_address(hostname) + except ValueError: + # Not an IP address (common case) + host_ip = None dnsnames = [] san = cert.get('subjectAltName', ()) for key, value in san: if key == 'DNS': - if _dnsname_match(value, hostname): + if host_ip is None and _dnsname_match(value, hostname): + return + dnsnames.append(value) + elif key == 'IP Address': + if host_ip is not None and _ipaddress_match(value, host_ip): return dnsnames.append(value) if not dnsnames: |