internal void ClearSession() { #if !FEATURE_PAL // Security GlobalLog.Print("AuthenticationState#" + ValidationHelper.HashString(this) + "::ClearSession() NTAuthentication#" + ValidationHelper.HashString(SecurityContext)); if (SecurityContext != null) { SecurityContext.CloseContext(); SecurityContext = null; } #endif // FEATURE_PAL // Security }
private void SaveDigestContext(NTAuthentication digestContext) { if (_savedDigests == null) { Interlocked.CompareExchange<DigestContext[]>(ref _savedDigests, new DigestContext[MaximumDigests], null); } // We want to actually close the contexts outside the lock. NTAuthentication oldContext = null; ArrayList digestsToClose = null; lock (_savedDigests) { // If we're stopped, just throw it away. if (!IsListening) { digestContext.CloseContext(); return; } int now = ((now = Environment.TickCount) == 0 ? 1 : now); _newestContext = (_newestContext + 1) & (MaximumDigests - 1); int oldTimestamp = _savedDigests[_newestContext].timestamp; oldContext = _savedDigests[_newestContext].context; _savedDigests[_newestContext].timestamp = now; _savedDigests[_newestContext].context = digestContext; // May need to move this up. if (_oldestContext == _newestContext) { _oldestContext = (_newestContext + 1) & (MaximumDigests - 1); } // Delete additional contexts older than five minutes. while (unchecked(now - _savedDigests[_oldestContext].timestamp) >= DigestLifetimeSeconds && _savedDigests[_oldestContext].context != null) { if (digestsToClose == null) { digestsToClose = new ArrayList(); } digestsToClose.Add(_savedDigests[_oldestContext].context); _savedDigests[_oldestContext].context = null; _oldestContext = (_oldestContext + 1) & (MaximumDigests - 1); } // If the old context is younger than 10 seconds, put it in the backup pile. if (oldContext != null && unchecked(now - oldTimestamp) <= MinimumDigestLifetimeSeconds * 1000) { // Use a two-tier ArrayList system to guarantee each entry lives at least 10 seconds. if (_extraSavedDigests == null || unchecked(now - _extraSavedDigestsTimestamp) > MinimumDigestLifetimeSeconds * 1000) { digestsToClose = _extraSavedDigestsBaking; _extraSavedDigestsBaking = _extraSavedDigests; _extraSavedDigestsTimestamp = now; _extraSavedDigests = new ArrayList(); } _extraSavedDigests.Add(oldContext); oldContext = null; } } if (oldContext != null) { oldContext.CloseContext(); } if (digestsToClose != null) { for (int i = 0; i < digestsToClose.Count; i++) { ((NTAuthentication)digestsToClose[i]).CloseContext(); } } }
internal unsafe HttpListenerContext HandleAuthentication(RequestContextBase memoryBlob, out bool stoleBlob) { string challenge = null; HttpListenerContext context3; stoleBlob = false; string verb = UnsafeNclNativeMethods.HttpApi.GetVerb(memoryBlob.RequestBlob); string knownHeader = UnsafeNclNativeMethods.HttpApi.GetKnownHeader(memoryBlob.RequestBlob, 0x18); ulong connectionId = memoryBlob.RequestBlob.ConnectionId; ulong requestId = memoryBlob.RequestBlob.RequestId; bool isSecureConnection = memoryBlob.RequestBlob.pSslInfo != null; DisconnectAsyncResult disconnectResult = (DisconnectAsyncResult) this.DisconnectResults[connectionId]; if (this.UnsafeConnectionNtlmAuthentication) { if (knownHeader == null) { WindowsPrincipal principal = (disconnectResult == null) ? null : disconnectResult.AuthenticatedConnection; if (principal != null) { stoleBlob = true; HttpListenerContext context = new HttpListenerContext(this, memoryBlob); context.SetIdentity(principal, null); context.Request.ReleasePins(); return context; } } else if (disconnectResult != null) { disconnectResult.AuthenticatedConnection = null; } } stoleBlob = true; HttpListenerContext context2 = null; NTAuthentication digestContext = null; NTAuthentication newContext = null; NTAuthentication authentication3 = null; System.Net.AuthenticationSchemes none = System.Net.AuthenticationSchemes.None; System.Net.AuthenticationSchemes authenticationSchemes = this.AuthenticationSchemes; System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy extendedProtectionPolicy = this.m_ExtendedProtectionPolicy; try { ExtendedProtectionSelector selector; SecurityStatus invalidToken; ChannelBinding binding; string str6; ArrayList list; if ((disconnectResult != null) && !disconnectResult.StartOwningDisconnectHandling()) { disconnectResult = null; } if (disconnectResult != null) { digestContext = disconnectResult.Session; } context2 = new HttpListenerContext(this, memoryBlob); AuthenticationSelectorInfo authenticationDelegate = this.m_AuthenticationDelegate; if (authenticationDelegate != null) { try { context2.Request.ReleasePins(); authenticationSchemes = authenticationDelegate.Delegate(context2.Request); if (!authenticationDelegate.AdvancedAuth && ((authenticationSchemes & (System.Net.AuthenticationSchemes.IntegratedWindowsAuthentication | System.Net.AuthenticationSchemes.Digest)) != System.Net.AuthenticationSchemes.None)) { throw this.m_SecurityException; } goto Label_01A2; } catch (Exception exception) { if (NclUtilities.IsFatal(exception)) { throw; } if (Logging.On) { Logging.PrintError(Logging.HttpListener, this, "HandleAuthentication", SR.GetString("net_log_listener_delegate_exception", new object[] { exception })); } this.SendError(requestId, HttpStatusCode.InternalServerError, null); context2.Close(); return null; } } stoleBlob = false; Label_01A2: selector = this.m_ExtendedProtectionSelectorDelegate; if (selector != null) { extendedProtectionPolicy = selector(context2.Request); if (extendedProtectionPolicy == null) { extendedProtectionPolicy = new System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy(PolicyEnforcement.Never); } } int length = -1; if ((knownHeader != null) && ((authenticationSchemes & ~System.Net.AuthenticationSchemes.Anonymous) != System.Net.AuthenticationSchemes.None)) { length = 0; while (length < knownHeader.Length) { if (((knownHeader[length] == ' ') || (knownHeader[length] == '\t')) || ((knownHeader[length] == '\r') || (knownHeader[length] == '\n'))) { break; } length++; } if (length < knownHeader.Length) { if (((authenticationSchemes & System.Net.AuthenticationSchemes.Negotiate) != System.Net.AuthenticationSchemes.None) && (string.Compare(knownHeader, 0, "Negotiate", 0, length, StringComparison.OrdinalIgnoreCase) == 0)) { none = System.Net.AuthenticationSchemes.Negotiate; } else if (((authenticationSchemes & System.Net.AuthenticationSchemes.Ntlm) != System.Net.AuthenticationSchemes.None) && (string.Compare(knownHeader, 0, "NTLM", 0, length, StringComparison.OrdinalIgnoreCase) == 0)) { none = System.Net.AuthenticationSchemes.Ntlm; } else if (((authenticationSchemes & System.Net.AuthenticationSchemes.Digest) != System.Net.AuthenticationSchemes.None) && (string.Compare(knownHeader, 0, "Digest", 0, length, StringComparison.OrdinalIgnoreCase) == 0)) { none = System.Net.AuthenticationSchemes.Digest; } else if (((authenticationSchemes & System.Net.AuthenticationSchemes.Basic) != System.Net.AuthenticationSchemes.None) && (string.Compare(knownHeader, 0, "Basic", 0, length, StringComparison.OrdinalIgnoreCase) == 0)) { none = System.Net.AuthenticationSchemes.Basic; } else if (Logging.On) { Logging.PrintWarning(Logging.HttpListener, this, "HandleAuthentication", SR.GetString("net_log_listener_unsupported_authentication_scheme", new object[] { knownHeader, authenticationSchemes })); } } } HttpStatusCode internalServerError = HttpStatusCode.InternalServerError; bool flag2 = false; if (none == System.Net.AuthenticationSchemes.None) { if (Logging.On) { Logging.PrintWarning(Logging.HttpListener, this, "HandleAuthentication", SR.GetString("net_log_listener_unmatched_authentication_scheme", new object[] { ValidationHelper.ToString(authenticationSchemes), (knownHeader == null) ? "<null>" : knownHeader })); } if ((authenticationSchemes & System.Net.AuthenticationSchemes.Anonymous) != System.Net.AuthenticationSchemes.None) { if (!stoleBlob) { stoleBlob = true; context2.Request.ReleasePins(); } return context2; } internalServerError = HttpStatusCode.Unauthorized; context2.Request.DetachBlob(memoryBlob); context2.Close(); context2 = null; goto Label_07AA; } byte[] bytes = null; byte[] inArray = null; string str4 = null; length++; while (length < knownHeader.Length) { if (((knownHeader[length] != ' ') && (knownHeader[length] != '\t')) && ((knownHeader[length] != '\r') && (knownHeader[length] != '\n'))) { break; } length++; } string incomingBlob = (length < knownHeader.Length) ? knownHeader.Substring(length) : ""; IPrincipal principal2 = null; switch (none) { case System.Net.AuthenticationSchemes.Digest: { binding = this.GetChannelBinding(connectionId, isSecureConnection, extendedProtectionPolicy); authentication3 = new NTAuthentication(true, "WDigest", null, this.GetContextFlags(extendedProtectionPolicy, isSecureConnection), binding); str4 = authentication3.GetOutgoingDigestBlob(incomingBlob, verb, null, this.Realm, false, false, out invalidToken); if (invalidToken == SecurityStatus.OK) { str4 = null; } if (!authentication3.IsValidContext) { break; } SafeCloseHandle contextToken = null; try { if (!this.CheckSpn(authentication3, isSecureConnection, extendedProtectionPolicy)) { internalServerError = HttpStatusCode.Unauthorized; } else { context2.Request.ServiceName = authentication3.ClientSpecifiedSpn; contextToken = authentication3.GetContextToken(out invalidToken); if (invalidToken != SecurityStatus.OK) { internalServerError = this.HttpStatusFromSecurityStatus(invalidToken); } else if (contextToken == null) { internalServerError = HttpStatusCode.Unauthorized; } else { principal2 = new WindowsPrincipal(this.CreateWindowsIdentity(contextToken.DangerousGetHandle(), "Digest", WindowsAccountType.Normal, true)); } } } finally { if (contextToken != null) { contextToken.Close(); } } newContext = authentication3; if (str4 != null) { challenge = "Digest " + str4; } goto Label_0761; } case System.Net.AuthenticationSchemes.Negotiate: case System.Net.AuthenticationSchemes.Ntlm: str6 = (none == System.Net.AuthenticationSchemes.Ntlm) ? "NTLM" : "Negotiate"; if ((digestContext == null) || !(digestContext.Package == str6)) { goto Label_0549; } authentication3 = digestContext; goto Label_056D; case System.Net.AuthenticationSchemes.Basic: try { bytes = Convert.FromBase64String(incomingBlob); incomingBlob = WebHeaderCollection.HeaderEncoding.GetString(bytes, 0, bytes.Length); length = incomingBlob.IndexOf(':'); if (length != -1) { string username = incomingBlob.Substring(0, length); string password = incomingBlob.Substring(length + 1); principal2 = new GenericPrincipal(new HttpListenerBasicIdentity(username, password), null); } else { internalServerError = HttpStatusCode.BadRequest; } } catch (FormatException) { } goto Label_0761; default: goto Label_0761; } internalServerError = this.HttpStatusFromSecurityStatus(invalidToken); goto Label_0761; Label_0549: binding = this.GetChannelBinding(connectionId, isSecureConnection, extendedProtectionPolicy); authentication3 = new NTAuthentication(true, str6, null, this.GetContextFlags(extendedProtectionPolicy, isSecureConnection), binding); Label_056D: try { bytes = Convert.FromBase64String(incomingBlob); } catch (FormatException) { internalServerError = HttpStatusCode.BadRequest; flag2 = true; } if (!flag2) { inArray = authentication3.GetOutgoingBlob(bytes, false, out invalidToken); flag2 = !authentication3.IsValidContext; if (flag2) { if (((invalidToken == SecurityStatus.InvalidHandle) && (digestContext == null)) && ((bytes != null) && (bytes.Length > 0))) { invalidToken = SecurityStatus.InvalidToken; } internalServerError = this.HttpStatusFromSecurityStatus(invalidToken); } } if (inArray != null) { str4 = Convert.ToBase64String(inArray); } if (!flag2) { if (authentication3.IsCompleted) { SafeCloseHandle handle2 = null; try { if (!this.CheckSpn(authentication3, isSecureConnection, extendedProtectionPolicy)) { internalServerError = HttpStatusCode.Unauthorized; } else { context2.Request.ServiceName = authentication3.ClientSpecifiedSpn; handle2 = authentication3.GetContextToken(out invalidToken); if (invalidToken != SecurityStatus.OK) { internalServerError = this.HttpStatusFromSecurityStatus(invalidToken); } else { WindowsPrincipal principal3 = new WindowsPrincipal(this.CreateWindowsIdentity(handle2.DangerousGetHandle(), authentication3.ProtocolName, WindowsAccountType.Normal, true)); principal2 = principal3; if (this.UnsafeConnectionNtlmAuthentication && (authentication3.ProtocolName == "NTLM")) { if (disconnectResult == null) { this.RegisterForDisconnectNotification(connectionId, ref disconnectResult); } if (disconnectResult != null) { lock (this.DisconnectResults.SyncRoot) { if (this.UnsafeConnectionNtlmAuthentication) { disconnectResult.AuthenticatedConnection = principal3; } } } } } } goto Label_0761; } finally { if (handle2 != null) { handle2.Close(); } } } newContext = authentication3; challenge = (none == System.Net.AuthenticationSchemes.Ntlm) ? "NTLM" : "Negotiate"; if (!string.IsNullOrEmpty(str4)) { challenge = challenge + " " + str4; } } Label_0761: if (principal2 != null) { context2.SetIdentity(principal2, str4); } else { if (Logging.On) { Logging.PrintWarning(Logging.HttpListener, this, "HandleAuthentication", SR.GetString("net_log_listener_create_valid_identity_failed")); } context2.Request.DetachBlob(memoryBlob); context2.Close(); context2 = null; } Label_07AA: list = null; if (context2 == null) { if (challenge != null) { AddChallenge(ref list, challenge); } else { if (newContext != null) { if (newContext == authentication3) { authentication3 = null; } if (newContext != digestContext) { NTAuthentication authentication4 = newContext; newContext = null; authentication4.CloseContext(); } else { newContext = null; } } if (internalServerError != HttpStatusCode.Unauthorized) { this.SendError(requestId, internalServerError, null); return null; } list = this.BuildChallenge(authenticationSchemes, connectionId, out newContext, extendedProtectionPolicy, isSecureConnection); } } if ((disconnectResult == null) && (newContext != null)) { this.RegisterForDisconnectNotification(connectionId, ref disconnectResult); if (disconnectResult == null) { if (newContext != null) { if (newContext == authentication3) { authentication3 = null; } if (newContext != digestContext) { NTAuthentication authentication5 = newContext; newContext = null; authentication5.CloseContext(); } else { newContext = null; } } this.SendError(requestId, HttpStatusCode.InternalServerError, null); context2.Request.DetachBlob(memoryBlob); context2.Close(); return null; } } if (digestContext != newContext) { if (digestContext == authentication3) { authentication3 = null; } NTAuthentication authentication6 = digestContext; digestContext = newContext; disconnectResult.Session = newContext; if (authentication6 != null) { if ((authenticationSchemes & System.Net.AuthenticationSchemes.Digest) != System.Net.AuthenticationSchemes.None) { this.SaveDigestContext(authentication6); } else { authentication6.CloseContext(); } } } if (context2 == null) { this.SendError(requestId, ((list != null) && (list.Count > 0)) ? HttpStatusCode.Unauthorized : HttpStatusCode.Forbidden, list); return null; } if (!stoleBlob) { stoleBlob = true; context2.Request.ReleasePins(); } context3 = context2; } catch { if (context2 != null) { context2.Request.DetachBlob(memoryBlob); context2.Close(); } if (newContext != null) { if (newContext == authentication3) { authentication3 = null; } if (newContext != digestContext) { NTAuthentication authentication7 = newContext; newContext = null; authentication7.CloseContext(); } else { newContext = null; } } throw; } finally { try { if ((digestContext != null) && (digestContext != newContext)) { if ((newContext == null) && (disconnectResult != null)) { disconnectResult.Session = null; } if ((authenticationSchemes & System.Net.AuthenticationSchemes.Digest) != System.Net.AuthenticationSchemes.None) { this.SaveDigestContext(digestContext); } else { digestContext.CloseContext(); } } if (((authentication3 != null) && (digestContext != authentication3)) && (newContext != authentication3)) { authentication3.CloseContext(); } } finally { if (disconnectResult != null) { disconnectResult.FinishOwningDisconnectHandling(); } } } return context3; }
private ArrayList BuildChallenge(System.Net.AuthenticationSchemes authenticationScheme, ulong connectionId, out NTAuthentication newContext, System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy policy, bool isSecureConnection) { ArrayList challenges = null; newContext = null; if ((authenticationScheme & System.Net.AuthenticationSchemes.Negotiate) != System.Net.AuthenticationSchemes.None) { AddChallenge(ref challenges, "Negotiate"); } if ((authenticationScheme & System.Net.AuthenticationSchemes.Ntlm) != System.Net.AuthenticationSchemes.None) { AddChallenge(ref challenges, "NTLM"); } if ((authenticationScheme & System.Net.AuthenticationSchemes.Digest) != System.Net.AuthenticationSchemes.None) { NTAuthentication authentication = null; try { SecurityStatus status; string str = null; ChannelBinding channelBinding = this.GetChannelBinding(connectionId, isSecureConnection, policy); authentication = new NTAuthentication(true, "WDigest", null, this.GetContextFlags(policy, isSecureConnection), channelBinding); str = authentication.GetOutgoingDigestBlob(null, null, null, this.Realm, false, false, out status); if (authentication.IsValidContext) { newContext = authentication; } AddChallenge(ref challenges, "Digest" + (string.IsNullOrEmpty(str) ? "" : (" " + str))); } finally { if ((authentication != null) && (newContext != authentication)) { authentication.CloseContext(); } } } if ((authenticationScheme & System.Net.AuthenticationSchemes.Basic) != System.Net.AuthenticationSchemes.None) { AddChallenge(ref challenges, "Basic realm=\"" + this.Realm + "\""); } return challenges; }
private void SaveDigestContext(NTAuthentication digestContext) { if (this.m_SavedDigests == null) { Interlocked.CompareExchange<DigestContext[]>(ref this.m_SavedDigests, new DigestContext[0x400], null); } NTAuthentication context = null; ArrayList extraSavedDigestsBaking = null; lock (this.m_SavedDigests) { int num; if (!this.IsListening) { digestContext.CloseContext(); return; } num = ((num = Environment.TickCount) == 0) ? 1 : num; this.m_NewestContext = (this.m_NewestContext + 1) & 0x3ff; int timestamp = this.m_SavedDigests[this.m_NewestContext].timestamp; context = this.m_SavedDigests[this.m_NewestContext].context; this.m_SavedDigests[this.m_NewestContext].timestamp = num; this.m_SavedDigests[this.m_NewestContext].context = digestContext; if (this.m_OldestContext == this.m_NewestContext) { this.m_OldestContext = (this.m_NewestContext + 1) & 0x3ff; } while (((num - this.m_SavedDigests[this.m_OldestContext].timestamp) >= 300) && (this.m_SavedDigests[this.m_OldestContext].context != null)) { if (extraSavedDigestsBaking == null) { extraSavedDigestsBaking = new ArrayList(); } extraSavedDigestsBaking.Add(this.m_SavedDigests[this.m_OldestContext].context); this.m_SavedDigests[this.m_OldestContext].context = null; this.m_OldestContext = (this.m_OldestContext + 1) & 0x3ff; } if ((context != null) && ((num - timestamp) <= 0x2710)) { if ((this.m_ExtraSavedDigests == null) || ((num - this.m_ExtraSavedDigestsTimestamp) > 0x2710)) { extraSavedDigestsBaking = this.m_ExtraSavedDigestsBaking; this.m_ExtraSavedDigestsBaking = this.m_ExtraSavedDigests; this.m_ExtraSavedDigestsTimestamp = num; this.m_ExtraSavedDigests = new ArrayList(); } this.m_ExtraSavedDigests.Add(context); context = null; } } if (context != null) { context.CloseContext(); } if (extraSavedDigestsBaking != null) { for (int i = 0; i < extraSavedDigestsBaking.Count; i++) { ((NTAuthentication) extraSavedDigestsBaking[i]).CloseContext(); } } }
private ArrayList BuildChallenge(AuthenticationSchemes authenticationScheme, ulong connectionId, out NTAuthentication newContext, ExtendedProtectionPolicy policy, bool isSecureConnection) { GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::BuildChallenge() authenticationScheme:" + authenticationScheme.ToString()); ArrayList challenges = null; newContext = null; if ((authenticationScheme & AuthenticationSchemes.Negotiate) != 0) { AddChallenge(ref challenges, NegotiateClient.AuthType); } if ((authenticationScheme & AuthenticationSchemes.Ntlm) != 0) { AddChallenge(ref challenges, NtlmClient.AuthType); } if ((authenticationScheme & AuthenticationSchemes.Digest) != 0) { GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::BuildChallenge() package:WDigest"); NTAuthentication context = null; try { string outBlob = null; ChannelBinding binding = GetChannelBinding(connectionId, isSecureConnection, policy); context = new NTAuthentication(true, NegotiationInfoClass.WDigest, null, GetContextFlags(policy, isSecureConnection), binding); SecurityStatus statusCode; outBlob = context.GetOutgoingDigestBlob(null, null, null, Realm, false, false, out statusCode); GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::BuildChallenge() GetOutgoingDigestBlob() returned IsCompleted:" + context.IsCompleted + " statusCode:" + statusCode + " outBlob:[" + outBlob + "]"); if (context.IsValidContext) { newContext = context; } AddChallenge(ref challenges, DigestClient.AuthType + (string.IsNullOrEmpty(outBlob) ? "" : " " + outBlob)); } finally { if (context != null && newContext != context) { context.CloseContext(); } } } if ((authenticationScheme & AuthenticationSchemes.Basic) != 0) { AddChallenge(ref challenges, BasicClient.AuthType + " realm=\"" + Realm + "\""); } return challenges; }