Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / TrustManager.cs / 1305376 / TrustManager.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* */ using System; using System.Security; using System.Security.Policy; using System.Windows.Forms; using System.Globalization; using System.Text; using System.IO; using System.Collections; using System.Reflection; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Security.Permissions; using System.Xml; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Deployment.Internal; using System.Deployment.Internal.Isolation; using System.Deployment.Internal.Isolation.Manifest; using System.Deployment.Internal.CodeSigning; using Microsoft.Win32; using System.Runtime.InteropServices; namespace System.Security.Policy { ///internal class TrustManager : IApplicationTrustManager { public const string PromptingLevelKeyName = @"Software\Microsoft\.NETFramework\Security\TrustManager\PromptingLevel"; /// public TrustManager() { } // IApplicationTrustManager Implementation /// [ HostProtection(UI=true) ] public ApplicationTrust DetermineApplicationTrust(ActivationContext activationContext, TrustManagerContext trustManagerContext) { if (activationContext == null) { throw new ArgumentNullException("activationContext"); } ApplicationSecurityInfo info = new ApplicationSecurityInfo(activationContext); ApplicationTrustExtraInfo appTrustExtraInfo = new ApplicationTrustExtraInfo(); // ISSUE - fix this.... HostContextInternal hostContextInternal = new HostContextInternal(trustManagerContext); ICMS cms = (ICMS)InternalActivationContextHelper.GetDeploymentComponentManifest(activationContext); ParsedData parsedData = new ParsedData(); if (ParseManifest(cms, parsedData)) { appTrustExtraInfo.RequestsShellIntegration = parsedData.RequestsShellIntegration; } string deploymentUrl = GetDeploymentUrl(info); string zoneName = GetZoneNameFromDeploymentUrl(deploymentUrl); MemoryStream ms; PromptsAllowed promptsAllowed; if (!ExtractManifestContent(cms, out ms)) { // Block prompt return BlockingPrompt(activationContext, parsedData, deploymentUrl, info, appTrustExtraInfo, zoneName, AppRequestsBeyondDefaultTrust(info) /*permissionElevationRequired*/); } bool distrustedPublisher, trustedPublisher, noCertificate; AnalyzeCertificate(parsedData, ms, out distrustedPublisher, out trustedPublisher, out noCertificate); /// Check whether application manifest allows to use deployment manifest certificate. /// If not then we have to use application manifest certificate instead. ICMS applicationCms = (ICMS)InternalActivationContextHelper.GetApplicationComponentManifest(activationContext); ParsedData applicationParsedData = new ParsedData(); if (ParseManifest(applicationCms, applicationParsedData)) { if (applicationParsedData.UseManifestForTrust) { MemoryStream applicationMs; if (ExtractManifestContent(applicationCms, out applicationMs)) { /// Use the old parsedData. bool applicationDistrustedPublisher, applicationTrustedPublisher, applicationNoCertificate; AnalyzeCertificate(parsedData, applicationMs, out applicationDistrustedPublisher, out applicationTrustedPublisher, out applicationNoCertificate); distrustedPublisher = applicationDistrustedPublisher; trustedPublisher = applicationTrustedPublisher; noCertificate = applicationNoCertificate; parsedData.AppName = applicationParsedData.AppName; parsedData.AppPublisher = applicationParsedData.AppPublisher; parsedData.SupportUrl = applicationParsedData.SupportUrl; } } } if (distrustedPublisher) { promptsAllowed = GetPromptsAllowed(hostContextInternal, zoneName, parsedData); if (promptsAllowed == PromptsAllowed.None) { // No prompt allowed, return Do Not Trust. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, false /*trust*/, false /*persist*/); } return BlockingPrompt(activationContext, parsedData, deploymentUrl, info, appTrustExtraInfo, zoneName, AppRequestsBeyondDefaultTrust(info) /*permissionElevationRequired*/); } if (noCertificate) { parsedData.AuthenticodedPublisher = null; parsedData.Certificate = null; } if (!hostContextInternal.IgnorePersistedDecision) { // Check if there are previously trusted versions installed. ArrayList matchingTrusts; if (SearchPreviousTrustedVersion(activationContext, hostContextInternal.PreviousAppId, out matchingTrusts)) { Debug.Assert(matchingTrusts != null && matchingTrusts.Count > 0); // Found a matching app, with normally a different version. if (ExistingTrustApplicable(info, matchingTrusts)) { // There is at least one old version that requires at the same or more permissions. // ExistingTrustApplicable removed the non-applicable version from the matchingTrusts arrays. Debug.Assert(matchingTrusts != null && matchingTrusts.Count > 0); // Check if the new app requires shell integration while none of the old ones did if (appTrustExtraInfo.RequestsShellIntegration && !SomePreviousTrustedVersionRequiresShellIntegration(matchingTrusts) && !trustedPublisher) { promptsAllowed = GetPromptsAllowed(hostContextInternal, zoneName, parsedData); switch (promptsAllowed) { case PromptsAllowed.None: // No prompt allowed, return Do Not Trust. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, false /*trust*/, false /*persist*/); case PromptsAllowed.BlockingOnly: return BlockingPrompt(activationContext, parsedData, deploymentUrl, info, appTrustExtraInfo, zoneName, AppRequestsBeyondDefaultTrust(info) /*permissionElevationRequired*/); case PromptsAllowed.All: // New app requires shell integration - bring up the Basic Install Prompt return BasicInstallPrompt(activationContext, parsedData, deploymentUrl, hostContextInternal, info, appTrustExtraInfo, zoneName, AppRequestsBeyondDefaultTrust(info) /*permissionElevationRequired*/); } } // No prompt, return Trust & Persist. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, true /*trust*/, hostContextInternal.Persist /*persist*/); } } } bool permissionElevationRequired = AppRequestsBeyondDefaultTrust(info); if (!permissionElevationRequired || trustedPublisher) { if (!trustedPublisher && appTrustExtraInfo.RequestsShellIntegration) { Debug.Assert(!permissionElevationRequired); promptsAllowed = GetPromptsAllowed(hostContextInternal, zoneName, parsedData); switch (promptsAllowed) { case PromptsAllowed.None: // No prompt allowed, return Do Not Trust. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, false /*trust*/, false /*persist*/); case PromptsAllowed.BlockingOnly: return BlockingPrompt(activationContext, parsedData, deploymentUrl, info, appTrustExtraInfo, zoneName, permissionElevationRequired); case PromptsAllowed.All: // App shell integrates and is not from a trusted deployer, bring up the Basic Install Prompt. return BasicInstallPrompt(activationContext, parsedData, deploymentUrl, hostContextInternal, info, appTrustExtraInfo, zoneName, false /*permissionElevationRequired*/); } } else { // App does not shell integrate or is from a trusted deployer, return Trust return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, true /*trust*/, hostContextInternal.Persist /*persist*/); } } promptsAllowed = GetPromptsAllowed(hostContextInternal, zoneName, parsedData); switch (promptsAllowed) { case PromptsAllowed.None: // No prompt allowed, return Do Not Trust. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, false /*trust*/, false /*persist*/); case PromptsAllowed.BlockingOnly: return BlockingPrompt(activationContext, parsedData, deploymentUrl, info, appTrustExtraInfo, zoneName, true /*permissionElevationRequired*/); default: // PromptsAllowed.All: // Bring up the HighRisk Install Prompt if the app shell integrates, or the HighRisk Run Prompt otherwise. return HighRiskPrompt(activationContext, parsedData, deploymentUrl, hostContextInternal, info, appTrustExtraInfo, zoneName); } } // ISecurityEncodable implementation /// public SecurityElement ToXml() { SecurityElement elRoot = new SecurityElement("IApplicationTrustManager"); elRoot.AddAttribute("class", SecurityElement.Escape(this.GetType().AssemblyQualifiedName)); elRoot.AddAttribute("version", "1"); return elRoot; } /// public void FromXml(SecurityElement element) { if (element == null) { throw new ArgumentNullException("element"); } if (!String.Equals(element.Tag, "IApplicationTrustManager", StringComparison.Ordinal)) { throw new ArgumentException(SR.GetString(SR.TrustManagerBadXml ,"IApplicationTrustManager")); } } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static string DefaultBrowserExePath { get { try { string strBrowserPath = null; new RegistryPermission(PermissionState.Unrestricted).Assert(); try { RegistryKey key = Registry.ClassesRoot.OpenSubKey("http\\shell\\open\\command"); if (key != null) { string strBrowserCommand = (string) key.GetValue(string.Empty); key.Close(); if (strBrowserCommand != null) { strBrowserCommand = strBrowserCommand.Trim(); if (strBrowserCommand.Length != 0) { if (strBrowserCommand[0] == '\"') { int closingQuoteIndex = strBrowserCommand.IndexOf('"', 1); if (closingQuoteIndex != -1) { strBrowserPath = strBrowserCommand.Substring(1, closingQuoteIndex - 1); } } else { int firstSpaceIndex = strBrowserCommand.IndexOf(' '); if (firstSpaceIndex != -1) { strBrowserPath = strBrowserCommand.Substring(0, firstSpaceIndex); } else { strBrowserPath = strBrowserCommand; } } } } } } finally { System.Security.CodeAccessPermission.RevertAssert(); } return strBrowserPath; } catch (Exception ex) { Debug.Fail("Exception occurred while locating default browser executable: " + ex.Message); return null; } } } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static bool AnalyzeCertificate(ParsedData parsedData, MemoryStream ms, out bool distrustedPublisher, out bool trustedPublisher, out bool noCertificate) { const int TRUST_E_REVOKED = unchecked((int) 0x80092010); Debug.Assert(parsedData != null); Debug.Assert(ms != null); distrustedPublisher = false; trustedPublisher = false; noCertificate = false; SignedCmiManifest signedManifest = null; try { XmlDocument deploymentManifestXmlDom = new XmlDocument(); deploymentManifestXmlDom.PreserveWhitespace = true; deploymentManifestXmlDom.Load(ms); signedManifest = new SignedCmiManifest(deploymentManifestXmlDom); signedManifest.Verify(CmiManifestVerifyFlags.None); } catch (Exception e) { if (e is CryptographicException) { // // AuthenticodeSignerInfo can be null if the manifest is only strong name signed // but not authenticode signed. This can happen when the strong name // signature is invalid. // if (signedManifest.AuthenticodeSignerInfo != null) { int error = signedManifest.AuthenticodeSignerInfo.ErrorCode; if (error == System.Deployment.Internal.CodeSigning.Win32.TRUST_E_EXPLICIT_DISTRUST || error == TRUST_E_REVOKED) { distrustedPublisher = true; return true; } else if (error == System.Deployment.Internal.CodeSigning.Win32.TRUST_E_SUBJECT_NOT_TRUSTED) { // Certificate is valid but publisher is not in trusted list return true; } else { // No certificate is equivalent to strong name signing only - run app only with user consent noCertificate = true; return true; } } } return false; } finally { if (signedManifest != null && signedManifest.AuthenticodeSignerInfo != null && signedManifest.AuthenticodeSignerInfo.SignerChain != null) { parsedData.Certificate = signedManifest.AuthenticodeSignerInfo.SignerChain.ChainElements[0].Certificate; parsedData.AuthenticodedPublisher = parsedData.Certificate.GetNameInfo(X509NameType.SimpleName, false); } } if (signedManifest == null || signedManifest.AuthenticodeSignerInfo == null) { noCertificate = true; } else { trustedPublisher = true; } return true; } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static bool AppRequestsBeyondDefaultTrust(ApplicationSecurityInfo info) { Debug.Assert(info != null); try { PermissionSet permSetDefaultZone = SecurityManager.GetStandardSandbox(info.ApplicationEvidence); PermissionSet permSetRequested = GetRequestedPermissionSet(info); if (permSetDefaultZone == null && permSetRequested != null) { // No permissions are granted, and this launch requests some permissions return true; } else if (permSetDefaultZone != null && permSetRequested == null) { // Some permissions are granted, and this launch does not require any permissions return false; } Debug.Assert(permSetDefaultZone != null); Debug.Assert(permSetRequested != null); return !permSetRequested.IsSubsetOf(permSetDefaultZone); } catch (Exception) { return true; } } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static ApplicationTrust BasicInstallPrompt(ActivationContext activationContext, ParsedData parsedData, String deploymentUrl, HostContextInternal hostContextInternal, ApplicationSecurityInfo info, ApplicationTrustExtraInfo appTrustExtraInfo, string zoneName, bool permissionElevationRequired) { DialogResult ret; TrustManagerPromptOptions options = CompletePromptOptions(permissionElevationRequired ? TrustManagerPromptOptions.RequiresPermissions : TrustManagerPromptOptions.None, appTrustExtraInfo, zoneName, info); try { TrustManagerPromptUIThread basicInstallDialog = new TrustManagerPromptUIThread(string.IsNullOrEmpty(parsedData.AppName) ? info.ApplicationId.Name : parsedData.AppName, DefaultBrowserExePath, parsedData.SupportUrl, GetHostFromDeploymentUrl(deploymentUrl), parsedData.AuthenticodedPublisher /*publisherName*/, parsedData.Certificate, options); ret = basicInstallDialog.ShowDialog(); } catch (Exception ex) { Debug.Fail("Error occurred while showing basic install dialog: " + ex.Message); ret = DialogResult.No; } return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, ret == DialogResult.OK /*trust*/, hostContextInternal.Persist && ret == DialogResult.OK /*persist*/); } private static TrustManagerPromptOptions CompletePromptOptions(TrustManagerPromptOptions options, ApplicationTrustExtraInfo appTrustExtraInfo, string zoneName, ApplicationSecurityInfo info) { if (appTrustExtraInfo.RequestsShellIntegration) { options |= TrustManagerPromptOptions.AddsShortcut; } if (zoneName != null) { if (string.Compare(zoneName, "Internet", true, CultureInfo.InvariantCulture) == 0) { options |= TrustManagerPromptOptions.InternetSource; } else if (string.Compare(zoneName, "TrustedSites", true, CultureInfo.InvariantCulture) == 0) { options |= TrustManagerPromptOptions.TrustedSitesSource; } else if (string.Compare(zoneName, "UntrustedSites", true, CultureInfo.InvariantCulture) == 0) { options |= TrustManagerPromptOptions.UntrustedSitesSource; } else if (string.Compare(zoneName, "LocalIntranet", true, CultureInfo.InvariantCulture) == 0) { options |= TrustManagerPromptOptions.LocalNetworkSource; } else if (string.Compare(zoneName, "MyComputer", true, CultureInfo.InvariantCulture) == 0) { options |= TrustManagerPromptOptions.LocalComputerSource; } } if (info != null) { PermissionSet pset = info.DefaultRequestSet; if (pset != null && pset.IsUnrestricted()) { options |= TrustManagerPromptOptions.WillHaveFullTrust; } } return options; } private static ApplicationTrust CreateApplicationTrust(ActivationContext activationContext, ApplicationSecurityInfo info, ApplicationTrustExtraInfo appTrustExtraInfo, bool trust, bool persist) { ApplicationTrust appTrust = new ApplicationTrust(activationContext.Identity); appTrust.ExtraInfo = appTrustExtraInfo; appTrust.IsApplicationTrustedToRun = trust; appTrust.DefaultGrantSet = new PolicyStatement(info.DefaultRequestSet, (PolicyStatementAttribute) 0); appTrust.Persist = persist; return appTrust; } private static bool ExistingTrustApplicable(ApplicationSecurityInfo info, ArrayList matchingTrusts) { Debug.Assert(info != null); Debug.Assert(matchingTrusts != null); int entry = 0; while (entry < matchingTrusts.Count) { ApplicationTrust matchingTrust = (ApplicationTrust) matchingTrusts[entry]; if (!matchingTrust.IsApplicationTrustedToRun) { // [....]: Can this ever happen? I have serious doubts... matchingTrusts.RemoveAt(entry); } PermissionSet permSetRequested = GetRequestedPermissionSet(info); PermissionSet permSetGranted = matchingTrust.DefaultGrantSet.PermissionSet; //PolicyStatement makes of copy of its permission set here. if (permSetGranted == null && permSetRequested != null) { // No permissions were granted, and this launch requests some permissions matchingTrusts.RemoveAt(entry); } else if (permSetGranted != null && permSetRequested == null) { // Some permissions were granted, and this launch does not require any permissions entry++; continue; } Debug.Assert(permSetGranted != null); Debug.Assert(permSetRequested != null); if (permSetRequested.IsSubsetOf(permSetGranted)) { entry++; // Found a version that requires at least as much } else { // This version does not require as much matchingTrusts.RemoveAt(entry); } } return matchingTrusts.Count > 0; } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private unsafe static bool ExtractManifestContent(ICMS cms, out MemoryStream ms) { ms = new MemoryStream(); try { System.Runtime.InteropServices.ComTypes.IStream pStream = cms as System.Runtime.InteropServices.ComTypes.IStream; if (pStream == null) { return false; } byte[] pv = new byte[4096]; int size = 4096; do { pStream.Read(pv, size, new IntPtr(&size)); ms.Write(pv, 0, size); } while (size == 4096); ms.Position = 0; return true; } catch (Exception) { Debug.Fail("Exception occurred in ExtractDeploymentManifestContent."); return false; } } private static PromptingLevel GetDefaultPromptingLevel(string zoneName) { PromptingLevel promptingLevel; switch (zoneName) { case "Internet": case "LocalIntranet": case "MyComputer": case "TrustedSites": promptingLevel = PromptingLevel.Prompt; break; case "UntrustedSites": promptingLevel = PromptingLevel.Disabled; break; default: promptingLevel = PromptingLevel.Disabled; break; } return promptingLevel; } private static string GetDeploymentUrl(ApplicationSecurityInfo info) { Debug.Assert(info != null); Evidence appEvidence = info.ApplicationEvidence; Url deploymentUrl = appEvidence.GetHostEvidence (); if (deploymentUrl != null) { return deploymentUrl.Value; } // Couldn't find deployment Url return null; } private static PermissionSet GetRequestedPermissionSet(ApplicationSecurityInfo info) { Debug.Assert(info != null); PermissionSet pset = info.DefaultRequestSet; PermissionSet permSetRequested = null; if (pset != null) { permSetRequested = pset.Copy(); } return permSetRequested; } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static string GetHostFromDeploymentUrl(string deploymentUrl) { if (deploymentUrl == null) { return string.Empty; } string host = null; try { System.Uri uri = new System.Uri(deploymentUrl); if (uri.Scheme == System.Uri.UriSchemeHttp || uri.Scheme == System.Uri.UriSchemeHttps) { host = uri.Host; } if (string.IsNullOrEmpty(host)) { host = uri.AbsolutePath; int separatorIndex = -1; if (string.IsNullOrEmpty(uri.Host) && host.StartsWith("/")) { host = host.TrimStart('/'); separatorIndex = host.IndexOf('/'); } else if (uri.LocalPath.Length > 2 && (uri.LocalPath[1] == ':' || uri.LocalPath.StartsWith("\\\\"))) { host = uri.LocalPath; separatorIndex = host.LastIndexOf('\\'); } if (separatorIndex != -1) { host = host.Remove(separatorIndex); } } } catch (Exception ex) { Debug.Fail("Exception occurred in GetHostFromDeploymentUrl: " + ex.Message); return string.Empty; } return host; } private static PromptsAllowed GetPromptsAllowed(HostContextInternal hostContextInternal, string zoneName, ParsedData parsedData) { Debug.Assert(hostContextInternal != null); Debug.Assert(zoneName != null); Debug.Assert(parsedData != null); if (hostContextInternal.NoPrompt) { return PromptsAllowed.None; } PromptingLevel promptingLevel = GetZonePromptingLevel(zoneName); if (promptingLevel == PromptingLevel.Disabled || (promptingLevel == PromptingLevel.PromptOnlyForAuthenticode && parsedData.AuthenticodedPublisher == null)) { return PromptsAllowed.BlockingOnly; } return PromptsAllowed.All; } private static string GetZoneNameFromDeploymentUrl(String deploymentUrl) { Zone zone = Zone.CreateFromUrl(deploymentUrl); if (zone == null || zone.SecurityZone == SecurityZone.NoZone) { return "UntrustedSites"; } switch (zone.SecurityZone) { case SecurityZone.Internet: return "Internet"; case SecurityZone.Intranet: return "LocalIntranet"; case SecurityZone.MyComputer: return "MyComputer"; case SecurityZone.Trusted: return "TrustedSites"; case SecurityZone.Untrusted: return "UntrustedSites"; default: Debug.Fail("Unexpected SecurityZone in GetZoneNameFromDeploymentUrl"); return "UntrustedSites"; } } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static PromptingLevel GetZonePromptingLevel(string zoneName) { try { string promptingLevelStr = null; new RegistryPermission(PermissionState.Unrestricted).Assert(); try { using (RegistryKey key = Registry.LocalMachine.OpenSubKey(PromptingLevelKeyName)) { if (key != null) { promptingLevelStr = (string)key.GetValue(zoneName); } } } finally { System.Security.CodeAccessPermission.RevertAssert(); } if (string.IsNullOrEmpty(promptingLevelStr)) { return GetDefaultPromptingLevel(zoneName); } else if (string.Compare(promptingLevelStr, "Enabled", true, CultureInfo.InvariantCulture) == 0) { return PromptingLevel.Prompt; } else if (string.Compare(promptingLevelStr, "Disabled", true, CultureInfo.InvariantCulture) == 0) { return PromptingLevel.Disabled; } else if (string.Compare(promptingLevelStr, "AuthenticodeRequired", true, CultureInfo.InvariantCulture) == 0) { return PromptingLevel.PromptOnlyForAuthenticode; } else { return GetDefaultPromptingLevel(zoneName); } } catch (Exception ex) { Debug.Fail("Exception occurred in GetZonePromptingLevel: " + ex.Message); return GetDefaultPromptingLevel(zoneName); } } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static ApplicationTrust HighRiskPrompt(ActivationContext activationContext, ParsedData parsedData, String deploymentUrl, HostContextInternal hostContextInternal, ApplicationSecurityInfo info, ApplicationTrustExtraInfo appTrustExtraInfo, string zoneName) { DialogResult ret; TrustManagerPromptOptions options = CompletePromptOptions(TrustManagerPromptOptions.RequiresPermissions, appTrustExtraInfo, zoneName, info); try { TrustManagerPromptUIThread highRiskDialog = new TrustManagerPromptUIThread(string.IsNullOrEmpty(parsedData.AppName) ? info.ApplicationId.Name : parsedData.AppName, DefaultBrowserExePath, parsedData.SupportUrl, GetHostFromDeploymentUrl(deploymentUrl), parsedData.AuthenticodedPublisher /*publisherName*/, parsedData.Certificate, options); ret = highRiskDialog.ShowDialog(); } catch (Exception ex) { Debug.Fail("Error occurred while showing high risk dialog: " + ex.Message); ret = DialogResult.No; } return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, ret == DialogResult.OK /*trust*/, hostContextInternal.Persist && ret == DialogResult.OK /*persist*/); } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static ApplicationTrust BlockingPrompt(ActivationContext activationContext, ParsedData parsedData, String deploymentUrl, ApplicationSecurityInfo info, ApplicationTrustExtraInfo appTrustExtraInfo, string zoneName, bool permissionElevationRequired) { TrustManagerPromptOptions options = CompletePromptOptions(permissionElevationRequired ? (TrustManagerPromptOptions.StopApp | TrustManagerPromptOptions.RequiresPermissions) : TrustManagerPromptOptions.StopApp, appTrustExtraInfo, zoneName, info); try { TrustManagerPromptUIThread errorDialog = new TrustManagerPromptUIThread(string.IsNullOrEmpty(parsedData.AppName) ? info.ApplicationId.Name : parsedData.AppName, DefaultBrowserExePath, parsedData.SupportUrl, GetHostFromDeploymentUrl(deploymentUrl), parsedData.AuthenticodedPublisher /*publisherName*/, parsedData.Certificate, options); errorDialog.ShowDialog(); } catch (Exception ex) { Debug.Fail("Error occurred while showing error dialog: " + ex.Message); } // Trust Manager should prompt, but is not allowed to. Return Don't Trust and Don't Persist. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, false /*trust*/, false /*persist*/); } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static bool ParseManifest(ICMS cms, ParsedData parsedData) { // parsedData is safely initialized to requestsShellIntegration:false/supportUrl:null/authenticodedPublisher:null //deploymentProviderCodebase:null try { if (cms != null) { // Extract SupportUrl and Shell Visibility if (cms.MetadataSectionEntry != null) { IMetadataSectionEntry metaDataSectionEntry = cms.MetadataSectionEntry as IMetadataSectionEntry; if (metaDataSectionEntry != null) { IDescriptionMetadataEntry description = metaDataSectionEntry.DescriptionData; if (description != null) { parsedData.SupportUrl = description.SupportUrl; parsedData.AppName = description.Product; parsedData.AppPublisher = description.Publisher; // [....]: description.Publisher is accessible here. Ask JamieC if we should grab it. } IDeploymentMetadataEntry deployment = metaDataSectionEntry.DeploymentData; if (deployment != null) { parsedData.RequestsShellIntegration = ((deployment.DeploymentFlags & (uint)(CMS_ASSEMBLY_DEPLOYMENT_FLAG.CMS_ASSEMBLY_DEPLOYMENT_FLAG_INSTALL)) != 0); // parsedData.DeploymentProviderCodebase = deployment.DeploymentProviderCodebase; } if ((metaDataSectionEntry.ManifestFlags & (uint)CMS_MANIFEST_FLAG.CMS_MANIFEST_FLAG_USEMANIFESTFORTRUST) != 0) { parsedData.UseManifestForTrust = true; } else { parsedData.UseManifestForTrust = false; } } } } } catch (Exception e) { Debug.Fail("Error parsing manifest: " + e.Message); return false; } return true; } private static bool SomePreviousTrustedVersionRequiresShellIntegration(ArrayList /*ApplicationTrust[]*/ matchingTrusts) { Debug.Assert(matchingTrusts != null); foreach (ApplicationTrust matchingTrust in matchingTrusts) { ApplicationTrustExtraInfo matchingAppTrustExtraInfo = matchingTrust.ExtraInfo as ApplicationTrustExtraInfo; if (matchingAppTrustExtraInfo != null && matchingAppTrustExtraInfo.RequestsShellIntegration) { return true; } if (null == matchingAppTrustExtraInfo && matchingTrust.DefaultGrantSet.PermissionSet.IsUnrestricted()) { // Full trust trumps RequestsShellIntegration, so return true in this case. return true; } } // No previous trusted version requires shell integration return false; } private static bool SearchPreviousTrustedVersion(ActivationContext activationContext, ApplicationIdentity previousAppId, out ArrayList matchingTrusts) { // No match found by default matchingTrusts = null; ApplicationTrustCollection appTrusts = ApplicationSecurityManager.UserApplicationTrusts; foreach (ApplicationTrust appTrust in appTrusts) { IDefinitionAppId appTrustAppId = IsolationInterop.AppIdAuthority.TextToDefinition(0, appTrust.ApplicationIdentity.FullName); IDefinitionAppId actCtxAppId = IsolationInterop.AppIdAuthority.TextToDefinition(0, activationContext.Identity.FullName); if (IsolationInterop.AppIdAuthority.AreDefinitionsEqual((uint) IAPPIDAUTHORITY_ARE_DEFINITIONS_EQUAL_FLAGS.IAPPIDAUTHORITY_ARE_DEFINITIONS_EQUAL_FLAG_IGNORE_VERSION, appTrustAppId, actCtxAppId)) { // Found an older matching app (or same version app which should never occur in theory) if (matchingTrusts == null) { matchingTrusts = new ArrayList(); } matchingTrusts.Add(appTrust); } } if (previousAppId != null) { foreach (ApplicationTrust appTrust in appTrusts) { IDefinitionAppId appTrustDefAppId = IsolationInterop.AppIdAuthority.TextToDefinition(0, appTrust.ApplicationIdentity.FullName); IDefinitionAppId previousDefAppId = IsolationInterop.AppIdAuthority.TextToDefinition(0, previousAppId.FullName); if (IsolationInterop.AppIdAuthority.AreDefinitionsEqual((uint) IAPPIDAUTHORITY_ARE_DEFINITIONS_EQUAL_FLAGS.IAPPIDAUTHORITY_ARE_DEFINITIONS_EQUAL_FLAG_IGNORE_VERSION, appTrustDefAppId, previousDefAppId)) { // Found an older matching app (or same version app which should never occur in theory) if (matchingTrusts == null) { matchingTrusts = new ArrayList(); } matchingTrusts.Add(appTrust); } } } // (matchingTrusts != null) <==> Found a prior version that was allowed to run. return (matchingTrusts != null); } private enum PromptingLevel { /// /// Disabled = 0, ////// In the cases the Trust Manager needs to prompt, it needs to show the blocking prompt /// ////// Prompt = 1, ////// Prompting is allowed for strong named and authenticode signed application deployments /// ////// PromptOnlyForAuthenticode = 2 } private enum PromptsAllowed { ////// Prompting is allowed for authenticode signed application deployments only /// ////// All = 0, ////// The Trust Manager is allowed to show any prompt /// ////// BlockingOnly = 1, ////// The Trust Manager is only allowed to show the blocking prompt /// ////// None = 2 } } [Serializable] internal class ApplicationTrustExtraInfo { private bool requestsShellIntegration = true; // If manifest parsing fails, we assume shell integration is required. public ApplicationTrustExtraInfo() { } public bool RequestsShellIntegration { get { return this.requestsShellIntegration; } set { this.requestsShellIntegration = value; } } } internal class TrustManagerPromptUIThread { private string m_appName, m_defaultBrowserExePath, m_supportUrl, m_deploymentUrl, m_publisherName; private X509Certificate2 m_certificate; private TrustManagerPromptOptions m_options; private DialogResult m_ret = DialogResult.No; public TrustManagerPromptUIThread(string appName, string defaultBrowserExePath, string supportUrl, string deploymentUrl, string publisherName, X509Certificate2 certificate, TrustManagerPromptOptions options) { this.m_appName = appName; this.m_defaultBrowserExePath = defaultBrowserExePath; this.m_supportUrl = supportUrl; this.m_deploymentUrl = deploymentUrl; this.m_publisherName = publisherName; this.m_certificate = certificate; this.m_options = options; } public DialogResult ShowDialog() { System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(ShowDialogWork)); thread.SetApartmentState(System.Threading.ApartmentState.STA); thread.Start(); thread.Join(); return m_ret; } [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] private void ShowDialogWork() { try { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); using (TrustManagerPromptUI trustManagerDialog = new TrustManagerPromptUI(this.m_appName, this.m_defaultBrowserExePath, this.m_supportUrl, this.m_deploymentUrl, this.m_publisherName, this.m_certificate, this.m_options)) { m_ret = trustManagerDialog.ShowDialog(); } } catch { } } } internal class ParsedData { private bool requestsShellIntegration; /* == false by default. shellVisible attribute is optional */ private string appName; private string appPublisher; private string supportUrl; private string authenticodedPublisher; private bool disallowTrustOverride; private X509Certificate2 certificate; // private string deploymentProviderCodebase; public ParsedData() { } public bool RequestsShellIntegration { get { return this.requestsShellIntegration; } set { this.requestsShellIntegration = value; } } public X509Certificate2 Certificate { get { return this.certificate; } set { this.certificate = value; } } public string AppName { get { return this.appName; } set { this.appName = value; } } public string AppPublisher { get { return this.appPublisher; } set { this.appPublisher = value; } } public string AuthenticodedPublisher { get { return this.authenticodedPublisher; } set { this.authenticodedPublisher = value; } } public bool UseManifestForTrust { get { return disallowTrustOverride; } set { disallowTrustOverride = value; } } // public string DeploymentProviderCodebase // { // get // { // return this.deploymentProviderCodebase; // } // set // { // this.deploymentProviderCodebase = value; // } // } public string SupportUrl { get { return this.supportUrl; } set { this.supportUrl = value; } } } internal class HostContextInternal { private bool ignorePersistedDecision; private bool noPrompt; private bool persist; private ApplicationIdentity previousAppId; public HostContextInternal(TrustManagerContext trustManagerContext) { if (trustManagerContext == null) { // Used in case DetermineApplicationTrust is not given a TrustManagerContext object. this.persist = true; } else { // ISSUE - fix this... // Note that exclusiveGrant is never set. It is read in CreateApplicationTrust however. this.ignorePersistedDecision = trustManagerContext.IgnorePersistedDecision; this.noPrompt = trustManagerContext.NoPrompt; this.persist = trustManagerContext.Persist; this.previousAppId = trustManagerContext.PreviousApplicationIdentity; } } public bool IgnorePersistedDecision { get { return this.ignorePersistedDecision; } } public bool NoPrompt { get { return this.noPrompt; } } public bool Persist { get { return this.persist; } } public ApplicationIdentity PreviousAppId { get { return this.previousAppId; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ ///// The Trust Manager is not allowed to prompt at all /// ///// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* */ using System; using System.Security; using System.Security.Policy; using System.Windows.Forms; using System.Globalization; using System.Text; using System.IO; using System.Collections; using System.Reflection; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Security.Permissions; using System.Xml; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Deployment.Internal; using System.Deployment.Internal.Isolation; using System.Deployment.Internal.Isolation.Manifest; using System.Deployment.Internal.CodeSigning; using Microsoft.Win32; using System.Runtime.InteropServices; namespace System.Security.Policy { ///internal class TrustManager : IApplicationTrustManager { public const string PromptingLevelKeyName = @"Software\Microsoft\.NETFramework\Security\TrustManager\PromptingLevel"; /// public TrustManager() { } // IApplicationTrustManager Implementation /// [ HostProtection(UI=true) ] public ApplicationTrust DetermineApplicationTrust(ActivationContext activationContext, TrustManagerContext trustManagerContext) { if (activationContext == null) { throw new ArgumentNullException("activationContext"); } ApplicationSecurityInfo info = new ApplicationSecurityInfo(activationContext); ApplicationTrustExtraInfo appTrustExtraInfo = new ApplicationTrustExtraInfo(); // ISSUE - fix this.... HostContextInternal hostContextInternal = new HostContextInternal(trustManagerContext); ICMS cms = (ICMS)InternalActivationContextHelper.GetDeploymentComponentManifest(activationContext); ParsedData parsedData = new ParsedData(); if (ParseManifest(cms, parsedData)) { appTrustExtraInfo.RequestsShellIntegration = parsedData.RequestsShellIntegration; } string deploymentUrl = GetDeploymentUrl(info); string zoneName = GetZoneNameFromDeploymentUrl(deploymentUrl); MemoryStream ms; PromptsAllowed promptsAllowed; if (!ExtractManifestContent(cms, out ms)) { // Block prompt return BlockingPrompt(activationContext, parsedData, deploymentUrl, info, appTrustExtraInfo, zoneName, AppRequestsBeyondDefaultTrust(info) /*permissionElevationRequired*/); } bool distrustedPublisher, trustedPublisher, noCertificate; AnalyzeCertificate(parsedData, ms, out distrustedPublisher, out trustedPublisher, out noCertificate); /// Check whether application manifest allows to use deployment manifest certificate. /// If not then we have to use application manifest certificate instead. ICMS applicationCms = (ICMS)InternalActivationContextHelper.GetApplicationComponentManifest(activationContext); ParsedData applicationParsedData = new ParsedData(); if (ParseManifest(applicationCms, applicationParsedData)) { if (applicationParsedData.UseManifestForTrust) { MemoryStream applicationMs; if (ExtractManifestContent(applicationCms, out applicationMs)) { /// Use the old parsedData. bool applicationDistrustedPublisher, applicationTrustedPublisher, applicationNoCertificate; AnalyzeCertificate(parsedData, applicationMs, out applicationDistrustedPublisher, out applicationTrustedPublisher, out applicationNoCertificate); distrustedPublisher = applicationDistrustedPublisher; trustedPublisher = applicationTrustedPublisher; noCertificate = applicationNoCertificate; parsedData.AppName = applicationParsedData.AppName; parsedData.AppPublisher = applicationParsedData.AppPublisher; parsedData.SupportUrl = applicationParsedData.SupportUrl; } } } if (distrustedPublisher) { promptsAllowed = GetPromptsAllowed(hostContextInternal, zoneName, parsedData); if (promptsAllowed == PromptsAllowed.None) { // No prompt allowed, return Do Not Trust. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, false /*trust*/, false /*persist*/); } return BlockingPrompt(activationContext, parsedData, deploymentUrl, info, appTrustExtraInfo, zoneName, AppRequestsBeyondDefaultTrust(info) /*permissionElevationRequired*/); } if (noCertificate) { parsedData.AuthenticodedPublisher = null; parsedData.Certificate = null; } if (!hostContextInternal.IgnorePersistedDecision) { // Check if there are previously trusted versions installed. ArrayList matchingTrusts; if (SearchPreviousTrustedVersion(activationContext, hostContextInternal.PreviousAppId, out matchingTrusts)) { Debug.Assert(matchingTrusts != null && matchingTrusts.Count > 0); // Found a matching app, with normally a different version. if (ExistingTrustApplicable(info, matchingTrusts)) { // There is at least one old version that requires at the same or more permissions. // ExistingTrustApplicable removed the non-applicable version from the matchingTrusts arrays. Debug.Assert(matchingTrusts != null && matchingTrusts.Count > 0); // Check if the new app requires shell integration while none of the old ones did if (appTrustExtraInfo.RequestsShellIntegration && !SomePreviousTrustedVersionRequiresShellIntegration(matchingTrusts) && !trustedPublisher) { promptsAllowed = GetPromptsAllowed(hostContextInternal, zoneName, parsedData); switch (promptsAllowed) { case PromptsAllowed.None: // No prompt allowed, return Do Not Trust. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, false /*trust*/, false /*persist*/); case PromptsAllowed.BlockingOnly: return BlockingPrompt(activationContext, parsedData, deploymentUrl, info, appTrustExtraInfo, zoneName, AppRequestsBeyondDefaultTrust(info) /*permissionElevationRequired*/); case PromptsAllowed.All: // New app requires shell integration - bring up the Basic Install Prompt return BasicInstallPrompt(activationContext, parsedData, deploymentUrl, hostContextInternal, info, appTrustExtraInfo, zoneName, AppRequestsBeyondDefaultTrust(info) /*permissionElevationRequired*/); } } // No prompt, return Trust & Persist. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, true /*trust*/, hostContextInternal.Persist /*persist*/); } } } bool permissionElevationRequired = AppRequestsBeyondDefaultTrust(info); if (!permissionElevationRequired || trustedPublisher) { if (!trustedPublisher && appTrustExtraInfo.RequestsShellIntegration) { Debug.Assert(!permissionElevationRequired); promptsAllowed = GetPromptsAllowed(hostContextInternal, zoneName, parsedData); switch (promptsAllowed) { case PromptsAllowed.None: // No prompt allowed, return Do Not Trust. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, false /*trust*/, false /*persist*/); case PromptsAllowed.BlockingOnly: return BlockingPrompt(activationContext, parsedData, deploymentUrl, info, appTrustExtraInfo, zoneName, permissionElevationRequired); case PromptsAllowed.All: // App shell integrates and is not from a trusted deployer, bring up the Basic Install Prompt. return BasicInstallPrompt(activationContext, parsedData, deploymentUrl, hostContextInternal, info, appTrustExtraInfo, zoneName, false /*permissionElevationRequired*/); } } else { // App does not shell integrate or is from a trusted deployer, return Trust return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, true /*trust*/, hostContextInternal.Persist /*persist*/); } } promptsAllowed = GetPromptsAllowed(hostContextInternal, zoneName, parsedData); switch (promptsAllowed) { case PromptsAllowed.None: // No prompt allowed, return Do Not Trust. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, false /*trust*/, false /*persist*/); case PromptsAllowed.BlockingOnly: return BlockingPrompt(activationContext, parsedData, deploymentUrl, info, appTrustExtraInfo, zoneName, true /*permissionElevationRequired*/); default: // PromptsAllowed.All: // Bring up the HighRisk Install Prompt if the app shell integrates, or the HighRisk Run Prompt otherwise. return HighRiskPrompt(activationContext, parsedData, deploymentUrl, hostContextInternal, info, appTrustExtraInfo, zoneName); } } // ISecurityEncodable implementation /// public SecurityElement ToXml() { SecurityElement elRoot = new SecurityElement("IApplicationTrustManager"); elRoot.AddAttribute("class", SecurityElement.Escape(this.GetType().AssemblyQualifiedName)); elRoot.AddAttribute("version", "1"); return elRoot; } /// public void FromXml(SecurityElement element) { if (element == null) { throw new ArgumentNullException("element"); } if (!String.Equals(element.Tag, "IApplicationTrustManager", StringComparison.Ordinal)) { throw new ArgumentException(SR.GetString(SR.TrustManagerBadXml ,"IApplicationTrustManager")); } } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static string DefaultBrowserExePath { get { try { string strBrowserPath = null; new RegistryPermission(PermissionState.Unrestricted).Assert(); try { RegistryKey key = Registry.ClassesRoot.OpenSubKey("http\\shell\\open\\command"); if (key != null) { string strBrowserCommand = (string) key.GetValue(string.Empty); key.Close(); if (strBrowserCommand != null) { strBrowserCommand = strBrowserCommand.Trim(); if (strBrowserCommand.Length != 0) { if (strBrowserCommand[0] == '\"') { int closingQuoteIndex = strBrowserCommand.IndexOf('"', 1); if (closingQuoteIndex != -1) { strBrowserPath = strBrowserCommand.Substring(1, closingQuoteIndex - 1); } } else { int firstSpaceIndex = strBrowserCommand.IndexOf(' '); if (firstSpaceIndex != -1) { strBrowserPath = strBrowserCommand.Substring(0, firstSpaceIndex); } else { strBrowserPath = strBrowserCommand; } } } } } } finally { System.Security.CodeAccessPermission.RevertAssert(); } return strBrowserPath; } catch (Exception ex) { Debug.Fail("Exception occurred while locating default browser executable: " + ex.Message); return null; } } } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static bool AnalyzeCertificate(ParsedData parsedData, MemoryStream ms, out bool distrustedPublisher, out bool trustedPublisher, out bool noCertificate) { const int TRUST_E_REVOKED = unchecked((int) 0x80092010); Debug.Assert(parsedData != null); Debug.Assert(ms != null); distrustedPublisher = false; trustedPublisher = false; noCertificate = false; SignedCmiManifest signedManifest = null; try { XmlDocument deploymentManifestXmlDom = new XmlDocument(); deploymentManifestXmlDom.PreserveWhitespace = true; deploymentManifestXmlDom.Load(ms); signedManifest = new SignedCmiManifest(deploymentManifestXmlDom); signedManifest.Verify(CmiManifestVerifyFlags.None); } catch (Exception e) { if (e is CryptographicException) { // // AuthenticodeSignerInfo can be null if the manifest is only strong name signed // but not authenticode signed. This can happen when the strong name // signature is invalid. // if (signedManifest.AuthenticodeSignerInfo != null) { int error = signedManifest.AuthenticodeSignerInfo.ErrorCode; if (error == System.Deployment.Internal.CodeSigning.Win32.TRUST_E_EXPLICIT_DISTRUST || error == TRUST_E_REVOKED) { distrustedPublisher = true; return true; } else if (error == System.Deployment.Internal.CodeSigning.Win32.TRUST_E_SUBJECT_NOT_TRUSTED) { // Certificate is valid but publisher is not in trusted list return true; } else { // No certificate is equivalent to strong name signing only - run app only with user consent noCertificate = true; return true; } } } return false; } finally { if (signedManifest != null && signedManifest.AuthenticodeSignerInfo != null && signedManifest.AuthenticodeSignerInfo.SignerChain != null) { parsedData.Certificate = signedManifest.AuthenticodeSignerInfo.SignerChain.ChainElements[0].Certificate; parsedData.AuthenticodedPublisher = parsedData.Certificate.GetNameInfo(X509NameType.SimpleName, false); } } if (signedManifest == null || signedManifest.AuthenticodeSignerInfo == null) { noCertificate = true; } else { trustedPublisher = true; } return true; } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static bool AppRequestsBeyondDefaultTrust(ApplicationSecurityInfo info) { Debug.Assert(info != null); try { PermissionSet permSetDefaultZone = SecurityManager.GetStandardSandbox(info.ApplicationEvidence); PermissionSet permSetRequested = GetRequestedPermissionSet(info); if (permSetDefaultZone == null && permSetRequested != null) { // No permissions are granted, and this launch requests some permissions return true; } else if (permSetDefaultZone != null && permSetRequested == null) { // Some permissions are granted, and this launch does not require any permissions return false; } Debug.Assert(permSetDefaultZone != null); Debug.Assert(permSetRequested != null); return !permSetRequested.IsSubsetOf(permSetDefaultZone); } catch (Exception) { return true; } } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static ApplicationTrust BasicInstallPrompt(ActivationContext activationContext, ParsedData parsedData, String deploymentUrl, HostContextInternal hostContextInternal, ApplicationSecurityInfo info, ApplicationTrustExtraInfo appTrustExtraInfo, string zoneName, bool permissionElevationRequired) { DialogResult ret; TrustManagerPromptOptions options = CompletePromptOptions(permissionElevationRequired ? TrustManagerPromptOptions.RequiresPermissions : TrustManagerPromptOptions.None, appTrustExtraInfo, zoneName, info); try { TrustManagerPromptUIThread basicInstallDialog = new TrustManagerPromptUIThread(string.IsNullOrEmpty(parsedData.AppName) ? info.ApplicationId.Name : parsedData.AppName, DefaultBrowserExePath, parsedData.SupportUrl, GetHostFromDeploymentUrl(deploymentUrl), parsedData.AuthenticodedPublisher /*publisherName*/, parsedData.Certificate, options); ret = basicInstallDialog.ShowDialog(); } catch (Exception ex) { Debug.Fail("Error occurred while showing basic install dialog: " + ex.Message); ret = DialogResult.No; } return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, ret == DialogResult.OK /*trust*/, hostContextInternal.Persist && ret == DialogResult.OK /*persist*/); } private static TrustManagerPromptOptions CompletePromptOptions(TrustManagerPromptOptions options, ApplicationTrustExtraInfo appTrustExtraInfo, string zoneName, ApplicationSecurityInfo info) { if (appTrustExtraInfo.RequestsShellIntegration) { options |= TrustManagerPromptOptions.AddsShortcut; } if (zoneName != null) { if (string.Compare(zoneName, "Internet", true, CultureInfo.InvariantCulture) == 0) { options |= TrustManagerPromptOptions.InternetSource; } else if (string.Compare(zoneName, "TrustedSites", true, CultureInfo.InvariantCulture) == 0) { options |= TrustManagerPromptOptions.TrustedSitesSource; } else if (string.Compare(zoneName, "UntrustedSites", true, CultureInfo.InvariantCulture) == 0) { options |= TrustManagerPromptOptions.UntrustedSitesSource; } else if (string.Compare(zoneName, "LocalIntranet", true, CultureInfo.InvariantCulture) == 0) { options |= TrustManagerPromptOptions.LocalNetworkSource; } else if (string.Compare(zoneName, "MyComputer", true, CultureInfo.InvariantCulture) == 0) { options |= TrustManagerPromptOptions.LocalComputerSource; } } if (info != null) { PermissionSet pset = info.DefaultRequestSet; if (pset != null && pset.IsUnrestricted()) { options |= TrustManagerPromptOptions.WillHaveFullTrust; } } return options; } private static ApplicationTrust CreateApplicationTrust(ActivationContext activationContext, ApplicationSecurityInfo info, ApplicationTrustExtraInfo appTrustExtraInfo, bool trust, bool persist) { ApplicationTrust appTrust = new ApplicationTrust(activationContext.Identity); appTrust.ExtraInfo = appTrustExtraInfo; appTrust.IsApplicationTrustedToRun = trust; appTrust.DefaultGrantSet = new PolicyStatement(info.DefaultRequestSet, (PolicyStatementAttribute) 0); appTrust.Persist = persist; return appTrust; } private static bool ExistingTrustApplicable(ApplicationSecurityInfo info, ArrayList matchingTrusts) { Debug.Assert(info != null); Debug.Assert(matchingTrusts != null); int entry = 0; while (entry < matchingTrusts.Count) { ApplicationTrust matchingTrust = (ApplicationTrust) matchingTrusts[entry]; if (!matchingTrust.IsApplicationTrustedToRun) { // [....]: Can this ever happen? I have serious doubts... matchingTrusts.RemoveAt(entry); } PermissionSet permSetRequested = GetRequestedPermissionSet(info); PermissionSet permSetGranted = matchingTrust.DefaultGrantSet.PermissionSet; //PolicyStatement makes of copy of its permission set here. if (permSetGranted == null && permSetRequested != null) { // No permissions were granted, and this launch requests some permissions matchingTrusts.RemoveAt(entry); } else if (permSetGranted != null && permSetRequested == null) { // Some permissions were granted, and this launch does not require any permissions entry++; continue; } Debug.Assert(permSetGranted != null); Debug.Assert(permSetRequested != null); if (permSetRequested.IsSubsetOf(permSetGranted)) { entry++; // Found a version that requires at least as much } else { // This version does not require as much matchingTrusts.RemoveAt(entry); } } return matchingTrusts.Count > 0; } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private unsafe static bool ExtractManifestContent(ICMS cms, out MemoryStream ms) { ms = new MemoryStream(); try { System.Runtime.InteropServices.ComTypes.IStream pStream = cms as System.Runtime.InteropServices.ComTypes.IStream; if (pStream == null) { return false; } byte[] pv = new byte[4096]; int size = 4096; do { pStream.Read(pv, size, new IntPtr(&size)); ms.Write(pv, 0, size); } while (size == 4096); ms.Position = 0; return true; } catch (Exception) { Debug.Fail("Exception occurred in ExtractDeploymentManifestContent."); return false; } } private static PromptingLevel GetDefaultPromptingLevel(string zoneName) { PromptingLevel promptingLevel; switch (zoneName) { case "Internet": case "LocalIntranet": case "MyComputer": case "TrustedSites": promptingLevel = PromptingLevel.Prompt; break; case "UntrustedSites": promptingLevel = PromptingLevel.Disabled; break; default: promptingLevel = PromptingLevel.Disabled; break; } return promptingLevel; } private static string GetDeploymentUrl(ApplicationSecurityInfo info) { Debug.Assert(info != null); Evidence appEvidence = info.ApplicationEvidence; Url deploymentUrl = appEvidence.GetHostEvidence (); if (deploymentUrl != null) { return deploymentUrl.Value; } // Couldn't find deployment Url return null; } private static PermissionSet GetRequestedPermissionSet(ApplicationSecurityInfo info) { Debug.Assert(info != null); PermissionSet pset = info.DefaultRequestSet; PermissionSet permSetRequested = null; if (pset != null) { permSetRequested = pset.Copy(); } return permSetRequested; } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static string GetHostFromDeploymentUrl(string deploymentUrl) { if (deploymentUrl == null) { return string.Empty; } string host = null; try { System.Uri uri = new System.Uri(deploymentUrl); if (uri.Scheme == System.Uri.UriSchemeHttp || uri.Scheme == System.Uri.UriSchemeHttps) { host = uri.Host; } if (string.IsNullOrEmpty(host)) { host = uri.AbsolutePath; int separatorIndex = -1; if (string.IsNullOrEmpty(uri.Host) && host.StartsWith("/")) { host = host.TrimStart('/'); separatorIndex = host.IndexOf('/'); } else if (uri.LocalPath.Length > 2 && (uri.LocalPath[1] == ':' || uri.LocalPath.StartsWith("\\\\"))) { host = uri.LocalPath; separatorIndex = host.LastIndexOf('\\'); } if (separatorIndex != -1) { host = host.Remove(separatorIndex); } } } catch (Exception ex) { Debug.Fail("Exception occurred in GetHostFromDeploymentUrl: " + ex.Message); return string.Empty; } return host; } private static PromptsAllowed GetPromptsAllowed(HostContextInternal hostContextInternal, string zoneName, ParsedData parsedData) { Debug.Assert(hostContextInternal != null); Debug.Assert(zoneName != null); Debug.Assert(parsedData != null); if (hostContextInternal.NoPrompt) { return PromptsAllowed.None; } PromptingLevel promptingLevel = GetZonePromptingLevel(zoneName); if (promptingLevel == PromptingLevel.Disabled || (promptingLevel == PromptingLevel.PromptOnlyForAuthenticode && parsedData.AuthenticodedPublisher == null)) { return PromptsAllowed.BlockingOnly; } return PromptsAllowed.All; } private static string GetZoneNameFromDeploymentUrl(String deploymentUrl) { Zone zone = Zone.CreateFromUrl(deploymentUrl); if (zone == null || zone.SecurityZone == SecurityZone.NoZone) { return "UntrustedSites"; } switch (zone.SecurityZone) { case SecurityZone.Internet: return "Internet"; case SecurityZone.Intranet: return "LocalIntranet"; case SecurityZone.MyComputer: return "MyComputer"; case SecurityZone.Trusted: return "TrustedSites"; case SecurityZone.Untrusted: return "UntrustedSites"; default: Debug.Fail("Unexpected SecurityZone in GetZoneNameFromDeploymentUrl"); return "UntrustedSites"; } } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static PromptingLevel GetZonePromptingLevel(string zoneName) { try { string promptingLevelStr = null; new RegistryPermission(PermissionState.Unrestricted).Assert(); try { using (RegistryKey key = Registry.LocalMachine.OpenSubKey(PromptingLevelKeyName)) { if (key != null) { promptingLevelStr = (string)key.GetValue(zoneName); } } } finally { System.Security.CodeAccessPermission.RevertAssert(); } if (string.IsNullOrEmpty(promptingLevelStr)) { return GetDefaultPromptingLevel(zoneName); } else if (string.Compare(promptingLevelStr, "Enabled", true, CultureInfo.InvariantCulture) == 0) { return PromptingLevel.Prompt; } else if (string.Compare(promptingLevelStr, "Disabled", true, CultureInfo.InvariantCulture) == 0) { return PromptingLevel.Disabled; } else if (string.Compare(promptingLevelStr, "AuthenticodeRequired", true, CultureInfo.InvariantCulture) == 0) { return PromptingLevel.PromptOnlyForAuthenticode; } else { return GetDefaultPromptingLevel(zoneName); } } catch (Exception ex) { Debug.Fail("Exception occurred in GetZonePromptingLevel: " + ex.Message); return GetDefaultPromptingLevel(zoneName); } } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static ApplicationTrust HighRiskPrompt(ActivationContext activationContext, ParsedData parsedData, String deploymentUrl, HostContextInternal hostContextInternal, ApplicationSecurityInfo info, ApplicationTrustExtraInfo appTrustExtraInfo, string zoneName) { DialogResult ret; TrustManagerPromptOptions options = CompletePromptOptions(TrustManagerPromptOptions.RequiresPermissions, appTrustExtraInfo, zoneName, info); try { TrustManagerPromptUIThread highRiskDialog = new TrustManagerPromptUIThread(string.IsNullOrEmpty(parsedData.AppName) ? info.ApplicationId.Name : parsedData.AppName, DefaultBrowserExePath, parsedData.SupportUrl, GetHostFromDeploymentUrl(deploymentUrl), parsedData.AuthenticodedPublisher /*publisherName*/, parsedData.Certificate, options); ret = highRiskDialog.ShowDialog(); } catch (Exception ex) { Debug.Fail("Error occurred while showing high risk dialog: " + ex.Message); ret = DialogResult.No; } return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, ret == DialogResult.OK /*trust*/, hostContextInternal.Persist && ret == DialogResult.OK /*persist*/); } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static ApplicationTrust BlockingPrompt(ActivationContext activationContext, ParsedData parsedData, String deploymentUrl, ApplicationSecurityInfo info, ApplicationTrustExtraInfo appTrustExtraInfo, string zoneName, bool permissionElevationRequired) { TrustManagerPromptOptions options = CompletePromptOptions(permissionElevationRequired ? (TrustManagerPromptOptions.StopApp | TrustManagerPromptOptions.RequiresPermissions) : TrustManagerPromptOptions.StopApp, appTrustExtraInfo, zoneName, info); try { TrustManagerPromptUIThread errorDialog = new TrustManagerPromptUIThread(string.IsNullOrEmpty(parsedData.AppName) ? info.ApplicationId.Name : parsedData.AppName, DefaultBrowserExePath, parsedData.SupportUrl, GetHostFromDeploymentUrl(deploymentUrl), parsedData.AuthenticodedPublisher /*publisherName*/, parsedData.Certificate, options); errorDialog.ShowDialog(); } catch (Exception ex) { Debug.Fail("Error occurred while showing error dialog: " + ex.Message); } // Trust Manager should prompt, but is not allowed to. Return Don't Trust and Don't Persist. return CreateApplicationTrust(activationContext, info, appTrustExtraInfo, false /*trust*/, false /*persist*/); } [ SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes") ] private static bool ParseManifest(ICMS cms, ParsedData parsedData) { // parsedData is safely initialized to requestsShellIntegration:false/supportUrl:null/authenticodedPublisher:null //deploymentProviderCodebase:null try { if (cms != null) { // Extract SupportUrl and Shell Visibility if (cms.MetadataSectionEntry != null) { IMetadataSectionEntry metaDataSectionEntry = cms.MetadataSectionEntry as IMetadataSectionEntry; if (metaDataSectionEntry != null) { IDescriptionMetadataEntry description = metaDataSectionEntry.DescriptionData; if (description != null) { parsedData.SupportUrl = description.SupportUrl; parsedData.AppName = description.Product; parsedData.AppPublisher = description.Publisher; // [....]: description.Publisher is accessible here. Ask JamieC if we should grab it. } IDeploymentMetadataEntry deployment = metaDataSectionEntry.DeploymentData; if (deployment != null) { parsedData.RequestsShellIntegration = ((deployment.DeploymentFlags & (uint)(CMS_ASSEMBLY_DEPLOYMENT_FLAG.CMS_ASSEMBLY_DEPLOYMENT_FLAG_INSTALL)) != 0); // parsedData.DeploymentProviderCodebase = deployment.DeploymentProviderCodebase; } if ((metaDataSectionEntry.ManifestFlags & (uint)CMS_MANIFEST_FLAG.CMS_MANIFEST_FLAG_USEMANIFESTFORTRUST) != 0) { parsedData.UseManifestForTrust = true; } else { parsedData.UseManifestForTrust = false; } } } } } catch (Exception e) { Debug.Fail("Error parsing manifest: " + e.Message); return false; } return true; } private static bool SomePreviousTrustedVersionRequiresShellIntegration(ArrayList /*ApplicationTrust[]*/ matchingTrusts) { Debug.Assert(matchingTrusts != null); foreach (ApplicationTrust matchingTrust in matchingTrusts) { ApplicationTrustExtraInfo matchingAppTrustExtraInfo = matchingTrust.ExtraInfo as ApplicationTrustExtraInfo; if (matchingAppTrustExtraInfo != null && matchingAppTrustExtraInfo.RequestsShellIntegration) { return true; } if (null == matchingAppTrustExtraInfo && matchingTrust.DefaultGrantSet.PermissionSet.IsUnrestricted()) { // Full trust trumps RequestsShellIntegration, so return true in this case. return true; } } // No previous trusted version requires shell integration return false; } private static bool SearchPreviousTrustedVersion(ActivationContext activationContext, ApplicationIdentity previousAppId, out ArrayList matchingTrusts) { // No match found by default matchingTrusts = null; ApplicationTrustCollection appTrusts = ApplicationSecurityManager.UserApplicationTrusts; foreach (ApplicationTrust appTrust in appTrusts) { IDefinitionAppId appTrustAppId = IsolationInterop.AppIdAuthority.TextToDefinition(0, appTrust.ApplicationIdentity.FullName); IDefinitionAppId actCtxAppId = IsolationInterop.AppIdAuthority.TextToDefinition(0, activationContext.Identity.FullName); if (IsolationInterop.AppIdAuthority.AreDefinitionsEqual((uint) IAPPIDAUTHORITY_ARE_DEFINITIONS_EQUAL_FLAGS.IAPPIDAUTHORITY_ARE_DEFINITIONS_EQUAL_FLAG_IGNORE_VERSION, appTrustAppId, actCtxAppId)) { // Found an older matching app (or same version app which should never occur in theory) if (matchingTrusts == null) { matchingTrusts = new ArrayList(); } matchingTrusts.Add(appTrust); } } if (previousAppId != null) { foreach (ApplicationTrust appTrust in appTrusts) { IDefinitionAppId appTrustDefAppId = IsolationInterop.AppIdAuthority.TextToDefinition(0, appTrust.ApplicationIdentity.FullName); IDefinitionAppId previousDefAppId = IsolationInterop.AppIdAuthority.TextToDefinition(0, previousAppId.FullName); if (IsolationInterop.AppIdAuthority.AreDefinitionsEqual((uint) IAPPIDAUTHORITY_ARE_DEFINITIONS_EQUAL_FLAGS.IAPPIDAUTHORITY_ARE_DEFINITIONS_EQUAL_FLAG_IGNORE_VERSION, appTrustDefAppId, previousDefAppId)) { // Found an older matching app (or same version app which should never occur in theory) if (matchingTrusts == null) { matchingTrusts = new ArrayList(); } matchingTrusts.Add(appTrust); } } } // (matchingTrusts != null) <==> Found a prior version that was allowed to run. return (matchingTrusts != null); } private enum PromptingLevel { /// /// Disabled = 0, ////// In the cases the Trust Manager needs to prompt, it needs to show the blocking prompt /// ////// Prompt = 1, ////// Prompting is allowed for strong named and authenticode signed application deployments /// ////// PromptOnlyForAuthenticode = 2 } private enum PromptsAllowed { ////// Prompting is allowed for authenticode signed application deployments only /// ////// All = 0, ////// The Trust Manager is allowed to show any prompt /// ////// BlockingOnly = 1, ////// The Trust Manager is only allowed to show the blocking prompt /// ////// None = 2 } } [Serializable] internal class ApplicationTrustExtraInfo { private bool requestsShellIntegration = true; // If manifest parsing fails, we assume shell integration is required. public ApplicationTrustExtraInfo() { } public bool RequestsShellIntegration { get { return this.requestsShellIntegration; } set { this.requestsShellIntegration = value; } } } internal class TrustManagerPromptUIThread { private string m_appName, m_defaultBrowserExePath, m_supportUrl, m_deploymentUrl, m_publisherName; private X509Certificate2 m_certificate; private TrustManagerPromptOptions m_options; private DialogResult m_ret = DialogResult.No; public TrustManagerPromptUIThread(string appName, string defaultBrowserExePath, string supportUrl, string deploymentUrl, string publisherName, X509Certificate2 certificate, TrustManagerPromptOptions options) { this.m_appName = appName; this.m_defaultBrowserExePath = defaultBrowserExePath; this.m_supportUrl = supportUrl; this.m_deploymentUrl = deploymentUrl; this.m_publisherName = publisherName; this.m_certificate = certificate; this.m_options = options; } public DialogResult ShowDialog() { System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(ShowDialogWork)); thread.SetApartmentState(System.Threading.ApartmentState.STA); thread.Start(); thread.Join(); return m_ret; } [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] private void ShowDialogWork() { try { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); using (TrustManagerPromptUI trustManagerDialog = new TrustManagerPromptUI(this.m_appName, this.m_defaultBrowserExePath, this.m_supportUrl, this.m_deploymentUrl, this.m_publisherName, this.m_certificate, this.m_options)) { m_ret = trustManagerDialog.ShowDialog(); } } catch { } } } internal class ParsedData { private bool requestsShellIntegration; /* == false by default. shellVisible attribute is optional */ private string appName; private string appPublisher; private string supportUrl; private string authenticodedPublisher; private bool disallowTrustOverride; private X509Certificate2 certificate; // private string deploymentProviderCodebase; public ParsedData() { } public bool RequestsShellIntegration { get { return this.requestsShellIntegration; } set { this.requestsShellIntegration = value; } } public X509Certificate2 Certificate { get { return this.certificate; } set { this.certificate = value; } } public string AppName { get { return this.appName; } set { this.appName = value; } } public string AppPublisher { get { return this.appPublisher; } set { this.appPublisher = value; } } public string AuthenticodedPublisher { get { return this.authenticodedPublisher; } set { this.authenticodedPublisher = value; } } public bool UseManifestForTrust { get { return disallowTrustOverride; } set { disallowTrustOverride = value; } } // public string DeploymentProviderCodebase // { // get // { // return this.deploymentProviderCodebase; // } // set // { // this.deploymentProviderCodebase = value; // } // } public string SupportUrl { get { return this.supportUrl; } set { this.supportUrl = value; } } } internal class HostContextInternal { private bool ignorePersistedDecision; private bool noPrompt; private bool persist; private ApplicationIdentity previousAppId; public HostContextInternal(TrustManagerContext trustManagerContext) { if (trustManagerContext == null) { // Used in case DetermineApplicationTrust is not given a TrustManagerContext object. this.persist = true; } else { // ISSUE - fix this... // Note that exclusiveGrant is never set. It is read in CreateApplicationTrust however. this.ignorePersistedDecision = trustManagerContext.IgnorePersistedDecision; this.noPrompt = trustManagerContext.NoPrompt; this.persist = trustManagerContext.Persist; this.previousAppId = trustManagerContext.PreviousApplicationIdentity; } } public bool IgnorePersistedDecision { get { return this.ignorePersistedDecision; } } public bool NoPrompt { get { return this.noPrompt; } } public bool Persist { get { return this.persist; } } public ApplicationIdentity PreviousAppId { get { return this.previousAppId; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007./// The Trust Manager is not allowed to prompt at all /// ///
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- LayoutUtils.cs
- EntityDesignerUtils.cs
- SQLChars.cs
- MainMenu.cs
- documentation.cs
- ServiceDesigner.xaml.cs
- Message.cs
- EncodingInfo.cs
- CapiSymmetricAlgorithm.cs
- OperationAbortedException.cs
- WebPartEditorOkVerb.cs
- ConsumerConnectionPoint.cs
- TcpConnectionPoolSettingsElement.cs
- CompensableActivity.cs
- DataGridViewCellStyle.cs
- ConfigurationLocationCollection.cs
- processwaithandle.cs
- BaseDataList.cs
- SafeNativeMethods.cs
- CustomCredentialPolicy.cs
- Parameter.cs
- PropertyEmitterBase.cs
- CLSCompliantAttribute.cs
- ValueSerializer.cs
- ClientTargetCollection.cs
- BaseProcessor.cs
- HttpBindingExtension.cs
- InstanceNormalEvent.cs
- QueryOutputWriter.cs
- StaticDataManager.cs
- ViewSimplifier.cs
- BufferModeSettings.cs
- ItemChangedEventArgs.cs
- PropertyBuilder.cs
- MultipartContentParser.cs
- GridErrorDlg.cs
- DataRecordInfo.cs
- XamlValidatingReader.cs
- Deflater.cs
- ValidatedMobileControlConverter.cs
- GroupBoxAutomationPeer.cs
- ActivityBindForm.cs
- RawStylusInputCustomDataList.cs
- PagePropertiesChangingEventArgs.cs
- Animatable.cs
- MSAANativeProvider.cs
- EmbeddedMailObject.cs
- MouseGesture.cs
- TableDetailsCollection.cs
- IPPacketInformation.cs
- XmlWellformedWriter.cs
- Utils.cs
- UpDownBase.cs
- AccessDataSourceView.cs
- DataColumnMappingCollection.cs
- FaultContractAttribute.cs
- RegexStringValidatorAttribute.cs
- FileCodeGroup.cs
- _DynamicWinsockMethods.cs
- PageContentAsyncResult.cs
- EncryptedPackage.cs
- TextParentUndoUnit.cs
- Parser.cs
- CharKeyFrameCollection.cs
- TakeOrSkipWhileQueryOperator.cs
- ServiceOperation.cs
- PageCodeDomTreeGenerator.cs
- HttpValueCollection.cs
- WrappingXamlSchemaContext.cs
- ILGenerator.cs
- CorrelationManager.cs
- PartialList.cs
- TypeElement.cs
- FrameworkElement.cs
- BrowserTree.cs
- EmptyStringExpandableObjectConverter.cs
- hwndwrapper.cs
- SqlDataSourceQueryConverter.cs
- HierarchicalDataBoundControlAdapter.cs
- NonVisualControlAttribute.cs
- QilStrConcatenator.cs
- ItemCheckEvent.cs
- CodeVariableReferenceExpression.cs
- RuntimeHandles.cs
- _NestedMultipleAsyncResult.cs
- SQLByte.cs
- PeerName.cs
- Int64.cs
- CellParagraph.cs
- _SslSessionsCache.cs
- Transform.cs
- BufferModesCollection.cs
- figurelengthconverter.cs
- LogicalExpressionEditor.cs
- SignatureDescription.cs
- TextElementEnumerator.cs
- DataBindingList.cs
- Decoder.cs
- DESCryptoServiceProvider.cs
- XamlStyleSerializer.cs