Skip to content

Commit

Permalink
add validation for urls with non-standard ports (#492)
Browse files Browse the repository at this point in the history
* add validation for urls with non-standard ports

* added validation behavior comment
  • Loading branch information
eshanholtz authored Sep 26, 2019
1 parent e07cedc commit 2d547de
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 4 deletions.
27 changes: 24 additions & 3 deletions src/Twilio/Security/RequestValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,16 @@ public bool Validate(string url, NameValueCollection parameters, string expected
/// <returns>true if the signature matches the result; false otherwise</returns>
public bool Validate(string url, IDictionary<string, string> parameters, string expected)
{
var signature = GetValidationSignature(url, parameters);
return SecureCompare(signature, expected);
// check signature of url with and without port, since sig generation on back end is inconsistent
var signatureWithoutPort = GetValidationSignature(RemovePort(new UriBuilder(url)), parameters);
var signatureWithPort = GetValidationSignature(AddPort(new UriBuilder(url)), parameters);
// If either url produces a valid signature, we accept the request as valid
return SecureCompare(signatureWithoutPort, expected) || SecureCompare(signatureWithPort, expected);
}

public bool Validate(string url, string body, string expected)
{
var paramString = new Uri(url).Query.TrimStart('?');
var paramString = new UriBuilder(url).Query.TrimStart('?');
var bodyHash = "";
foreach (var param in paramString.Split('&'))
{
Expand Down Expand Up @@ -121,5 +124,23 @@ private static bool SecureCompare(string a, string b)
return mismatch == 0;
}

private string RemovePort(UriBuilder uri)
{
// UriBuilder.ToString() will not display the port
// if the Port property is set to -1
uri.Port = -1;
return uri.ToString();
}

private string AddPort(UriBuilder uri)
{
if (uri.Port != -1)
{
return uri.ToString();
}
uri.Port = uri.Scheme == "https" ? 443 : 80;
return uri.ToString();
}

}
}
31 changes: 30 additions & 1 deletion test/Twilio.Test/Security/RequestValidatorTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Specialized;
using System;
using System.Collections.Specialized;
using NUnit.Framework;
using Twilio.Security;

Expand Down Expand Up @@ -69,5 +70,33 @@ public void TestValidateWithBodyWithoutSignature()
{
Assert.IsFalse(_validator.Validate(Url, Body, "RSOYDt4T1cUTdK1PDd93/VVr8B8="), "Request signature or body validation failed");
}

[Test]
public void TestValidateRemovesPortHttps()
{
const string url = "https://mycompany.com:1234/myapp.php?foo=1&bar=2";
Assert.IsTrue(_validator.Validate(url, _parameters, "RSOYDt4T1cUTdK1PDd93/VVr8B8="), "Request does not match provided signature");
}

[Test]
public void TestValidateRemovesPortHttp()
{
const string url = "http://mycompany.com:1234/myapp.php?foo=1&bar=2";
Assert.IsTrue(_validator.Validate(url, _parameters, "Zmvh+3yNM1Phv2jhDCwEM3q5ebU="), "Request does not match provided signature");
}

[Test]
public void TestValidateAddsPortHttps()
{
Assert.IsTrue(_validator.Validate(Url, _parameters, "kvajT1Ptam85bY51eRf/AJRuM3w="), "Request does not match provided signature");
}

[Test]
public void TestValidateAddsPortHttp()
{
const string url = "http://mycompany.com/myapp.php?foo=1&bar=2";
Assert.IsTrue(_validator.Validate(url, _parameters, "0ZXoZLH/DfblKGATFgpif+LLRf4="), "Request does not match provided signature");
}

}
}

0 comments on commit 2d547de

Please sign in to comment.