Skip to content

Commit 7c0a937

Browse files
committed
Treat the 'algorithm' parameter in Digest HTTP authentication as case-insensitive (dotnet/corefx#32632)
dotnet/corefx#32632
1 parent fc15f27 commit 7c0a937

File tree

4 files changed

+16
-6
lines changed

4 files changed

+16
-6
lines changed

StandardSocketsHttpHandler.FunctionalTests/Common/Net/LoopbackServer.AuthenticationHelpers.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,11 @@ internal static bool IsDigestAuthTokenValid(string clientResponse, string reques
248248
}
249249

250250
if (string.IsNullOrEmpty(algorithm))
251-
algorithm = "sha-256";
251+
algorithm = "MD5";
252252

253253
// Calculate response and compare with the client response hash.
254254
string a1 = options.Username + ":" + realm + ":" + options.Password;
255-
if (algorithm.Contains("sess"))
255+
if (algorithm.EndsWith("sess", StringComparison.OrdinalIgnoreCase))
256256
{
257257
a1 = ComputeHash(a1, algorithm) + ":" + nonce;
258258

@@ -288,7 +288,7 @@ private static string ComputeHash(string data, string algorithm)
288288
{
289289
// Disable MD5 insecure warning.
290290
#pragma warning disable CA5351
291-
using (HashAlgorithm hash = algorithm.Contains("SHA-256") ? SHA256.Create() : (HashAlgorithm)MD5.Create())
291+
using (HashAlgorithm hash = algorithm.StartsWith("SHA-256", StringComparison.OrdinalIgnoreCase) ? SHA256.Create() : (HashAlgorithm)MD5.Create())
292292
#pragma warning restore CA5351
293293
{
294294
Encoding enc = Encoding.UTF8;

StandardSocketsHttpHandler.FunctionalTests/HttpClientHandlerTest.Authentication.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ public static IEnumerable<object[]> Authentication_TestData()
145145
yield return new object[] { "basic", true };
146146

147147
yield return new object[] { $"Digest realm=\"testrealm\", nonce=\"{Convert.ToBase64String(Encoding.UTF8.GetBytes($"{DateTimeOffset.UtcNow}:XMh;z+$5|`i6Hx}}\", qop=auth-int, algorithm=MD5"))}\"", true };
148+
yield return new object[] { $"Digest realm=\"testrealm\", nonce=\"{Convert.ToBase64String(Encoding.UTF8.GetBytes($"{DateTimeOffset.UtcNow}:XMh;z+$5|`i6Hx}}\", qop=auth-int, algorithm=md5"))}\"", true };
148149
yield return new object[] { $"Basic realm=\"testrealm\", " +
149150
$"Digest realm=\"testrealm\", nonce=\"{Convert.ToBase64String(Encoding.UTF8.GetBytes($"{DateTimeOffset.UtcNow}:XMh;z+$5|`i6Hx}}"))}\", algorithm=MD5", true };
150151

StandardSocketsHttpHandler.FunctionalTests/SocketsHttpHandlerTest.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,12 @@ public static IEnumerable<object[]> Authentication_SocketsHttpHandler_TestData()
566566
yield return new object[] { "Digest realm=withoutquotes, nonce=withoutquotes", false };
567567
yield return new object[] { "Digest realm=\"testrealm\" nonce=\"testnonce\"", false };
568568
yield return new object[] { "Digest realm=\"testrealm1\", nonce=\"testnonce1\" Digest realm=\"testrealm2\", nonce=\"testnonce2\"", false };
569+
570+
// These tests check that the algorithm parameter is treated in case insensitive way.
571+
// WinHTTP only supports plain MD5, so other algorithms are included here.
572+
yield return new object[] { $"Digest realm=\"testrealm\", algorithm=md5-Sess, nonce=\"testnonce\"", true };
573+
yield return new object[] { $"Digest realm=\"testrealm\", algorithm=sha-256, nonce=\"testnonce\"", true };
574+
yield return new object[] { $"Digest realm=\"testrealm\", algorithm=sha-256-SESS, nonce=\"testnonce\"", true };
569575
}
570576
}
571577

StandardSocketsHttpHandler/Net/Http/SocketsHttpHandler/AuthenticationHelper.Digest.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ public static async Task<string> GetDigestTokenForCredential(NetworkCredential c
4949
string algorithm;
5050
if (digestResponse.Parameters.TryGetValue(Algorithm, out algorithm))
5151
{
52-
if (algorithm != Sha256 && algorithm != Md5 && algorithm != Sha256Sess && algorithm != MD5Sess)
52+
if (!algorithm.Equals(Sha256, StringComparison.OrdinalIgnoreCase) &&
53+
!algorithm.Equals(Md5, StringComparison.OrdinalIgnoreCase) &&
54+
!algorithm.Equals(Sha256Sess, StringComparison.OrdinalIgnoreCase) &&
55+
!algorithm.Equals(MD5Sess, StringComparison.OrdinalIgnoreCase))
5356
{
5457
if (NetEventSource.IsEnabled) NetEventSource.Error(digestResponse, "Algorithm not supported: {algorithm}");
5558
return null;
@@ -138,7 +141,7 @@ public static async Task<string> GetDigestTokenForCredential(NetworkCredential c
138141

139142
// Calculate response
140143
string a1 = credential.UserName + ":" + realm + ":" + credential.Password;
141-
if (algorithm.IndexOf("sess") != -1)
144+
if (algorithm.EndsWith("sess", StringComparison.OrdinalIgnoreCase))
142145
{
143146
a1 = ComputeHash(a1, algorithm) + ":" + nonce + ":" + cnonce;
144147
}
@@ -209,7 +212,7 @@ private static string ComputeHash(string data, string algorithm)
209212
{
210213
// Disable MD5 insecure warning.
211214
#pragma warning disable CA5351
212-
using (HashAlgorithm hash = algorithm.Contains(Sha256) ? SHA256.Create() : (HashAlgorithm)MD5.Create())
215+
using (HashAlgorithm hash = algorithm.StartsWith(Sha256, StringComparison.OrdinalIgnoreCase) ? SHA256.Create() : (HashAlgorithm)MD5.Create())
213216
#pragma warning restore CA5351
214217
{
215218
Span<byte> result = stackalloc byte[hash.HashSize / 8]; // HashSize is in bits

0 commit comments

Comments
 (0)