Skip to content

Commit 2d547de

Browse files
authored
add validation for urls with non-standard ports (#492)
* add validation for urls with non-standard ports * added validation behavior comment
1 parent e07cedc commit 2d547de

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

src/Twilio/Security/RequestValidator.cs

+24-3
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,16 @@ public bool Validate(string url, NameValueCollection parameters, string expected
4545
/// <returns>true if the signature matches the result; false otherwise</returns>
4646
public bool Validate(string url, IDictionary<string, string> parameters, string expected)
4747
{
48-
var signature = GetValidationSignature(url, parameters);
49-
return SecureCompare(signature, expected);
48+
// check signature of url with and without port, since sig generation on back end is inconsistent
49+
var signatureWithoutPort = GetValidationSignature(RemovePort(new UriBuilder(url)), parameters);
50+
var signatureWithPort = GetValidationSignature(AddPort(new UriBuilder(url)), parameters);
51+
// If either url produces a valid signature, we accept the request as valid
52+
return SecureCompare(signatureWithoutPort, expected) || SecureCompare(signatureWithPort, expected);
5053
}
5154

5255
public bool Validate(string url, string body, string expected)
5356
{
54-
var paramString = new Uri(url).Query.TrimStart('?');
57+
var paramString = new UriBuilder(url).Query.TrimStart('?');
5558
var bodyHash = "";
5659
foreach (var param in paramString.Split('&'))
5760
{
@@ -121,5 +124,23 @@ private static bool SecureCompare(string a, string b)
121124
return mismatch == 0;
122125
}
123126

127+
private string RemovePort(UriBuilder uri)
128+
{
129+
// UriBuilder.ToString() will not display the port
130+
// if the Port property is set to -1
131+
uri.Port = -1;
132+
return uri.ToString();
133+
}
134+
135+
private string AddPort(UriBuilder uri)
136+
{
137+
if (uri.Port != -1)
138+
{
139+
return uri.ToString();
140+
}
141+
uri.Port = uri.Scheme == "https" ? 443 : 80;
142+
return uri.ToString();
143+
}
144+
124145
}
125146
}

test/Twilio.Test/Security/RequestValidatorTest.cs

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Specialized;
1+
using System;
2+
using System.Collections.Specialized;
23
using NUnit.Framework;
34
using Twilio.Security;
45

@@ -69,5 +70,33 @@ public void TestValidateWithBodyWithoutSignature()
6970
{
7071
Assert.IsFalse(_validator.Validate(Url, Body, "RSOYDt4T1cUTdK1PDd93/VVr8B8="), "Request signature or body validation failed");
7172
}
73+
74+
[Test]
75+
public void TestValidateRemovesPortHttps()
76+
{
77+
const string url = "https://mycompany.com:1234/myapp.php?foo=1&bar=2";
78+
Assert.IsTrue(_validator.Validate(url, _parameters, "RSOYDt4T1cUTdK1PDd93/VVr8B8="), "Request does not match provided signature");
79+
}
80+
81+
[Test]
82+
public void TestValidateRemovesPortHttp()
83+
{
84+
const string url = "http://mycompany.com:1234/myapp.php?foo=1&bar=2";
85+
Assert.IsTrue(_validator.Validate(url, _parameters, "Zmvh+3yNM1Phv2jhDCwEM3q5ebU="), "Request does not match provided signature");
86+
}
87+
88+
[Test]
89+
public void TestValidateAddsPortHttps()
90+
{
91+
Assert.IsTrue(_validator.Validate(Url, _parameters, "kvajT1Ptam85bY51eRf/AJRuM3w="), "Request does not match provided signature");
92+
}
93+
94+
[Test]
95+
public void TestValidateAddsPortHttp()
96+
{
97+
const string url = "http://mycompany.com/myapp.php?foo=1&bar=2";
98+
Assert.IsTrue(_validator.Validate(url, _parameters, "0ZXoZLH/DfblKGATFgpif+LLRf4="), "Request does not match provided signature");
99+
}
100+
72101
}
73102
}

0 commit comments

Comments
 (0)