} // RemoveSessionStateItem

        /// <summary>
        /// Gets a flattened view of the environment variables in session state
        /// </summary>
        ///
        /// <returns>
        /// An IDictionary representing the flattened view of the environment variables in
        /// session state.
        /// </returns>
        ///
        internal override IDictionary GetSessionStateTable()
        {
            // Environment variables are case-sensitive on Unix and
            // case-insensitive on Windows
#if UNIX
            Dictionary <string, DictionaryEntry> providerTable =
                new Dictionary <string, DictionaryEntry>(StringComparer.Ordinal);
#else
            Dictionary <string, DictionaryEntry> providerTable =
                new Dictionary <string, DictionaryEntry>(StringComparer.OrdinalIgnoreCase);
#endif

            // The environment variables returns a dictionary of keys and values that are
            // both strings. We want to return a dictionary with the key as a string and
            // the value as the DictionaryEntry containing both the name and env variable
            // value.

            IDictionary environmentTable = Environment.GetEnvironmentVariables();
            foreach (DictionaryEntry entry in environmentTable)
            {
                providerTable.Add((string)entry.Key, entry);
            }

            return(providerTable);
        } // GetSessionStateTable
        } // SetSessionStateItem

        /// <summary>
        /// Removes the specified environment variable from session state.
        /// </summary>
        ///
        /// <param name="name">
        /// The name of the environment variable to remove from session state.
        /// </param>
        ///
        internal override void RemoveSessionStateItem(string name)
        {
            Dbg.Diagnostics.Assert(
                !String.IsNullOrEmpty(name),
                "The caller should verify this parameter");

            Environment.SetEnvironmentVariable(name, null);
        } // RemoveSessionStateItem
        } // InitializeDefaultDrives

        #endregion DriveCmdletProvider overrides

        #region protected members


        /// <summary>
        /// Gets a environment variable from session state
        /// </summary>
        ///
        /// <param name="name">
        /// The name of the environment variable to retrieve.
        /// </param>
        ///
        /// <returns>
        /// A DictionaryEntry that represents the value of the environment variable.
        /// </returns>
        ///
        internal override object GetSessionStateItem(string name)
        {
            Dbg.Diagnostics.Assert(
                !String.IsNullOrEmpty(name),
                "The caller should verify this parameter");

            object result = null;

            string value = Environment.GetEnvironmentVariable(name);

            if (value != null)
            {
                result = new DictionaryEntry(name, value);
            }
            return(result);
        } // GetSessionStateItem
        /// <summary>
        /// This value is not writable via the API and must be set using a text editor.
        /// </summary>
        /// <param name="scope"></param>
        /// <returns>Value if found, null otherwise. The behavior matches ModuleIntrinsics.GetExpandedEnvironmentVariable().</returns>
        internal override string GetModulePath(PropertyScope scope)
        {
            string scopeDirectory = psHomeConfigDirectory;

            // Defaults to system wide.
            if (PropertyScope.CurrentUser == scope)
            {
                scopeDirectory = appDataConfigDirectory;
            }

            string fileName = Path.Combine(scopeDirectory, configFileName);

            string modulePath = ReadValueFromFile <string>(fileName, "PsModulePath");

            if (!string.IsNullOrEmpty(modulePath))
            {
                modulePath = Environment.ExpandEnvironmentVariables(modulePath);
            }
            return(modulePath);
        }
        /// <summary>
        /// Report that a module was loaded, but only do so for modules that *might* be authored by Microsoft. We can't
        /// be 100% certain, but we'll ignore non-Microsoft module names when looking at any data, so it's best to
        /// at least attempt avoiding collecting data we'll ignore.
        /// </summary>
        internal static void ReportModuleLoad(PSModuleInfo foundModule)
        {
            var  modulePath             = foundModule.Path;
            var  companyName            = foundModule.CompanyName;
            bool couldBeMicrosoftModule =
                (modulePath != null &&
                 (modulePath.StartsWith(Utils.GetApplicationBase(Utils.DefaultPowerShellShellID), StringComparison.OrdinalIgnoreCase) ||
                  // The following covers both 64 and 32 bit Program Files by assuming 32bit is just ...\Program Files + " (x86)"
                  modulePath.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), StringComparison.OrdinalIgnoreCase))) ||
                (companyName != null &&
                 foundModule.CompanyName.StartsWith("Microsoft", StringComparison.OrdinalIgnoreCase));

            if (couldBeMicrosoftModule)
            {
                TelemetryWrapper.TraceMessage("PSImportModule", new
                {
                    ModuleName = foundModule.Name,
                    Version    = foundModule.Version.ToString()
                });
            }
        }
        } // GetSessionStateItem

        /// <summary>
        /// Sets the environment variable of the specified name to the specified value
        /// </summary>
        ///
        /// <param name="name">
        /// The name of the environment variable to set.
        /// </param>
        ///
        /// <param name="value">
        /// The new value for the environment variable.
        /// </param>
        ///
        /// <param name="writeItem">
        /// If true, the item that was set should be written to WriteItemObject.
        /// </param>
        ///
        internal override void SetSessionStateItem(string name, object value, bool writeItem)
        {
            Dbg.Diagnostics.Assert(
                !String.IsNullOrEmpty(name),
                "The caller should verify this parameter");

            if (value == null)
            {
                Environment.SetEnvironmentVariable(name, null);
            }
            else
            {
                // First see if we got a DictionaryEntry which represents
                // an item for this provider. If so, use the value from
                // the dictionary entry.

                if (value is DictionaryEntry)
                {
                    value = ((DictionaryEntry)value).Value;
                }

                string stringValue = value as string;
                if (stringValue == null)
                {
                    // try using ETS to convert to a string.

                    PSObject wrappedObject = PSObject.AsPSObject(value);
                    stringValue = wrappedObject.ToString();
                }
                Environment.SetEnvironmentVariable(name, stringValue);

                DictionaryEntry item = new DictionaryEntry(name, stringValue);

                if (writeItem)
                {
                    WriteItemObject(item, name, false);
                }
            }
        } // SetSessionStateItem
