diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index 500bdc61eb..fadab44826 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -8,6 +8,7 @@ using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; using System; using System.Linq; +using MediaBrowser.Model.Services; namespace Emby.Server.Implementations.HttpServer.Security { @@ -37,19 +38,19 @@ namespace Emby.Server.Implementations.HttpServer.Security /// public string HtmlRedirect { get; set; } - public void Authenticate(IServiceRequest request, + public void Authenticate(IRequest request, IAuthenticationAttributes authAttribtues) { ValidateUser(request, authAttribtues); } - private void ValidateUser(IServiceRequest request, + private void ValidateUser(IRequest request, IAuthenticationAttributes authAttribtues) { // This code is executed before the service var auth = AuthorizationContext.GetAuthorizationInfo(request); - if (!IsExemptFromAuthenticationToken(auth, authAttribtues)) + if (!IsExemptFromAuthenticationToken(auth, authAttribtues, request)) { var valid = IsValidConnectKey(auth.Token); @@ -75,7 +76,7 @@ namespace Emby.Server.Implementations.HttpServer.Security var info = GetTokenInfo(request); - if (!IsExemptFromRoles(auth, authAttribtues, info)) + if (!IsExemptFromRoles(auth, authAttribtues, request, info)) { var roles = authAttribtues.GetRoles(); @@ -95,7 +96,7 @@ namespace Emby.Server.Implementations.HttpServer.Security } } - private void ValidateUserAccess(User user, IServiceRequest request, + private void ValidateUserAccess(User user, IRequest request, IAuthenticationAttributes authAttribtues, AuthorizationInfo auth) { @@ -111,7 +112,7 @@ namespace Emby.Server.Implementations.HttpServer.Security !authAttribtues.EscapeParentalControl && !user.IsParentalScheduleAllowed()) { - request.AddResponseHeader("X-Application-Error-Code", "ParentalControl"); + request.Response.AddHeader("X-Application-Error-Code", "ParentalControl"); throw new SecurityException("This user account is not allowed access at this time.") { @@ -131,23 +132,33 @@ namespace Emby.Server.Implementations.HttpServer.Security } } - private bool IsExemptFromAuthenticationToken(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues) + private bool IsExemptFromAuthenticationToken(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues, IRequest request) { if (!_config.Configuration.IsStartupWizardCompleted && authAttribtues.AllowBeforeStartupWizard) { return true; } + if (authAttribtues.AllowLocal && request.IsLocal) + { + return true; + } + return false; } - private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues, AuthenticationInfo tokenInfo) + private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues, IRequest request, AuthenticationInfo tokenInfo) { if (!_config.Configuration.IsStartupWizardCompleted && authAttribtues.AllowBeforeStartupWizard) { return true; } + if (authAttribtues.AllowLocal && request.IsLocal) + { + return true; + } + if (string.IsNullOrWhiteSpace(auth.Token)) { return true; @@ -195,7 +206,7 @@ namespace Emby.Server.Implementations.HttpServer.Security } } - private AuthenticationInfo GetTokenInfo(IServiceRequest request) + private AuthenticationInfo GetTokenInfo(IRequest request) { object info; request.Items.TryGetValue("OriginalAuthenticationInfo", out info); @@ -212,7 +223,7 @@ namespace Emby.Server.Implementations.HttpServer.Security return ConnectManager.IsAuthorizationTokenValid(token); } - private void ValidateSecurityToken(IServiceRequest request, string token) + private void ValidateSecurityToken(IRequest request, string token) { if (string.IsNullOrWhiteSpace(token)) { diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index f402777789..c9d5ed0071 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -21,11 +21,10 @@ namespace Emby.Server.Implementations.HttpServer.Security public AuthorizationInfo GetAuthorizationInfo(object requestContext) { - var req = new ServiceRequest((IRequest)requestContext); - return GetAuthorizationInfo(req); + return GetAuthorizationInfo((IRequest)requestContext); } - public AuthorizationInfo GetAuthorizationInfo(IServiceRequest requestContext) + public AuthorizationInfo GetAuthorizationInfo(IRequest requestContext) { object cached; if (requestContext.Items.TryGetValue("AuthorizationInfo", out cached)) @@ -41,7 +40,7 @@ namespace Emby.Server.Implementations.HttpServer.Security /// /// The HTTP req. /// Dictionary{System.StringSystem.String}. - private AuthorizationInfo GetAuthorization(IServiceRequest httpReq) + private AuthorizationInfo GetAuthorization(IRequest httpReq) { var auth = GetAuthorizationDictionary(httpReq); @@ -135,7 +134,7 @@ namespace Emby.Server.Implementations.HttpServer.Security /// /// The HTTP req. /// Dictionary{System.StringSystem.String}. - private Dictionary GetAuthorizationDictionary(IServiceRequest httpReq) + private Dictionary GetAuthorizationDictionary(IRequest httpReq) { var auth = httpReq.Headers["X-Emby-Authorization"]; diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs index 33dd4e2d77..dd5d64bf65 100644 --- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs @@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.HttpServer.Security _sessionManager = sessionManager; } - public Task GetSession(IServiceRequest requestContext) + public Task GetSession(IRequest requestContext) { var authorization = _authContext.GetAuthorizationInfo(requestContext); @@ -38,7 +38,7 @@ namespace Emby.Server.Implementations.HttpServer.Security return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.RemoteIp, user); } - private AuthenticationInfo GetTokenInfo(IServiceRequest request) + private AuthenticationInfo GetTokenInfo(IRequest request) { object info; request.Items.TryGetValue("OriginalAuthenticationInfo", out info); @@ -47,11 +47,10 @@ namespace Emby.Server.Implementations.HttpServer.Security public Task GetSession(object requestContext) { - var req = new ServiceRequest((IRequest)requestContext); - return GetSession(req); + return GetSession((IRequest)requestContext); } - public async Task GetUser(IServiceRequest requestContext) + public async Task GetUser(IRequest requestContext) { var session = await GetSession(requestContext).ConfigureAwait(false); @@ -60,8 +59,7 @@ namespace Emby.Server.Implementations.HttpServer.Security public Task GetUser(object requestContext) { - var req = new ServiceRequest((IRequest)requestContext); - return GetUser(req); + return GetUser((IRequest)requestContext); } } } diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs index edb9f063dd..6df2db26c7 100644 --- a/MediaBrowser.Api/System/SystemService.cs +++ b/MediaBrowser.Api/System/SystemService.cs @@ -43,7 +43,7 @@ namespace MediaBrowser.Api.System /// Class RestartApplication /// [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")] - [Authenticated(Roles = "Admin")] + [Authenticated(Roles = "Admin", AllowLocal = true)] public class RestartApplication { } @@ -52,10 +52,9 @@ namespace MediaBrowser.Api.System /// This is currently not authenticated because the uninstaller needs to be able to shutdown the server. /// [Route("/System/Shutdown", "POST", Summary = "Shuts down the application")] + [Authenticated(Roles = "Admin", AllowLocal = true)] public class ShutdownApplication { - // TODO: This is not currently authenticated due to uninstaller - // Improve later } [Route("/System/Logs", "GET", Summary = "Gets a list of available server log files")] @@ -126,7 +125,7 @@ namespace MediaBrowser.Api.System } catch (IOException) { - files = new FileSystemMetadata[]{}; + files = new FileSystemMetadata[] { }; } var result = files.Select(i => new LogFile diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 26766f51a6..5ef763b62b 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -183,14 +183,12 @@ - - diff --git a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs index 6ded3761fc..ecbfaecea5 100644 --- a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs +++ b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs @@ -25,6 +25,8 @@ namespace MediaBrowser.Controller.Net /// true if [allow before startup wizard]; otherwise, false. public bool AllowBeforeStartupWizard { get; set; } + public bool AllowLocal { get; set; } + /// /// The request filter is executed before the service. /// @@ -33,9 +35,7 @@ namespace MediaBrowser.Controller.Net /// The request DTO public void RequestFilter(IRequest request, IResponse response, object requestDto) { - var serviceRequest = new ServiceRequest(request); - - AuthService.Authenticate(serviceRequest, this); + AuthService.Authenticate(request, this); } /// @@ -59,6 +59,7 @@ namespace MediaBrowser.Controller.Net { bool EscapeParentalControl { get; } bool AllowBeforeStartupWizard { get; } + bool AllowLocal { get; } string[] GetRoles(); } diff --git a/MediaBrowser.Controller/Net/IAuthService.cs b/MediaBrowser.Controller/Net/IAuthService.cs index dc298c8d90..361320250c 100644 --- a/MediaBrowser.Controller/Net/IAuthService.cs +++ b/MediaBrowser.Controller/Net/IAuthService.cs @@ -1,9 +1,9 @@ - +using MediaBrowser.Model.Services; + namespace MediaBrowser.Controller.Net { public interface IAuthService { - void Authenticate(IServiceRequest request, - IAuthenticationAttributes authAttribtues); + void Authenticate(IRequest request, IAuthenticationAttributes authAttribtues); } } diff --git a/MediaBrowser.Controller/Net/IAuthorizationContext.cs b/MediaBrowser.Controller/Net/IAuthorizationContext.cs index bdaed60469..5a9d0aa30c 100644 --- a/MediaBrowser.Controller/Net/IAuthorizationContext.cs +++ b/MediaBrowser.Controller/Net/IAuthorizationContext.cs @@ -1,4 +1,5 @@ - +using MediaBrowser.Model.Services; + namespace MediaBrowser.Controller.Net { public interface IAuthorizationContext @@ -15,6 +16,6 @@ namespace MediaBrowser.Controller.Net /// /// The request context. /// AuthorizationInfo. - AuthorizationInfo GetAuthorizationInfo(IServiceRequest requestContext); + AuthorizationInfo GetAuthorizationInfo(IRequest requestContext); } } diff --git a/MediaBrowser.Controller/Net/IServiceRequest.cs b/MediaBrowser.Controller/Net/IServiceRequest.cs deleted file mode 100644 index ebc7e8d65d..0000000000 --- a/MediaBrowser.Controller/Net/IServiceRequest.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using MediaBrowser.Model.Services; - -namespace MediaBrowser.Controller.Net -{ - public interface IServiceRequest - { - string RemoteIp { get; } - QueryParamCollection Headers { get; } - QueryParamCollection QueryString { get; } - IDictionary Items { get; } - void AddResponseHeader(string name, string value); - } -} diff --git a/MediaBrowser.Controller/Net/ISessionContext.cs b/MediaBrowser.Controller/Net/ISessionContext.cs index 167e178671..213a66dacc 100644 --- a/MediaBrowser.Controller/Net/ISessionContext.cs +++ b/MediaBrowser.Controller/Net/ISessionContext.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Session; using System.Threading.Tasks; +using MediaBrowser.Model.Services; namespace MediaBrowser.Controller.Net { @@ -9,7 +10,7 @@ namespace MediaBrowser.Controller.Net Task GetSession(object requestContext); Task GetUser(object requestContext); - Task GetSession(IServiceRequest requestContext); - Task GetUser(IServiceRequest requestContext); + Task GetSession(IRequest requestContext); + Task GetUser(IRequest requestContext); } } diff --git a/MediaBrowser.Controller/Net/LoggedAttribute.cs b/MediaBrowser.Controller/Net/LoggedAttribute.cs index 6a2a5e2e3b..eb57392e2e 100644 --- a/MediaBrowser.Controller/Net/LoggedAttribute.cs +++ b/MediaBrowser.Controller/Net/LoggedAttribute.cs @@ -30,10 +30,8 @@ namespace MediaBrowser.Controller.Net /// The request DTO public void Filter(IRequest request, IResponse response, object requestDto) { - var serviceRequest = new ServiceRequest(request); - //This code is executed before the service - var auth = AuthorizationContext.GetAuthorizationInfo(serviceRequest); + var auth = AuthorizationContext.GetAuthorizationInfo(request); if (auth != null) { diff --git a/MediaBrowser.Controller/Net/ServiceRequest.cs b/MediaBrowser.Controller/Net/ServiceRequest.cs deleted file mode 100644 index 1f72d0eb29..0000000000 --- a/MediaBrowser.Controller/Net/ServiceRequest.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using MediaBrowser.Model.Services; - -namespace MediaBrowser.Controller.Net -{ - public class ServiceRequest : IServiceRequest - { - private readonly IRequest _request; - - public ServiceRequest(IRequest request) - { - _request = request; - } - - public string RemoteIp - { - get { return _request.RemoteIp; } - } - - public QueryParamCollection Headers - { - get { return _request.Headers; } - } - - public QueryParamCollection QueryString - { - get { return _request.QueryString; } - } - - public IDictionary Items - { - get { return _request.Items; } - } - - public void AddResponseHeader(string name, string value) - { - _request.Response.AddHeader(name, value); - } - } -}