public Authorization Authenticate(string challenge, NetworkCredential credential, object sessionCookie, string spn, ChannelBinding channelBindingToken)
        {

            lock (this.sessions)
            {
                NTAuthentication clientContext = this.sessions[sessionCookie] as NTAuthentication;
                if (clientContext == null)
                {
                    if (credential == null){
                        return null;
                    }
                    // 


                   

                    this.sessions[sessionCookie] = clientContext = new NTAuthentication(false, "WDigest", credential, spn, ContextFlags.Connection, channelBindingToken);
                }

                string resp = clientContext.GetOutgoingBlob(challenge);

                if (!clientContext.IsCompleted)
                {
                    return new Authorization(resp, false);
                }
                else
                {
                    this.sessions.Remove(sessionCookie);
                    return new Authorization(resp, true);
                }
            }
        }
 public Authorization Authenticate(string challenge, NetworkCredential credential, object sessionCookie, string spn, ChannelBinding channelBindingToken)
 {
     Authorization authorization;
     if (Logging.On)
     {
         Logging.Enter(Logging.Web, this, "Authenticate", (string) null);
     }
     try
     {
         lock (this.sessions)
         {
             NTAuthentication clientContext = this.sessions[sessionCookie] as NTAuthentication;
             if (clientContext == null)
             {
                 if (credential == null)
                 {
                     return null;
                 }
                 this.sessions[sessionCookie] = clientContext = new NTAuthentication(false, "Negotiate", credential, spn, ContextFlags.AcceptStream | ContextFlags.Connection, channelBindingToken);
             }
             string token = null;
             if (!clientContext.IsCompleted)
             {
                 SecurityStatus status;
                 byte[] incomingBlob = null;
                 if (challenge != null)
                 {
                     incomingBlob = Convert.FromBase64String(challenge);
                 }
                 byte[] inArray = clientContext.GetOutgoingBlob(incomingBlob, false, out status);
                 if (clientContext.IsCompleted && (inArray == null))
                 {
                     token = "\r\n";
                 }
                 if (inArray != null)
                 {
                     token = Convert.ToBase64String(inArray);
                 }
             }
             else
             {
                 token = this.GetSecurityLayerOutgoingBlob(challenge, clientContext);
             }
             authorization = new Authorization(token, clientContext.IsCompleted);
         }
     }
     finally
     {
         if (Logging.On)
         {
             Logging.Exit(Logging.Web, this, "Authenticate", (string) null);
         }
     }
     return authorization;
 }
 public Authorization Authenticate(string challenge, NetworkCredential credential, object sessionCookie, string spn, ChannelBinding channelBindingToken)
 {
     lock (this.sessions)
     {
         NTAuthentication authentication = this.sessions[sessionCookie] as NTAuthentication;
         if (authentication == null)
         {
             if (credential == null)
             {
                 return null;
             }
             this.sessions[sessionCookie] = authentication = new NTAuthentication(false, "WDigest", credential, spn, ContextFlags.Connection, channelBindingToken);
         }
         string outgoingBlob = authentication.GetOutgoingBlob(challenge);
         if (!authentication.IsCompleted)
         {
             return new Authorization(outgoingBlob, false);
         }
         this.sessions.Remove(sessionCookie);
         return new Authorization(outgoingBlob, true);
     }
 }
 private Authorization DoAuthenticate(string challenge, WebRequest webRequest, ICredentials credentials, bool preAuthenticate)
 {
     if (credentials == null)
     {
         return null;
     }
     HttpWebRequest request = webRequest as HttpWebRequest;
     NTAuthentication securityContext = null;
     string incomingBlob = null;
     if (!preAuthenticate)
     {
         int index = AuthenticationManager.FindSubstringNotInQuotes(challenge, Signature);
         if (index < 0)
         {
             return null;
         }
         int startIndex = index + SignatureSize;
         if ((challenge.Length > startIndex) && (challenge[startIndex] != ','))
         {
             startIndex++;
         }
         else
         {
             index = -1;
         }
         if ((index >= 0) && (challenge.Length > startIndex))
         {
             index = challenge.IndexOf(',', startIndex);
             if (index != -1)
             {
                 incomingBlob = challenge.Substring(startIndex, index - startIndex);
             }
             else
             {
                 incomingBlob = challenge.Substring(startIndex);
             }
         }
         securityContext = request.CurrentAuthenticationState.GetSecurityContext(this);
     }
     if (securityContext == null)
     {
         NetworkCredential credential = credentials.GetCredential(request.ChallengedUri, Signature);
         string str2 = string.Empty;
         if ((credential == null) || (!(credential is SystemNetworkCredential) && ((str2 = credential.InternalGetUserName()).Length == 0)))
         {
             return null;
         }
         if (((str2.Length + credential.InternalGetPassword().Length) + credential.InternalGetDomain().Length) > 0x20f)
         {
             return null;
         }
         ICredentialPolicy credentialPolicy = AuthenticationManager.CredentialPolicy;
         if ((credentialPolicy != null) && !credentialPolicy.ShouldSendCredential(request.ChallengedUri, request, credential, this))
         {
             return null;
         }
         string computeSpn = request.CurrentAuthenticationState.GetComputeSpn(request);
         ChannelBinding channelBinding = null;
         if (request.CurrentAuthenticationState.TransportContext != null)
         {
             channelBinding = request.CurrentAuthenticationState.TransportContext.GetChannelBinding(ChannelBindingKind.Endpoint);
         }
         securityContext = new NTAuthentication("NTLM", credential, computeSpn, request, channelBinding);
         request.CurrentAuthenticationState.SetSecurityContext(securityContext, this);
     }
     string outgoingBlob = securityContext.GetOutgoingBlob(incomingBlob);
     if (outgoingBlob == null)
     {
         return null;
     }
     bool unsafeOrProxyAuthenticatedConnectionSharing = request.UnsafeOrProxyAuthenticatedConnectionSharing;
     if (unsafeOrProxyAuthenticatedConnectionSharing)
     {
         request.LockConnection = true;
     }
     request.NtlmKeepAlive = incomingBlob == null;
     return AuthenticationManager.GetGroupAuthorization(this, "NTLM " + outgoingBlob, securityContext.IsCompleted, securityContext, unsafeOrProxyAuthenticatedConnectionSharing, false);
 }
Exemple #5
0
        private Authorization XPDoAuthenticate(string challenge, HttpWebRequest httpWebRequest, ICredentials credentials, bool preAuthenticate)
        {
            NTAuthentication securityContext = null;
            string           incomingBlob    = null;
            SecurityStatus   status;

            if (!preAuthenticate)
            {
                int index = AuthenticationManager.FindSubstringNotInQuotes(challenge, Signature);
                if (index < 0)
                {
                    return(null);
                }
                securityContext = httpWebRequest.CurrentAuthenticationState.GetSecurityContext(this);
                incomingBlob    = RefineDigestChallenge(challenge, index);
            }
            else
            {
                HttpDigestChallenge challenge2 = challengeCache.Lookup(httpWebRequest.ChallengedUri.AbsoluteUri) as HttpDigestChallenge;
                if (challenge2 == null)
                {
                    return(null);
                }
                challenge2 = challenge2.CopyAndIncrementNonce();
                challenge2.SetFromRequest(httpWebRequest);
                incomingBlob = challenge2.ToBlob();
            }
            UriComponents uriParts = 0;

            if (httpWebRequest.CurrentMethod.ConnectRequest)
            {
                uriParts = UriComponents.HostAndPort;
            }
            else if (httpWebRequest.UsesProxySemantics)
            {
                uriParts = UriComponents.HttpRequestUrl;
            }
            else
            {
                uriParts = UriComponents.PathAndQuery;
            }
            string parts = httpWebRequest.GetRemoteResourceUri().GetParts(uriParts, UriFormat.UriEscaped);

            if (securityContext == null)
            {
                NetworkCredential credential = credentials.GetCredential(httpWebRequest.ChallengedUri, Signature);
                if ((credential == null) || (!(credential is SystemNetworkCredential) && (credential.InternalGetUserName().Length == 0)))
                {
                    return(null);
                }
                ICredentialPolicy credentialPolicy = AuthenticationManager.CredentialPolicy;
                if ((credentialPolicy != null) && !credentialPolicy.ShouldSendCredential(httpWebRequest.ChallengedUri, httpWebRequest, credential, this))
                {
                    return(null);
                }
                string         computeSpn     = httpWebRequest.CurrentAuthenticationState.GetComputeSpn(httpWebRequest);
                ChannelBinding channelBinding = null;
                if (httpWebRequest.CurrentAuthenticationState.TransportContext != null)
                {
                    channelBinding = httpWebRequest.CurrentAuthenticationState.TransportContext.GetChannelBinding(ChannelBindingKind.Endpoint);
                }
                securityContext = new NTAuthentication("WDigest", credential, computeSpn, httpWebRequest, channelBinding);
                httpWebRequest.CurrentAuthenticationState.SetSecurityContext(securityContext, this);
            }
            string str4 = securityContext.GetOutgoingDigestBlob(incomingBlob, httpWebRequest.CurrentMethod.Name, parts, null, false, false, out status);

            if (str4 == null)
            {
                return(null);
            }
            Authorization authorization = new Authorization("Digest " + str4, securityContext.IsCompleted, string.Empty, securityContext.IsMutualAuthFlag);

            if (!preAuthenticate && httpWebRequest.PreAuthenticate)
            {
                HttpDigestChallenge challenge3 = HttpDigest.Interpret(incomingBlob, -1, httpWebRequest);
                string[]            strArray   = (challenge3.Domain == null) ? new string[] { httpWebRequest.ChallengedUri.GetParts(UriComponents.SchemeAndServer, UriFormat.UriEscaped) } : challenge3.Domain.Split(singleSpaceArray);
                authorization.ProtectionRealm = (challenge3.Domain == null) ? null : strArray;
                for (int i = 0; i < strArray.Length; i++)
                {
                    challengeCache.Add(strArray[i], challenge3);
                }
            }
            return(authorization);
        }
 internal InitializeCallbackContext(NTAuthentication thisPtr, bool isServer, string package, NetworkCredential credential, string spn, ContextFlags requestedContextFlags, ChannelBinding channelBinding)
 {
     this.thisPtr = thisPtr;
     this.isServer = isServer;
     this.package = package;
     this.credential = credential;
     this.spn = spn;
     this.requestedContextFlags = requestedContextFlags;
     this.channelBinding = channelBinding;
 }
        public static Authorization Authenticate(string challenge, WebRequest webRequest, ICredentials credentials)
        {
            GlobalLog.Print("XPDigestClient::Authenticate(): " + challenge);

            GlobalLog.Assert(credentials != null, "XPDigestClient::Authenticate() credentials==null", "");
            if (credentials == null)
            {
                return(null);
            }

            HttpWebRequest httpWebRequest = webRequest as HttpWebRequest;

            GlobalLog.Assert(httpWebRequest != null, "XPDigestClient::Authenticate() httpWebRequest==null", "");
            if (httpWebRequest == null || httpWebRequest.ChallengedUri == null)
            {
                //
                // there has been no challenge:
                // 1) the request never went on the wire
                // 2) somebody other than us is calling into AuthenticationManager
                //
                return(null);
            }

            int index = AuthenticationManager.FindSubstringNotInQuotes(challenge.ToLower(CultureInfo.InvariantCulture), DigestClient.Signature);

            if (index < 0)
            {
                return(null);
            }

            int    blobBegin = index + DigestClient.SignatureSize;
            string incoming  = null;

            //
            // there may be multiple challenges. If the next character after the
            // package name is not a comma then it is challenge data
            //
            if (challenge.Length > blobBegin && challenge[blobBegin] != ',')
            {
                ++blobBegin;
            }
            else
            {
                index = -1;
            }
            if (index >= 0 && challenge.Length > blobBegin)
            {
                incoming = challenge.Substring(blobBegin);
            }

            NTAuthentication authSession = sessions[httpWebRequest.CurrentAuthenticationState] as NTAuthentication;

            GlobalLog.Print("XPDigestClient::Authenticate() key:" + ValidationHelper.HashString(httpWebRequest.CurrentAuthenticationState) + " retrieved authSession:" + ValidationHelper.HashString(authSession));

            if (authSession == null)
            {
                NetworkCredential NC = credentials.GetCredential(httpWebRequest.ChallengedUri, DigestClient.Signature);
                GlobalLog.Print("XPDigestClient::Authenticate() GetCredential() returns:" + ValidationHelper.ToString(NC));

                if (NC == null)
                {
                    return(null);
                }
                string username = NC.UserName;
                if (username == null || (username.Length == 0 && !(NC is SystemNetworkCredential)))
                {
                    return(null);
                }
                authSession =
                    new NTAuthentication(
                        "WDigest",
                        NC,
                        httpWebRequest.ChallengedUri.AbsolutePath,
                        httpWebRequest.DelegationFix);

                GlobalLog.Print("XPDigestClient::Authenticate() adding authSession:" + ValidationHelper.HashString(authSession) + " for:" + ValidationHelper.HashString(httpWebRequest.CurrentAuthenticationState));
                sessions.Add(httpWebRequest.CurrentAuthenticationState, authSession);
            }

            bool   handshakeComplete;
            string clientResponse = authSession.GetOutgoingDigestBlob(incoming, httpWebRequest.CurrentMethod, out handshakeComplete);

            GlobalLog.Print("XPDigestClient::Authenticate() GetOutgoingDigestBlob(" + incoming + ") returns:" + ValidationHelper.ToString(clientResponse));

            GlobalLog.Assert(handshakeComplete, "XPDigestClient::Authenticate() handshakeComplete==false", "");
            if (!handshakeComplete)
            {
                return(null);
            }

            // completion is decided in Update()
            Authorization finalAuthorization = new Authorization(DigestClient.AuthType + " " + clientResponse, false);

            return(finalAuthorization);
        }
