8000 added validation of signature without stripping port number (#477) · githubib/twilio-python@d881810 · GitHub
[go: up one dir, main page]

Skip to content

Commit d881810

Browse files
authored
added validation of signature without stripping port number (twilio#477)
* added validation of signature without stripping port number * fixed style errors * refactored signature validation * refactored control flow for efficiency * added test case for new validation control flow * refactored add/remove port * simplified port selection * style/formatting improvements
1 parent 77b44a5 commit d881810

File tree

2 files changed

+48
-7
lines changed

2 files changed

+48
-7
lines changed

tests/unit/test_request_validator.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ def test_validation_removes_port_on_https(self):
5353
uri = self.uri.replace(".com", ".com:1234")
5454
assert_true(self.validator.validate(uri, self.params, self.expected))
5555

56+
def test_validation_removes_port_on_http(self):
57+
expected = "Zmvh+3yNM1Phv2jhDCwEM3q5ebU=" # hash of http uri with port 1234
58+
uri = self.uri.replace(".com", ".com:1234").replace("https", "http")
59+
assert_true(self.validator.validate(uri, self.params, expected))
60+
61+
def test_validation_adds_port_on_https(self):
62+
expected = "kvajT1Ptam85bY51eRf/AJRuM3w=" # hash of uri with port 443
63+
assert_true(self.validator.validate(self.uri, self.params, expected))
64+
65+
def test_validation_adds_port_on_http(self):
66+
uri = self.uri.replace("https", "http")
67+
expected = "0ZXoZLH/DfblKGATFgpif+LLRf4=" # hash of uri with port 80
68+
assert_true(self.validator.validate(uri, self.params, expected))
69+
5670
def test_validation_of_body_succeeds(self):
5771
uri = self.uriWithBody
5872
is_valid = self.validator.validate(uri, self.body, "a9nBmqA0ju/hNViExpshrM61xv4=")

twilio/request_validator.py

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,42 @@ def compare(string1, string2):
2121
result = True
2222
for c1, c2 in izip(string1, string2):
2323
result &= c1 == c2
24+
2425
return result
2526

2627

2728
def remove_port(uri):
2829
"""Remove the port number from a URI
2930
30-
:param uri: full URI that Twilio requested on your server
31+
:param uri: parsed URI that Twilio requested on your server
3132
3233
:returns: full URI without a port number
3334
:rtype: str
3435
"""
36+
if not uri.port:
37+
return uri.geturl()
38+
3539
new_netloc = uri.netloc.split(':')[0]
3640
new_uri = uri._replace(netloc=new_netloc)
41+
42+
return new_uri.geturl()
43+
44+
45+
def add_port(uri):
46+
"""Add the port number to a URI
47+
48+
:param uri: parsed URI that Twilio requested on your server
49+
50+
:returns: full URI with a port number
51+
:rtype: str
52+
"""
53+
if uri.port:
54+
return uri.geturl()
55+
56+
port = 443 if uri.scheme == "https" else 80
57+
new_netloc = uri.netloc + ":" + str(port)
58+
new_uri = uri._replace(netloc=new_netloc)
59+
3760
return new_uri.geturl()
3861

3962

@@ -82,17 +105,21 @@ def validate(self, uri, params, signature):
82105
params = {}
83106

84107
parsed_uri = urlparse(uri)
85-
if parsed_uri.scheme == "https" and parsed_uri.port:
86-
uri = remove_port(parsed_uri)
108+
uri_with_port = add_port(parsed_uri)
109+
uri_without_port = remove_port(parsed_uri)
87110

88111
valid_signature = False # Default fail
112+
valid_signature_with_port = False
89113
valid_body_hash = True # May not receive body hash, so default succeed
90114

91115
query = parse_qs(parsed_uri.query)
92116
if "bodySHA256" in query and isinstance(params, string_types):
93117
valid_body_hash = compare(self.compute_hash(params), query["bodySHA256"][0])
94-
valid_signature = compare(self.compute_signature(uri, {}), signature)
95-
else:
96-
valid_signature = compare(self.compute_signature(uri, params), signature)
118+
params = {}
119+
120+
# check signature of uri with and without port,
121+
# since sig generation on back end is inconsistent
122+
valid_signature = compare(self.compute_signature(uri_without_port, params), signature)
123+
valid_signature_with_port = compare(self.compute_signature(uri_with_port, params), signature)
97124

98-
return valid_signature and valid_body_hash
125+
return valid_body_hash and (valid_signature or valid_signature_with_port)

0 commit comments

Comments
 (0)
0