public void TestGetDigest() { Request request = new Request(); List<CustomProperty> props = new List<CustomProperty>(); props.Add(new CustomProperty("Subject", "This is a subject")); RoutingEntity sourceRouting = new RoutingEntity(); RoutingItem item = new RoutingItem(); item.Content = "*****@*****.**"; sourceRouting.Items = new RoutingItem[] {item}; request.Source = sourceRouting; request.Properties = props.ToArray(); string digest1 = new RequestDigestProvider().GetDigest(request); //change the request, get a different digest value. request.Source.Items[0].Content = "*****@*****.**"; string digest2 = new RequestDigestProvider().GetDigest(request); Assert.AreNotEqual(digest1,digest2); request.Properties[0].Value = "Change the subject"; string digest3 = new RequestDigestProvider().GetDigest(request); Assert.AreNotEqual(digest1,digest2); Assert.AreNotEqual(digest2, digest3); //Empty subject is OK request.Properties[0].Value = string.Empty; string digest4 = new RequestDigestProvider().GetDigest(request); Assert.AreNotEqual(digest1,digest4); }
public void GetDigestRoutingItemIsCaseInsensitive() { Request request = new Request(); List<CustomProperty> props = new List<CustomProperty>(); props.Add(new CustomProperty("Subject", "This is a subject")); RoutingEntity sourceRouting = new RoutingEntity(); RoutingItem item = new RoutingItem(); item.Content = "*****@*****.**"; sourceRouting.Items = new RoutingItem[] { item }; request.Source = sourceRouting; request.Properties = props.ToArray(); string digest1 = new RequestDigestProvider().GetDigest(request); request.Source.Items[0].Content = request.Source.Items[0].Content.ToUpperInvariant(); string digest2 = new RequestDigestProvider().GetDigest(request); Assert.AreEqual(digest1,digest2); }
public void GetDigestMissingSource() { Request request = new Request(); List<CustomProperty> props = new List<CustomProperty>(); props.Add(new CustomProperty("Subject", "This is a subject")); request.Properties = props.ToArray(); request.Source = null; //Invalid, this should cause the throw try { string digest = new RequestDigestProvider().GetDigest(request); } catch (ArgumentException) { Assert.IsTrue(true, "Expecting method to throw this ArgumentException"); return; } Assert.Fail("Should have thrown the ArgumentException"); }
public void GetDigestMissingSubjectProperty() { Request request = new Request(); request.Properties = new CustomProperty[0];//Invalid, this should cause the throw RoutingEntity sourceRouting = new RoutingEntity(); sourceRouting.RoutingType = "Source"; RoutingItem item = new RoutingItem(); item.Content = "*****@*****.**"; sourceRouting.Items = new RoutingItem[] { item }; request.Source = sourceRouting; try { string digest = new RequestDigestProvider().GetDigest(request); } catch (ArgumentException) { Assert.IsTrue(true, "Expecting method to throw this ArgumentException"); return; } Assert.Fail("Should have thrown the ArgumentException"); }
public void GetDigestEmptyRoutingItem() { Request request = new Request(); List<CustomProperty> props = new List<CustomProperty>(); props.Add(new CustomProperty("Subject", "This is a subject")); request.Properties = props.ToArray(); RoutingEntity sourceRouting = new RoutingEntity(); RoutingItem item = new RoutingItem(); item.Content = string.Empty; //Invalid, this should cause the throw sourceRouting.Items = new RoutingItem[] { item }; request.Source = sourceRouting; request.Properties = props.ToArray(); try { string digest = new RequestDigestProvider().GetDigest(request); } catch (ArgumentException) { Assert.IsTrue(true, "Expecting method to throw this ArgumentException"); return; } Assert.Fail("Should have thrown the ArgumentException"); }
/// <summary> /// This method checks a certain property is present in the FileHeaders property, and that the value matches /// a hash of some request-specific properties. /// </summary> /// <param name="request"></param> /// <returns></returns> /// <remarks> /// Only expect this to be true for messages that were processed by Protect on the client, and then picked up at another /// egress point such as the MTA or Network monitor. /// Only messages processed by protect client will have the prerequisite fileheader property. ///</remarks> private static bool VerifyRequest(Request request) { try { if (request == null || request.Properties == null) { return false; } CustomProperty fileHeaderProperty = Array.Find(request.Properties, cp => cp.Name.Equals("FileHeader", StringComparison.InvariantCultureIgnoreCase)); if (fileHeaderProperty == null || string.IsNullOrEmpty(fileHeaderProperty.Value)) { return false; } HeaderParser parser = new HeaderParser(fileHeaderProperty.Value); string actualValue = parser.GetHeaderValue(RequestDigestProvider.XHEADER_MESSAGE_PROTECTED); if (string.IsNullOrEmpty(actualValue)) { return false; } actualValue = actualValue.Trim(); string expectedHashValue = new RequestDigestProvider().GetDigest(request); if (!actualValue.Equals(expectedHashValue, StringComparison.InvariantCultureIgnoreCase)) { Logger.LogInfo("A request failed hash validation. It will be processed by all policies. FileHeader contents: " + fileHeaderProperty.Value); return false; } Logger.LogInfo("Request passed hash validation, therefore it was sent via a Protect-compatible email client."); return true; } catch (Exception e) { //Some requests passed in here will currently pass unexpected arguments, namely the NetworkMonitor. //NetMon code is currently passing an unexpected number of routing items. //In all cases where unexpected arguments are passed or any other problem is encountered, //treat this as failure to verify the message, therefore returning false. Logger.LogError("A request failed hash validation due to an exception. It will be processed by all policies."); Logger.LogError(e); return false; } }