|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
//
// Description:
//
// This creates and registers a custom ICredentialPolicy that will be used
// whenever a server sends a 401 UNAUTHORIZED in response to a WebRequest. The
// .NET framework will call ShouldSendCredential to determine if credentials
// should be sent.
//
// Our policy is to go ahead and send whatever credentials there might be,
// EXCEPT if we are using default credentials and the request is not going to
// an Intranet, Local Machine or Trusted domain.
//
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// IMPORTANT: We are creating an instance of IInternetSecurityManager here. This
// is currently also done in the AppSecurityManager at the Framework level. Any
// modification to either of these classes--especially concerning MapUrlToZone--
// should be considered for both classes.
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// An IInternetSecurityManagerSite is not currently needed here, because the
// only method of IInternetSecurityManager that we are calling is MapUrlToZone,
// and that does not prompt the user.
//
using System.Net;
using System.Runtime.InteropServices;
using MS.Internal.PresentationCore;
using MS.Win32;
namespace MS.Internal.AppModel
{
internal class CustomCredentialPolicy : ICredentialPolicy
{
static CustomCredentialPolicy()
{
_lockObj = new object();
_initialized = false;
}
static internal void EnsureCustomCredentialPolicy()
{
if (!_initialized)
{
lock (_lockObj)
{
if (!_initialized)
{
// We should allow an application to set its own credential policy, if it has permssion to.
// We do not want to overwrite the application's setting.
// Check whether it is already set before setting it.
// The default of this property is null. It demands ControlPolicy permission to be set.
#pragma warning disable SYSLIB0009
if (AuthenticationManager.CredentialPolicy == null)
{
AuthenticationManager.CredentialPolicy = new CustomCredentialPolicy();
}
#pragma warning restore SYSLIB0009
_initialized = true;
}
}
}
}
#region ICredentialPolicy Members
public bool ShouldSendCredential(Uri challengeUri, WebRequest request, NetworkCredential credential, IAuthenticationModule authenticationModule)
{
switch (MapUrlToZone(challengeUri))
{
// Always send credentials (including default credentials) to these zones
case NativeMethods.URLZONE_INTRANET:
case NativeMethods.URLZONE_TRUSTED:
case NativeMethods.URLZONE_LOCAL_MACHINE:
return true;
// Don't send default credentials to any of these zones
case NativeMethods.URLZONE_INTERNET:
case NativeMethods.URLZONE_UNTRUSTED:
default:
return !IsDefaultCredentials(credential);
}
}
#endregion
private bool IsDefaultCredentials(NetworkCredential credential)
{
return credential == CredentialCache.DefaultCredentials;
}
internal static int MapUrlToZone(Uri uri)
{
EnsureSecurityManager();
int targetZone;
_securityManager.MapUrlToZone(BindUriHelper.UriToString(uri), out targetZone, 0);
return targetZone;
}
private static void EnsureSecurityManager()
{
// IMPORTANT: See comments in header r.e. IInternetSecurityManager
if (_securityManager == null)
{
lock (_lockObj)
{
if (_securityManager == null)
{
_securityManager = (UnsafeNativeMethods.IInternetSecurityManager)new InternetSecurityManager();
}
}
}
}
[ComImport, ComVisible(false), Guid("7b8a2d94-0ac9-11d1-896c-00c04Fb6bfc4")]
private class InternetSecurityManager
{
}
private static UnsafeNativeMethods.IInternetSecurityManager _securityManager;
private static object _lockObj;
private static bool _initialized;
}
}
|