Don't rely on netloc for determining hostname and port, just use hostname and port (#56270)

* Add changelog fragment
* Fix IPv6 address parsing for py2.6, and add tests
* make sure hostname isn't None
This commit is contained in:
Matt Martz 2019-05-20 15:50:55 -05:00 committed by Sam Doran
parent 66bfa27685
commit 493cf817a9
3 changed files with 33 additions and 13 deletions

View file

@ -0,0 +1,4 @@
bugfixes:
- urls - Handle redirects properly for IPv6 address by not splitting on ``:``
and rely on already parsed hostname and port values
(https://github.com/ansible/ansible/issues/56258)

View file

@ -559,8 +559,24 @@ def generic_urlparse(parts):
generic_parts['fragment'] = parts.fragment generic_parts['fragment'] = parts.fragment
generic_parts['username'] = parts.username generic_parts['username'] = parts.username
generic_parts['password'] = parts.password generic_parts['password'] = parts.password
generic_parts['hostname'] = parts.hostname hostname = parts.hostname
generic_parts['port'] = parts.port if hostname and hostname[0] == '[' and '[' in parts.netloc and ']' in parts.netloc:
# Py2.6 doesn't parse IPv6 addresses correctly
hostname = parts.netloc.split(']')[0][1:].lower()
generic_parts['hostname'] = hostname
try:
port = parts.port
except ValueError:
# Py2.6 doesn't parse IPv6 addresses correctly
netloc = parts.netloc.split('@')[-1].split(']')[-1]
if ':' in netloc:
port = netloc.split(':')[1]
if port:
port = int(port)
else:
port = None
generic_parts['port'] = port
else: else:
# we have to use indexes, and then parse out # we have to use indexes, and then parse out
# the other parts not supported by indexing # the other parts not supported by indexing
@ -963,19 +979,9 @@ def maybe_add_ssl_handler(url, validate_certs):
raise NoSSLError('SSL validation is not available in your version of python. You can use validate_certs=False,' raise NoSSLError('SSL validation is not available in your version of python. You can use validate_certs=False,'
' however this is unsafe and not recommended') ' however this is unsafe and not recommended')
# do the cert validation
netloc = parsed.netloc
if '@' in netloc:
netloc = netloc.split('@', 1)[1]
if ':' in netloc:
hostname, port = netloc.split(':', 1)
port = int(port)
else:
hostname = netloc
port = 443
# create the SSL validation handler and # create the SSL validation handler and
# add it to the list of handlers # add it to the list of handlers
return SSLValidationHandler(hostname, port) return SSLValidationHandler(parsed.hostname, parsed.port or 443)
def rfc2822_date_string(timetuple, zone='-0000'): def rfc2822_date_string(timetuple, zone='-0000'):

View file

@ -76,6 +76,16 @@ def test_maybe_add_ssl_handler(mocker):
handler = urls.maybe_add_ssl_handler(url, True) handler = urls.maybe_add_ssl_handler(url, True)
assert handler is None assert handler is None
url = 'https://[2a00:16d8:0:7::205]:4443/'
handler = urls.maybe_add_ssl_handler(url, True)
assert handler.hostname == '2a00:16d8:0:7::205'
assert handler.port == 4443
url = 'https://[2a00:16d8:0:7::205]/'
handler = urls.maybe_add_ssl_handler(url, True)
assert handler.hostname == '2a00:16d8:0:7::205'
assert handler.port == 443
def test_basic_auth_header(): def test_basic_auth_header():
header = urls.basic_auth_header('user', 'passwd') header = urls.basic_auth_header('user', 'passwd')