Exemple #8
0
        private Authorization DoAuthenticate(string challenge, WebRequest webRequest, ICredentials credentials, bool preAuthenticate) {
            GlobalLog.Print("NtlmClient::DoAuthenticate() challenge:[" + ValidationHelper.ToString(challenge) + "] webRequest#" + ValidationHelper.HashString(webRequest) + " credentials#" + ValidationHelper.HashString(credentials) + " preAuthenticate:" + preAuthenticate.ToString());

            GlobalLog.Assert(credentials != null, "NtlmClient::DoAuthenticate()|credentials == null");
            if (credentials == null) {
                return null;
            }

            HttpWebRequest httpWebRequest = webRequest as HttpWebRequest;

            GlobalLog.Assert(httpWebRequest != null, "NtlmClient::DoAuthenticate()|httpWebRequest == null");
            GlobalLog.Assert(httpWebRequest.ChallengedUri != null, "NtlmClient::DoAuthenticate()|httpWebRequest.ChallengedUri == null");

            NTAuthentication authSession = null;
            string incoming = null;

            if (!preAuthenticate) {
                int index = AuthenticationManager.FindSubstringNotInQuotes(challenge, Signature);
                if (index < 0) {
                    return null;
                }

                int blobBegin = index + SignatureSize;

                //
                // there may be multiple challenges. If the next character after the
                // package name is not a comma then it is challenge data
                //
                if (challenge.Length > blobBegin && challenge[blobBegin] != ',') {
                    ++blobBegin;
                }
                else {
                    index = -1;
                }

                if (index >= 0 && challenge.Length > blobBegin)
                {
                    // Strip other modules information in case of multiple challenges
                    // i.e do not take ", NTLM" as part of the following Negotiate blob
                    // Negotiate TlRMTVNTUAACAAAADgAOADgAAAA1wo ... MAbwBmAHQALgBjAG8AbQAAAAAA,NTLM
                    index = challenge.IndexOf(',', blobBegin);
                    if (index != -1)
                        incoming = challenge.Substring(blobBegin, index - blobBegin);
                    else
                        incoming = challenge.Substring(blobBegin);
                }


                authSession = httpWebRequest.CurrentAuthenticationState.GetSecurityContext(this);
                GlobalLog.Print("NtlmClient::DoAuthenticate() key:" + ValidationHelper.HashString(httpWebRequest.CurrentAuthenticationState) + " retrieved authSession:" + ValidationHelper.HashString(authSession));
            }

            if (authSession==null) {
                NetworkCredential NC = credentials.GetCredential(httpWebRequest.ChallengedUri, Signature);
                GlobalLog.Print("NtlmClient::DoAuthenticate() GetCredential() returns:" + ValidationHelper.ToString(NC));

                string username = string.Empty;
                if (NC == null || (!(NC is SystemNetworkCredential) && (username = NC.InternalGetUserName()).Length == 0))
                {
                    return null;
                }

                ICredentialPolicy policy = AuthenticationManager.CredentialPolicy;
                if (policy != null && !policy.ShouldSendCredential(httpWebRequest.ChallengedUri, httpWebRequest, NC, this))
                    return null;

                SpnToken spn = httpWebRequest.CurrentAuthenticationState.GetComputeSpn(httpWebRequest);
                GlobalLog.Print("NtlmClient::Authenticate() ChallengedSpn:" + ValidationHelper.ToString(spn));

                ChannelBinding binding = null;
                if (httpWebRequest.CurrentAuthenticationState.TransportContext != null)
                {
                    binding = httpWebRequest.CurrentAuthenticationState.TransportContext.GetChannelBinding(ChannelBindingKind.Endpoint);
                }

                authSession =
                    new NTAuthentication(
                        AuthType,
                        NC,
                        spn,
                        httpWebRequest,
                        binding);

                GlobalLog.Print("NtlmClient::DoAuthenticate() setting SecurityContext for:" + ValidationHelper.HashString(httpWebRequest.CurrentAuthenticationState) + " to authSession:" + ValidationHelper.HashString(authSession));
                httpWebRequest.CurrentAuthenticationState.SetSecurityContext(authSession, this);
            }

            string clientResponse = authSession.GetOutgoingBlob(incoming);
            if (clientResponse==null) {
                return null;
            }

            bool canShareConnection = httpWebRequest.UnsafeOrProxyAuthenticatedConnectionSharing;
            if (canShareConnection) {
                httpWebRequest.LockConnection = true;
            }

            // this is the first leg of an NTLM handshake,
            // set the NtlmKeepAlive override *STRICTLY* only in this case.
            httpWebRequest.NtlmKeepAlive = incoming==null;

            return AuthenticationManager.GetGroupAuthorization(this, AuthType + " " + clientResponse, authSession.IsCompleted, authSession, canShareConnection, false);
        }
        private ArrayList BuildChallenge(AuthenticationSchemes authenticationScheme, ulong connectionId,
            out NTAuthentication newContext, ExtendedProtectionPolicy policy, bool isSecureConnection)
        {
            if (NetEventSource.IsEnabled) NetEventSource.Info(this, "AuthenticationScheme:" + authenticationScheme.ToString());
            ArrayList challenges = null;
            newContext = null;

            if ((authenticationScheme & AuthenticationSchemes.Negotiate) != 0)
            {
                AddChallenge(ref challenges, AuthConstants.Negotiate);
            }

            if ((authenticationScheme & AuthenticationSchemes.Ntlm) != 0)
            {
                AddChallenge(ref challenges, AuthConstants.NTLM);
            }

            if ((authenticationScheme & AuthenticationSchemes.Digest) != 0)
            {
                if (NetEventSource.IsEnabled) NetEventSource.Info(this, "WDigest");
                throw new NotImplementedException();
            }

            if ((authenticationScheme & AuthenticationSchemes.Basic) != 0)
            {
                AddChallenge(ref challenges, "Basic realm =\"" + Realm + "\"");
            }

            return challenges;
        }
        //
        internal void ValidateCreateContext(
                                            string package,
                                            bool isServer,
                                            NetworkCredential credential,
                                            string servicePrincipalName,
                                            ChannelBinding channelBinding,
                                            ProtectionLevel         protectionLevel,
                                            TokenImpersonationLevel impersonationLevel
                                            )
        {

            if (_Exception != null && !_CanRetryAuthentication) {
                throw _Exception;
            }

            if (_Context != null && _Context.IsValidContext) {
                throw new InvalidOperationException(SR.GetString(SR.net_auth_reauth));
            }

            if (credential == null) {
                throw new ArgumentNullException("credential");
            }

            if (servicePrincipalName == null) {
                throw new ArgumentNullException("servicePrincipalName");
            }

            if (impersonationLevel != TokenImpersonationLevel.Identification &&
                impersonationLevel != TokenImpersonationLevel.Impersonation &&
                impersonationLevel != TokenImpersonationLevel.Delegation)
            {
                throw new ArgumentOutOfRangeException("impersonationLevel", impersonationLevel.ToString(), SR.GetString(SR.net_auth_supported_impl_levels));
            }

            if (_Context != null && IsServer != isServer) {
                throw new InvalidOperationException(SR.GetString(SR.net_auth_client_server));
            }

            _Exception = null;
            _RemoteOk = false;
            _Framer = new StreamFramer(_InnerStream);
            _Framer.WriteHeader.MessageId = FrameHeader.HandshakeId;

            _ExpectedProtectionLevel    = protectionLevel;
            _ExpectedImpersonationLevel = isServer? impersonationLevel: TokenImpersonationLevel.None;
            _WriteSequenceNumber        = 0;
            _ReadSequenceNumber         = 0;

            ContextFlags flags = ContextFlags.Connection;

            // A workaround for the client when talking to Win9x on the server side
            if (protectionLevel == ProtectionLevel.None && !isServer)
            {
                package = NegotiationInfoClass.NTLM;
            }

            else if (protectionLevel == ProtectionLevel.EncryptAndSign)
            {
                flags |= ContextFlags.Confidentiality;
            }
            else if (protectionLevel == ProtectionLevel.Sign)
            {
                // Assuming user expects NT4 SP4 and above
                flags |= ContextFlags.ReplayDetect | ContextFlags.SequenceDetect | ContextFlags.InitIntegrity;
            }

            if (isServer)
            {
                if (_ExtendedProtectionPolicy.PolicyEnforcement == PolicyEnforcement.WhenSupported) { flags |= ContextFlags.AllowMissingBindings; }
                if (_ExtendedProtectionPolicy.PolicyEnforcement != PolicyEnforcement.Never &&
                    _ExtendedProtectionPolicy.ProtectionScenario == ProtectionScenario.TrustedProxy)
                {
                    flags |= ContextFlags.ProxyBindings;
                }
            }
            else
            {
                // According to lzhu server side should not request any of these flags
                if (protectionLevel != ProtectionLevel.None)                        {flags |= ContextFlags.MutualAuth;}
                if (impersonationLevel == TokenImpersonationLevel.Identification)   {flags |= ContextFlags.InitIdentify;}
                if (impersonationLevel == TokenImpersonationLevel.Delegation)       {flags |= ContextFlags.Delegate;}
            }
            

            _CanRetryAuthentication = false;

            //
            // Security: We used to rely on NetworkCredential class to demand permission
            //           Switched over to explicit ControlPrincipalPermission demand (except for DefaultCredential case)
            //           The mitigated attack is brute-force pasword guessing through SSPI.
            if (!(credential is SystemNetworkCredential))
                ExceptionHelper.ControlPrincipalPermission.Demand();

            try {
                //
                _Context = new NTAuthentication(isServer, package, credential, servicePrincipalName, flags, channelBinding);
            }
            catch (Win32Exception e)
            {
                throw new AuthenticationException(SR.GetString(SR.net_auth_SSPI), e);
            }
        }
 private bool CheckSpn(NTAuthentication context, bool isSecureConnection, System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy policy)
 {
     if (context.IsKerberos)
     {
         if (Logging.On)
         {
             Logging.PrintInfo(Logging.HttpListener, this, SR.GetString("net_log_listener_no_spn_kerberos"));
         }
         return true;
     }
     if (policy.PolicyEnforcement == PolicyEnforcement.Never)
     {
         if (Logging.On)
         {
             Logging.PrintInfo(Logging.HttpListener, this, SR.GetString("net_log_listener_no_spn_disabled"));
         }
         return true;
     }
     if (ScenarioChecksChannelBinding(isSecureConnection, policy.ProtectionScenario))
     {
         if (Logging.On)
         {
             Logging.PrintInfo(Logging.HttpListener, this, SR.GetString("net_log_listener_no_spn_cbt"));
         }
         return true;
     }
     if (!AuthenticationManager.OSSupportsExtendedProtection)
     {
         if (Logging.On)
         {
             Logging.PrintInfo(Logging.HttpListener, this, SR.GetString("net_log_listener_no_spn_platform"));
         }
         return true;
     }
     string clientSpecifiedSpn = context.ClientSpecifiedSpn;
     if (string.IsNullOrEmpty(clientSpecifiedSpn))
     {
         if (policy.PolicyEnforcement == PolicyEnforcement.WhenSupported)
         {
             if (Logging.On)
             {
                 Logging.PrintInfo(Logging.HttpListener, this, SR.GetString("net_log_listener_no_spn_whensupported"));
             }
             return true;
         }
         if (Logging.On)
         {
             Logging.PrintInfo(Logging.HttpListener, this, SR.GetString("net_log_listener_spn_failed_always"));
         }
         return false;
     }
     if (string.Compare(clientSpecifiedSpn, "http/localhost", StringComparison.OrdinalIgnoreCase) == 0)
     {
         if (Logging.On)
         {
             Logging.PrintInfo(Logging.HttpListener, this, SR.GetString("net_log_listener_no_spn_loopback"));
         }
         return true;
     }
     if (Logging.On)
     {
         Logging.PrintInfo(Logging.HttpListener, this, SR.GetString("net_log_listener_spn", new object[] { clientSpecifiedSpn }));
     }
     ServiceNameCollection serviceNames = this.GetServiceNames(policy);
     bool flag = false;
     foreach (string str2 in serviceNames)
     {
         if (string.Compare(clientSpecifiedSpn, str2, StringComparison.OrdinalIgnoreCase) == 0)
         {
             flag = true;
             if (Logging.On)
             {
                 Logging.PrintInfo(Logging.HttpListener, this, SR.GetString("net_log_listener_spn_passed"));
             }
             break;
         }
     }
     if (Logging.On && !flag)
     {
         Logging.PrintInfo(Logging.HttpListener, this, SR.GetString("net_log_listener_spn_failed"));
         if (serviceNames.Count == 0)
         {
             Logging.PrintWarning(Logging.HttpListener, this, "CheckSpn", SR.GetString("net_log_listener_spn_failed_empty"));
             return flag;
         }
         Logging.PrintInfo(Logging.HttpListener, this, SR.GetString("net_log_listener_spn_failed_dump"));
         foreach (string str3 in serviceNames)
         {
             Logging.PrintInfo(Logging.HttpListener, this, "\t" + str3);
         }
     }
     return flag;
 }
        internal HttpListenerContext HandleAuthentication(RequestContextBase memoryBlob, out bool stoleBlob)
        {
            if (NetEventSource.IsEnabled) NetEventSource.Info(this, "HandleAuthentication() memoryBlob:0x" + ((IntPtr)memoryBlob.RequestBlob).ToString("x"));

            string challenge = null;
            stoleBlob = false;

            // Some things we need right away.  Lift them out now while it's convenient.
            string verb = Interop.HttpApi.GetVerb(memoryBlob.RequestBlob);
            string authorizationHeader = Interop.HttpApi.GetKnownHeader(memoryBlob.RequestBlob, (int)HttpRequestHeader.Authorization);
            ulong connectionId = memoryBlob.RequestBlob->ConnectionId;
            ulong requestId = memoryBlob.RequestBlob->RequestId;
            bool isSecureConnection = memoryBlob.RequestBlob->pSslInfo != null;

            if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"HandleAuthentication() authorizationHeader: ({authorizationHeader})");

            // if the app has turned on AuthPersistence, an anonymous request might
            // be authenticated by virtue of it coming on a connection that was
            // previously authenticated.
            // assurance that we do this only for NTLM/Negotiate is not here, but in the
            // code that caches WindowsIdentity instances in the Dictionary.
            DisconnectAsyncResult disconnectResult;
            DisconnectResults.TryGetValue(connectionId, out disconnectResult);
            if (UnsafeConnectionNtlmAuthentication)
            {
                if (authorizationHeader == null)
                {
                    WindowsPrincipal principal = disconnectResult?.AuthenticatedConnection;
                    if (principal != null)
                    {
                        if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Principal: {principal} principal.Identity.Name: {principal.Identity.Name} creating request");
                        stoleBlob = true;
                        HttpListenerContext ntlmContext = new HttpListenerContext(this, memoryBlob);
                        ntlmContext.SetIdentity(principal, null);
                        ntlmContext.Request.ReleasePins();
                        return ntlmContext;
                    }
                }
                else
                {
                    // They sent an authorization - destroy their previous credentials.
                    if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Clearing principal cache");
                    if (disconnectResult != null)
                    {
                        disconnectResult.AuthenticatedConnection = null;
                    }
                }
            }

            // Figure out what schemes we're allowing, what context we have.
            stoleBlob = true;
            HttpListenerContext httpContext = null;
            NTAuthentication oldContext = null;
            NTAuthentication newContext = null;
            NTAuthentication context = null;
            AuthenticationSchemes headerScheme = AuthenticationSchemes.None;
            AuthenticationSchemes authenticationScheme = AuthenticationSchemes;
            ExtendedProtectionPolicy extendedProtectionPolicy = _extendedProtectionPolicy;
            try
            {
                // Take over handling disconnects for now.
                if (disconnectResult != null && !disconnectResult.StartOwningDisconnectHandling())
                {
                    // Just disconnected just then.  Pretend we didn't see the disconnectResult.
                    disconnectResult = null;
                }

                // Pick out the old context now.  By default, it'll be removed in the finally, unless context is set somewhere. 
                if (disconnectResult != null)
                {
                    oldContext = disconnectResult.Session;
                }

                httpContext = new HttpListenerContext(this, memoryBlob);

                AuthenticationSchemeSelector authenticationSelector = _authenticationDelegate;
                if (authenticationSelector != null)
                {
                    try
                    {
                        httpContext.Request.ReleasePins();
                        authenticationScheme = authenticationSelector(httpContext.Request);
                        // Cache the results of authenticationSelector (if any)
                        httpContext.AuthenticationSchemes = authenticationScheme;
                        if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"AuthenticationScheme: {authenticationScheme}");
                    }
                    catch (Exception exception) when (!ExceptionCheck.IsFatal(exception))
                    {
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Error(this, SR.Format(SR.net_log_listener_delegate_exception, exception));
                            NetEventSource.Info(this, $"authenticationScheme: {authenticationScheme}");
                        }
                        SendError(requestId, HttpStatusCode.InternalServerError, null);
                        httpContext.Close();
                        return null;
                    }
                }
                else
                {
                    // We didn't give the request to the user yet, so we haven't lost control of the unmanaged blob and can
                    // continue to reuse the buffer.
                    stoleBlob = false;
                }

                ExtendedProtectionSelector extendedProtectionSelector = _extendedProtectionSelectorDelegate;
                if (extendedProtectionSelector != null)
                {
                    extendedProtectionPolicy = extendedProtectionSelector(httpContext.Request);

                    if (extendedProtectionPolicy == null)
                    {
                        extendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Never);
                    }
                    // Cache the results of extendedProtectionSelector (if any)
                    httpContext.ExtendedProtectionPolicy = extendedProtectionPolicy;
                }

                // Then figure out what scheme they're trying (if any are allowed)
                int index = -1;
                if (authorizationHeader != null && (authenticationScheme & ~AuthenticationSchemes.Anonymous) != AuthenticationSchemes.None)
                {
                    // Find the end of the scheme name.  Trust that HTTP.SYS parsed out just our header ok.
                    for (index = 0; index < authorizationHeader.Length; index++)
                    {
                        if (authorizationHeader[index] == ' ' || authorizationHeader[index] == '\t' ||
                            authorizationHeader[index] == '\r' || authorizationHeader[index] == '\n')
                        {
                            break;
                        }
                    }

                    // Currently only allow one Authorization scheme/header per request.
                    if (index < authorizationHeader.Length)
                    {
                        if ((authenticationScheme & AuthenticationSchemes.Negotiate) != AuthenticationSchemes.None &&
                            string.Compare(authorizationHeader, 0, AuthenticationTypes.Negotiate, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            headerScheme = AuthenticationSchemes.Negotiate;
                        }
                        else if ((authenticationScheme & AuthenticationSchemes.Ntlm) != AuthenticationSchemes.None &&
                            string.Compare(authorizationHeader, 0, AuthenticationTypes.NTLM, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            headerScheme = AuthenticationSchemes.Ntlm;
                        }
                        else if ((authenticationScheme & AuthenticationSchemes.Basic) != AuthenticationSchemes.None &&
                            string.Compare(authorizationHeader, 0, AuthenticationTypes.Basic, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            headerScheme = AuthenticationSchemes.Basic;
                        }
                        else
                        {
                            if (NetEventSource.IsEnabled) NetEventSource.Error(this, SR.Format(SR.net_log_listener_unsupported_authentication_scheme, authorizationHeader, authenticationScheme));
                        }
                    }
                }

                // httpError holds the error we will return if an Authorization header is present but can't be authenticated
                HttpStatusCode httpError = HttpStatusCode.InternalServerError;
                bool error = false;

                // See if we found an acceptable auth header
                if (headerScheme == AuthenticationSchemes.None)
                {
                    if (NetEventSource.IsEnabled) NetEventSource.Error(this, SR.Format(SR.net_log_listener_unmatched_authentication_scheme, authenticationScheme.ToString(), (authorizationHeader == null ? "<null>" : authorizationHeader)));

                    // If anonymous is allowed, just return the context.  Otherwise go for the 401.
                    if ((authenticationScheme & AuthenticationSchemes.Anonymous) != AuthenticationSchemes.None)
                    {
                        if (!stoleBlob)
                        {
                            stoleBlob = true;
                            httpContext.Request.ReleasePins();
                        }
                        return httpContext;
                    }

                    httpError = HttpStatusCode.Unauthorized;
                    httpContext.Request.DetachBlob(memoryBlob);
                    httpContext.Close();
                    httpContext = null;
                }
                else
                {
                    // Perform Authentication
                    byte[] bytes = null;
                    byte[] decodedOutgoingBlob = null;
                    string outBlob = null;

                    // Find the beginning of the blob.  Trust that HTTP.SYS parsed out just our header ok.
                    for (index++; index < authorizationHeader.Length; index++)
                    {
                        if (authorizationHeader[index] != ' ' && authorizationHeader[index] != '\t' &&
                            authorizationHeader[index] != '\r' && authorizationHeader[index] != '\n')
                        {
                            break;
                        }
                    }
                    string inBlob = index < authorizationHeader.Length ? authorizationHeader.Substring(index) : "";

                    IPrincipal principal = null;
                    SecurityStatusPal statusCodeNew;
                    ChannelBinding binding;
                    if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Performing Authentication headerScheme: {headerScheme}");
                    switch (headerScheme)
                    {
                        case AuthenticationSchemes.Negotiate:
                        case AuthenticationSchemes.Ntlm:
                            if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"context: {oldContext} for connectionId: {connectionId}");

                            string package = headerScheme == AuthenticationSchemes.Ntlm ? NegotiationInfoClass.NTLM : NegotiationInfoClass.Negotiate;
                            if (oldContext != null && oldContext.Package == package)
                            {
                                context = oldContext;
                            }
                            else
                            {
                                binding = GetChannelBinding(connectionId, isSecureConnection, extendedProtectionPolicy);
                                ContextFlagsPal contextFlags = GetContextFlags(extendedProtectionPolicy, isSecureConnection);
                                context = new NTAuthentication(true, package, CredentialCache.DefaultNetworkCredentials, null, contextFlags, binding);
                            }

                            try
                            {
                                bytes = Convert.FromBase64String(inBlob);
                            }
                            catch (FormatException)
                            {
                                if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"FormatException from FormBase64String");
                                httpError = HttpStatusCode.BadRequest;
                                error = true;
                            }
                            if (!error)
                            {
                                decodedOutgoingBlob = context.GetOutgoingBlob(bytes, false, out statusCodeNew);
                                if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"GetOutgoingBlob returned IsCompleted: {context.IsCompleted} and statusCodeNew: {statusCodeNew}");
                                error = !context.IsValidContext;
                                if (error)
                                {
                                    // SSPI Workaround
                                    // If a client sends up a blob on the initial request, Negotiate returns SEC_E_INVALID_HANDLE
                                    // when it should return SEC_E_INVALID_TOKEN.
                                    if (statusCodeNew.ErrorCode == SecurityStatusPalErrorCode.InvalidHandle && oldContext == null && bytes != null && bytes.Length > 0)
                                    {
                                        statusCodeNew = new SecurityStatusPal(SecurityStatusPalErrorCode.InvalidToken);
                                    }

                                    httpError = HttpStatusFromSecurityStatus(statusCodeNew.ErrorCode);
                                }
                            }

                            if (decodedOutgoingBlob != null)
                            {
                                outBlob = Convert.ToBase64String(decodedOutgoingBlob);
                            }

                            if (!error)
                            {
                                if (context.IsCompleted)
                                {
                                    SecurityContextTokenHandle userContext = null;
                                    try
                                    {
                                        if (!CheckSpn(context, isSecureConnection, extendedProtectionPolicy))
                                        {
                                            httpError = HttpStatusCode.Unauthorized;
                                        }
                                        else
                                        {
                                            httpContext.Request.ServiceName = context.ClientSpecifiedSpn;

                                            SafeDeleteContext securityContext = context.GetContext(out statusCodeNew);
                                            if (statusCodeNew.ErrorCode != SecurityStatusPalErrorCode.OK)
                                            {
                                                if (NetEventSource.IsEnabled)
                                                {
                                                    NetEventSource.Info(this,
                                                        $"HandleAuthentication GetContextToken failed with statusCodeNew: {statusCodeNew}");
                                                }

                                                httpError = HttpStatusFromSecurityStatus(statusCodeNew.ErrorCode);
                                            }
                                            else
                                            {
                                                SSPIWrapper.QuerySecurityContextToken(GlobalSSPI.SSPIAuth, securityContext, out userContext);

                                                if (NetEventSource.IsEnabled)
                                                {
                                                    NetEventSource.Info(this,
                                                        $"HandleAuthentication creating new WindowsIdentity from user context: {userContext.DangerousGetHandle().ToString("x8")}");
                                                }

                                                WindowsPrincipal windowsPrincipal = new WindowsPrincipal(
                                                    new WindowsIdentity(userContext.DangerousGetHandle(), context.ProtocolName));

                                                principal = windowsPrincipal;
                                                // if appropriate, cache this credential on this connection
                                                if (UnsafeConnectionNtlmAuthentication && context.ProtocolName == NegotiationInfoClass.NTLM)
                                                {
                                                    if (NetEventSource.IsEnabled)
                                                    {
                                                        NetEventSource.Info(this,
                                                            $"HandleAuthentication inserting principal: {principal} for connectionId: {connectionId}");
                                                    }

                                                    // We may need to call WaitForDisconnect.
                                                    if (disconnectResult == null)
                                                    {
                                                        RegisterForDisconnectNotification(connectionId, ref disconnectResult);
                                                    }
                                                    if (disconnectResult != null)
                                                    {
                                                        lock ((DisconnectResults as ICollection).SyncRoot)
                                                        {
                                                            if (UnsafeConnectionNtlmAuthentication)
                                                            {
                                                                disconnectResult.AuthenticatedConnection = windowsPrincipal;
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        // Registration failed - UnsafeConnectionNtlmAuthentication ignored.
                                                        if (NetEventSource.IsEnabled)
                                                        {
                                                            NetEventSource.Info(this, $"HandleAuthentication RegisterForDisconnectNotification failed.");
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    finally
                                    {
                                        if (userContext != null)
                                        {
                                            userContext.Close();
                                        }
                                    }
                                }
                                else
                                {
                                    // auth incomplete
                                    newContext = context;

                                    challenge = (headerScheme == AuthenticationSchemes.Ntlm ? NegotiationInfoClass.NTLM : NegotiationInfoClass.Negotiate);
                                    if (!String.IsNullOrEmpty(outBlob))
                                    {
                                        challenge += " " + outBlob;
                                    }
                                }
                            }
                            break;

                        case AuthenticationSchemes.Basic:
                            try
                            {
                                bytes = Convert.FromBase64String(inBlob);

                                inBlob = WebHeaderEncoding.GetString(bytes, 0, bytes.Length);
                                index = inBlob.IndexOf(':');

                                if (index != -1)
                                {
                                    string userName = inBlob.Substring(0, index);
                                    string password = inBlob.Substring(index + 1);
                                    if (NetEventSource.IsEnabled)
                                    {
                                        NetEventSource.Info(this, $"Basic Identity found, userName: {userName}");
                                    }

                                    principal = new GenericPrincipal(new HttpListenerBasicIdentity(userName, password), null);
                                }
                                else
                                {
                                    httpError = HttpStatusCode.BadRequest;
                                }
                            }
                            catch (FormatException)
                            {
                                if (NetEventSource.IsEnabled)
                                {
                                    NetEventSource.Info(this, $"FromBase64String threw a FormatException.");
                                }
                            }
                            break;
                    }

                    if (principal != null)
                    {
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Info(this, $"Got principal: {principal}, IdentityName: {principal.Identity.Name} for creating request.");
                        }

                        httpContext.SetIdentity(principal, outBlob);
                    }
                    else
                    {
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Info(this, "Handshake has failed.");
                        }

                        httpContext.Request.DetachBlob(memoryBlob);
                        httpContext.Close();
                        httpContext = null;
                    }
                }

                // if we're not giving a request to the application, we need to send an error
                ArrayList challenges = null;
                if (httpContext == null)
                {
                    // If we already have a challenge, just use it.  Otherwise put a challenge for each acceptable scheme.
                    if (challenge != null)
                    {
                        AddChallenge(ref challenges, challenge);
                    }
                    else
                    {
                        // We're starting over.  Any context SSPI might have wanted us to keep is useless.
                        if (newContext != null)
                        {
                            if (newContext == context)
                            {
                                context = null;
                            }

                            if (newContext != oldContext)
                            {
                                NTAuthentication toClose = newContext;
                                newContext = null;
                                toClose.CloseContext();
                            }
                            else
                            {
                                newContext = null;
                            }
                        }

                        // If we're sending something besides 401, do it here.
                        if (httpError != HttpStatusCode.Unauthorized)
                        {
                            if (NetEventSource.IsEnabled) NetEventSource.Info(this, "ConnectionId:" + connectionId + " because of error:" + httpError.ToString());
                            SendError(requestId, httpError, null);
                            return null;
                        }

                        challenges = BuildChallenge(authenticationScheme, connectionId, out newContext,
                            extendedProtectionPolicy, isSecureConnection);
                    }
                }

                // Check if we need to call WaitForDisconnect, because if we do and it fails, we want to send a 500 instead.
                if (disconnectResult == null && newContext != null)
                {
                    RegisterForDisconnectNotification(connectionId, ref disconnectResult);

                    // Failed - send 500.
                    if (disconnectResult == null)
                    {
                        if (newContext != null)
                        {
                            if (newContext == context)
                            {
                                context = null;
                            }

                            if (newContext != oldContext)
                            {
                                NTAuthentication toClose = newContext;
                                newContext = null;
                                toClose.CloseContext();
                            }
                            else
                            {
                                newContext = null;
                            }
                        }

                        if (NetEventSource.IsEnabled) NetEventSource.Info(this, "connectionId:" + connectionId + " because of failed HttpWaitForDisconnect");
                        SendError(requestId, HttpStatusCode.InternalServerError, null);
                        httpContext.Request.DetachBlob(memoryBlob);
                        httpContext.Close();
                        return null;
                    }
                }

                // Update Session if necessary.
                if (oldContext != newContext)
                {
                    if (oldContext == context)
                    {
                        // Prevent the finally from closing this twice.
                        context = null;
                    }

                    NTAuthentication toClose = oldContext;
                    oldContext = newContext;
                    disconnectResult.Session = newContext;

                    if (toClose != null)
                    {
                        toClose.CloseContext();
                    }
                }

                // Send the 401 here.
                if (httpContext == null)
                {
                    SendError(requestId, challenges != null && challenges.Count > 0 ? HttpStatusCode.Unauthorized : HttpStatusCode.Forbidden, challenges);
                    if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Scheme:" + authenticationScheme);
                    return null;
                }

                if (!stoleBlob)
                {
                    stoleBlob = true;
                    httpContext.Request.ReleasePins();
                }
                return httpContext;
            }
            catch
            {
                if (httpContext != null)
                {
                    httpContext.Request.DetachBlob(memoryBlob);
                    httpContext.Close();
                }
                if (newContext != null)
                {
                    if (newContext == context)
                    {
                        // Prevent the finally from closing this twice.
                        context = null;
                    }

                    if (newContext != oldContext)
                    {
                        NTAuthentication toClose = newContext;
                        newContext = null;
                        toClose.CloseContext();
                    }
                    else
                    {
                        newContext = null;
                    }
                }
                throw;
            }
            finally
            {
                try
                {
                    // Clean up the previous context if necessary.
                    if (oldContext != null && oldContext != newContext)
                    {
                        // Clear out Session if it wasn't already.
                        if (newContext == null && disconnectResult != null)
                        {
                            disconnectResult.Session = null;
                        }

                        oldContext.CloseContext();
                    }

                    // Delete any context created but not stored.
                    if (context != null && oldContext != context && newContext != context)
                    {
                        context.CloseContext();
                    }
                }
                finally
                {
                    // Check if the connection got deleted while in this method, and clear out the hashtables if it did.
                    // In a nested finally because if this doesn't happen, we leak.
                    if (disconnectResult != null)
                    {
                        disconnectResult.FinishOwningDisconnectHandling();
                    }
                }
            }
        }
        private bool CheckSpn(NTAuthentication context, bool isSecureConnection, ExtendedProtectionPolicy policy)
        {
            // Kerberos does SPN check already in ASC
            if (context.IsKerberos)
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, SR.net_log_listener_no_spn_kerberos);
                }
                return true;
            }

            // Don't check the SPN if Extended Protection is off or we already checked the CBT
            if (policy.PolicyEnforcement == PolicyEnforcement.Never)
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, SR.net_log_listener_no_spn_disabled);
                }
                return true;
            }

            if (ScenarioChecksChannelBinding(isSecureConnection, policy.ProtectionScenario))
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, SR.net_log_listener_no_spn_cbt);
                }
                return true;
            }

            string clientSpn = context.ClientSpecifiedSpn;

            // An empty SPN is only allowed in the WhenSupported case
            if (String.IsNullOrEmpty(clientSpn))
            {
                if (policy.PolicyEnforcement == PolicyEnforcement.WhenSupported)
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this,
                            SR.net_log_listener_no_spn_whensupported);
                    }
                    return true;
                }
                else
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this,
                            SR.net_log_listener_spn_failed_always);
                    }
                    return false;
                }
            }
            else if (string.Equals(clientSpn, "http/localhost", StringComparison.OrdinalIgnoreCase))
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, SR.net_log_listener_no_spn_loopback);
                }

                return true;
            }
            else
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, SR.net_log_listener_spn, clientSpn);
                }

                ServiceNameCollection serviceNames = GetServiceNames(policy);

                bool found = serviceNames.Contains(clientSpn);

                if (NetEventSource.IsEnabled)
                {
                    if (found)
                    {
                        NetEventSource.Info(this, SR.net_log_listener_spn_passed);
                    }
                    else
                    {
                        NetEventSource.Info(this, SR.net_log_listener_spn_failed);

                        if (serviceNames.Count == 0)
                        {
                            if (NetEventSource.IsEnabled)
                            {
                                NetEventSource.Info(this, SR.net_log_listener_spn_failed_empty);
                            }
                        }
                        else
                        {
                            NetEventSource.Info(this, SR.net_log_listener_spn_failed_dump);

                            foreach (string serviceName in serviceNames)
                            {
                                NetEventSource.Info(this, "\t" + serviceName);
                            }
                        }
                    }
                }

                return found;
            }
        }
 internal void ValidateCreateContext(string package, bool isServer, NetworkCredential credential, string servicePrincipalName, ChannelBinding channelBinding, ProtectionLevel protectionLevel, TokenImpersonationLevel impersonationLevel)
 {
     if ((this._Exception != null) && !this._CanRetryAuthentication)
     {
         throw this._Exception;
     }
     if ((this._Context != null) && this._Context.IsValidContext)
     {
         throw new InvalidOperationException(SR.GetString("net_auth_reauth"));
     }
     if (credential == null)
     {
         throw new ArgumentNullException("credential");
     }
     if (servicePrincipalName == null)
     {
         throw new ArgumentNullException("servicePrincipalName");
     }
     if (ComNetOS.IsWin9x && (protectionLevel != ProtectionLevel.None))
     {
         throw new NotSupportedException(SR.GetString("net_auth_no_protection_on_win9x"));
     }
     if (((impersonationLevel != TokenImpersonationLevel.Identification) && (impersonationLevel != TokenImpersonationLevel.Impersonation)) && (impersonationLevel != TokenImpersonationLevel.Delegation))
     {
         throw new ArgumentOutOfRangeException("impersonationLevel", impersonationLevel.ToString(), SR.GetString("net_auth_supported_impl_levels"));
     }
     if ((this._Context != null) && (this.IsServer != isServer))
     {
         throw new InvalidOperationException(SR.GetString("net_auth_client_server"));
     }
     this._Exception = null;
     this._RemoteOk = false;
     this._Framer = new StreamFramer(this._InnerStream);
     this._Framer.WriteHeader.MessageId = 0x16;
     this._ExpectedProtectionLevel = protectionLevel;
     this._ExpectedImpersonationLevel = isServer ? impersonationLevel : TokenImpersonationLevel.None;
     this._WriteSequenceNumber = 0;
     this._ReadSequenceNumber = 0;
     ContextFlags connection = ContextFlags.Connection;
     if ((protectionLevel == ProtectionLevel.None) && !isServer)
     {
         package = "NTLM";
     }
     else if (protectionLevel == ProtectionLevel.EncryptAndSign)
     {
         connection |= ContextFlags.Confidentiality;
     }
     else if (protectionLevel == ProtectionLevel.Sign)
     {
         connection |= ContextFlags.AcceptStream | ContextFlags.SequenceDetect | ContextFlags.ReplayDetect;
     }
     if (isServer)
     {
         if (this._ExtendedProtectionPolicy.PolicyEnforcement == PolicyEnforcement.WhenSupported)
         {
             connection |= ContextFlags.AllowMissingBindings;
         }
         if ((this._ExtendedProtectionPolicy.PolicyEnforcement != PolicyEnforcement.Never) && (this._ExtendedProtectionPolicy.ProtectionScenario == ProtectionScenario.TrustedProxy))
         {
             connection |= ContextFlags.ProxyBindings;
         }
     }
     else
     {
         if (protectionLevel != ProtectionLevel.None)
         {
             connection |= ContextFlags.MutualAuth;
         }
         if (impersonationLevel == TokenImpersonationLevel.Identification)
         {
             connection |= ContextFlags.AcceptIntegrity;
         }
         if (impersonationLevel == TokenImpersonationLevel.Delegation)
         {
             connection |= ContextFlags.Delegate;
         }
     }
     this._CanRetryAuthentication = false;
     if (!(credential is SystemNetworkCredential))
     {
         ExceptionHelper.ControlPrincipalPermission.Demand();
     }
     try
     {
         this._Context = new NTAuthentication(isServer, package, credential, servicePrincipalName, connection, channelBinding);
     }
     catch (Win32Exception exception)
     {
         throw new AuthenticationException(SR.GetString("net_auth_SSPI"), exception);
     }
 }
 private Authorization DoAuthenticate(string challenge, WebRequest webRequest, ICredentials credentials, bool preAuthenticate)
 {
     if (credentials == null)
     {
         return null;
     }
     HttpWebRequest request = webRequest as HttpWebRequest;
     NTAuthentication securityContext = null;
     string incomingBlob = null;
     if (!preAuthenticate)
     {
         int index = AuthenticationManager.FindSubstringNotInQuotes(challenge, Signature);
         if (index < 0)
         {
             return null;
         }
         int startIndex = index + SignatureSize;
         if ((challenge.Length > startIndex) && (challenge[startIndex] != ','))
         {
             startIndex++;
         }
         else
         {
             index = -1;
         }
         if ((index >= 0) && (challenge.Length > startIndex))
         {
             index = challenge.IndexOf(',', startIndex);
             if (index != -1)
             {
                 incomingBlob = challenge.Substring(startIndex, index - startIndex);
             }
             else
             {
                 incomingBlob = challenge.Substring(startIndex);
             }
         }
         securityContext = request.CurrentAuthenticationState.GetSecurityContext(this);
     }
     if (securityContext == null)
     {
         NetworkCredential credential = credentials.GetCredential(request.ChallengedUri, Signature);
         if ((credential == null) || (!(credential is SystemNetworkCredential) && (credential.InternalGetUserName().Length == 0)))
         {
             return null;
         }
         ICredentialPolicy credentialPolicy = AuthenticationManager.CredentialPolicy;
         if ((credentialPolicy != null) && !credentialPolicy.ShouldSendCredential(request.ChallengedUri, request, credential, this))
         {
             return null;
         }
         string computeSpn = request.CurrentAuthenticationState.GetComputeSpn(request);
         ChannelBinding channelBinding = null;
         if (request.CurrentAuthenticationState.TransportContext != null)
         {
             channelBinding = request.CurrentAuthenticationState.TransportContext.GetChannelBinding(ChannelBindingKind.Endpoint);
         }
         securityContext = new NTAuthentication("Kerberos", credential, computeSpn, request, channelBinding);
         request.CurrentAuthenticationState.SetSecurityContext(securityContext, this);
     }
     string outgoingBlob = securityContext.GetOutgoingBlob(incomingBlob);
     if (outgoingBlob == null)
     {
         return null;
     }
     return new Authorization("Kerberos " + outgoingBlob, securityContext.IsCompleted, string.Empty, securityContext.IsMutualAuthFlag);
 }
 private string GetSecurityLayerOutgoingBlob(string challenge, NTAuthentication clientContext)
 {
     int num;
     if (challenge == null)
     {
         return null;
     }
     byte[] buffer = Convert.FromBase64String(challenge);
     try
     {
         num = clientContext.VerifySignature(buffer, 0, buffer.Length);
     }
     catch (Win32Exception)
     {
         return null;
     }
     if (((num < 4) || (buffer[0] != 1)) || (((buffer[1] != 0) || (buffer[2] != 0)) || (buffer[3] != 0)))
     {
         return null;
     }
     byte[] output = null;
     try
     {
         num = clientContext.MakeSignature(buffer, 0, 4, ref output);
     }
     catch (Win32Exception)
     {
         return null;
     }
     return Convert.ToBase64String(output, 0, num);
 }
 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();
         }
     }
 }
        // Function for SASL security layer negotiation after
        // authorization completes.   
        //
        // Returns null for failure, Base64 encoded string on
        // success.
        private string GetSecurityLayerOutgoingBlob(
                            string challenge, 
                            NTAuthentication clientContext) {

            // must have a security layer challenge

            if (challenge == null) 
                return null;

            // "unwrap" challenge

            byte[] input = Convert.FromBase64String(challenge);

            int len;

            try {
                len = clientContext.VerifySignature(input, 0, input.Length);
            }
            catch (Win32Exception) {
                // any decrypt failure is an auth failure
                return null;
            }

            // Per RFC 2222 Section 7.2.2:
            //   the client should then expect the server to issue a 
            //   token in a subsequent challenge.  The client passes
            //   this token to GSS_Unwrap and interprets the first 
            //   octet of cleartext as a bit-mask specifying the 
            //   security layers supported by the server and the 
            //   second through fourth octets as the maximum size 
            //   output_message to send to the server.   
            // Section 7.2.3
            //   The security layer and their corresponding bit-masks
            //   are as follows:
            //     1 No security layer
            //     2 Integrity protection
            //       Sender calls GSS_Wrap with conf_flag set to FALSE
            //     4 Privacy protection
            //       Sender calls GSS_Wrap with conf_flag set to TRUE
            //
            // Exchange 2007 and our client only support 
            // "No security layer". Therefore verify first byte is value 1
            // and the 2nd-4th bytes are value zero since token size is not
            // applicable when there is no security layer.

            if (len < 4 ||          // expect 4 bytes
                input[0] != 1 ||    // first value 1
                input[1] != 0 ||    // rest value 0
                input[2] != 0 || 
                input[3] != 0) {
                return null;                
            }

            // Continuing with RFC 2222 section 7.2.2:
            //   The client then constructs data, with the first octet 
            //   containing the bit-mask specifying the selected security
            //   layer, the second through fourth octets containing in 
            //   network byte order the maximum size output_message the client
            //   is able to receive, and the remaining octets containing the
            //   authorization identity.  
            // 
            // So now this contructs the "wrapped" response.  The response is
            // payload is identical to the received server payload and the 
            // "authorization identity" is not supplied as it is unnecessary.

            // let MakeSignature figure out length of output
            byte[] output = null; 
            try {
                len = clientContext.MakeSignature(input, 0, 4, ref output); 
            }
            catch (Win32Exception) {
                // any decrypt failure is an auth failure
                return null;
            }

            // return Base64 encoded string of signed payload
            return Convert.ToBase64String(output, 0, len); 
        }
 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;
 }
        public Authorization Authenticate(string challenge, NetworkCredential credential, object sessionCookie, string spn, ChannelBinding channelBindingToken)
        {
            if(Logging.On)Logging.Enter(Logging.Web, this, "Authenticate", null);
            try {
                lock (this.sessions)
                {

                    NTAuthentication clientContext = this.sessions[sessionCookie] as NTAuthentication;
                    
                    if (clientContext == null)
                    {
                        if(credential == null){
                            return null;
                        }

                        this.sessions[sessionCookie] =
                            clientContext =
                            new NTAuthentication(false, "Negotiate", credential, spn,
                                                 ContextFlags.Connection | ContextFlags.InitIntegrity, channelBindingToken);
                    }
                    byte[] byteResp; 
                    string resp = null;
                    
                    if (!clientContext.IsCompleted) {

                        // If auth is not yet completed keep producing
                        // challenge responses with GetOutgoingBlob

                        SecurityStatus statusCode;
                        byte[] decodedChallenge = null;
                        if (challenge != null) {
                            decodedChallenge = 
                                Convert.FromBase64String(challenge);
                        }
                        byteResp = clientContext.GetOutgoingBlob(
                                                    decodedChallenge, 
                                                    false,
                                                    out statusCode);
                        // Note sure why this is here...keeping it.
                        if (clientContext.IsCompleted && byteResp == null) {
                            resp = "\r\n";
                        }
                        if (byteResp != null) {
                            resp = Convert.ToBase64String(byteResp);
                        }                        
                    } else {
                    
                        // If auth completed and still have a challenge then
                        // server may be doing "correct" form of GSSAPI SASL.
                        // Validate incoming and produce outgoing SASL security 
                        // layer negotiate message.
                    
                        resp = GetSecurityLayerOutgoingBlob(
                                    challenge,
                                    clientContext);
                    }

                    return new Authorization(resp, clientContext.IsCompleted);
                }
            }
            finally {
                if(Logging.On)Logging.Exit(Logging.Web, this, "Authenticate", null);
            }
        }
        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 Authorization DoAuthenticate(string challenge, WebRequest webRequest, ICredentials credentials, bool preAuthenticate)
 {
     if (credentials == null)
     {
         return null;
     }
     HttpWebRequest request = webRequest as HttpWebRequest;
     NTAuthentication securityContext = null;
     string incomingBlob = null;
     bool flag = false;
     if (!preAuthenticate)
     {
         int signatureIndex = GetSignatureIndex(challenge, out flag);
         if (signatureIndex < 0)
         {
             return null;
         }
         int startIndex = signatureIndex + (flag ? "nego2".Length : "negotiate".Length);
         if ((challenge.Length > startIndex) && (challenge[startIndex] != ','))
         {
             startIndex++;
         }
         else
         {
             signatureIndex = -1;
         }
         if ((signatureIndex >= 0) && (challenge.Length > startIndex))
         {
             signatureIndex = challenge.IndexOf(',', startIndex);
             if (signatureIndex != -1)
             {
                 incomingBlob = challenge.Substring(startIndex, signatureIndex - startIndex);
             }
             else
             {
                 incomingBlob = challenge.Substring(startIndex);
             }
         }
         securityContext = request.CurrentAuthenticationState.GetSecurityContext(this);
     }
     if (securityContext == null)
     {
         NetworkCredential credential = credentials.GetCredential(request.ChallengedUri, "negotiate");
         if ((credential == null) || (!(credential is SystemNetworkCredential) && (credential.InternalGetUserName().Length == 0)))
         {
             return null;
         }
         ICredentialPolicy credentialPolicy = AuthenticationManager.CredentialPolicy;
         if ((credentialPolicy != null) && !credentialPolicy.ShouldSendCredential(request.ChallengedUri, request, credential, this))
         {
             return null;
         }
         string computeSpn = request.CurrentAuthenticationState.GetComputeSpn(request);
         ChannelBinding channelBinding = null;
         if (request.CurrentAuthenticationState.TransportContext != null)
         {
             channelBinding = request.CurrentAuthenticationState.TransportContext.GetChannelBinding(ChannelBindingKind.Endpoint);
         }
         securityContext = new NTAuthentication("Negotiate", credential, computeSpn, request, channelBinding);
         request.CurrentAuthenticationState.SetSecurityContext(securityContext, this);
     }
     string outgoingBlob = securityContext.GetOutgoingBlob(incomingBlob);
     if (outgoingBlob == null)
     {
         return null;
     }
     bool unsafeOrProxyAuthenticatedConnectionSharing = request.UnsafeOrProxyAuthenticatedConnectionSharing;
     if (unsafeOrProxyAuthenticatedConnectionSharing)
     {
         request.LockConnection = true;
     }
     request.NtlmKeepAlive = ((incomingBlob == null) && securityContext.IsValidContext) && !securityContext.IsKerberos;
     return AuthenticationManager.GetGroupAuthorization(this, (flag ? "Nego2" : "Negotiate") + " " + outgoingBlob, securityContext.IsCompleted, securityContext, unsafeOrProxyAuthenticatedConnectionSharing, securityContext.IsKerberos);
 }
