Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / MS / Internal / AppModel / AppSecurityManager.cs / 3 / AppSecurityManager.cs
//------------------------------------------------------------------------------ // Microsoft Avalon // Copyright (c) Microsoft Corporation, 2001 // // File: appsecuritymanager.cs // // Description: AppSecurityManager class. // //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // IMPORTANT: We are creating an instance of IInternetSecurityManager here. This // is currently also done in the CustomCredentialPolicy at the Core level. Any // modification to either of these classes--especially concerning MapUrlToZone-- // should be considered for both classes. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // // History: 04-24-02 - [....] - created //----------------------------------------------------------------------------- using System; using System.Collections; using System.Diagnostics; using System.Globalization; using System.Security; using System.Security.Permissions; using Microsoft.Win32; using System.IO.Packaging; using System.Windows; using System.Windows.Interop; using MS.Internal.Utility; using MS.Internal.PresentationFramework; // SecurityHelper using MS.Win32; using System.Runtime.InteropServices; using MS.Internal.Documents.Application; namespace MS.Internal.AppModel { enum LaunchResult { Launched, NotLaunched, NotLaunchedDueToPrompt }; internal static class AppSecurityManager { #region Internal Methods ////// Safely launch the browser if you can. /// If you can't demand unmanaged code permisison. /// /// originatingUri = the current uri /// destinationUri = the uri you are going to. /// ////// Critical - gets access to critical resource (uri), calls critical code (launch browser) /// TreatAsSafe because /// we consider navigates to http or http to the top-level browser as safe. /// we consider navigates to mailto as safe. /// for all other cases - we demand Unmanaged Code Permission /// [SecurityCritical, SecurityTreatAsSafe] internal static void SafeLaunchBrowserDemandWhenUnsafe( Uri originatingUri, Uri destinationUri, bool fIsTopLevel ) { LaunchResult launched = LaunchResult.NotLaunched; launched = SafeLaunchBrowserOnlyIfPossible( originatingUri, destinationUri, fIsTopLevel ) ; if ( launched == LaunchResult.NotLaunched ) { SecurityHelper.DemandUnmanagedCode(); UnsafeLaunchBrowser( destinationUri ); } } ////// Safely launch the browser if it's possible to do so in partial trust /// Returns enum indicating whether we safely launched ( or at least think we did). /// /// This function is appropriate for use when we launch the browser from partial trust /// ( as it doesn't perform demands for the "unsafe" cases ) /// internal static LaunchResult SafeLaunchBrowserOnlyIfPossible(Uri originatingUri, Uri destinationUri, bool fIsTopLevel) { return SafeLaunchBrowserOnlyIfPossible(originatingUri, destinationUri, null, fIsTopLevel); } ////// Safely launch the browser if it's possible to do so in partial trust /// Returns enum indicating whether we safely launched ( or at least think we did). /// Html target names can be passed in with this. /// This function is appropriate for use when we launch the browser from partial trust /// ( as it doesn't perform demands for the "unsafe" cases ) /// ////// Critical - gets access to critical resource (uri), calls critical code (launch browser) /// /// TreatAsSafe because /// we consider navigates to http or http to the top-level browser as safe. /// we consider navigates to mailto as safe. /// /// for all other cases - we don't launch the browser - and return a result /// indicating that we didn't launch. /// [SecurityCritical, SecurityTreatAsSafe] internal static LaunchResult SafeLaunchBrowserOnlyIfPossible(Uri originatingUri, Uri destinationUri, string targetName, bool fIsTopLevel ) { LaunchResult launched = LaunchResult.NotLaunched ; // // check to see if this is a sub-classed URI // if it is a sub-class - demand unmanaged code permission. // this prevents exploits where the Uri has been subclassed, and overrides toString() // // Note that in whidbey RTM - these types of exploits will not be possible. // As there is inheritance demand on callers. // if ( destinationUri.GetType().IsSubclassOf( typeof( Uri ))) { SecurityHelper.DemandInfrastructurePermission(); } bool isKnownScheme = (Object.ReferenceEquals(destinationUri.Scheme, Uri.UriSchemeHttp)) || (Object.ReferenceEquals(destinationUri.Scheme, Uri.UriSchemeHttps)) || destinationUri.IsFile; bool fIsMailTo = String.Compare(destinationUri.Scheme, Uri.UriSchemeMailto, StringComparison.OrdinalIgnoreCase) == 0 ; // We elevate to navigate the browser iff: // We are user initiated AND // Scheme == http/https & topLevel OR scheme == mailto. // // For all other cases ( evil protocols etc). // We will demand. // // The check of IsInitialViewerNavigation is necessary because viewer applications will probably // need to call Navigate on the URI they receive, but we want them to be able to do it in partial trust. if ( (!BrowserInteropHelper.IsInitialViewerNavigation && SecurityHelper.CallerHasUserInitiatedNavigationPermission()) && ((fIsTopLevel && isKnownScheme) || fIsMailTo ) ) { if (isKnownScheme) { IBrowserCallbackServices ibcs = ( Application.Current != null ) ? Application.Current.BrowserCallbackServices : null ; if (ibcs != null) { launched = CanNavigateToUrlWithZoneCheck(originatingUri , destinationUri); if ( launched == LaunchResult.Launched ) { // resetting launched to NotLaunched here; if the assert succeeds // and ibcs.DelegateNavigation does not throw then we will set it to Launched. launched = LaunchResult.NotLaunched; // Browser app. // ibcs.DelegateNavigation( BindUriHelper.UriToString( destinationUri ), targetName, GetHeaders(destinationUri)); launched = LaunchResult.Launched ; } } } else if ( fIsMailTo ) // unnecessary if - but being paranoid. { // Shell-Exec the browser to the mailto url. // assumed safe - because we're only allowing this for mailto urls. // UnsafeNativeMethods.ShellExecute( new HandleRef( null, IntPtr.Zero) , /*hwnd*/ null, /*operation*/ BindUriHelper.UriToString( destinationUri ), /*file*/ null, /*parameters*/ null, /*directory*/ 0 ); /*nShowCmd*/ launched = LaunchResult.Launched ; } } return launched ; } // This invokes the browser unsafely. // Whoever is calling this function should do the right demands. ////// Critical - gets access to critical resource (uri and browsercallback services), calls critical code (launch browser) /// [SecurityCritical] internal static void UnsafeLaunchBrowser(Uri uri) { // This'll likely go into SafeLaunchBrowser() function. if (Application.Current != null) { IBrowserCallbackServices ibcs = Application.Current.BrowserCallbackServices; if (ibcs != null) { // Browser app. // ibcs.DelegateNavigation(BindUriHelper.UriToString(uri), null, GetHeaders(uri)); return; } } ShellExecuteDefaultBrowser(uri); } ////// Opens the default browser for the passed in Uri. /// ////// Critical - calls critical code (ShellExecuteEx) /// [SecurityCritical] internal static void ShellExecuteDefaultBrowser(Uri uri) { UnsafeNativeMethods.ShellExecuteInfo sei = new UnsafeNativeMethods.ShellExecuteInfo(); sei.cbSize = Marshal.SizeOf(sei); sei.fMask = UnsafeNativeMethods.ShellExecuteFlags.SEE_MASK_FLAG_DDEWAIT; /* There is a bug on Windows Vista (with IE 7): ShellExecute via SEE_MASK_CLASSNAME fails for an http[s]:// URL. It works fine for file://. The cause appears to be that the DDE command template defined in HKCR\IE.AssocFile.HTM\shell\opennew\ddeexec is used: [file://%1",-1,,,,,]. On XP, the the key used is (supposedly) HKCR\htmlfile\shell\opennew\ddeexec, and its value is ["%1",,-1,0,,,,]. The workaround here is to add the SEE_MASK_CLASSNAME flag only for non-HTTP URLs. For HTTP, "plain" ShellExecute just works, incl. with Firefox/Netscape as the default browser. */ if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps) { sei.fMask |= UnsafeNativeMethods.ShellExecuteFlags.SEE_MASK_CLASSNAME; sei.lpClass = ".htm"; // The default browser is looked up by this. } sei.lpFile = uri.ToString(); if (!UnsafeNativeMethods.ShellExecuteEx(sei)) throw new InvalidOperationException(SR.Get(SRID.FailToLaunchDefaultBrowser), new System.ComponentModel.Win32Exception(/*uses the last Win32 error*/)); } #endregion Internal Methods #region Private Methods ////// Returns the HTTP "Referer" header. /// ///returns a string containing one or more HTTP headers separated by \r\n; the string must also be terminated with a \r\n private static string GetHeaders(Uri destinationUri) { string referer = BindUriHelper.GetReferer(destinationUri); if (!String.IsNullOrEmpty(referer)) { // The headers we pass in to IWebBrowser2.Navigate must // be terminated with a \r\n because the browser then // concatenates its own headers on to the end of that string. referer = RefererHeader + referer + "\r\n"; } return referer; } // // Functionally equivalent copy of Trident's CanNavigateToUrlWithZoneCheck function // Checks to see whether a navigation is considered a zone elevation. // Once a zone elevation is identified - calls into urlmon to check settings. // ////// Critical - performs elevations to call IsFeatureEnabled, calls EnsureSecurityManager, /// call critical method MUTZ /// /// TreatAsSafe - information disclosed is whether a navigation is "safe" or not. /// considered ok to give out. you will be able to get this anyway by trapping exceptions /// or seeing whether a navigation succeeded/failed. /// [SecurityCritical, SecurityTreatAsSafe ] private static LaunchResult CanNavigateToUrlWithZoneCheck( Uri originatingUri, Uri destinationUri ) { LaunchResult launchResult = LaunchResult.NotLaunched ; // fail securely - assume this is the default. int targetZone = NativeMethods.URLZONE_LOCAL_MACHINE ; // fail securely this is the most priveleged zone int sourceZone = NativeMethods.URLZONE_INTERNET ; // fail securely this is the least priveleged zone. bool fEnabled = true; EnsureSecurityManager(); // is this feature enabled ? fEnabled = UnsafeNativeMethods.CoInternetIsFeatureEnabled( NativeMethods.FEATURE_ZONE_ELEVATION, NativeMethods.GET_FEATURE_FROM_PROCESS) != NativeMethods.S_FALSE ; // Get target zone. string destinationUriString = BindUriHelper.UriToString( destinationUri ); _secMgr.MapUrlToZone( destinationUriString , out targetZone, 0 ); // Get source zone. // Initialize sourceUri to null so that source zone defaults to the least privileged zone. Uri sourceUri = null; // If the MimeType is not a container, attempt to find sourceUri. // sourceUri should be null for Container cases, since it always assumes // the least privileged zone (InternetZone). if (Application.Current.MimeType != MimeType.Document) { sourceUri = BrowserInteropHelper.Source; } else if (destinationUri.IsFile && System.IO.Path.GetExtension(destinationUri.LocalPath) .Equals(DocumentStream.XpsFileExtension, StringComparison.OrdinalIgnoreCase)) { // In this case we know the following: // 1) We are currently a Container // 2) The destination is a File and another Container // In this case we want to treat the destination as internet too so Container // can navigate to other Containers by passing zone checks targetZone = NativeMethods.URLZONE_INTERNET; } if ( sourceUri != null ) { string sourceUriString = BindUriHelper.UriToString( sourceUri ); _secMgr.MapUrlToZone( sourceUriString , out sourceZone, 0 ); } else { // 2 potential ways to get here. // a) We aren't a fusion hosted app. Assume full-trust. // b) Some bug in hosting caused source Uri to be null. // // For a - we will say there is no cross-domain check. // b - we'll assume InternetZone, and use Source. bool fTrusted = SecurityHelper.CheckUnmanagedCodePermission(); if ( fTrusted ) { return LaunchResult.Launched; } else { // // If we didn't get a SourceUri, we'll assume internet zone. // And use Source for the uri of origin. // // This isn't quite right - but the sourceUri is only used to show a message to the user. // Worse case is confusing user experience. ( this uri is not used in the elevation determination). // sourceZone = NativeMethods.URLZONE_INTERNET ; sourceUri = originatingUri ; } } //// ------------------------------ // Check if there is a zone elevation. // Custom zones would have a higher value that URLZONE_UNTRUSTED, so this solution isn't quite complete. // However, we don't know of any product actively using custom zones, so rolling this out. // INTRANET and TRUSTED are treated as equals. // ------------------------------ // // // Note the negative logic - it first sees to see something is *not* a zone elevation. // if ( // Even if feature is disabled. // We still block navigation to local machine. // IF source zone is internet or restricted. (!fEnabled && ((sourceZone != NativeMethods.URLZONE_INTERNET && sourceZone != NativeMethods.URLZONE_UNTRUSTED) || targetZone != NativeMethods.URLZONE_LOCAL_MACHINE)) || // If feature is enabled // It's not a zone elevation if // the zones are equal OR // the zones are both less than restricted and // the sourceZone is more trusted than Target OR // sourceZone and TargetZone are both Intranet or Trusted // // per aganjam - Intranet and Trusted are treated as equivalent // as it was a common scenario for IE. ( website on intranet points to trusted site). // (fEnabled && ( sourceZone == targetZone || ( sourceZone <= NativeMethods.URLZONE_UNTRUSTED && targetZone <= NativeMethods.URLZONE_UNTRUSTED && ( sourceZone < targetZone || ( (sourceZone == NativeMethods.URLZONE_TRUSTED || sourceZone == NativeMethods.URLZONE_INTRANET) && (targetZone == NativeMethods.URLZONE_TRUSTED || targetZone == NativeMethods.URLZONE_INTRANET) ) ) ) ))) { // There is no zone elevation. You can launch away ! return LaunchResult.Launched ; } launchResult = CheckBlockNavigation( sourceUri , destinationUri, fEnabled ) ; return launchResult ; } ////// Called when we suspect there is a zone elevation. /// Calls the Urlmon IsFeatureZoneElevationEnabled which may pop UI based on settings. /// functionally equivalent to the BlockNavigation: label in Trident's CanNavigateToUrlWithZoneCheck /// ////// Critical - calls a function that has a SUC on it. ( CoIntenrnetIsFeatureZoneElevationEnabled) /// [SecurityCritical] private static LaunchResult CheckBlockNavigation(Uri originatingUri, Uri destinationUri, bool fEnabled ) { if (fEnabled) { if( UnsafeNativeMethods.CoInternetIsFeatureZoneElevationEnabled( BindUriHelper.UriToString( originatingUri ) , BindUriHelper.UriToString( destinationUri ) , _secMgr, NativeMethods.GET_FEATURE_FROM_PROCESS) == NativeMethods.S_FALSE) { return LaunchResult.Launched; } else { if ( IsZoneElevationSettingPrompt( destinationUri ) ) { // url action is query, and we got a "no" answer back. // we can assume user responded No. return LaunchResult.NotLaunchedDueToPrompt ; } else return LaunchResult.NotLaunched ; } } else { return LaunchResult.Launched ; } } // Is ZoneElevation setting set to prompt ? ////// Critical - elevates to call ProcessUrlAction. /// TreatAsSafe - information return indicates whether we will prompt for the current zone. /// considered ok to expose. /// [SecurityCritical, SecurityTreatAsSafe] private static bool IsZoneElevationSettingPrompt( Uri target ) { Invariant.Assert(_secMgr != null ); // Was this due to a prompt ? int policy = NativeMethods.URLPOLICY_DISALLOW ; unsafe { String targetString = BindUriHelper.UriToString( target ) ; new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // BlessedAssert: try { _secMgr.ProcessUrlAction( targetString, NativeMethods.URLACTION_FEATURE_ZONE_ELEVATION , (byte*) & policy , Marshal.SizeOf( typeof (int) ), null, 0, NativeMethods.PUAF_NOUI, 0 ); } finally { CodeAccessPermission.RevertAssert(); } } return ( policy == NativeMethods.URLPOLICY_QUERY ) ; } ////// Critical - elevates to call unmanaged code to set the security site. /// [SecurityCritical ] private static void EnsureSecurityManager() { // IMPORTANT: See comments in header r.e. IInternetSecurityManager if( _secMgr == null ) { lock( _lockObj ) { if ( _secMgr == null ) // null check again - now that we're in the lock. { _secMgr = (UnsafeNativeMethods.IInternetSecurityManager) new InternetSecurityManager(); // // Set the Security Manager Site. // This enables any dialogs popped to be modal to our window. // _secMgrSite = new SecurityMgrSite(); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // BlessedAssert: try { _secMgr.SetSecuritySite( (NativeMethods.IInternetSecurityMgrSite) _secMgrSite ) ; } finally { CodeAccessPermission.RevertAssert(); } } } } } ////// Critical - elevates to call SetSecuritySite. /// TreatAsSafe - clearing the security site is considered safe. /// worse that can happen is any urlmon prompts will be non-modal. /// [SecurityCritical, SecurityTreatAsSafe ] internal static void ClearSecurityManager() { if (_secMgr != null ) { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // BlessedAssert: try { lock ( _lockObj ) { if ( _secMgr != null ) { _secMgr.SetSecuritySite( null ) ; _secMgrSite = null ; _secMgr = null ; } } } finally { CodeAccessPermission.RevertAssert(); } } } [ComImport, ComVisible(false), Guid("7b8a2d94-0ac9-11d1-896c-00c04Fb6bfc4")] internal class InternetSecurityManager { } #endregion Private Methods #region Private Fields private const string RefererHeader = "Referer: "; private const string BrowserOpenCommandLookupKey = "htmlfile\\shell\\open\\command"; // Object to be used for locking. Using typeof(Util) causes an FxCop // violation DoNotLockOnObjectsWithWeakIdentity private static object _lockObj = new object(); ////// Critical - requires an elevation to create. /// [SecurityCritical] private static UnsafeNativeMethods.IInternetSecurityManager _secMgr ; private static SecurityMgrSite _secMgrSite ; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RuntimeArgumentHandle.cs
- XamlToRtfParser.cs
- XmlUtf8RawTextWriter.cs
- dataobject.cs
- COSERVERINFO.cs
- RotateTransform.cs
- QueryServiceConfigHandle.cs
- DescendantOverDescendantQuery.cs
- Instrumentation.cs
- XmlSchemas.cs
- DataGridViewBindingCompleteEventArgs.cs
- panel.cs
- ContainerVisual.cs
- PathSegment.cs
- EventLogPermissionHolder.cs
- HorizontalAlignConverter.cs
- VideoDrawing.cs
- DynamicILGenerator.cs
- ContextStaticAttribute.cs
- SmtpMail.cs
- GroupBox.cs
- TextPatternIdentifiers.cs
- ObjectDataSource.cs
- DataSourceControlBuilder.cs
- TextTreeText.cs
- WebBrowserNavigatingEventHandler.cs
- ShadowGlyph.cs
- ClientCredentialsSecurityTokenManager.cs
- CodeBlockBuilder.cs
- ExclusiveCanonicalizationTransform.cs
- RegionData.cs
- AttributeCollection.cs
- SqlBulkCopyColumnMappingCollection.cs
- SequentialWorkflowHeaderFooter.cs
- TraceContextEventArgs.cs
- EntityRecordInfo.cs
- GPStream.cs
- ObjectDataSourceMethodEventArgs.cs
- DatePickerTextBox.cs
- FrameworkObject.cs
- ObjectContextServiceProvider.cs
- OutputCacheProfileCollection.cs
- StackOverflowException.cs
- EntryWrittenEventArgs.cs
- SchemaEntity.cs
- ResourceDictionaryCollection.cs
- WizardForm.cs
- HttpContext.cs
- RegionData.cs
- KnownTypes.cs
- FlowDocumentFormatter.cs
- MouseOverProperty.cs
- ByteConverter.cs
- SelectionEditingBehavior.cs
- ListViewCommandEventArgs.cs
- ObjectStateManager.cs
- FixedLineResult.cs
- SafeRightsManagementPubHandle.cs
- ErrorInfoXmlDocument.cs
- ConstraintManager.cs
- UserPreferenceChangingEventArgs.cs
- InfoCardMasterKey.cs
- DrawingAttributes.cs
- RadioButtonRenderer.cs
- ToolBarTray.cs
- FocusManager.cs
- PropertyCollection.cs
- DataGridViewCellParsingEventArgs.cs
- DataTemplateKey.cs
- Simplifier.cs
- EnumType.cs
- RadioButton.cs
- FrameworkRichTextComposition.cs
- VersionedStream.cs
- FontDialog.cs
- GeneralTransform2DTo3D.cs
- StringPropertyBuilder.cs
- DashStyles.cs
- XmlReader.cs
- OleDbConnectionFactory.cs
- DateTime.cs
- RadioButtonAutomationPeer.cs
- QueryOpeningEnumerator.cs
- DataControlImageButton.cs
- milrender.cs
- TraceSwitch.cs
- Helpers.cs
- DataFormats.cs
- ScrollBarRenderer.cs
- StructuredCompositeActivityDesigner.cs
- SmiContext.cs
- MimeMultiPart.cs
- PlaceHolder.cs
- XamlStyleSerializer.cs
- COM2ExtendedUITypeEditor.cs
- RelationshipFixer.cs
- FixedPageProcessor.cs
- OpCodes.cs
- AutoCompleteStringCollection.cs
- CancelEventArgs.cs