Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

179 lines
7.4 KiB
C#

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Web.Mvc;
using Moq;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Helpers.AntiXsrf.Test
{
public class AntiForgeryTokenSerializerTest
{
private static readonly AntiForgeryTokenSerializer _testSerializer = new AntiForgeryTokenSerializer(cryptoSystem: CreateIdentityTransformCryptoSystem());
private static readonly BinaryBlob _claimUid = new BinaryBlob(256, new byte[] { 0x6F, 0x16, 0x48, 0xE9, 0x72, 0x49, 0xAA, 0x58, 0x75, 0x40, 0x36, 0xA6, 0x7E, 0x24, 0x8C, 0xF0, 0x44, 0xF0, 0x7E, 0xCF, 0xB0, 0xED, 0x38, 0x75, 0x56, 0xCE, 0x02, 0x9A, 0x4F, 0x9A, 0x40, 0xE0 });
private static readonly BinaryBlob _securityToken = new BinaryBlob(128, new byte[] { 0x70, 0x5E, 0xED, 0xCC, 0x7D, 0x42, 0xF1, 0xD6, 0xB3, 0xB9, 0x8A, 0x59, 0x36, 0x25, 0xBB, 0x4C });
[Theory]
[InlineData(
"01" // Version
+ "705EEDCC7D42F1D6B3B9" // SecurityToken
// (WRONG!) Stream ends too early
)]
[InlineData(
"01" // Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "01" // IsSessionToken
+ "00" // (WRONG!) Too much data in stream
)]
[InlineData(
"02" // (WRONG! - must be 0x01) Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "01" // IsSessionToken
)]
[InlineData(
"01" // Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "00" // IsSessionToken
+ "00" // IsClaimsBased
+ "05" // Username length header
+ "0000" // (WRONG!) Too little data in stream
)]
public void Deserialize_BadToken(string serializedToken)
{
// Act & assert
var ex = Assert.Throws<HttpAntiForgeryException>(() => _testSerializer.Deserialize(serializedToken));
Assert.Equal(@"The anti-forgery token could not be decrypted. If this application is hosted by a Web Farm or cluster, ensure that all machines are running the same version of ASP.NET Web Pages and that the <machineKey> configuration specifies explicit encryption and validation keys. AutoGenerate cannot be used in a cluster.", ex.Message);
}
[Fact]
public void Serialize_FieldToken_WithClaimUid()
{
// Arrange
const string expectedSerializedData =
"01" // Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "00" // IsSessionToken
+ "01" // IsClaimsBased
+ "6F1648E97249AA58754036A67E248CF044F07ECFB0ED387556CE029A4F9A40E0" // ClaimUid
+ "05" // AdditionalData length header
+ "E282AC3437"; // AdditionalData ("€47") as UTF8
AntiForgeryToken token = new AntiForgeryToken()
{
SecurityToken = _securityToken,
IsSessionToken = false,
ClaimUid = _claimUid,
AdditionalData = "€47"
};
// Act & assert - serialization
string actualSerializedData = _testSerializer.Serialize(token);
Assert.Equal(expectedSerializedData, actualSerializedData);
// Act & assert - deserialization
AntiForgeryToken deserializedToken = _testSerializer.Deserialize(actualSerializedData);
AssertTokensEqual(token, deserializedToken);
}
[Fact]
public void Serialize_FieldToken_WithUsername()
{
// Arrange
const string expectedSerializedData =
"01" // Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "00" // IsSessionToken
+ "00" // IsClaimsBased
+ "08" // Username length header
+ "4AC3A972C3B46D65" // Username ("Jérôme") as UTF8
+ "05" // AdditionalData length header
+ "E282AC3437"; // AdditionalData ("€47") as UTF8
AntiForgeryToken token = new AntiForgeryToken()
{
SecurityToken = _securityToken,
IsSessionToken = false,
Username = "Jérôme",
AdditionalData = "€47"
};
// Act & assert - serialization
string actualSerializedData = _testSerializer.Serialize(token);
Assert.Equal(expectedSerializedData, actualSerializedData);
// Act & assert - deserialization
AntiForgeryToken deserializedToken = _testSerializer.Deserialize(actualSerializedData);
AssertTokensEqual(token, deserializedToken);
}
[Fact]
public void Serialize_SessionToken()
{
// Arrange
const string expectedSerializedData =
"01" // Version
+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
+ "01"; // IsSessionToken
AntiForgeryToken token = new AntiForgeryToken()
{
SecurityToken = _securityToken,
IsSessionToken = true
};
// Act & assert - serialization
string actualSerializedData = _testSerializer.Serialize(token);
Assert.Equal(expectedSerializedData, actualSerializedData);
// Act & assert - deserialization
AntiForgeryToken deserializedToken = _testSerializer.Deserialize(actualSerializedData);
AssertTokensEqual(token, deserializedToken);
}
private static string BytesToHex(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in bytes)
{
sb.AppendFormat(CultureInfo.InvariantCulture, "{0:X2}", b);
}
return sb.ToString();
}
private static byte[] HexToBytes(string hex)
{
List<byte> bytes = new List<byte>();
for (int i = 0; i < hex.Length; i += 2)
{
byte b = Byte.Parse(hex.Substring(i, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
bytes.Add(b);
}
return bytes.ToArray();
}
private static ICryptoSystem CreateIdentityTransformCryptoSystem()
{
Mock<MockableCryptoSystem> mockCryptoSystem = new Mock<MockableCryptoSystem>();
mockCryptoSystem.Setup(o => o.Protect(It.IsAny<byte[]>())).Returns<byte[]>(HexUtil.HexEncode);
mockCryptoSystem.Setup(o => o.Unprotect(It.IsAny<string>())).Returns<string>(HexUtil.HexDecode);
return mockCryptoSystem.Object;
}
private static void AssertTokensEqual(AntiForgeryToken expected, AntiForgeryToken actual)
{
Assert.NotNull(expected);
Assert.NotNull(actual);
Assert.Equal(expected.AdditionalData, actual.AdditionalData);
Assert.Equal(expected.ClaimUid, actual.ClaimUid);
Assert.Equal(expected.IsSessionToken, actual.IsSessionToken);
Assert.Equal(expected.SecurityToken, actual.SecurityToken);
Assert.Equal(expected.Username, actual.Username);
}
}
}