Exemple #23
0
        // On Windows XP and up, WDigest.dll supports the Digest authentication scheme (in addition to
        // support for HTTP client sides, it also supports HTTP server side and SASL) through SSPI.

        private Authorization XPDoAuthenticate(string challenge, HttpWebRequest httpWebRequest, ICredentials credentials, bool preAuthenticate) {
            GlobalLog.Print("DigestClient::XPDoAuthenticate() challenge:[" + ValidationHelper.ToString(challenge) + "] httpWebRequest#" + ValidationHelper.HashString(httpWebRequest) + " credentials#" + ValidationHelper.HashString(credentials) + " preAuthenticate:" + preAuthenticate.ToString());

            NTAuthentication authSession = null;
            string incoming = null;
            int index;

            if (!preAuthenticate) {
                index = AuthenticationManager.FindSubstringNotInQuotes(challenge, Signature);
                if (index < 0) {
                    return null;
                }
                authSession = httpWebRequest.CurrentAuthenticationState.GetSecurityContext(this);
                GlobalLog.Print("DigestClient::XPDoAuthenticate() key:" + ValidationHelper.HashString(httpWebRequest.CurrentAuthenticationState) + " retrieved authSession:" + ValidationHelper.HashString(authSession));
                incoming = RefineDigestChallenge(challenge, index);
            }
            else {
#if WDIGEST_PREAUTH
                GlobalLog.Print("DigestClient::XPDoAuthenticate() looking up digestChallenge for prefix:" + httpWebRequest.ChallengedUri.AbsoluteUri);
                authSession = challengeCache.Lookup(httpWebRequest.ChallengedUri.AbsoluteUri) as NTAuthentication;
                if (authSession==null) {
                    return null;
                }
#else
                GlobalLog.Print("DigestClient::XPDoAuthenticate() looking up digestChallenge for prefix:" + httpWebRequest.ChallengedUri.AbsoluteUri);
                HttpDigestChallenge digestChallenge = challengeCache.Lookup(httpWebRequest.ChallengedUri.AbsoluteUri) as HttpDigestChallenge;
                if (digestChallenge==null) {
                    return null;
                }

                GlobalLog.Print("DigestClient::XPDoAuthenticate() retrieved digestChallenge#" + ValidationHelper.HashString(digestChallenge) + " digestChallenge for prefix:" + httpWebRequest.ChallengedUri.AbsoluteUri);
                digestChallenge = digestChallenge.CopyAndIncrementNonce();
                digestChallenge.SetFromRequest(httpWebRequest);
                incoming = digestChallenge.ToBlob();
#endif
            }

            UriComponents uriParts = 0;
            Uri remoteUri = httpWebRequest.GetRemoteResourceUri();
            if (httpWebRequest.CurrentMethod.ConnectRequest) {
                uriParts = UriComponents.HostAndPort;
                // Use the orriginal request Uri, not the proxy Uri
                remoteUri = httpWebRequest.RequestUri;
            }
            else {
                uriParts = UriComponents.PathAndQuery;
            }
            // here we use Address instead of ChallengedUri. This is because the
            // Digest hash is generated using the uri as it is present on the wire
            string rawUri = remoteUri.GetParts(uriParts, UriFormat.UriEscaped);
            GlobalLog.Print("DigestClient::XPDoAuthenticate() rawUri:" + ValidationHelper.ToString(rawUri));

            if (authSession==null) {
                NetworkCredential NC = credentials.GetCredential(httpWebRequest.ChallengedUri, Signature);
                GlobalLog.Print("DigestClient::XPDoAuthenticate() GetCredential() returns:" + ValidationHelper.ToString(NC));

                if (NC == null || (!(NC is SystemNetworkCredential) && NC.InternalGetUserName().Length == 0))
                {
                    return null;
                }

                ICredentialPolicy policy = AuthenticationManager.CredentialPolicy;
                if (policy != null && !policy.ShouldSendCredential(httpWebRequest.ChallengedUri, httpWebRequest, NC, this))
                    return null;

                SpnToken spn = httpWebRequest.CurrentAuthenticationState.GetComputeSpn(httpWebRequest);
                GlobalLog.Print("NtlmClient::Authenticate() ChallengedSpn:" + ValidationHelper.ToString(spn));

                ChannelBinding binding = null;
                if (httpWebRequest.CurrentAuthenticationState.TransportContext != null)
                {
                    binding = httpWebRequest.CurrentAuthenticationState.TransportContext.GetChannelBinding(ChannelBindingKind.Endpoint);
                }

                authSession =
                    new NTAuthentication(
                        NegotiationInfoClass.WDigest,
                        NC,
                        spn,
                        httpWebRequest,
                        binding);

                GlobalLog.Print("DigestClient::XPDoAuthenticate() setting SecurityContext for:" + ValidationHelper.HashString(httpWebRequest.CurrentAuthenticationState) + " to authSession:" + ValidationHelper.HashString(authSession));
                httpWebRequest.CurrentAuthenticationState.SetSecurityContext(authSession, this);
            }

            SecurityStatus statusCode;
            string clientResponse;

            GlobalLog.Print("DigestClient::XPDoAuthenticate() incoming:" + ValidationHelper.ToString(incoming));

#if WDIGEST_PREAUTH
            clientResponse = authSession.GetOutgoingDigestBlob(incoming, httpWebRequest.CurrentMethod.Name, rawUri, null, preAuthenticate, true, out statusCode);
#else
            clientResponse = authSession.GetOutgoingDigestBlob(incoming, httpWebRequest.CurrentMethod.Name, rawUri, null, false, false, out statusCode);
#endif
            if (clientResponse == null)
                return null;

            GlobalLog.Print("DigestClient::XPDoAuthenticate() GetOutgoingDigestBlob(" + incoming + ") returns:" + ValidationHelper.ToString(clientResponse));

            Authorization digestResponse = new Authorization(AuthType + " " + clientResponse, authSession.IsCompleted, string.Empty, authSession.IsMutualAuthFlag);

            if (!preAuthenticate && httpWebRequest.PreAuthenticate) {
                // add this to the cache of challenges so we can preauthenticate
                // use this DCR when avaialble to do this without calling HttpDigest.Interpret():
                // 762115   3   WDigest should allow an application to retrieve the parsed domain directive
                HttpDigestChallenge digestChallenge = HttpDigest.Interpret(incoming, -1, httpWebRequest);

                string[] prefixes = digestChallenge.Domain==null ?
                        new string[]{httpWebRequest.ChallengedUri.GetParts(UriComponents.SchemeAndServer, UriFormat.UriEscaped)}
                        : digestChallenge.Domain.Split(singleSpaceArray);

                // If Domain property is not set we associate Digest only with the server Uri namespace (used to do with whole server)
                digestResponse.ProtectionRealm = digestChallenge.Domain==null ? null: prefixes;

                for (int i=0; i<prefixes.Length; i++) {
                    GlobalLog.Print("DigestClient::XPDoAuthenticate() adding authSession#" + ValidationHelper.HashString(authSession) + " for prefix:" + prefixes[i]);
#if WDIGEST_PREAUTH
                    challengeCache.Add(prefixes[i], authSession);
#else
                    challengeCache.Add(prefixes[i], digestChallenge);
#endif
                }
            }
            return digestResponse;
        }
 private Authorization XPDoAuthenticate(string challenge, HttpWebRequest httpWebRequest, ICredentials credentials, bool preAuthenticate)
 {
     NTAuthentication securityContext = null;
     string incomingBlob = null;
     SecurityStatus status;
     if (!preAuthenticate)
     {
         int index = AuthenticationManager.FindSubstringNotInQuotes(challenge, Signature);
         if (index < 0)
         {
             return null;
         }
         securityContext = httpWebRequest.CurrentAuthenticationState.GetSecurityContext(this);
         incomingBlob = RefineDigestChallenge(challenge, index);
     }
     else
     {
         HttpDigestChallenge challenge2 = challengeCache.Lookup(httpWebRequest.ChallengedUri.AbsoluteUri) as HttpDigestChallenge;
         if (challenge2 == null)
         {
             return null;
         }
         challenge2 = challenge2.CopyAndIncrementNonce();
         challenge2.SetFromRequest(httpWebRequest);
         incomingBlob = challenge2.ToBlob();
     }
     UriComponents uriParts = 0;
     if (httpWebRequest.CurrentMethod.ConnectRequest)
     {
         uriParts = UriComponents.HostAndPort;
     }
     else if (httpWebRequest.UsesProxySemantics)
     {
         uriParts = UriComponents.HttpRequestUrl;
     }
     else
     {
         uriParts = UriComponents.PathAndQuery;
     }
     string parts = httpWebRequest.GetRemoteResourceUri().GetParts(uriParts, UriFormat.UriEscaped);
     if (securityContext == null)
     {
         NetworkCredential credential = credentials.GetCredential(httpWebRequest.ChallengedUri, Signature);
         if ((credential == null) || (!(credential is SystemNetworkCredential) && (credential.InternalGetUserName().Length == 0)))
         {
             return null;
         }
         ICredentialPolicy credentialPolicy = AuthenticationManager.CredentialPolicy;
         if ((credentialPolicy != null) && !credentialPolicy.ShouldSendCredential(httpWebRequest.ChallengedUri, httpWebRequest, credential, this))
         {
             return null;
         }
         string computeSpn = httpWebRequest.CurrentAuthenticationState.GetComputeSpn(httpWebRequest);
         ChannelBinding channelBinding = null;
         if (httpWebRequest.CurrentAuthenticationState.TransportContext != null)
         {
             channelBinding = httpWebRequest.CurrentAuthenticationState.TransportContext.GetChannelBinding(ChannelBindingKind.Endpoint);
         }
         securityContext = new NTAuthentication("WDigest", credential, computeSpn, httpWebRequest, channelBinding);
         httpWebRequest.CurrentAuthenticationState.SetSecurityContext(securityContext, this);
     }
     string str4 = securityContext.GetOutgoingDigestBlob(incomingBlob, httpWebRequest.CurrentMethod.Name, parts, null, false, false, out status);
     if (str4 == null)
     {
         return null;
     }
     Authorization authorization = new Authorization("Digest " + str4, securityContext.IsCompleted, string.Empty, securityContext.IsMutualAuthFlag);
     if (!preAuthenticate && httpWebRequest.PreAuthenticate)
     {
         HttpDigestChallenge challenge3 = HttpDigest.Interpret(incomingBlob, -1, httpWebRequest);
         string[] strArray = (challenge3.Domain == null) ? new string[] { httpWebRequest.ChallengedUri.GetParts(UriComponents.SchemeAndServer, UriFormat.UriEscaped) } : challenge3.Domain.Split(singleSpaceArray);
         authorization.ProtectionRealm = (challenge3.Domain == null) ? null : strArray;
         for (int i = 0; i < strArray.Length; i++)
         {
             challengeCache.Add(strArray[i], challenge3);
         }
     }
     return authorization;
 }
