1 //------------------------------------------------------------------------------
2 // <copyright file="AuthenticationManagerBase.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
9 using System.Collections;
10 using System.Collections.Generic;
11 using System.Collections.Specialized;
12 using System.Configuration;
13 using System.Globalization;
14 using System.Net.Configuration;
15 using System.Reflection;
16 using System.Security.Authentication.ExtendedProtection;
17 using System.Security.Permissions;
19 using System.Threading;
20 using System.Diagnostics;
21 using System.Diagnostics.CodeAnalysis;
23 internal abstract class AuthenticationManagerBase : IAuthenticationManager
25 private static volatile ICredentialPolicy s_ICredentialPolicy;
26 private static SpnDictionary m_SpnDictionary = new SpnDictionary();
28 private static TriState s_OSSupportsExtendedProtection = TriState.Unspecified;
29 private static TriState s_SspSupportsExtendedProtection = TriState.Unspecified;
31 public ICredentialPolicy CredentialPolicy
35 return s_ICredentialPolicy;
39 s_ICredentialPolicy = value;
43 public virtual void EnsureConfigLoaded()
45 // No-op: performed at object creation.
48 public StringDictionary CustomTargetNameDictionary
50 get { return m_SpnDictionary; }
53 // This will give access to some internal methods
55 public SpnDictionary SpnDictionary
57 get { return m_SpnDictionary; }
60 [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety.")]
61 public bool OSSupportsExtendedProtection
67 if (s_OSSupportsExtendedProtection == TriState.Unspecified)
69 if (ComNetOS.IsWin7orLater)
71 s_OSSupportsExtendedProtection = TriState.True;
75 if (SspSupportsExtendedProtection)
77 // EP is considered supported only if both SSPs and http.sys support CBT/EP.
78 // We don't support scenarios where e.g. only SSPs support CBT. In such cases
79 // the customer needs to patch also http.sys (even if he may not use it).
80 if (UnsafeNclNativeMethods.HttpApi.ExtendedProtectionSupported)
82 s_OSSupportsExtendedProtection = TriState.True;
86 s_OSSupportsExtendedProtection = TriState.False;
91 s_OSSupportsExtendedProtection = TriState.False;
96 return (s_OSSupportsExtendedProtection == TriState.True);
100 [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety.")]
101 public bool SspSupportsExtendedProtection
107 if (s_SspSupportsExtendedProtection == TriState.Unspecified)
109 if (ComNetOS.IsWin7orLater)
111 s_SspSupportsExtendedProtection = TriState.True;
115 // Perform a loopback NTLM authentication to determine whether the underlying OS supports
116 // extended protection
117 ContextFlags clientFlags = ContextFlags.Connection | ContextFlags.InitIdentify;
119 NTAuthentication client = new NTAuthentication(false, NtlmClient.AuthType,
120 SystemNetworkCredential.defaultCredential, "http/localhost", clientFlags, null);
124 NTAuthentication server = new NTAuthentication(true, NtlmClient.AuthType,
125 SystemNetworkCredential.defaultCredential, null, ContextFlags.Connection, null);
129 SecurityStatus status;
132 while (!server.IsCompleted)
134 blob = client.GetOutgoingBlob(blob, true, out status);
135 blob = server.GetOutgoingBlob(blob, true, out status);
138 if (server.OSSupportsExtendedProtection)
140 s_SspSupportsExtendedProtection = TriState.True;
144 if (Logging.On) Logging.PrintWarning(Logging.Web, SR.GetString(SR.net_ssp_dont_support_cbt));
145 s_SspSupportsExtendedProtection = TriState.False;
150 server.CloseContext();
155 client.CloseContext();
160 return (s_SspSupportsExtendedProtection == TriState.True);
165 /// <para>Call each registered authentication module to determine the first module that
166 /// can respond to the authentication request.</para>
168 public abstract Authorization Authenticate(string challenge, WebRequest request, ICredentials credentials);
170 // These four authentication modules require a Channel Binding Token to be able to preauthenticate over https.
171 // After a successful authentication, they will cache the CBT used on the ServicePoint. In order to PreAuthenticate,
172 // they require that a CBT has previously been cached. Any other module should be allowed to try preauthentication
173 // without a cached CBT
175 // This method is only called as part of an assert
176 protected static bool ModuleRequiresChannelBinding(IAuthenticationModule authenticationModule)
178 return (authenticationModule is NtlmClient || authenticationModule is KerberosClient ||
179 authenticationModule is NegotiateClient || authenticationModule is DigestClient);
184 /// <para>Pre-authenticates a request.</para>
186 public abstract Authorization PreAuthenticate(WebRequest request, ICredentials credentials);
189 /// <para>Registers an authentication module with the authentication manager.</para>
191 public abstract void Register(IAuthenticationModule authenticationModule);
194 /// <para>Unregisters authentication modules for an authentication scheme.</para>
196 public abstract void Unregister(IAuthenticationModule authenticationModule);
198 /// <para>Unregisters authentication modules for an authentication scheme.</para>
200 public abstract void Unregister(string authenticationScheme);
204 /// Returns a list of registered authentication modules.
207 public abstract IEnumerator RegisteredModules
214 /// Binds an authentication response to a request for pre-authentication.
217 // Create binding between an authorization response and the module
218 // generating that response
219 // This association is used for deciding which module to invoke
220 // for preauthentication purposes
221 public abstract void BindModule(Uri uri, Authorization response, IAuthenticationModule module);
223 // This function returns a prefix of the given absolute Uri
224 // which will be used for associating authentication information
225 // The purpose is to associate the module-binding not with a single
226 // Uri but some collection generalizing that Uri to the loosely-defined
227 // notion of "protection realm"
228 protected static string generalize(Uri location)
230 string completeUri = location.GetComponents(UriComponents.AbsoluteUri
231 & ~(UriComponents.Query | UriComponents.Fragment), UriFormat.UriEscaped);
232 int lastFwdSlash = completeUri.LastIndexOf('/');
233 if (lastFwdSlash < 0)
237 return completeUri.Substring(0, lastFwdSlash + 1);
239 }; // class AuthenticationManagerBase
241 } // namespace System.Net