Exemple #7
0
        private bool CheckPolicy(ExternalScriptInfo script, PSHost host, out Exception reason)
        {
            bool policyCheckPassed = false;

            reason = null;
            string path = script.Path;
            string reasonMessage;

            // path is assumed to be fully qualified here
            if (path.IndexOf(System.IO.Path.DirectorySeparatorChar) < 0)
            {
                throw PSTraceSource.NewArgumentException("path");
            }

            if (path.LastIndexOf(System.IO.Path.DirectorySeparatorChar) == (path.Length - 1))
            {
                throw PSTraceSource.NewArgumentException("path");
            }

            FileInfo fi = new FileInfo(path);

            // Return false if the file does not exist, so that
            // we don't introduce a race condition
            if (!fi.Exists)
            {
                reason = new FileNotFoundException(path);
                return(false);
            }

            // Quick exit if we don't support the file type
            if (!IsSupportedExtension(fi.Extension))
            {
                return(true);
            }

            // Product binaries are always trusted
            if (SecuritySupport.IsProductBinary(path))
            {
                return(true);
            }

            // Get the execution policy
            _executionPolicy = SecuritySupport.GetExecutionPolicy(_shellId);

            // See if they want to bypass the authorization manager
            if (_executionPolicy == ExecutionPolicy.Bypass)
            {
                return(true);
            }
#if !CORECLR
            // Always check the SAFER APIs if code integrity isn't being handled system-wide through
            // WLDP or AppLocker. In those cases, the scripts will be run in ConstrainedLanguage.
            // Otherwise, block.
            // SAFER APIs are not on CSS or OneCore
            if (SystemPolicy.GetSystemLockdownPolicy() != SystemEnforcementMode.Enforce)
            {
                SaferPolicy saferPolicy    = SaferPolicy.Disallowed;
                int         saferAttempt   = 0;
                bool        gotSaferPolicy = false;

                // We need to put in a retry workaround, as the SAFER APIs fail when under stress.
                while ((!gotSaferPolicy) && (saferAttempt < 5))
                {
                    try
                    {
                        saferPolicy    = SecuritySupport.GetSaferPolicy(path, null);
                        gotSaferPolicy = true;
                    }
                    catch (System.ComponentModel.Win32Exception)
                    {
                        if (saferAttempt > 4)
                        {
                            throw;
                        }

                        saferAttempt++;
                        System.Threading.Thread.Sleep(100);
                    }
                }

                // If the script is disallowed via AppLocker, block the file
                // unless the system-wide lockdown policy is "Enforce" (where all PowerShell
                // scripts are in blocked). If the system policy is "Enforce", then the
                // script will be allowed (but ConstrainedLanguage will be applied).
                if (saferPolicy == SaferPolicy.Disallowed)
                {
                    reasonMessage = StringUtil.Format(Authenticode.Reason_DisallowedBySafer, path);
                    reason        = new UnauthorizedAccessException(reasonMessage);

                    return(false);
                }
            }
#endif
            if (_executionPolicy == ExecutionPolicy.Unrestricted)
            {
                // We need to give the "Remote File" warning
                // if the file originated from the internet
                if (!IsLocalFile(fi.FullName))
                {
                    // Get the signature of the file.
                    if (String.IsNullOrEmpty(script.ScriptContents))
                    {
                        reasonMessage = StringUtil.Format(Authenticode.Reason_FileContentUnavailable, path);
                        reason        = new UnauthorizedAccessException(reasonMessage);

                        return(false);
                    }

                    Signature signature = GetSignatureWithEncodingRetry(path, script);

                    // The file is signed, with a publisher that
                    // we trust
                    if (signature.Status == SignatureStatus.Valid)
                    {
                        // The file is signed by a trusted publisher
                        if (IsTrustedPublisher(signature, path))
                        {
                            policyCheckPassed = true;
                        }
                    }

                    // We don't care about the signature.  If you distrust them,
                    // or the signature does not exist, we prompt you only
                    // because it's remote.
                    if (!policyCheckPassed)
                    {
                        RunPromptDecision decision = RunPromptDecision.DoNotRun;

                        // Get their remote prompt answer, allowing them to
                        // enter nested prompts, if wanted.
                        do
                        {
                            decision = RemoteFilePrompt(path, host);

                            if (decision == RunPromptDecision.Suspend)
                            {
                                host.EnterNestedPrompt();
                            }
                        } while (decision == RunPromptDecision.Suspend);

                        switch (decision)
                        {
                        case RunPromptDecision.RunOnce:
                            policyCheckPassed = true;
                            break;

                        case RunPromptDecision.DoNotRun:
                        default:
                            policyCheckPassed = false;
                            reasonMessage     = StringUtil.Format(Authenticode.Reason_DoNotRun, path);
                            reason            = new UnauthorizedAccessException(reasonMessage);
                            break;
                        }
                    }
                }
                else
                {
                    policyCheckPassed = true;
                }
            }
            // Don't need to check the signature if the file is local
            // and we're in "RemoteSigned" mode
            else if ((IsLocalFile(fi.FullName)) &&
                     (_executionPolicy == ExecutionPolicy.RemoteSigned))
            {
                policyCheckPassed = true;
            }
            else if ((_executionPolicy == ExecutionPolicy.AllSigned) ||
                     (_executionPolicy == ExecutionPolicy.RemoteSigned))
            {
                // if policy requires signature verification,
                // make it so.

                // Get the signature of the file.
                if (String.IsNullOrEmpty(script.ScriptContents))
                {
                    reasonMessage = StringUtil.Format(Authenticode.Reason_FileContentUnavailable, path);
                    reason        = new UnauthorizedAccessException(reasonMessage);

                    return(false);
                }

                Signature signature = GetSignatureWithEncodingRetry(path, script);

                // The file is signed.
                if (signature.Status == SignatureStatus.Valid)
                {
                    // The file is signed by a trusted publisher
                    if (IsTrustedPublisher(signature, path))
                    {
                        policyCheckPassed = true;
                    }
                    // The file is signed by an unknown publisher,
                    // So prompt.
                    else
                    {
                        policyCheckPassed = SetPolicyFromAuthenticodePrompt(path, host, ref reason, signature);
                    }
                }
                // The file is UnknownError, NotSigned, HashMismatch,
                // NotTrusted, NotSupportedFileFormat
                else
                {
                    policyCheckPassed = false;

                    if (signature.Status == SignatureStatus.NotTrusted)
                    {
                        reason = new UnauthorizedAccessException(
                            StringUtil.Format(Authenticode.Reason_NotTrusted,
                                              path,
                                              signature.SignerCertificate.SubjectName.Name));
                    }
                    else
                    {
                        reason = new UnauthorizedAccessException(
                            StringUtil.Format(Authenticode.Reason_Unknown,
                                              path,
                                              signature.StatusMessage));
                    }
                }
            }
            else // if(executionPolicy == ExecutionPolicy.Restricted)
            {
                // Deny everything
                policyCheckPassed = false;

                // But accept mshxml files from publishers that we
                // trust, or files in the system protected directories
                bool reasonSet = false;
                if (String.Equals(fi.Extension, ".ps1xml", StringComparison.OrdinalIgnoreCase))
                {
                    string[] trustedDirectories = new string[]
                    { Environment.GetFolderPath(Environment.SpecialFolder.System),
                      Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) };

                    foreach (string trustedDirectory in trustedDirectories)
                    {
                        if (fi.FullName.StartsWith(trustedDirectory, StringComparison.OrdinalIgnoreCase))
                        {
                            policyCheckPassed = true;
                        }
                    }

                    if (!policyCheckPassed)
                    {
                        // Get the signature of the file.
                        Signature signature = GetSignatureWithEncodingRetry(path, script);

                        // The file is signed by a trusted publisher
                        if (signature.Status == SignatureStatus.Valid)
                        {
                            if (IsTrustedPublisher(signature, path))
                            {
                                policyCheckPassed = true;
                            }
                            // The file is signed by an unknown publisher,
                            // So prompt.
                            else
                            {
                                policyCheckPassed = SetPolicyFromAuthenticodePrompt(path, host, ref reason, signature);
                                reasonSet         = true;
                            }
                        }
                    }
                }

                if (!policyCheckPassed && !reasonSet)
                {
                    reason = new UnauthorizedAccessException(
                        StringUtil.Format(Authenticode.Reason_RestrictedMode,
                                          path));
                }
            }

            return(policyCheckPassed);
        }