Skip to content

Commit

Permalink
[stable-2.8] Don't rely on netloc for determining hostname and port, …
Browse files Browse the repository at this point in the history
…just use hostname and port (ansible#56270)

* Add changelog fragment
* Fix IPv6 address parsing for py2.6, and add tests
* make sure hostname isn't None
(cherry picked from commit 493cf81)

Co-authored-by: Matt Martz <matt@sivel.net>
  • Loading branch information
sivel committed May 21, 2019
1 parent 0586534 commit bc64637
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 13 deletions.
4 changes: 4 additions & 0 deletions changelogs/fragments/urls-ipv6-redirects.yml
Original file line number Diff line number Diff line change
@@ -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)
32 changes: 19 additions & 13 deletions lib/ansible/module_utils/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,8 +478,24 @@ def generic_urlparse(parts):
generic_parts['fragment'] = parts.fragment
generic_parts['username'] = parts.username
generic_parts['password'] = parts.password
generic_parts['hostname'] = parts.hostname
generic_parts['port'] = parts.port
hostname = parts.hostname
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:
# we have to use indexes, and then parse out
# the other parts not supported by indexing
Expand Down Expand Up @@ -882,19 +898,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,'
' 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
# 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'):
Expand Down
10 changes: 10 additions & 0 deletions test/units/module_utils/urls/test_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ def test_maybe_add_ssl_handler(mocker):
handler = urls.maybe_add_ssl_handler(url, True)
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():
header = urls.basic_auth_header('user', 'passwd')
Expand Down

0 comments on commit bc64637

Please sign in to comment.