From 064a9cedbd205594fa529ff996b2cd359c5be07c Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Mon, 14 Dec 2020 13:07:39 +0100 Subject: [PATCH 01/19] No htlml encoding on server side --- .../HttpServer/Security/AuthorizationContext.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 024404ceb0..ce2644b8db 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -275,17 +275,11 @@ namespace Emby.Server.Implementations.HttpServer.Security if (param.Length == 2) { - var value = NormalizeValue(param[1].Trim('"')); - result[param[0]] = value; + result[param[0]] = param[1].Trim('"'); } } return result; } - - private static string NormalizeValue(string value) - { - return string.IsNullOrEmpty(value) ? value : WebUtility.HtmlEncode(value); - } } } From 13bc57ecc39ebd485634f64f90ed526b134a521c Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Mon, 14 Dec 2020 13:08:07 +0100 Subject: [PATCH 02/19] No need to double check param length --- .../HttpServer/Security/AuthorizationContext.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index ce2644b8db..f335aa5c56 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -273,10 +273,7 @@ namespace Emby.Server.Implementations.HttpServer.Security { var param = item.Trim().Split('=', 2); - if (param.Length == 2) - { - result[param[0]] = param[1].Trim('"'); - } + result[param[0]] = param[1].Trim('"'); } return result; From 305e5ebaf40d02f15664c49c26391531a548608d Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Mon, 14 Dec 2020 13:14:18 +0100 Subject: [PATCH 03/19] Allow commas in auth values when wappred in a double quote --- .../HttpServer/Security/AuthorizationContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index f335aa5c56..354e037153 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -265,7 +265,7 @@ namespace Emby.Server.Implementations.HttpServer.Security // Remove uptil the first space authorizationHeader = parts[1]; - parts = authorizationHeader.Split(','); + parts = authorizationHeader.Split("\",\""); var result = new Dictionary(StringComparer.OrdinalIgnoreCase); From b611a108f89ab77b219aecc6d6155540f772cf32 Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Mon, 14 Dec 2020 13:15:21 +0100 Subject: [PATCH 04/19] -fix split on comma and double quotes --- .../HttpServer/Security/AuthorizationContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 354e037153..5d85facab8 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -265,7 +265,7 @@ namespace Emby.Server.Implementations.HttpServer.Security // Remove uptil the first space authorizationHeader = parts[1]; - parts = authorizationHeader.Split("\",\""); + parts = authorizationHeader.Split("\","); var result = new Dictionary(StringComparer.OrdinalIgnoreCase); From 6e2cfc6569044251a7968fdeb16f245cecc46fe6 Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Mon, 14 Dec 2020 14:05:53 +0100 Subject: [PATCH 05/19] Url decode for auth value --- .../HttpServer/Security/AuthorizationContext.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 5d85facab8..0f8011495f 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -273,10 +273,16 @@ namespace Emby.Server.Implementations.HttpServer.Security { var param = item.Trim().Split('=', 2); - result[param[0]] = param[1].Trim('"'); + var value =param[1].Trim('"'); + result[param[0]] = value; } return result; } + + private static string NormalizeValue(string value) + { + return string.IsNullOrEmpty(value) ? value : WebUtility.UrlDecode(value); + } } } From c6eefaac0975c351cfb20ace1c67d837dc0b7393 Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Tue, 15 Dec 2020 21:01:42 +0100 Subject: [PATCH 06/19] Added function to split the authorization header parts --- .../Security/AuthorizationContext.cs | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 0f8011495f..74a678aa62 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -265,7 +265,7 @@ namespace Emby.Server.Implementations.HttpServer.Security // Remove uptil the first space authorizationHeader = parts[1]; - parts = authorizationHeader.Split("\","); + parts = GetParts(authorizationHeader); var result = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -274,7 +274,7 @@ namespace Emby.Server.Implementations.HttpServer.Security var param = item.Trim().Split('=', 2); var value =param[1].Trim('"'); - result[param[0]] = value; + result[param[0]] = NormalizeValue(value); } return result; @@ -284,5 +284,46 @@ namespace Emby.Server.Implementations.HttpServer.Security { return string.IsNullOrEmpty(value) ? value : WebUtility.UrlDecode(value); } + + public static string[] GetParts(string authtorizationHeader) + { + var result = new List(); + var escapeChars = new[] {'"', ','}; + var escaped = false; + var authtorizationHeaderChars = authtorizationHeader.ToCharArray(); + var value = new List(); + + for(var i = 0; i < authtorizationHeaderChars.Length; i++) + { + if(!escapeChars.Contains(authtorizationHeaderChars[i])) + { + value = value.Append(authtorizationHeaderChars[i]).ToList(); + } + else + { + escaped = (!escaped) == (authtorizationHeaderChars[i] == '"'); + if(authtorizationHeaderChars[i] == ',') + { + if(escaped) + { + value = value.Append(authtorizationHeaderChars[i]).ToList(); + } + else + { + result.Add(new string(value.ToArray())); + value = new List(); + } + } + else + { + value = value.Append(authtorizationHeaderChars[i]).ToList(); + } + } + } + // Add last value + result.Add(new string(value.ToArray())); + + return result.ToArray(); + } } } From 7c7f2316faa36fbdd6044ae27e05823e317d167f Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Tue, 15 Dec 2020 21:06:47 +0100 Subject: [PATCH 07/19] Added comments --- .../HttpServer/Security/AuthorizationContext.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 74a678aa62..855c616826 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -285,6 +285,11 @@ namespace Emby.Server.Implementations.HttpServer.Security return string.IsNullOrEmpty(value) ? value : WebUtility.UrlDecode(value); } + /// + /// Get the authorization header components. + /// + /// The authorization header. + /// string public static string[] GetParts(string authtorizationHeader) { var result = new List(); @@ -301,6 +306,7 @@ namespace Emby.Server.Implementations.HttpServer.Security } else { + // Applying a XOR logic to evaluate wether it is opening or closing a value escaped = (!escaped) == (authtorizationHeaderChars[i] == '"'); if(authtorizationHeaderChars[i] == ',') { @@ -310,6 +316,7 @@ namespace Emby.Server.Implementations.HttpServer.Security } else { + // Meeting a comma after a closing escape char means the value is complete result.Add(new string(value.ToArray())); value = new List(); } From a03880b687cf1b69c25bd8d207b2ebfb0c420571 Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Sat, 2 Jan 2021 18:18:47 +0100 Subject: [PATCH 08/19] Improve get auth header parts using substring --- .../Security/AuthorizationContext.cs | 49 +++++++++---------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 855c616826..8fa20aea9a 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -273,7 +273,7 @@ namespace Emby.Server.Implementations.HttpServer.Security { var param = item.Trim().Split('=', 2); - var value =param[1].Trim('"'); + var value = param[1].Trim('"'); result[param[0]] = NormalizeValue(value); } @@ -293,42 +293,37 @@ namespace Emby.Server.Implementations.HttpServer.Security public static string[] GetParts(string authtorizationHeader) { var result = new List(); - var escapeChars = new[] {'"', ','}; + var escapeChars = new[] { '"', ',' }; var escaped = false; - var authtorizationHeaderChars = authtorizationHeader.ToCharArray(); - var value = new List(); - - for(var i = 0; i < authtorizationHeaderChars.Length; i++) + int start = 0; + int i = 0; + while (i < authtorizationHeader.Length) { - if(!escapeChars.Contains(authtorizationHeaderChars[i])) + var token = authtorizationHeader[i]; + if (escapeChars.Contains(token)) { - value = value.Append(authtorizationHeaderChars[i]).ToList(); - } - else - { - // Applying a XOR logic to evaluate wether it is opening or closing a value - escaped = (!escaped) == (authtorizationHeaderChars[i] == '"'); - if(authtorizationHeaderChars[i] == ',') + // Applying a XOR logic to evaluate whether it is opening or closing a value + escaped = (!escaped) == (token == '"'); + if (token == ',' && !escaped) { - if(escaped) + // Meeting a comma after a closing escape char means the value is complete + if (start < i) { - value = value.Append(authtorizationHeaderChars[i]).ToList(); + result.Add(authtorizationHeader[start..(i)]); } - else - { - // Meeting a comma after a closing escape char means the value is complete - result.Add(new string(value.ToArray())); - value = new List(); - } - } - else - { - value = value.Append(authtorizationHeaderChars[i]).ToList(); + + start = i + 1; } } + + i++; } + // Add last value - result.Add(new string(value.ToArray())); + if (start < i) + { + result.Add(authtorizationHeader[start..(i)]); + } return result.ToArray(); } From 452af30511a80e99e22794fc8009d7a6a9b9c904 Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Sun, 3 Jan 2021 19:32:58 +0100 Subject: [PATCH 09/19] Added UrlDecode for authorization parts --- .../HttpServer/Security/AuthorizationContext.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 8fa20aea9a..6b4588dbcf 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -309,7 +309,7 @@ namespace Emby.Server.Implementations.HttpServer.Security // Meeting a comma after a closing escape char means the value is complete if (start < i) { - result.Add(authtorizationHeader[start..(i)]); + result.Add(WebUtility.UrlDecode(authtorizationHeader[start..(i)])); } start = i + 1; @@ -322,7 +322,7 @@ namespace Emby.Server.Implementations.HttpServer.Security // Add last value if (start < i) { - result.Add(authtorizationHeader[start..(i)]); + result.Add(WebUtility.UrlDecode(authtorizationHeader[start..(i)])); } return result.ToArray(); From 414e918c01a2458aa28c654332a8bad4f79cfa90 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Fri, 26 Feb 2021 14:30:00 +0000 Subject: [PATCH 10/19] Optimized and added test --- .../Security/AuthorizationContext.cs | 39 +++++++------------ .../DefaultAuthorizationHandlerTests.cs | 14 ++++++- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 6b4588dbcf..7a83b72133 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -263,26 +263,9 @@ namespace Emby.Server.Implementations.HttpServer.Security return null; } - // Remove uptil the first space + // Remove up until the first space authorizationHeader = parts[1]; - parts = GetParts(authorizationHeader); - - var result = new Dictionary(StringComparer.OrdinalIgnoreCase); - - foreach (var item in parts) - { - var param = item.Trim().Split('=', 2); - - var value = param[1].Trim('"'); - result[param[0]] = NormalizeValue(value); - } - - return result; - } - - private static string NormalizeValue(string value) - { - return string.IsNullOrEmpty(value) ? value : WebUtility.UrlDecode(value); + return GetParts(authorizationHeader); } /// @@ -290,13 +273,15 @@ namespace Emby.Server.Implementations.HttpServer.Security /// /// The authorization header. /// string - public static string[] GetParts(string authtorizationHeader) + public static Dictionary GetParts(string authtorizationHeader) { - var result = new List(); + var result = new Dictionary(); var escapeChars = new[] { '"', ',' }; var escaped = false; int start = 0; int i = 0; + string key = string.Empty; + while (i < authtorizationHeader.Length) { var token = authtorizationHeader[i]; @@ -309,12 +294,18 @@ namespace Emby.Server.Implementations.HttpServer.Security // Meeting a comma after a closing escape char means the value is complete if (start < i) { - result.Add(WebUtility.UrlDecode(authtorizationHeader[start..(i)])); + result[key] = WebUtility.UrlDecode(authtorizationHeader[start..i].Trim('"')); + key = string.Empty; } start = i + 1; } } + else if (!escaped && token == '=') + { + key = authtorizationHeader[start.. i]; + start = i + 1; + } i++; } @@ -322,10 +313,10 @@ namespace Emby.Server.Implementations.HttpServer.Security // Add last value if (start < i) { - result.Add(WebUtility.UrlDecode(authtorizationHeader[start..(i)])); + result[key] = WebUtility.UrlDecode(authtorizationHeader[start..i].Trim('"')); } - return result.ToArray(); + return result; } } } diff --git a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs index a62fd8d5ae..5387922ab9 100644 --- a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs @@ -1,7 +1,8 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; using AutoFixture; using AutoFixture.AutoMoq; +using Emby.Server.Implementations.HttpServer.Security; using Jellyfin.Api.Auth.DefaultAuthorizationPolicy; using Jellyfin.Api.Constants; using MediaBrowser.Common.Configuration; @@ -49,5 +50,16 @@ namespace Jellyfin.Api.Tests.Auth.DefaultAuthorizationPolicy await _sut.HandleAsync(context); Assert.True(context.HasSucceeded); } + + [Theory] + [InlineData("x=\"123,123\",y=\"123\"", "x", "123,123")] + [InlineData("x=\"ab\"", "x", "ab")] + [InlineData("param=Hörbücher", "param", "Hörbücher")] + [InlineData("param=%22%Hörbücher", "param", "\"%Hörbücher")] + public void TestAuthHeaders(string input, string key, string value) + { + var dict = AuthorizationContext.GetParts(input); + Assert.True(string.Equals(dict[key], value, System.StringComparison.Ordinal)); + } } } From 3951546b1f388cb7aa388a7d6daa5b84ae90b945 Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Thu, 3 Jun 2021 17:07:25 +0200 Subject: [PATCH 11/19] Update Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs Co-authored-by: artiume --- .../HttpServer/Security/AuthorizationContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 7a83b72133..f6c8976ecf 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -271,7 +271,7 @@ namespace Emby.Server.Implementations.HttpServer.Security /// /// Get the authorization header components. /// - /// The authorization header. + /// The authorization header. /// string public static Dictionary GetParts(string authtorizationHeader) { From 3c019d1324c6ec29bf96aab28b94208924bb317f Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Thu, 3 Jun 2021 17:10:19 +0200 Subject: [PATCH 12/19] Using for instead of while --- .../HttpServer/Security/AuthorizationContext.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 7a83b72133..26f3b8d68f 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -276,16 +276,15 @@ namespace Emby.Server.Implementations.HttpServer.Security public static Dictionary GetParts(string authtorizationHeader) { var result = new Dictionary(); - var escapeChars = new[] { '"', ',' }; var escaped = false; int start = 0; - int i = 0; string key = string.Empty; - while (i < authtorizationHeader.Length) + int i; + for (i = 0; i < authtorizationHeader.Length; i++) { var token = authtorizationHeader[i]; - if (escapeChars.Contains(token)) + if (token == '"' || token == ',') { // Applying a XOR logic to evaluate whether it is opening or closing a value escaped = (!escaped) == (token == '"'); @@ -306,8 +305,6 @@ namespace Emby.Server.Implementations.HttpServer.Security key = authtorizationHeader[start.. i]; start = i + 1; } - - i++; } // Add last value From dc261b815f4ce5fbace33e787902636c43618881 Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Thu, 3 Jun 2021 17:12:16 +0200 Subject: [PATCH 13/19] -fix AuthorizationHeader parameter name --- .../HttpServer/Security/AuthorizationContext.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index c9b94cfdee..ab43e088b9 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -273,7 +273,7 @@ namespace Emby.Server.Implementations.HttpServer.Security /// /// The authorization header. /// string - public static Dictionary GetParts(string authtorizationHeader) + public static Dictionary GetParts(string authorizationHeader) { var result = new Dictionary(); var escaped = false; @@ -281,9 +281,9 @@ namespace Emby.Server.Implementations.HttpServer.Security string key = string.Empty; int i; - for (i = 0; i < authtorizationHeader.Length; i++) + for (i = 0; i < authorizationHeader.Length; i++) { - var token = authtorizationHeader[i]; + var token = authorizationHeader[i]; if (token == '"' || token == ',') { // Applying a XOR logic to evaluate whether it is opening or closing a value @@ -293,7 +293,7 @@ namespace Emby.Server.Implementations.HttpServer.Security // Meeting a comma after a closing escape char means the value is complete if (start < i) { - result[key] = WebUtility.UrlDecode(authtorizationHeader[start..i].Trim('"')); + result[key] = WebUtility.UrlDecode(authorizationHeader[start..i].Trim('"')); key = string.Empty; } @@ -302,7 +302,7 @@ namespace Emby.Server.Implementations.HttpServer.Security } else if (!escaped && token == '=') { - key = authtorizationHeader[start.. i]; + key = authorizationHeader[start.. i]; start = i + 1; } } @@ -310,7 +310,7 @@ namespace Emby.Server.Implementations.HttpServer.Security // Add last value if (start < i) { - result[key] = WebUtility.UrlDecode(authtorizationHeader[start..i].Trim('"')); + result[key] = WebUtility.UrlDecode(authorizationHeader[start..i].Trim('"')); } return result; From d1b34a1e9797f4d6bbfe104bed5c42bdc953a692 Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Thu, 3 Jun 2021 17:37:42 +0200 Subject: [PATCH 14/19] -fix authorizationHeader is no longer a string --- .../HttpServer/Security/AuthorizationContext.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 95be6552b0..f0a706ff52 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -264,8 +264,8 @@ namespace Emby.Server.Implementations.HttpServer.Security } // Remove up until the first space - authorizationHeader = parts[1]; - return GetParts(authorizationHeader); + authorizationHeader = authorizationHeader[(firstSpace + 1)..]; + return GetParts(authorizationHeader.ToString()); } /// From 2a72c33ba6ef257aff23c5281c9276d7a0258024 Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Thu, 3 Jun 2021 17:43:50 +0200 Subject: [PATCH 15/19] authorizationheader as readonlyspan instead of string --- .../HttpServer/Security/AuthorizationContext.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index f0a706ff52..7b9f72efda 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -265,7 +265,7 @@ namespace Emby.Server.Implementations.HttpServer.Security // Remove up until the first space authorizationHeader = authorizationHeader[(firstSpace + 1)..]; - return GetParts(authorizationHeader.ToString()); + return GetParts(authorizationHeader); } /// @@ -273,7 +273,7 @@ namespace Emby.Server.Implementations.HttpServer.Security /// /// The authorization header. /// string - public static Dictionary GetParts(string authorizationHeader) + public static Dictionary GetParts(ReadOnlySpan authorizationHeader) { var result = new Dictionary(); var escaped = false; @@ -293,7 +293,7 @@ namespace Emby.Server.Implementations.HttpServer.Security // Meeting a comma after a closing escape char means the value is complete if (start < i) { - result[key] = WebUtility.UrlDecode(authorizationHeader[start..i].Trim('"')); + result[key] = WebUtility.UrlDecode(authorizationHeader[start..i].Trim('"').ToString()); key = string.Empty; } @@ -302,7 +302,7 @@ namespace Emby.Server.Implementations.HttpServer.Security } else if (!escaped && token == '=') { - key = authorizationHeader[start.. i]; + key = authorizationHeader[start.. i].ToString(); start = i + 1; } } @@ -310,7 +310,7 @@ namespace Emby.Server.Implementations.HttpServer.Security // Add last value if (start < i) { - result[key] = WebUtility.UrlDecode(authorizationHeader[start..i].Trim('"')); + result[key] = WebUtility.UrlDecode(authorizationHeader[start..i].Trim('"').ToString()); } return result; From 02a56d8cf73e6745f651fe230520182f0398fae3 Mon Sep 17 00:00:00 2001 From: Tommaso Stocchi Date: Thu, 3 Jun 2021 17:45:22 +0200 Subject: [PATCH 16/19] Changed return type desc in GetParts() summary --- .../HttpServer/Security/AuthorizationContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 7b9f72efda..bcdf71b326 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -272,7 +272,7 @@ namespace Emby.Server.Implementations.HttpServer.Security /// Get the authorization header components. /// /// The authorization header. - /// string + /// Dictionary{System.StringSystem.String}. public static Dictionary GetParts(ReadOnlySpan authorizationHeader) { var result = new Dictionary(); From 60185f99c4329da7c93cc3769c4c017aab61b6bf Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 3 Sep 2021 21:43:06 +0200 Subject: [PATCH 17/19] fix the build --- .../Security/AuthorizationContext.cs | 1 - .../DefaultAuthorizationHandlerTests.cs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index d993ca2345..e559d698a3 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; -using Jellyfin.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using Microsoft.AspNetCore.Http; diff --git a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs index 5387922ab9..312dffde23 100644 --- a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs @@ -1,10 +1,10 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; using AutoFixture; using AutoFixture.AutoMoq; -using Emby.Server.Implementations.HttpServer.Security; using Jellyfin.Api.Auth.DefaultAuthorizationPolicy; using Jellyfin.Api.Constants; +using Jellyfin.Server.Implementations.Security; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Library; using Microsoft.AspNetCore.Authorization; From 1172ece856d91d060ba5122269fc9ea55f336495 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 3 Sep 2021 23:56:19 +0200 Subject: [PATCH 18/19] remove leading and trailing whitespace from the key --- .../Security/AuthorizationContext.cs | 2 +- .../DefaultAuthorizationHandlerTests.cs | 59 +++++++++++++++++-- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index e559d698a3..244abf469e 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -291,7 +291,7 @@ namespace Jellyfin.Server.Implementations.Security } else if (!escaped && token == '=') { - key = authorizationHeader[start.. i].ToString(); + key = authorizationHeader[start.. i].Trim().ToString(); start = i + 1; } } diff --git a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs index 312dffde23..ee4af34ad5 100644 --- a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs @@ -52,14 +52,61 @@ namespace Jellyfin.Api.Tests.Auth.DefaultAuthorizationPolicy } [Theory] - [InlineData("x=\"123,123\",y=\"123\"", "x", "123,123")] - [InlineData("x=\"ab\"", "x", "ab")] - [InlineData("param=Hörbücher", "param", "Hörbücher")] - [InlineData("param=%22%Hörbücher", "param", "\"%Hörbücher")] - public void TestAuthHeaders(string input, string key, string value) + [MemberData(nameof(GetParts_ValidAuthHeader_Success_Data))] + public void GetParts_ValidAuthHeader_Success(string input, Dictionary parts) { var dict = AuthorizationContext.GetParts(input); - Assert.True(string.Equals(dict[key], value, System.StringComparison.Ordinal)); + foreach (var (key, value) in parts) + { + Assert.Equal(dict[key], value); + } + } + + private static TheoryData> GetParts_ValidAuthHeader_Success_Data() + { + var data = new TheoryData>(); + + data.Add( + "x=\"123,123\",y=\"123\"", + new Dictionary + { + { "x", "123,123" }, + { "y", "123" } + }); + + data.Add( + "x=\"123,123\", y=\"123\",z=\"'hi'\"", + new Dictionary + { + { "x", "123,123" }, + { "y", "123" }, + { "z", "'hi'" } + }); + + data.Add( + "x=\"ab\"", + new Dictionary + { + { "x", "ab" } + }); + + data.Add( + "param=Hörbücher", + new Dictionary + { + { "param", "Hörbücher" } + } + ); + + data.Add( + "param=%22%Hörbücher", + new Dictionary + { + { "param", "\"%Hörbücher" } + } + ); + + return data; } } } From 907d9fa195ccc7ca63229cc597ecaa591ed087c1 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 3 Sep 2021 23:58:07 +0200 Subject: [PATCH 19/19] remove some newlines --- .../DefaultAuthorizationHandlerTests.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs index ee4af34ad5..23c51999fa 100644 --- a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs @@ -95,16 +95,14 @@ namespace Jellyfin.Api.Tests.Auth.DefaultAuthorizationPolicy new Dictionary { { "param", "Hörbücher" } - } - ); + }); data.Add( "param=%22%Hörbücher", new Dictionary { { "param", "\"%Hörbücher" } - } - ); + }); return data; }