Exemple #25
0
        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 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
       }
Exemple #27
0
 internal InitializeCallbackContext(NTAuthentication thisPtr, bool isServer, string package, NetworkCredential credential, string spn, ContextFlagsPal requestedContextFlags, ChannelBinding channelBinding)
 {
     ThisPtr = thisPtr;
     IsServer = isServer;
     Package = package;
     Credential = credential;
     Spn = spn;
     RequestedContextFlags = requestedContextFlags;
     ChannelBinding = channelBinding;
 }
        public static bool Update(string challenge, WebRequest webRequest)
        {
            GlobalLog.Print("XPDigestClient::Update(): " + challenge);

            HttpWebRequest httpWebRequest = webRequest as HttpWebRequest;

            GlobalLog.Assert(httpWebRequest != null, "XPDigestClient::Update() httpWebRequest==null", "");
            if (httpWebRequest == null || httpWebRequest.ChallengedUri == null)
            {
                //
                // there has been no challenge:
                // 1) the request never went on the wire
                // 2) somebody other than us is calling into AuthenticationManager
                //
                GlobalLog.Print("XPDigestClient::Update(): no request. returning true");
                return(true);
            }

            NTAuthentication authSession = sessions[httpWebRequest.CurrentAuthenticationState] as NTAuthentication;

            GlobalLog.Print("XPDigestClient::Update() key:" + ValidationHelper.HashString(httpWebRequest.CurrentAuthenticationState) + " retrieved authSession:" + ValidationHelper.HashString(authSession));
            if (authSession == null)
            {
                return(false);
            }

            int index = challenge == null ? -1 : AuthenticationManager.FindSubstringNotInQuotes(challenge.ToLower(CultureInfo.InvariantCulture), DigestClient.Signature);

            if (index < 0)
            {
                GlobalLog.Print("XPDigestClient::Update(): no challenge. returning true");
                return(true);
            }

            // here's how we know if the handshake is complete when we get the response back,
            // (keeping in mind that we need to support stale credentials):
            // !40X - complete & success
            // 40X & stale=false - complete & failure
            // 40X & stale=true - !complete

            if (httpWebRequest.ResponseStatusCode != httpWebRequest.CurrentAuthenticationState.StatusCodeMatch)
            {
                GlobalLog.Print("XPDigestClient::Update() removing authSession:" + ValidationHelper.HashString(authSession) + " from:" + ValidationHelper.HashString(httpWebRequest.CurrentAuthenticationState));
                sessions.Remove(httpWebRequest.CurrentAuthenticationState);

                GlobalLog.Print("XPDigestClient::Update(): no status code match. returning true");
                return(true);
            }

            int    blobBegin = index + DigestClient.SignatureSize;
            string incoming  = null;

            //
            // there may be multiple challenges. If the next character after the
            // package name is not a comma then it is challenge data
            //
            if (challenge.Length > blobBegin && challenge[blobBegin] != ',')
            {
                ++blobBegin;
            }
            else
            {
                index = -1;
            }
            if (index >= 0 && challenge.Length > blobBegin)
            {
                incoming = challenge.Substring(blobBegin);
            }

            // we should get here only on invalid or stale credentials:

            bool   handshakeComplete;
            string clientResponse = authSession.GetOutgoingDigestBlob(incoming, httpWebRequest.CurrentMethod, out handshakeComplete);

            GlobalLog.Print("XPDigestClient::Update() GetOutgoingDigestBlob(" + incoming + ") returns:" + ValidationHelper.ToString(clientResponse));

            GlobalLog.Assert(handshakeComplete, "XPDigestClient::Update() handshakeComplete==false", "");

            GlobalLog.Print("XPDigestClient::Update() GetOutgoingBlob() returns clientResponse:[" + ValidationHelper.ToString(clientResponse) + "] handshakeComplete:" + handshakeComplete.ToString());

            return(handshakeComplete);
        }
        internal HttpListenerContext HandleAuthentication(RequestContextBase memoryBlob, out bool stoleBlob)
        {
            GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() memoryBlob:0x" + ((IntPtr) memoryBlob.RequestBlob).ToString("x"));

            string challenge = null;
            stoleBlob = false;

            // Some things we need right away.  Lift them out now while it's convenient.
            string verb = UnsafeNclNativeMethods.HttpApi.GetVerb(memoryBlob.RequestBlob);
            string authorizationHeader = UnsafeNclNativeMethods.HttpApi.GetKnownHeader(memoryBlob.RequestBlob, (int) HttpRequestHeader.Authorization);
            ulong connectionId = memoryBlob.RequestBlob->ConnectionId;
            ulong requestId = memoryBlob.RequestBlob->RequestId;
            bool isSecureConnection = memoryBlob.RequestBlob->pSslInfo != null;

            GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() authorizationHeader:" + ValidationHelper.ToString(authorizationHeader));

            // if the app has turned on AuthPersistence, an anonymous request might
            // be authenticated by virtue of it coming on a connection that was
            // previously authenticated.
            // assurance that we do this only for NTLM/Negotiate is not here, but in the
            // code that caches WindowsIdentity instances in the Dictionary.
            DisconnectAsyncResult disconnectResult = (DisconnectAsyncResult) DisconnectResults[connectionId];
            if (UnsafeConnectionNtlmAuthentication)
            {
                if (authorizationHeader == null)
                {
                    WindowsPrincipal principal = disconnectResult == null ? null : disconnectResult.AuthenticatedConnection;
                    if (principal != null)
                    {
                        GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() got principal:" + ValidationHelper.ToString(principal) + " principal.Identity.Name:" + ValidationHelper.ToString(principal.Identity.Name) + " creating request");
                        stoleBlob = true;
                        HttpListenerContext ntlmContext = new HttpListenerContext(this, memoryBlob);
                        ntlmContext.SetIdentity(principal, null);
                        ntlmContext.Request.ReleasePins();
                        return ntlmContext;
                    }
                }
                else
                {
                    // They sent an authorization - destroy their previous credentials.
                    GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() clearing principal cache");
                    if (disconnectResult != null)
                    {
                        disconnectResult.AuthenticatedConnection = null;
                    }
                }
            }

            // Figure out what schemes we're allowing, what context we have.
            stoleBlob = true;
            HttpListenerContext httpContext = null;
            NTAuthentication oldContext = null;
            NTAuthentication newContext = null;
            NTAuthentication context = null;
            AuthenticationSchemes headerScheme = AuthenticationSchemes.None;
            AuthenticationSchemes authenticationScheme = AuthenticationSchemes;
            ExtendedProtectionPolicy extendedProtectionPolicy = m_ExtendedProtectionPolicy;
            try
            {
                // Take over handling disconnects for now.
                if (disconnectResult != null && !disconnectResult.StartOwningDisconnectHandling())
                {
                    // Oops!  Just disconnected just then.  Pretend we didn't see the disconnectResult.
                    disconnectResult = null;
                }

                // Pick out the old context now.  By default, it'll be removed in the finally, unless context is set somewhere. 
                if (disconnectResult != null)
                {
                    oldContext = disconnectResult.Session;
                }

                httpContext = new HttpListenerContext(this, memoryBlob);

                AuthenticationSelectorInfo authenticationSelector = m_AuthenticationDelegate;
                if (authenticationSelector != null)
                {
                    try
                    {
                        httpContext.Request.ReleasePins();
                        authenticationScheme = authenticationSelector.Delegate(httpContext.Request);
                        // Cache the results of authenticationSelector (if any)
                        httpContext.AuthenticationSchemes = authenticationScheme;
                        if (!authenticationSelector.AdvancedAuth &&
                            (authenticationScheme & (AuthenticationSchemes.Negotiate | AuthenticationSchemes.Ntlm | AuthenticationSchemes.Digest)) != 0)
                        {
                            throw m_SecurityException;
                        }
                        GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() AuthenticationSchemeSelectorDelegate() returned authenticationScheme:" + authenticationScheme);
                    }
                    catch (Exception exception)
                    {
                        if (NclUtilities.IsFatal(exception)) throw;

                        if (Logging.On) Logging.PrintError(Logging.HttpListener, this, "HandleAuthentication", SR.GetString(SR.net_log_listener_delegate_exception, exception));
                        GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() AuthenticationSchemeSelectorDelegate() returned authenticationScheme:" + authenticationScheme);
                        SendError(requestId, HttpStatusCode.InternalServerError, null);
                        httpContext.Close();
                        return null;
                    }
                }
                else
                {
                    // We didn't give the request to the user yet, so we haven't lost control of the unmanaged blob and can
                    // continue to reuse the buffer.
                    stoleBlob = false;
                }

                ExtendedProtectionSelector extendedProtectionSelector = m_ExtendedProtectionSelectorDelegate;
                if (extendedProtectionSelector != null) 
                {
                    extendedProtectionPolicy = extendedProtectionSelector(httpContext.Request);

                    if (extendedProtectionPolicy == null) 
                    {
                        extendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Never);
                    }
                    // Cache the results of extendedProtectionSelector (if any)
                    httpContext.ExtendedProtectionPolicy = extendedProtectionPolicy;
                }

                // Then figure out what scheme they're trying (if any are allowed)
                int index = -1;
                if (authorizationHeader != null && (authenticationScheme & ~AuthenticationSchemes.Anonymous) != AuthenticationSchemes.None)
                {
                    // Find the end of the scheme name.  Trust that HTTP.SYS parsed out just our header ok.
                    for (index = 0; index < authorizationHeader.Length; index++)
                    {
                        if (authorizationHeader[index] == ' ' || authorizationHeader[index] == '\t' ||
                            authorizationHeader[index] == '\r' || authorizationHeader[index] == '\n')
                        {
                            break;
                        }
                    }

                    // Currently only allow one Authorization scheme/header per request.
                    if (index < authorizationHeader.Length)
                    {
                        if ((authenticationScheme & AuthenticationSchemes.Negotiate) != AuthenticationSchemes.None &&
                            string.Compare(authorizationHeader, 0, NegotiateClient.AuthType, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            headerScheme = AuthenticationSchemes.Negotiate;
                        }
                        else if ((authenticationScheme & AuthenticationSchemes.Ntlm) != AuthenticationSchemes.None &&
                            string.Compare(authorizationHeader, 0, NtlmClient.AuthType, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            headerScheme = AuthenticationSchemes.Ntlm;
                        }
                        else if ((authenticationScheme & AuthenticationSchemes.Digest) != AuthenticationSchemes.None &&
                            string.Compare(authorizationHeader, 0, DigestClient.AuthType, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            headerScheme = AuthenticationSchemes.Digest;
                        }
                        else if ((authenticationScheme & AuthenticationSchemes.Basic) != AuthenticationSchemes.None &&
                            string.Compare(authorizationHeader, 0, BasicClient.AuthType, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            headerScheme = AuthenticationSchemes.Basic;
                        }
                        else
                        {
                            if (Logging.On) Logging.PrintWarning(Logging.HttpListener, this, "HandleAuthentication", SR.GetString(SR.net_log_listener_unsupported_authentication_scheme, authorizationHeader , authenticationScheme));
                        }
                    }
                }

                // httpError holds the error we will return if an Authorization header is present but can't be authenticated
                HttpStatusCode httpError = HttpStatusCode.InternalServerError;
                bool error = false;

                // See if we found an acceptable auth header
                if (headerScheme == AuthenticationSchemes.None)
                {
                    if (Logging.On) Logging.PrintWarning(Logging.HttpListener, this, "HandleAuthentication", SR.GetString(SR.net_log_listener_unmatched_authentication_scheme, ValidationHelper.ToString(authenticationScheme), (authorizationHeader == null ? "<null>" : authorizationHeader)));

                    // If anonymous is allowed, just return the context.  Otherwise go for the 401.
                    if ((authenticationScheme & AuthenticationSchemes.Anonymous) != AuthenticationSchemes.None)
                    {
                        if (!stoleBlob)
                        {
                            stoleBlob = true;
                            httpContext.Request.ReleasePins();
                        }
                        return httpContext;
                    }

                    httpError = HttpStatusCode.Unauthorized;
                    httpContext.Request.DetachBlob(memoryBlob);
                    httpContext.Close();
                    httpContext = null;
                }
                else
                {
                    // Perform Authentication
                    byte[] bytes = null;
                    byte[] decodedOutgoingBlob = null;
                    string outBlob = null;

                    // Find the beginning of the blob.  Trust that HTTP.SYS parsed out just our header ok.
                    for (index++; index < authorizationHeader.Length; index++)
                    {
                        if (authorizationHeader[index] != ' ' && authorizationHeader[index] != '\t' &&
                            authorizationHeader[index] != '\r' && authorizationHeader[index] != '\n')
                        {
                            break;
                        }
                    }
                    string inBlob = index < authorizationHeader.Length ? authorizationHeader.Substring(index) : "";

                    IPrincipal principal = null;
                    SecurityStatus statusCodeNew;
                    ChannelBinding binding;
                    GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() Performing Authentication headerScheme:" + ValidationHelper.ToString(headerScheme));
                    switch (headerScheme)
                    {
                        case AuthenticationSchemes.Digest:
                            GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() package:WDigest headerScheme:" + headerScheme);

                            // WDigest had some weird behavior.  This is what I have discovered:
                            // Local accounts don't work, only domain accounts.  The domain (i.e. REDMOND) is implied.  Not sure how it is chosen.
                            // If the domain is specified and the credentials are correct, it works.  If they're not (domain, username or password):
                            //      AcceptSecurityContext (GetOutgoingDigestBlob) returns success but with a bogus 4k challenge, and
                            //      QuerySecurityContextToken (GetContextToken) fails with NoImpersonation.
                            // If the domain isn't specified, AcceptSecurityContext returns NoAuthenticatingAuthority for a bad username,
                            // and LogonDenied for a bad password.

                            // Also interesting is that WDigest requires us to keep a reference to the previous context, but fails if we
                            // actually pass it in!  (It't ok to pass it in for the first request, but not if nc > 1.)  For Whidbey,
                            // we create a new context and associate it with the connection, just like NTLM, but instead of using it for
                            // the next request on the connection, we always create a new context and swap the old one out.  As long
                            // as we keep the old one around until after we authenticate with the new one, it works.  For this reason,
                            // we also keep these contexts around past the lifetime of the connection, so that KeepAlive=false works.
                            binding = GetChannelBinding(connectionId, isSecureConnection, extendedProtectionPolicy);

                            context = new NTAuthentication(true, NegotiationInfoClass.WDigest, null,
                                GetContextFlags(extendedProtectionPolicy, isSecureConnection), binding);

                            GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() verb:" + verb + " context.IsValidContext:" + context.IsValidContext.ToString());

                            outBlob = context.GetOutgoingDigestBlob(inBlob, verb, null, Realm, false, false, out statusCodeNew);
                            GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() GetOutgoingDigestBlob() returned IsCompleted:" + context.IsCompleted + " statusCodeNew:" + statusCodeNew + " outBlob:[" + outBlob + "]");

                            // WDigest bug: sometimes when AcceptSecurityContext returns success, it provides a bogus, empty 4k buffer.
                            // Ignore it.  (Should find out what's going on here from WDigest people.)
                            if (statusCodeNew == SecurityStatus.OK)
                            {
                                outBlob = null;
                            }

                            if (context.IsValidContext)
                            {
                                SafeCloseHandle userContext = null;
                                try
                                {
                                    if (!CheckSpn(context, isSecureConnection, extendedProtectionPolicy)) {
                                        httpError = HttpStatusCode.Unauthorized;
                                    }
                                    else {
                                        httpContext.Request.ServiceName = context.ClientSpecifiedSpn;

                                        userContext = context.GetContextToken(out statusCodeNew);
                                        GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() GetContextToken() returned:" + statusCodeNew.ToString());
                                        if (statusCodeNew != SecurityStatus.OK)
                                        {
                                             httpError = HttpStatusFromSecurityStatus(statusCodeNew);
                                        }
                                        else if (userContext == null)
                                        {
                                            GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() error: GetContextToken() returned:null statusCodeNew:" + statusCodeNew.ToString());
                                            httpError = HttpStatusCode.Unauthorized;
                                        }
                                        else
                                        {
                                            GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() creating new WindowsIdentity() from userContext:" + userContext.DangerousGetHandle().ToString("x8"));
                                            principal = new WindowsPrincipal(CreateWindowsIdentity(userContext.DangerousGetHandle(), DigestClient.AuthType, WindowsAccountType.Normal, true));
                                        }
                                    }
                                }
                                finally {
                                    if (userContext!=null) {
                                        userContext.Close();
                                    }
                                }

                                newContext = context;

                                if (outBlob != null)
                                {
                                    challenge = DigestClient.AuthType + " " + outBlob;
                                }
                            }
                            else
                            {
                                httpError = HttpStatusFromSecurityStatus(statusCodeNew);
                            }
                            break;

                        case AuthenticationSchemes.Negotiate:
                        case AuthenticationSchemes.Ntlm:
                            GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() headerScheme:" + headerScheme);
                            GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() returned context#" + ValidationHelper.HashString(oldContext) + " for connectionId:" + connectionId);

                            string package = headerScheme == AuthenticationSchemes.Ntlm ? NtlmClient.AuthType : NegotiateClient.AuthType;
                            if (oldContext != null && oldContext.Package == package)
                            {
                                context = oldContext;
                            }
                            else
                            {
                                binding = GetChannelBinding(connectionId, isSecureConnection, extendedProtectionPolicy);

                                context = new NTAuthentication(true, package, null,
                                    GetContextFlags(extendedProtectionPolicy, isSecureConnection), binding);
                            }

                            try
                            {
                                bytes = Convert.FromBase64String(inBlob);
                            }
                            catch (FormatException)
                            {
                                GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() FromBase64String threw a FormatException.");
                                httpError = HttpStatusCode.BadRequest;
                                error = true;
                            }
                            if (!error)
                            {
                                decodedOutgoingBlob = context.GetOutgoingBlob(bytes, false, out statusCodeNew);
                                GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() GetOutgoingBlob() returned IsCompleted:" + context.IsCompleted + " statusCodeNew:" + statusCodeNew);
                                error = !context.IsValidContext;
                                if (error)
                                {
                                    // Bug #474228: SSPI Workaround
                                    // If a client sends up a blob on the initial request, Negotiate returns SEC_E_INVALID_HANDLE
                                    // when it should return SEC_E_INVALID_TOKEN.
                                    if (statusCodeNew == SecurityStatus.InvalidHandle && oldContext == null && bytes != null && bytes.Length > 0)
                                    {
                                        statusCodeNew = SecurityStatus.InvalidToken;
                                    }

                                    httpError = HttpStatusFromSecurityStatus(statusCodeNew);
                                }
                            }

                            if (decodedOutgoingBlob!=null) {
                                outBlob = Convert.ToBase64String(decodedOutgoingBlob);
                            }

                            if (!error)
                            {
                                if (context.IsCompleted) {
                                    SafeCloseHandle userContext = null;
                                    try
                                    {
                                        if (!CheckSpn(context, isSecureConnection, extendedProtectionPolicy)) {
                                            httpError = HttpStatusCode.Unauthorized;
                                        }
                                        else {
                                            httpContext.Request.ServiceName = context.ClientSpecifiedSpn;

                                            userContext = context.GetContextToken(out statusCodeNew);
                                            if (statusCodeNew != SecurityStatus.OK)
                                            {
                                                GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() GetContextToken() failed with statusCodeNew:" + statusCodeNew.ToString());
                                                httpError = HttpStatusFromSecurityStatus(statusCodeNew);
                                            }
                                            else
                                            {
                                                GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() creating new WindowsIdentity() from userContext:" + userContext.DangerousGetHandle().ToString("x8"));
                                                WindowsPrincipal windowsPrincipal = new WindowsPrincipal(CreateWindowsIdentity(userContext.DangerousGetHandle(), context.ProtocolName, WindowsAccountType.Normal, true));
                                                principal = windowsPrincipal;

                                                // if appropriate, cache this credential on this connection
                                                if (UnsafeConnectionNtlmAuthentication && context.ProtocolName == NegotiationInfoClass.NTLM)
                                                {
                                                    GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() inserting principal#" + ValidationHelper.HashString(principal) + " for connectionId:" + connectionId);

                                                    // We may need to call WaitForDisconnect.
                                                    if (disconnectResult == null)
                                                    {
                                                        RegisterForDisconnectNotification(connectionId, ref disconnectResult);
                                                    }
                                                    if (disconnectResult != null)
                                                    {
                                                        lock (DisconnectResults.SyncRoot)
                                                        {
                                                            if (UnsafeConnectionNtlmAuthentication)
                                                            {
                                                                disconnectResult.AuthenticatedConnection = windowsPrincipal;
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        // Registration failed - UnsafeConnectionNtlmAuthentication ignored.
                                                        GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() RegisterForDisconnectNotification() failed.");
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    finally {
                                        if (userContext!=null) {
                                            userContext.Close();
                                        }
                                    }
                                }
                                else
                                {
                                    // auth incomplete
                                    newContext = context;

                                    challenge = (headerScheme==AuthenticationSchemes.Ntlm ? NtlmClient.AuthType : NegotiateClient.AuthType);
                                    if (!String.IsNullOrEmpty(outBlob))
                                    {
                                        challenge += " " + outBlob;
                                    }
                                }
                            }
                            break;

                        case AuthenticationSchemes.Basic:
                            try
                            {
                                bytes = Convert.FromBase64String(inBlob);

                                inBlob = WebHeaderCollection.HeaderEncoding.GetString(bytes, 0, bytes.Length);
                                index = inBlob.IndexOf(':');

                                if (index!=-1) {
                                    string userName = inBlob.Substring(0, index);
                                    string password = inBlob.Substring(index+1);

                                    GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() basic identity found, userName:"******"HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() FromBase64String threw a FormatException.");
                            }
                            break;
                    }

                    if (principal != null)
                    {
                        GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() got principal:" + ValidationHelper.ToString(principal) + " principal.Identity.Name:" + ValidationHelper.ToString(principal.Identity.Name) + " creating request");
                        httpContext.SetIdentity(principal, outBlob);
                    }
                    else
                    {
                        GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() handshake has failed");
                        if(Logging.On)Logging.PrintWarning(Logging.HttpListener, this, "HandleAuthentication", SR.GetString(SR.net_log_listener_create_valid_identity_failed));
                        httpContext.Request.DetachBlob(memoryBlob);
                        httpContext.Close();
                        httpContext = null;
                    }
                }

                // if we're not giving a request to the application, we need to send an error
                ArrayList challenges = null;
                if (httpContext == null)
                {
                    // If we already have a challenge, just use it.  Otherwise put a challenge for each acceptable scheme.
                    if (challenge != null)
                    {
                        AddChallenge(ref challenges, challenge);
                    }
                    else
                    {
                        // We're starting over.  Any context SSPI might have wanted us to keep is useless.
                        if (newContext != null)
                        {
                            if (newContext == context)
                            {
                                context = null;
                            }

                            if (newContext != oldContext)
                            {
                                NTAuthentication toClose = newContext;
                                newContext = null;
                                toClose.CloseContext();
                            }
                            else
                            {
                                newContext = null;
                            }
                        }

                        // If we're sending something besides 401, do it here.
                        if (httpError != HttpStatusCode.Unauthorized)
                        {
                            GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() failed context#" + ValidationHelper.HashString(context) + " for connectionId:" + connectionId + " because of error:" + httpError.ToString());
                            SendError(requestId, httpError, null);
                            return null;
                        }

                        challenges = BuildChallenge(authenticationScheme, connectionId, out newContext,
                            extendedProtectionPolicy, isSecureConnection);
                    }
                }

                // Check if we need to call WaitForDisconnect, because if we do and it fails, we want to send a 500 instead.
                if (disconnectResult == null && newContext != null)
                {
                    RegisterForDisconnectNotification(connectionId, ref disconnectResult);

                    // Failed - send 500.
                    if (disconnectResult == null)
                    {
                        if (newContext != null)
                        {
                            if (newContext == context)
                            {
                                context = null;
                            }

                            if (newContext != oldContext)
                            {
                                NTAuthentication toClose = newContext;
                                newContext = null;
                                toClose.CloseContext();
                            }
                            else
                            {
                                newContext = null;
                            }
                        }

                        GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() failed context#" + ValidationHelper.HashString(context) + " for connectionId:" + connectionId + " because of failed HttpWaitForDisconnect");
                        SendError(requestId, HttpStatusCode.InternalServerError, null);
                        httpContext.Request.DetachBlob(memoryBlob);
                        httpContext.Close();
                        return null;
                    }
                }

                // Update Session if necessary.
                if (oldContext != newContext)
                {
                    if (oldContext == context)
                    {
                        // Prevent the finally from closing this twice.
                        context = null;
                    }

                    NTAuthentication toClose = oldContext;
                    oldContext = newContext;
                    disconnectResult.Session = newContext;

                    if (toClose != null)
                    {
                        // Save digest context in digest cache, we may need it later because of
                        // subsequest responses to the same req on the same/diff connection
                        if ((authenticationScheme & AuthenticationSchemes.Digest) != 0)
                        {
                            SaveDigestContext(toClose);
                        }
                        else
                        {
                            toClose.CloseContext();
                        }
                    }
                }

                // Send the 401 here.
                if (httpContext == null)
                {
                    SendError(requestId, challenges != null && challenges.Count > 0 ? HttpStatusCode.Unauthorized : HttpStatusCode.Forbidden, challenges);
                    GlobalLog.Print("HttpListener#" + ValidationHelper.HashString(this) + "::HandleAuthentication() SendUnauthorized(Scheme:" + authenticationScheme + ")");
                    return null;
                }

                if (!stoleBlob)
                {
                    stoleBlob = true;
                    httpContext.Request.ReleasePins();
                }
                return httpContext;
            }
            catch
            {
                if (httpContext != null)
                {
                    httpContext.Request.DetachBlob(memoryBlob);
                    httpContext.Close();
                }
                if (newContext != null)
                {
                    if (newContext == context)
                    {
                        // Prevent the finally from closing this twice.
                        context = null;
                    }

                    if (newContext != oldContext)
                    {
                        NTAuthentication toClose = newContext;
                        newContext = null;
                        toClose.CloseContext();
                    }
                    else
                    {
                        newContext = null;
                    }
                }
                throw;
            }
            finally
            {
                try
                {
                    // Clean up the previous context if necessary.
                    if (oldContext != null && oldContext != newContext)
                    {
                        // Clear out Session if it wasn't already.
                        if (newContext == null && disconnectResult != null)
                        {
                            disconnectResult.Session = null;
                        }

                        // Save digest context in digest cache, we may need it later because of
                        // subsequest responses to the same req on the same/diff connection

                        if ((authenticationScheme & AuthenticationSchemes.Digest) != 0)
                        {
                            SaveDigestContext(oldContext);
                        }
                        else
                        {
                            oldContext.CloseContext();
                        }
                    }

                    // Delete any context created but not stored.
                    if (context != null && oldContext != context && newContext != context)
                    {
                        context.CloseContext();
                    }
                }
                finally
                {
                    // Check if the connection got deleted while in this method, and clear out the hashtables if it did.
                    // In a nested finally because if this doesn't happen, we leak.
                    if (disconnectResult != null)
                    {
                        disconnectResult.FinishOwningDisconnectHandling();
                    }
                }
            }
        }
        private bool CheckSpn(NTAuthentication context, bool isSecureConnection, ExtendedProtectionPolicy policy)
        {
            // Kerberos does SPN check already in ASC
            if (context.IsKerberos)
            {
                if (Logging.On)
                {
                    Logging.PrintInfo(Logging.HttpListener, this, SR.GetString(SR.net_log_listener_no_spn_kerberos));
                }
                return true;
            }

            // Don't check the SPN if Extended Protection is off or we already checked the CBT
            if (policy.PolicyEnforcement == PolicyEnforcement.Never)
            {
                if (Logging.On)
                {
                    Logging.PrintInfo(Logging.HttpListener, this, SR.GetString(SR.net_log_listener_no_spn_disabled));
                }
                return true;
            }

            if (ScenarioChecksChannelBinding(isSecureConnection, policy.ProtectionScenario))
            {
                if (Logging.On)
                {
                    Logging.PrintInfo(Logging.HttpListener, this, SR.GetString(SR.net_log_listener_no_spn_cbt));
                }
                return true;
            }

            if (!AuthenticationManager.OSSupportsExtendedProtection)
            {
                GlobalLog.Assert(policy.PolicyEnforcement != PolicyEnforcement.Always, "User managed to set PolicyEnforcement.Always when the OS does not support extended protection!");
                if (Logging.On)
                {
                    Logging.PrintInfo(Logging.HttpListener, this, SR.GetString(SR.net_log_listener_no_spn_platform));
                }
                return true;
            }

            string clientSpn = context.ClientSpecifiedSpn;

            // An empty SPN is only allowed in the WhenSupported case
            if (String.IsNullOrEmpty(clientSpn))
            {
                if (policy.PolicyEnforcement == PolicyEnforcement.WhenSupported)
                {
                    if (Logging.On)
                    {
                        Logging.PrintInfo(Logging.HttpListener, this, 
                            SR.GetString(SR.net_log_listener_no_spn_whensupported));
                    }
                    return true;
                }
                else
                {
                    if (Logging.On)
                    {
                        Logging.PrintInfo(Logging.HttpListener, this, 
                            SR.GetString(SR.net_log_listener_spn_failed_always));
                    }
                    return false;
                }
            }
            else if (ServiceNameCollection.Match(clientSpn, "http/localhost"))
            {
                if (Logging.On)
                {
                    Logging.PrintInfo(Logging.HttpListener, this, SR.GetString(SR.net_log_listener_no_spn_loopback));
                }

                return true;
            }
            else
            {
                if (Logging.On)
                {
                    Logging.PrintInfo(Logging.HttpListener, this, SR.GetString(SR.net_log_listener_spn, clientSpn));
                }

                ServiceNameCollection serviceNames = GetServiceNames(policy);

                bool found = serviceNames.Contains(clientSpn);

                if (Logging.On)
                {
                    if (found)
                    {
                        Logging.PrintInfo(Logging.HttpListener, this, SR.GetString(SR.net_log_listener_spn_passed));
                    }
                    else
                    {
                        Logging.PrintInfo(Logging.HttpListener, this, SR.GetString(SR.net_log_listener_spn_failed));

                        if (serviceNames.Count == 0)
                        {
                            Logging.PrintWarning(Logging.HttpListener, this, "CheckSpn",
                                SR.GetString(SR.net_log_listener_spn_failed_empty));
                        }
                        else
                        {
                            Logging.PrintInfo(Logging.HttpListener, this, 
                                SR.GetString(SR.net_log_listener_spn_failed_dump));

                            foreach (string serviceName in serviceNames)
                            {
                                Logging.PrintInfo(Logging.HttpListener, this, "\t" + serviceName);
                            }
                        }
                    }
                }

                return found;
            }
        }
 internal void SetSecurityContext(NTAuthentication securityContext, IAuthenticationModule module) {
     GlobalLog.Print("AuthenticationState#" + ValidationHelper.HashString(this) + "::SetSecurityContext(" + module.AuthenticationType + ") was NTAuthentication#" + ValidationHelper.HashString(SecurityContext) + " now NTAuthentication#" + ValidationHelper.HashString(securityContext));
     SecurityContext = securityContext;
 }
        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;
        }
 internal static Authorization GetGroupAuthorization(
     IAuthenticationModule thisModule, 
     string token, 
     bool finished, 
     NTAuthentication authSession, 
     bool shareAuthenticatedConnections, 
     bool mutualAuth) 
 {
     return new Authorization(
             token,
             finished,
             (shareAuthenticatedConnections) ? null 
                 : (thisModule.GetType().FullName + "/" + authSession.UniqueUserId),
             mutualAuth);
 }
Exemple #34
0
        private Authorization DoAuthenticate(string challenge, WebRequest webRequest, ICredentials credentials, bool preAuthenticate)
        {
            if (credentials == null)
            {
                return(null);
            }
            HttpWebRequest   request         = webRequest as HttpWebRequest;
            NTAuthentication securityContext = null;
            string           incomingBlob    = null;

            if (!preAuthenticate)
            {
                int index = AuthenticationManager.FindSubstringNotInQuotes(challenge, Signature);
                if (index < 0)
                {
                    return(null);
                }
                int startIndex = index + SignatureSize;
                if ((challenge.Length > startIndex) && (challenge[startIndex] != ','))
                {
                    startIndex++;
                }
                else
                {
                    index = -1;
                }
                if ((index >= 0) && (challenge.Length > startIndex))
                {
                    index = challenge.IndexOf(',', startIndex);
                    if (index != -1)
                    {
                        incomingBlob = challenge.Substring(startIndex, index - startIndex);
                    }
                    else
                    {
                        incomingBlob = challenge.Substring(startIndex);
                    }
                }
                securityContext = request.CurrentAuthenticationState.GetSecurityContext(this);
            }
            if (securityContext == null)
            {
                NetworkCredential credential = credentials.GetCredential(request.ChallengedUri, Signature);
                if ((credential == null) || (!(credential is SystemNetworkCredential) && (credential.InternalGetUserName().Length == 0)))
                {
                    return(null);
                }
                ICredentialPolicy credentialPolicy = AuthenticationManager.CredentialPolicy;
                if ((credentialPolicy != null) && !credentialPolicy.ShouldSendCredential(request.ChallengedUri, request, credential, this))
                {
                    return(null);
                }
                string         computeSpn     = request.CurrentAuthenticationState.GetComputeSpn(request);
                ChannelBinding channelBinding = null;
                if (request.CurrentAuthenticationState.TransportContext != null)
                {
                    channelBinding = request.CurrentAuthenticationState.TransportContext.GetChannelBinding(ChannelBindingKind.Endpoint);
                }
                securityContext = new NTAuthentication("Kerberos", credential, computeSpn, request, channelBinding);
                request.CurrentAuthenticationState.SetSecurityContext(securityContext, this);
            }
            string outgoingBlob = securityContext.GetOutgoingBlob(incomingBlob);

            if (outgoingBlob == null)
            {
                return(null);
            }
            return(new Authorization("Kerberos " + outgoingBlob, securityContext.IsCompleted, string.Empty, securityContext.IsMutualAuthFlag));
        }