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
- Italic.cs
- CharEnumerator.cs
- HostingPreferredMapPath.cs
- PinProtectionHelper.cs
- DropShadowEffect.cs
- DataGridViewElement.cs
- RelationshipNavigation.cs
- MultipartIdentifier.cs
- Update.cs
- ProfileServiceManager.cs
- UrlSyndicationContent.cs
- TimeIntervalCollection.cs
- VisualSerializer.cs
- XmlChildNodes.cs
- TypeExtension.cs
- CroppedBitmap.cs
- CultureInfoConverter.cs
- TextStore.cs
- RuntimeComponentFilter.cs
- XmlAtomicValue.cs
- BitmapPalettes.cs
- CRYPTPROTECT_PROMPTSTRUCT.cs
- SoapCodeExporter.cs
- XsdCachingReader.cs
- PerfCounterSection.cs
- securitymgrsite.cs
- LicFileLicenseProvider.cs
- UInt16Storage.cs
- ToolStripPanelSelectionBehavior.cs
- Int32CollectionConverter.cs
- DefaultEventAttribute.cs
- RequestContext.cs
- WebBrowser.cs
- HMACMD5.cs
- QueryableDataSourceHelper.cs
- AuditLevel.cs
- EditorResources.cs
- Thumb.cs
- PageBreakRecord.cs
- VisualStyleTypesAndProperties.cs
- Quaternion.cs
- CodeTypeDeclarationCollection.cs
- TextTreeInsertElementUndoUnit.cs
- NullToBooleanConverter.cs
- XmlNodeList.cs
- DetailsViewPagerRow.cs
- XmlElementList.cs
- XmlChildEnumerator.cs
- InitiatorSessionSymmetricMessageSecurityProtocol.cs
- Variable.cs
- ContentValidator.cs
- TemplatedWizardStep.cs
- DecimalAnimation.cs
- WebPartVerbsEventArgs.cs
- LinqDataSourceSelectEventArgs.cs
- BevelBitmapEffect.cs
- ResizeGrip.cs
- XmlPreloadedResolver.cs
- UserPersonalizationStateInfo.cs
- StrokeCollectionDefaultValueFactory.cs
- ZipIOExtraField.cs
- SystemWebExtensionsSectionGroup.cs
- TextDecorationCollection.cs
- MouseActionConverter.cs
- PolicyLevel.cs
- NamespaceCollection.cs
- PropertyNames.cs
- UpDownEvent.cs
- TraceHandler.cs
- FlowDocumentView.cs
- QilTypeChecker.cs
- HwndMouseInputProvider.cs
- UIAgentInitializationException.cs
- ToolStripPanelRenderEventArgs.cs
- DataGridCell.cs
- XmlComplianceUtil.cs
- TransformProviderWrapper.cs
- Nodes.cs
- DbDeleteCommandTree.cs
- ArraySortHelper.cs
- FaultHandlingFilter.cs
- EventToken.cs
- SecurityCriticalDataForSet.cs
- Buffer.cs
- SystemThemeKey.cs
- DebugInfoExpression.cs
- WriteableBitmap.cs
- BulletDecorator.cs
- Control.cs
- FigureParaClient.cs
- EntityDataSourceWrapper.cs
- oledbconnectionstring.cs
- DynamicRenderer.cs
- PreviewKeyDownEventArgs.cs
- ECDiffieHellmanCng.cs
- DescendantOverDescendantQuery.cs
- WorkflowRuntimeServiceElement.cs
- WindowsEditBoxRange.cs
- CollectionType.cs
- BulletedList.cs