From 7efa4e38c1c7aa3d234aad929bf6184a408d1428 Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Sun, 26 Jun 2022 12:43:17 +0200 Subject: [PATCH 1/4] Fix password change during parental schedule --- Jellyfin.Api/Controllers/UserController.cs | 5 +++-- Jellyfin.Server.Implementations/Users/UserManager.cs | 5 +++-- MediaBrowser.Controller/Library/IUserManager.cs | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index 6d15d91858..6fb295eb89 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -256,7 +256,7 @@ namespace Jellyfin.Api.Controllers /// User not found. /// A indicating success or a or a on failure. [HttpPost("{userId}/Password")] - [Authorize(Policy = Policies.DefaultAuthorization)] + [Authorize(Policy = Policies.IgnoreParentalControl)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -287,7 +287,8 @@ namespace Jellyfin.Api.Controllers request.CurrentPw, request.CurrentPw, HttpContext.GetNormalizedRemoteIp().ToString(), - false).ConfigureAwait(false); + false, + ignoreParentalSchedule: true).ConfigureAwait(false); if (success == null) { diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 2100fa6d59..09ee7fc6e6 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -382,7 +382,8 @@ namespace Jellyfin.Server.Implementations.Users string password, string passwordSha1, string remoteEndPoint, - bool isUserSession) + bool isUserSession, + bool ignoreParentalSchedule = false) { if (string.IsNullOrWhiteSpace(username)) { @@ -458,7 +459,7 @@ namespace Jellyfin.Server.Implementations.Users throw new SecurityException("Forbidden."); } - if (!user.IsParentalScheduleAllowed()) + if (!ignoreParentalSchedule && !user.IsParentalScheduleAllowed()) { _logger.LogInformation( "Authentication request for {UserName} is not allowed at this time due parental restrictions (IP: {IP}).", diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index 993e3e18f9..7884362635 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -138,8 +138,9 @@ namespace MediaBrowser.Controller.Library /// Hash of password. /// Remove endpoint to use. /// Specifies if a user session. + /// Ignore parental control schedule during authentication. /// User wrapped in awaitable task. - Task AuthenticateUser(string username, string password, string passwordSha1, string remoteEndPoint, bool isUserSession); + Task AuthenticateUser(string username, string password, string passwordSha1, string remoteEndPoint, bool isUserSession, bool ignoreParentalSchedule = false); /// /// Starts the forgot password process. From 5f3dbd82942593352d1cad2f7f168ab1aabe8b70 Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Mon, 4 Jul 2022 18:16:36 +0200 Subject: [PATCH 2/4] Allow administrator to always change password --- Jellyfin.Api/Controllers/UserController.cs | 23 ++++++++++++---------- Jellyfin.Api/Helpers/RequestHelpers.cs | 12 +++++++++++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index 6fb295eb89..25dc6a785c 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -282,17 +282,20 @@ namespace Jellyfin.Api.Controllers } else { - var success = await _userManager.AuthenticateUser( - user.Username, - request.CurrentPw, - request.CurrentPw, - HttpContext.GetNormalizedRemoteIp().ToString(), - false, - ignoreParentalSchedule: true).ConfigureAwait(false); - - if (success == null) + if (await RequestHelpers.IsUserAdministrator(_authContext, HttpContext.Request).ConfigureAwait(false)) { - return StatusCode(StatusCodes.Status403Forbidden, "Invalid user or password entered."); + var success = await _userManager.AuthenticateUser( + user.Username, + request.CurrentPw, + request.CurrentPw, + HttpContext.GetNormalizedRemoteIp().ToString(), + false, + ignoreParentalSchedule: true).ConfigureAwait(false); + + if (success == null) + { + return StatusCode(StatusCodes.Status403Forbidden, "Invalid user or password entered."); + } } await _userManager.ChangePassword(user, request.NewPw).ConfigureAwait(false); diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs index 20427d7fab..f79a301341 100644 --- a/Jellyfin.Api/Helpers/RequestHelpers.cs +++ b/Jellyfin.Api/Helpers/RequestHelpers.cs @@ -76,6 +76,18 @@ namespace Jellyfin.Api.Helpers return true; } + /// + /// Checks if the user is administrator. + /// + /// Instance of the interface. + /// The . + /// A whether the user can update the entry. + internal static async Task IsUserAdministrator(IAuthorizationContext authContext, HttpRequest requestContext) + { + var auth = await authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false); + return auth.User.HasPermission(PermissionKind.IsAdministrator); + } + internal static async Task GetSession(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request) { var authorization = await authContext.GetAuthorizationInfo(request).ConfigureAwait(false); From f9d26ea1bcf14c148b2eceff56923f9316a85a12 Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Mon, 4 Jul 2022 19:08:40 +0200 Subject: [PATCH 3/4] Use IsInRole --- Jellyfin.Api/Controllers/UserController.cs | 2 +- Jellyfin.Api/Helpers/RequestHelpers.cs | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index 25dc6a785c..0c70517531 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -282,7 +282,7 @@ namespace Jellyfin.Api.Controllers } else { - if (await RequestHelpers.IsUserAdministrator(_authContext, HttpContext.Request).ConfigureAwait(false)) + if (HttpContext.User.IsInRole(UserRoles.Administrator)) { var success = await _userManager.AuthenticateUser( user.Username, diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs index f79a301341..20427d7fab 100644 --- a/Jellyfin.Api/Helpers/RequestHelpers.cs +++ b/Jellyfin.Api/Helpers/RequestHelpers.cs @@ -76,18 +76,6 @@ namespace Jellyfin.Api.Helpers return true; } - /// - /// Checks if the user is administrator. - /// - /// Instance of the interface. - /// The . - /// A whether the user can update the entry. - internal static async Task IsUserAdministrator(IAuthorizationContext authContext, HttpRequest requestContext) - { - var auth = await authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false); - return auth.User.HasPermission(PermissionKind.IsAdministrator); - } - internal static async Task GetSession(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request) { var authorization = await authContext.GetAuthorizationInfo(request).ConfigureAwait(false); From 81e535fc6214ba6b92f0135750831fc717edfb70 Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Mon, 4 Jul 2022 19:10:37 +0200 Subject: [PATCH 4/4] Rollback changes in IUserManager --- Jellyfin.Api/Controllers/UserController.cs | 7 +++---- Jellyfin.Server.Implementations/Users/UserManager.cs | 5 ++--- MediaBrowser.Controller/Library/IUserManager.cs | 3 +-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index 0c70517531..82c8563a80 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -256,7 +256,7 @@ namespace Jellyfin.Api.Controllers /// User not found. /// A indicating success or a or a on failure. [HttpPost("{userId}/Password")] - [Authorize(Policy = Policies.IgnoreParentalControl)] + [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -282,15 +282,14 @@ namespace Jellyfin.Api.Controllers } else { - if (HttpContext.User.IsInRole(UserRoles.Administrator)) + if (!HttpContext.User.IsInRole(UserRoles.Administrator)) { var success = await _userManager.AuthenticateUser( user.Username, request.CurrentPw, request.CurrentPw, HttpContext.GetNormalizedRemoteIp().ToString(), - false, - ignoreParentalSchedule: true).ConfigureAwait(false); + false).ConfigureAwait(false); if (success == null) { diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 09ee7fc6e6..2100fa6d59 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -382,8 +382,7 @@ namespace Jellyfin.Server.Implementations.Users string password, string passwordSha1, string remoteEndPoint, - bool isUserSession, - bool ignoreParentalSchedule = false) + bool isUserSession) { if (string.IsNullOrWhiteSpace(username)) { @@ -459,7 +458,7 @@ namespace Jellyfin.Server.Implementations.Users throw new SecurityException("Forbidden."); } - if (!ignoreParentalSchedule && !user.IsParentalScheduleAllowed()) + if (!user.IsParentalScheduleAllowed()) { _logger.LogInformation( "Authentication request for {UserName} is not allowed at this time due parental restrictions (IP: {IP}).", diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index 7884362635..993e3e18f9 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -138,9 +138,8 @@ namespace MediaBrowser.Controller.Library /// Hash of password. /// Remove endpoint to use. /// Specifies if a user session. - /// Ignore parental control schedule during authentication. /// User wrapped in awaitable task. - Task AuthenticateUser(string username, string password, string passwordSha1, string remoteEndPoint, bool isUserSession, bool ignoreParentalSchedule = false); + Task AuthenticateUser(string username, string password, string passwordSha1, string remoteEndPoint, bool isUserSession); /// /// Starts the forgot password process.