Example #1
0
        public SecurityState ValidateRequest(HttpRequestBase request)
        {
            Assert.ArgumentNotNull(request, nameof(request));

            var user = AuthenticationManager.GetActiveUser();

            if (user != null && user.IsAdministrator)
            {
                return(new SecurityState(true, false));
            }

            var authToken = request.Headers["X-MC-MAC"];

            if (!string.IsNullOrWhiteSpace(authToken))
            {
                ValidateSharedSecret();

                if (Server.ValidateRequest(request, ServerLogger))
                {
                    return(new SecurityState(true, true));
                }

                return(new SecurityState(false, true));
            }

            // if dynamic debug compilation is enabled, you can use it without auth (eg local dev)
            if (HttpContext.Current.IsDebuggingEnabled)
            {
                return(new SecurityState(true, false));
            }

            return(new SecurityState(false, false));
        }
        public SecurityState ValidateRequest(HttpRequestBase request)
        {
            var user = AuthenticationManager.GetActiveUser();

            if (user.IsAdministrator)
            {
                return(new SecurityState(true, false));
            }

            var authToken = HttpContext.Current.Request.Headers["Authenticate"];

            if (!string.IsNullOrWhiteSpace(CorrectAuthToken) &&
                !string.IsNullOrWhiteSpace(authToken) &&
                authToken.Equals(CorrectAuthToken, StringComparison.Ordinal))
            {
                return(new SecurityState(true, true));
            }

            // if dynamic debug compilation is enabled, you can use it without auth (eg local dev)
            if (HttpContext.Current.IsDebuggingEnabled)
            {
                return(new SecurityState(true, false));
            }

            return(new SecurityState(false, false));
        }
        public void ProcessRequest(HttpContext context)
        {
            var request           = context.Request;
            var requestParameters = request.Params;

            var username   = requestParameters.Get("user");
            var password   = requestParameters.Get("password");
            var authHeader = request.Headers["Authorization"];

            if (string.IsNullOrEmpty(username) && string.IsNullOrEmpty(password) && !string.IsNullOrEmpty(authHeader))
            {
                if (authHeader.StartsWith("Basic"))
                {
                    var encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();
                    var encoding         = Encoding.GetEncoding("iso-8859-1");
                    var usernamePassword = encoding.GetString(System.Convert.FromBase64String(encodedUsernamePassword));

                    var separatorIndex = usernamePassword.IndexOf(':');

                    username = usernamePassword.Substring(0, separatorIndex);
                    password = usernamePassword.Substring(separatorIndex + 1);
                }
            }

            var itemParam         = requestParameters.Get("script");
            var pathParam         = requestParameters.Get("path");
            var originParam       = requestParameters.Get("scriptDb");
            var sessionId         = requestParameters.Get("sessionId");
            var persistentSession = requestParameters.Get("persistentSession").Is("true");
            var rawOutput         = requestParameters.Get("rawOutput").Is("true");
            var apiVersion        = requestParameters.Get("apiVersion");
            var serviceMappingKey = request.HttpMethod + "/" + apiVersion;
            var isUpload          = request.HttpMethod.Is("POST") && request.InputStream.Length > 0;
            var unpackZip         = requestParameters.Get("skipunpack").IsNot("true");
            var skipExisting      = requestParameters.Get("skipexisting").Is("true");
            var scDb = requestParameters.Get("sc_database");

            var serviceName = ApiVersionToServiceMapping.ContainsKey(serviceMappingKey)
                ? ApiVersionToServiceMapping[serviceMappingKey]
                : string.Empty;

            // verify that the service is enabled
            if (!CheckServiceEnabled(context, apiVersion, request.HttpMethod))
            {
                return;
            }

            // verify that the user is authorized to access the end point
            var authUserName = string.IsNullOrEmpty(username) ? Context.User.Name : username;
            var identity     = new AccountIdentity(authUserName);

            if (!CheckIsUserAuthorized(context, identity.Name, serviceName))
            {
                return;
            }

            lock (LoginLock)
            {
                // login user if specified explicitly
                if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
                {
                    AuthenticationManager.Login(identity.Name, password, false);
                }
            }

            var isAuthenticated = Context.IsLoggedIn;

            if (!CheckServiceAuthentication(context, apiVersion, serviceName, isAuthenticated))
            {
                return;
            }

            // in some cases we need to set the database as it's still set to web after authentication
            if (!scDb.IsNullOrEmpty())
            {
                Context.Database = Database.GetDatabase(scDb);
            }

            var useContextDatabase = apiVersion.Is("file") || apiVersion.Is("handle") || !isAuthenticated ||
                                     string.IsNullOrEmpty(originParam) || originParam.Is("current");
            var scriptDb = useContextDatabase ? Context.Database : Database.GetDatabase(originParam);
            var dbName   = scriptDb?.Name;

            if (scriptDb == null && !apiVersion.Is("file") && !apiVersion.Is("handle"))
            {
                PowerShellLog.Error($"The '{serviceMappingKey}' service requires a database but none was found in parameters or Context.");
                return;
            }

            PowerShellLog.Info($"'{serviceMappingKey}' called by user: '******'");
            PowerShellLog.Debug($"'{request.Url}'");

            Item scriptItem = null;

            switch (apiVersion)
            {
            case "1":
                scriptItem = scriptDb.GetItem(itemParam) ??
                             scriptDb.GetItem(ApplicationSettings.ScriptLibraryPath + itemParam);
                break;

            case "media":
                ProcessMedia(context, isUpload, scriptDb, itemParam, unpackZip, skipExisting);
                return;

            case "file":
                ProcessFile(context, isUpload, originParam, pathParam);
                return;

            case "handle":
                ProcessHandle(context, originParam);
                return;

            case "2":
                var apiScripts = GetApiScripts(dbName);
                if (apiScripts.ContainsKey(dbName))
                {
                    var dbScripts = apiScripts[dbName];
                    if (dbScripts.ContainsKey(itemParam))
                    {
                        scriptItem = scriptDb.GetItem(dbScripts[itemParam].Id);
                    }
                }

                if (scriptItem == null)
                {
                    context.Response.StatusCode        = 404;
                    context.Response.StatusDescription = "The specified script is invalid.";
                    return;
                }
                break;

            case "script":
                ProcessScript(context, request, rawOutput, sessionId, persistentSession);
                return;

            default:
                PowerShellLog.Error($"Requested API/Version ({serviceMappingKey}) is not supported.");
                return;
            }

            ProcessScript(context, scriptItem);
        }
        public void ProcessRequest(HttpContext context)
        {
            var request           = HttpContext.Current.Request;
            var userName          = request.Params.Get("user");
            var password          = request.Params.Get("password");
            var itemParam         = request.Params.Get("script");
            var pathParam         = request.Params.Get("path");
            var originParam       = request.Params.Get("scriptDb");
            var apiVersion        = request.Params.Get("apiVersion");
            var serviceMappingKey = request.HttpMethod + "/" + apiVersion;
            var isUpload          = request.HttpMethod.Is("POST") && request.InputStream.Length > 0;
            var unpackZip         = request.Params.Get("skipunpack").IsNot("true");
            var skipExisting      = request.Params.Get("skipexisting").Is("true");
            var scDB = request.Params.Get("sc_database");

            var serviceName = apiVersionToServiceMapping.ContainsKey(serviceMappingKey)
                ? apiVersionToServiceMapping[serviceMappingKey]
                : string.Empty;

            // verify that the service is enabled
            if (!CheckServiceEnabled(apiVersion, request.HttpMethod))
            {
                PowerShellLog.Error($"Attempt to call the {apiVersion} service failed as it is not enabled.");
                return;
            }

            // verify that the user is authorized to access the end point
            var authUserName = string.IsNullOrEmpty(userName) ? Context.User.Name : userName;
            var identity     = new AccountIdentity(authUserName);

            if (!ServiceAuthorizationManager.IsUserAuthorized(serviceName, identity.Name))
            {
                HttpContext.Current.Response.StatusCode = 401;
                PowerShellLog.Error(
                    $"Attempt to call the '{serviceMappingKey}' service failed as user '{authUserName}' was not authorized.");
                return;
            }

            lock (loginLock)
            {
                // login user if specified explicitly
                if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
                {
                    AuthenticationManager.Login(identity.Name, password, false);
                }
            }

            var isAuthenticated = Context.IsLoggedIn;

            // in some cases we need to set the database as it's still set to web after authentication
            if (!scDB.IsNullOrEmpty())
            {
                Context.Database = Database.GetDatabase(scDB);
            }

            var useContextDatabase = apiVersion.Is("file") || apiVersion.Is("handle") || !isAuthenticated ||
                                     string.IsNullOrEmpty(originParam) || originParam.Is("current");
            var scriptDb = useContextDatabase ? Context.Database : Database.GetDatabase(originParam);
            var dbName   = scriptDb?.Name;

            if (!CheckServiceAuthentication(apiVersion, isAuthenticated))
            {
                PowerShellLog.Error(
                    $"Attempt to call the {serviceMappingKey} service failed as - user not logged in, authentication failed or no credentials provided.");
                return;
            }

            if (scriptDb == null && !apiVersion.Is("file") && !apiVersion.Is("handle"))
            {
                PowerShellLog.Error(
                    $"The '{serviceMappingKey}' service requires a database but none was found in parameters or Context.");
                return;
            }

            PowerShellLog.Info($"'{serviceMappingKey}' called by user: '******'");
            PowerShellLog.Debug($"'{request.Url}'");

            Item scriptItem;

            switch (apiVersion)
            {
            case "1":
                scriptItem = scriptDb.GetItem(itemParam) ??
                             scriptDb.GetItem(ApplicationSettings.ScriptLibraryPath + itemParam);
                break;

            case "media":
                if (isUpload)
                {
                    if (ZipUtils.IsZipContent(request.InputStream) && unpackZip)
                    {
                        PowerShellLog.Debug("The uploaded asset will be extracted to Media Library.");
                        using (var packageReader = new Sitecore.Zip.ZipReader(request.InputStream))
                        {
                            itemParam = Path.GetDirectoryName(itemParam.TrimEnd('\\', '/'));
                            foreach (var zipEntry in packageReader.Entries)
                            {
                                if (!zipEntry.IsDirectory && zipEntry.Size > 0)
                                {
                                    ProcessMediaUpload(zipEntry.GetStream(), scriptDb, $"{itemParam}/{zipEntry.Name}",
                                                       skipExisting);
                                }
                            }
                        }
                    }
                    else if (request.Files?.AllKeys?.Length > 0)
                    {
                        foreach (string fileName in request.Files.Keys)
                        {
                            var file = request.Files[fileName];
                            ProcessMediaUpload(file.InputStream, scriptDb, $"{itemParam}/{file.FileName}",
                                               skipExisting);
                        }
                    }
                    else
                    {
                        ProcessMediaUpload(request.InputStream, scriptDb, itemParam, skipExisting);
                    }
                }
                else
                {
                    ProcessMediaDownload(scriptDb, itemParam);
                }
                return;

            case "file":
                if (isUpload)
                {
                    ProcessFileUpload(request.InputStream, originParam, pathParam);
                }
                else
                {
                    ProcessFileDownload(originParam, pathParam);
                }
                return;

            case "handle":
                ProcessHandle(originParam);
                return;

            case "2":
                UpdateCache(dbName);
                if (!apiScripts.ContainsKey(dbName))
                {
                    HttpContext.Current.Response.StatusCode = 404;
                    return;
                }
                var dbScripts = apiScripts[dbName];
                if (!dbScripts.ContainsKey(itemParam))
                {
                    HttpContext.Current.Response.StatusCode = 404;
                    return;
                }
                scriptItem = scriptDb.GetItem(dbScripts[itemParam].Id);
                apiScripts = null;
                break;

            default:
                PowerShellLog.Error($"Requested API/Version ({serviceMappingKey}) is not supported.");
                return;
            }

            var streams = new Dictionary <string, Stream>();

            if (request.Files?.AllKeys?.Length > 0)
            {
                foreach (string fileName in request.Files.AllKeys)
                {
                    streams.Add(fileName, request.Files[fileName].InputStream);
                }
            }
            else if (request.InputStream != null)
            {
                streams.Add("stream", request.InputStream);
            }

            ProcessScript(context, scriptItem, streams);
        }