示例#1
0
            public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity)
            {
                if (reference == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(reference));
                }

                identity = reference.Identity;

                if (identity == null)
                {
                    identity = TryCreateDnsIdentity(reference);
                }

                if (identity == null)
                {
                    SecurityTraceRecordHelper.TraceIdentityDeterminationFailure(reference, typeof(DefaultIdentityVerifier));
                    return(false);
                }
                else
                {
                    SecurityTraceRecordHelper.TraceIdentityDeterminationSuccess(reference, identity, typeof(DefaultIdentityVerifier));
                    return(true);
                }
            }
 protected virtual void OnVerifyIncomingMessageFailure(Message message, Exception exception)
 {
     SecurityTraceRecordHelper.TraceVerifyIncomingMessageFailure(this, message);
     if ((PerformanceCounters.PerformanceCountersEnabled && (null != this.factory.ListenUri)) && (((exception.GetType() == typeof(MessageSecurityException)) || exception.GetType().IsSubclassOf(typeof(MessageSecurityException))) || ((exception.GetType() == typeof(SecurityTokenException)) || exception.GetType().IsSubclassOf(typeof(SecurityTokenException)))))
     {
         PerformanceCounters.AuthenticationFailed(message, this.factory.ListenUri);
     }
     if (AuditLevel.Failure == (this.factory.MessageAuthenticationAuditLevel & AuditLevel.Failure))
     {
         try
         {
             string identityNamesFromContext;
             SecurityMessageProperty security = message.Properties.Security;
             if ((security != null) && (security.ServiceSecurityContext != null))
             {
                 identityNamesFromContext = System.ServiceModel.Security.SecurityUtils.GetIdentityNamesFromContext(security.ServiceSecurityContext.AuthorizationContext);
             }
             else
             {
                 identityNamesFromContext = System.ServiceModel.Security.SecurityUtils.AnonymousIdentity.Name;
             }
             SecurityAuditHelper.WriteMessageAuthenticationFailureEvent(this.factory.AuditLogLocation, this.factory.SuppressAuditFailure, message, message.Headers.To, message.Headers.Action, identityNamesFromContext, exception);
         }
         catch (Exception exception2)
         {
             if (Fx.IsFatal(exception2))
             {
                 throw;
             }
             DiagnosticUtility.ExceptionUtility.TraceHandledException(exception2, TraceEventType.Error);
         }
     }
 }
示例#3
0
            public SessionOperationAsyncResult(SecuritySessionSecurityTokenProvider requestor, SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state)
            {
                this.requestor     = requestor;
                this.operation     = operation;
                this.target        = target;
                this.via           = via;
                this.currentToken  = currentToken;
                this.timeoutHelper = new TimeoutHelper(timeout);
                SecurityTraceRecordHelper.TraceBeginSecuritySessionOperation(operation, target, currentToken);
                bool flag = false;

                try
                {
                    flag = this.StartOperation();
                }
                catch (Exception exception)
                {
                    if (Fx.IsFatal(exception))
                    {
                        throw;
                    }
                    this.OnOperationFailure(exception);
                    throw;
                }
                if (flag)
                {
                    this.OnOperationComplete();
                    base.Complete(true);
                }
            }
示例#4
0
 protected override ArrayList OnQuotaReached(Hashtable cacheTable)
 {
     if (!this.replaceOldestEntries)
     {
         SecurityTraceRecordHelper.TraceSecurityContextTokenCacheFull(this.Capacity, 0);
         return(base.OnQuotaReached(cacheTable));
     }
     else
     {
         List <SecurityContextSecurityToken> tokens = new List <SecurityContextSecurityToken>(cacheTable.Count);
         foreach (IExpirableItem value in cacheTable.Values)
         {
             SecurityContextSecurityToken token = (SecurityContextSecurityToken)ExtractItem(value);
             tokens.Add(token);
         }
         tokens.Sort(sctEffectiveTimeComparer);
         int pruningAmount = (int)(((double)this.Capacity) * pruningFactor);
         pruningAmount = pruningAmount <= 0 ? this.Capacity : pruningAmount;
         ArrayList keys = new ArrayList(pruningAmount);
         for (int i = 0; i < pruningAmount; ++i)
         {
             keys.Add(GetHashKey(tokens[i].ContextId, tokens[i].KeyGeneration));
             OnRemove(tokens[i]);
         }
         SecurityTraceRecordHelper.TraceSecurityContextTokenCacheFull(this.Capacity, pruningAmount);
         return(keys);
     }
 }
        protected override ArrayList OnQuotaReached(Hashtable cacheTable)
        {
            if (!this.replaceOldestEntries)
            {
                SecurityTraceRecordHelper.TraceSecurityContextTokenCacheFull(base.Capacity, 0);
                return(base.OnQuotaReached(cacheTable));
            }
            List <SecurityContextSecurityToken> list = new List <SecurityContextSecurityToken>(cacheTable.Count);

            foreach (TimeBoundedCache.IExpirableItem item in cacheTable.Values)
            {
                SecurityContextSecurityToken token = (SecurityContextSecurityToken)base.ExtractItem(item);
                list.Add(token);
            }
            list.Sort(sctEffectiveTimeComparer);
            int capacity = (int)(base.Capacity * pruningFactor);

            capacity = (capacity <= 0) ? base.Capacity : capacity;
            ArrayList list2 = new ArrayList(capacity);

            for (int i = 0; i < capacity; i++)
            {
                list2.Add(this.GetHashKey(list[i].ContextId, list[i].KeyGeneration));
                this.OnRemove(list[i]);
            }
            SecurityTraceRecordHelper.TraceSecurityContextTokenCacheFull(base.Capacity, capacity);
            return(list2);
        }
示例#6
0
        protected SecurityToken EndNegotiation(IAsyncResult result)
        {
            SecurityToken serviceToken = SecurityNegotiationAsyncResult <T> .End(result);

            SecurityTraceRecordHelper.TraceEndSecurityNegotiation <T>((IssuanceTokenProviderBase <T>) this, serviceToken, this.targetAddress);
            return(serviceToken);
        }
            public SessionOperationAsyncResult(SecuritySessionSecurityTokenProvider requestor, SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout, AsyncCallback callback, object state)
                : base(callback, state)
            {
                this.requestor     = requestor;
                this.operation     = operation;
                this.target        = target;
                this.via           = via;
                this.currentToken  = currentToken;
                this.timeoutHelper = new TimeoutHelper(timeout);
                SecurityTraceRecordHelper.TraceBeginSecuritySessionOperation(operation, target, currentToken);
                bool completeSelf = false;

                try
                {
                    completeSelf = this.StartOperation();
                }
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                    {
                        throw;
                    }

                    this.OnOperationFailure(e);
                    throw;
                }
                if (completeSelf)
                {
                    this.OnOperationComplete();
                    Complete(true);
                }
            }
 internal SecurityIdentifier GetUpnSid()
 {
     if (!this.hasUpnSidBeenComputed)
     {
         lock (this.thisLock)
         {
             string resource = (string)base.IdentityClaim.Resource;
             if (!this.hasUpnSidBeenComputed)
             {
                 try
                 {
                     NTAccount account = new NTAccount(resource);
                     this.upnSid = account.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier;
                 }
                 catch (Exception exception)
                 {
                     if (Fx.IsFatal(exception))
                     {
                         throw;
                     }
                     if (exception is NullReferenceException)
                     {
                         throw;
                     }
                     SecurityTraceRecordHelper.TraceSpnToSidMappingFailure(resource, exception);
                 }
                 finally
                 {
                     this.hasUpnSidBeenComputed = true;
                 }
             }
         }
     }
     return(this.upnSid);
 }
        protected SecurityToken EndNegotiation(IAsyncResult result)
        {
            SecurityToken token = SecurityNegotiationAsyncResult.End(result);

            SecurityTraceRecordHelper.TraceEndSecurityNegotiation(this, token, this.targetAddress);
            return(token);
        }
 public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext)
 {
     if (identity == null)
     {
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identity");
     }
     if (authContext == null)
     {
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("authContext");
     }
     for (int i = 0; i < authContext.ClaimSets.Count; i++)
     {
         ClaimSet claimSet = authContext.ClaimSets[i];
         if (claimSet.ContainsClaim(identity.IdentityClaim))
         {
             SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(identity, identity.IdentityClaim, base.GetType());
             return(true);
         }
         string expectedSpn = null;
         if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType))
         {
             expectedSpn = string.Format(CultureInfo.InvariantCulture, "host/{0}", new object[] { (string)identity.IdentityClaim.Resource });
             Claim claim = this.CheckDnsEquivalence(claimSet, expectedSpn);
             if (claim != null)
             {
                 SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(identity, claim, base.GetType());
                 return(true);
             }
         }
         SecurityIdentifier identitySid = null;
         if (ClaimTypes.Sid.Equals(identity.IdentityClaim.ClaimType))
         {
             identitySid = this.GetSecurityIdentifier(identity.IdentityClaim);
         }
         else if (ClaimTypes.Upn.Equals(identity.IdentityClaim.ClaimType))
         {
             identitySid = ((UpnEndpointIdentity)identity).GetUpnSid();
         }
         else if (ClaimTypes.Spn.Equals(identity.IdentityClaim.ClaimType))
         {
             identitySid = ((SpnEndpointIdentity)identity).GetSpnSid();
         }
         else if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType))
         {
             identitySid = new SpnEndpointIdentity(expectedSpn).GetSpnSid();
         }
         if (identitySid != null)
         {
             Claim claim2 = this.CheckSidEquivalence(identitySid, claimSet);
             if (claim2 != null)
             {
                 SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(identity, claim2, base.GetType());
                 return(true);
             }
         }
     }
     SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity, authContext, base.GetType());
     return(false);
 }
 protected virtual void OnIncomingMessageVerified(Message verifiedMessage)
 {
     SecurityTraceRecordHelper.TraceIncomingMessageVerified(this, verifiedMessage);
     if (AuditLevel.Success == (this.factory.MessageAuthenticationAuditLevel & AuditLevel.Success))
     {
         SecurityAuditHelper.WriteMessageAuthenticationSuccessEvent(this.factory.AuditLogLocation, this.factory.SuppressAuditFailure, verifiedMessage, verifiedMessage.Headers.To, verifiedMessage.Headers.Action, System.ServiceModel.Security.SecurityUtils.GetIdentityNamesFromContext(verifiedMessage.Properties.Security.ServiceSecurityContext.AuthorizationContext));
     }
 }
 void OnOperationFailure(SecuritySessionOperation operation, EndpointAddress target, SecurityToken currentToken, Exception e, IChannel channel)
 {
     SecurityTraceRecordHelper.TraceSecuritySessionOperationFailure(operation, target, currentToken, e);
     if (channel != null)
     {
         channel.Abort();
     }
 }
示例#13
0
 // negotiation failure methods
 Message HandleNegotiationException(Message request, Exception e)
 {
     SecurityTraceRecordHelper.TraceServiceSecurityNegotiationFailure <T>(
         EventTraceActivityHelper.TryExtractActivity(request),
         this,
         e);
     return(CreateFault(request, e));
 }
示例#14
0
        private GenericXmlSecurityToken DoOperation(SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout)
        {
            GenericXmlSecurityToken token2;

            if (target == null)
            {
                throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("target");
            }
            if ((operation == SecuritySessionOperation.Renew) && (currentToken == null))
            {
                throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("currentToken");
            }
            IRequestChannel channel = null;

            try
            {
                object obj2;
                GenericXmlSecurityToken token;
                SecurityTraceRecordHelper.TraceBeginSecuritySessionOperation(operation, target, currentToken);
                channel = this.CreateChannel(operation, target, via);
                TimeoutHelper helper = new TimeoutHelper(timeout);
                channel.Open(helper.RemainingTime());
                using (Message message = this.CreateRequest(operation, target, currentToken, out obj2))
                {
                    TraceUtility.ProcessOutgoingMessage(message);
                    using (Message message2 = channel.Request(message, helper.RemainingTime()))
                    {
                        if (message2 == null)
                        {
                            throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(System.ServiceModel.SR.GetString("FailToRecieveReplyFromNegotiation")));
                        }
                        TraceUtility.ProcessIncomingMessage(message2);
                        ThrowIfFault(message2, this.targetAddress);
                        token = this.ProcessReply(message2, operation, obj2);
                        this.ValidateKeySize(token);
                    }
                }
                channel.Close(helper.RemainingTime());
                this.OnOperationSuccess(operation, target, token, currentToken);
                token2 = token;
            }
            catch (Exception exception)
            {
                if (Fx.IsFatal(exception))
                {
                    throw;
                }
                if (exception is TimeoutException)
                {
                    exception = new TimeoutException(System.ServiceModel.SR.GetString("ClientSecuritySessionRequestTimeout", new object[] { timeout }), exception);
                }
                this.OnOperationFailure(operation, target, currentToken, exception, channel);
                throw;
            }
            return(token2);
        }
示例#15
0
 protected override IAsyncResult BeginGetTokenCore(TimeSpan timeout, AsyncCallback callback, object state)
 {
     base.CommunicationObject.ThrowIfClosedOrNotOpen();
     lock (this.ThisLock)
     {
         SecurityToken currentServiceToken = this.GetCurrentServiceToken();
         if (currentServiceToken != null)
         {
             SecurityTraceRecordHelper.TraceUsingCachedServiceToken <T>((IssuanceTokenProviderBase <T>) this, currentServiceToken, this.targetAddress);
             return(new CompletedAsyncResult <SecurityToken>(currentServiceToken, callback, state));
         }
         return(this.BeginNegotiation(timeout, callback, state));
     }
 }
        protected override ReadOnlyCollection <IAuthorizationPolicy> ValidateSspiNegotiation(ISspiNegotiation sspiNegotiation)
        {
            WindowsSspiNegotiation windowsNegotiation = (WindowsSspiNegotiation)sspiNegotiation;

            if (!windowsNegotiation.IsValidContext)
            {
                throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(System.ServiceModel.SR.GetString("InvalidSspiNegotiation")));
            }
            if (this.AuthenticateServer && !windowsNegotiation.IsMutualAuthFlag)
            {
                throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(System.ServiceModel.SR.GetString("CannotAuthenticateServer")));
            }
            SecurityTraceRecordHelper.TraceClientSpnego(windowsNegotiation);
            return(System.ServiceModel.Security.SecurityUtils.CreatePrincipalNameAuthorizationPolicies(windowsNegotiation.ServicePrincipalName));
        }
示例#17
0
        protected override SecurityToken GetTokenCore(TimeSpan timeout)
        {
            SecurityToken currentServiceToken;

            base.CommunicationObject.ThrowIfClosedOrNotOpen();
            lock (this.ThisLock)
            {
                currentServiceToken = this.GetCurrentServiceToken();
                if (currentServiceToken != null)
                {
                    SecurityTraceRecordHelper.TraceUsingCachedServiceToken <T>((IssuanceTokenProviderBase <T>) this, currentServiceToken, this.targetAddress);
                }
            }
            if (currentServiceToken == null)
            {
                currentServiceToken = this.DoNegotiation(timeout);
            }
            return(currentServiceToken);
        }
        private void EnsureIdentity(EndpointAddress serviceReference, AuthorizationContext authorizationContext, string errorString)
        {
            EndpointIdentity identity;

            if (authorizationContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("authorizationContext");
            }
            if (!this.TryGetIdentity(serviceReference, out identity))
            {
                SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity, authorizationContext, base.GetType());
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(System.ServiceModel.SR.GetString(errorString, new object[] { identity, serviceReference })));
            }
            if (!this.CheckAccess(identity, authorizationContext))
            {
                Exception exception = this.CreateIdentityCheckException(identity, authorizationContext, errorString, serviceReference);
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(exception);
            }
        }
        protected override SecurityToken GetTokenCore(TimeSpan timeout)
        {
            this.CommunicationObject.ThrowIfClosedOrNotOpen();
            SecurityToken result;

            lock (ThisLock)
            {
                result = GetCurrentServiceToken();
                if (result != null)
                {
                    SecurityTraceRecordHelper.TraceUsingCachedServiceToken(this, result, this.targetAddress);
                }
            }
            if (result == null)
            {
                result = DoNegotiation(timeout);
            }
            return(result);
        }
示例#20
0
        protected virtual void OnVerifyIncomingMessageFailure(Message message, Exception exception)
        {
            SecurityTraceRecordHelper.TraceVerifyIncomingMessageFailure(this, message);
            if (PerformanceCounters.PerformanceCountersEnabled && null != this.factory.ListenUri) //service side
            {
                if ((exception.GetType() == typeof(MessageSecurityException) || exception.GetType().IsSubclassOf(typeof(MessageSecurityException))) ||
                    (exception.GetType() == typeof(SecurityTokenException) || exception.GetType().IsSubclassOf(typeof(SecurityTokenException))))
                {
                    PerformanceCounters.AuthenticationFailed(message, this.factory.ListenUri);
                }
            }

            if (AuditLevel.Failure == (this.factory.MessageAuthenticationAuditLevel & AuditLevel.Failure))
            {
                try
                {
                    SecurityMessageProperty security = message.Properties.Security;
                    string primaryIdentity;
                    if (security != null && security.ServiceSecurityContext != null)
                    {
                        primaryIdentity = SecurityUtils.GetIdentityNamesFromContext(security.ServiceSecurityContext.AuthorizationContext);
                    }
                    else
                    {
                        primaryIdentity = SecurityUtils.AnonymousIdentity.Name;
                    }

                    SecurityAuditHelper.WriteMessageAuthenticationFailureEvent(this.factory.AuditLogLocation,
                                                                               this.factory.SuppressAuditFailure, message, message.Headers.To, message.Headers.Action, primaryIdentity, exception);
                }
#pragma warning suppress 56500
                catch (Exception auditException)
                {
                    if (Fx.IsFatal(auditException))
                    {
                        throw;
                    }

                    DiagnosticUtility.TraceHandledException(auditException, TraceEventType.Error);
                }
            }
        }
        protected override IAsyncResult BeginGetTokenCore(TimeSpan timeout, AsyncCallback callback, object state)
        {
            this.CommunicationObject.ThrowIfClosedOrNotOpen();
            IAsyncResult asyncResult;

            lock (ThisLock)
            {
                SecurityToken token = GetCurrentServiceToken();
                if (token != null)
                {
                    SecurityTraceRecordHelper.TraceUsingCachedServiceToken(this, token, this.targetAddress);
                    asyncResult = new CompletedAsyncResult <SecurityToken>(token, callback, state);
                }
                else
                {
                    asyncResult = BeginNegotiation(timeout, callback, state);
                }
            }
            return(asyncResult);
        }
        internal SecurityIdentifier GetUpnSid()
        {
            Fx.Assert(ClaimTypes.Upn.Equals(this.IdentityClaim.ClaimType), "");
            if (!hasUpnSidBeenComputed)
            {
                lock (thisLock)
                {
                    string upn = (string)this.IdentityClaim.Resource;
                    if (!hasUpnSidBeenComputed)
                    {
                        try
                        {
                            NTAccount userAccount = new NTAccount(upn);
                            this.upnSid = userAccount.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier;
                        }
#pragma warning suppress 56500 // covered by FxCOP
                        catch (Exception e)
                        {
                            // Always immediately rethrow fatal exceptions.
                            if (Fx.IsFatal(e))
                            {
                                throw;
                            }

                            if (e is NullReferenceException)
                            {
                                throw;
                            }

                            SecurityTraceRecordHelper.TraceSpnToSidMappingFailure(upn, e);
                        }
                        finally
                        {
                            hasUpnSidBeenComputed = true;
                        }
                    }
                }
            }
            return(this.upnSid);
        }
示例#23
0
        private void EnsureIdentity(EndpointAddress serviceReference, AuthorizationContext authorizationContext, String errorString)
        {
            if (authorizationContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("authorizationContext");
            }
            EndpointIdentity identity;

            if (!TryGetIdentity(serviceReference, out identity))
            {
                SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity, authorizationContext, this.GetType());
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(string.Format(errorString, identity, serviceReference)));
            }
            else
            {
                if (!CheckAccess(identity, authorizationContext))
                {
                    // CheckAccess performs a Trace on failure, no need to do it twice
                    Exception e = CreateIdentityCheckException(identity, authorizationContext, errorString, serviceReference);
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(e);
                }
            }
        }
        protected override ReadOnlyCollection <IAuthorizationPolicy> ValidateSspiNegotiation(ISspiNegotiation sspiNegotiation)
        {
            WindowsSspiNegotiation windowsNegotiation = (WindowsSspiNegotiation)sspiNegotiation;

            if (!windowsNegotiation.IsValidContext)
            {
                throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(System.ServiceModel.SR.GetString("InvalidSspiNegotiation")));
            }
            SecurityTraceRecordHelper.TraceServiceSpnego(windowsNegotiation);
            if (base.IsClientAnonymous)
            {
                return(System.ServiceModel.Security.EmptyReadOnlyCollection <IAuthorizationPolicy> .Instance);
            }
            using (System.IdentityModel.SafeCloseHandle handle = windowsNegotiation.GetContextToken())
            {
                WindowsIdentity identity = new WindowsIdentity(handle.DangerousGetHandle(), windowsNegotiation.ProtocolName);
                System.ServiceModel.Security.SecurityUtils.ValidateAnonymityConstraint(identity, this.AllowUnauthenticatedCallers);
                List <IAuthorizationPolicy> list     = new List <IAuthorizationPolicy>(1);
                WindowsClaimSet             issuance = new WindowsClaimSet(identity, windowsNegotiation.ProtocolName, this.extractGroupsForWindowsAccounts, false);
                list.Add(new UnconditionalPolicy(issuance, TimeoutHelper.Add(DateTime.UtcNow, base.ServiceTokenLifetime)));
                return(list.AsReadOnly());
            }
        }
示例#25
0
        internal SecurityIdentifier GetSpnSid()
        {
            Fx.Assert(ClaimTypes.Spn.Equals(this.IdentityClaim.ClaimType) || ClaimTypes.Dns.Equals(this.IdentityClaim.ClaimType), "");
            if (!hasSpnSidBeenComputed)
            {
                lock (thisLock)
                {
                    if (!hasSpnSidBeenComputed)
                    {
                        string spn = null;
                        try
                        {
                            if (ClaimTypes.Dns.Equals(this.IdentityClaim.ClaimType))
                            {
                                spn = "host/" + (string)this.IdentityClaim.Resource;
                            }
                            else
                            {
                                spn = (string)this.IdentityClaim.Resource;
                            }
                            // canonicalize SPN for use in LDAP filter following RFC 1960:
                            if (spn != null)
                            {
                                spn = spn.Replace("*", @"\*").Replace("(", @"\(").Replace(")", @"\)");
                            }

                            DirectoryEntry de = GetDirectoryEntry();
                            using (DirectorySearcher searcher = new DirectorySearcher(de))
                            {
                                searcher.CacheResults  = true;
                                searcher.ClientTimeout = SpnLookupTime;
                                searcher.Filter        = "(&(objectCategory=Computer)(objectClass=computer)(servicePrincipalName=" + spn + "))";
                                searcher.PropertiesToLoad.Add("objectSid");
                                SearchResult result = searcher.FindOne();
                                if (result != null)
                                {
                                    byte[] sidBinaryForm = (byte[])result.Properties["objectSid"][0];
                                    this.spnSid = new SecurityIdentifier(sidBinaryForm, 0);
                                }
                                else
                                {
                                    SecurityTraceRecordHelper.TraceSpnToSidMappingFailure(spn, null);
                                }
                            }
                        }
#pragma warning suppress 56500 // covered by FxCOP
                        catch (Exception e)
                        {
                            // Always immediately rethrow fatal exceptions.
                            if (Fx.IsFatal(e))
                            {
                                throw;
                            }

                            if (e is NullReferenceException || e is SEHException)
                            {
                                throw;
                            }

                            SecurityTraceRecordHelper.TraceSpnToSidMappingFailure(spn, e);
                        }
                        finally
                        {
                            hasSpnSidBeenComputed = true;
                        }
                    }
                }
            }
            return(this.spnSid);
        }
示例#26
0
            public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext)
            {
                //EventTraceActivity eventTraceActivity = null;

                if (identity == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(identity));
                }

                if (authContext == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(authContext));
                }


                //if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled)
                //{
                //    eventTraceActivity = EventTraceActivityHelper.TryExtractActivity((OperationContext.Current != null) ? OperationContext.Current.IncomingMessage : null);
                //}

                for (int i = 0; i < authContext.ClaimSets.Count; ++i)
                {
                    ClaimSet claimSet = authContext.ClaimSets[i];
                    if (claimSet.ContainsClaim(identity.IdentityClaim))
                    {
                        //SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, identity.IdentityClaim, this.GetType());
                        return(true);
                    }

                    // try Claim equivalence
                    string expectedSpn = null;
                    if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType))
                    {
                        expectedSpn = string.Format(CultureInfo.InvariantCulture, "host/{0}", (string)identity.IdentityClaim.Resource);
                        Claim claim = CheckDnsEquivalence(claimSet, expectedSpn);
                        if (claim != null)
                        {
                            //SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, claim, this.GetType());
                            return(true);
                        }
                    }
                    // Allow a Sid claim to support UPN, and SPN identities
                    SecurityIdentifier identitySid = null;
                    if (ClaimTypes.Sid.Equals(identity.IdentityClaim.ClaimType))
                    {
                        identitySid = GetSecurityIdentifier(identity.IdentityClaim);
                    }
                    else if (ClaimTypes.Upn.Equals(identity.IdentityClaim.ClaimType))
                    {
                        identitySid = ((UpnEndpointIdentity)identity).GetUpnSid();
                    }
                    else if (ClaimTypes.Spn.Equals(identity.IdentityClaim.ClaimType))
                    {
                        identitySid = ((SpnEndpointIdentity)identity).GetSpnSid();
                    }
                    else if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType))
                    {
                        identitySid = new SpnEndpointIdentity(expectedSpn).GetSpnSid();
                    }
                    if (identitySid != null)
                    {
                        Claim claim = CheckSidEquivalence(identitySid, claimSet);
                        if (claim != null)
                        {
                            //SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, claim, this.GetType());
                            return(true);
                        }
                    }
                }
                SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity, authContext, GetType());
                //if (TD.SecurityIdentityVerificationFailureIsEnabled())
                //{
                //    TD.SecurityIdentityVerificationFailure(eventTraceActivity);
                //}

                return(false);
            }
示例#27
0
            public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext)
            {
                EventTraceActivity eventTraceActivity = null;

                if (identity == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identity");
                }

                if (authContext == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("authContext");
                }


                if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled)
                {
                    eventTraceActivity = EventTraceActivityHelper.TryExtractActivity((OperationContext.Current != null) ? OperationContext.Current.IncomingMessage : null);
                }

                for (int i = 0; i < authContext.ClaimSets.Count; ++i)
                {
                    ClaimSet claimSet = authContext.ClaimSets[i];
                    if (claimSet.ContainsClaim(identity.IdentityClaim))
                    {
                        SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, identity.IdentityClaim, this.GetType());
                        return(true);
                    }

                    // try Claim equivalence
                    string expectedSpn = null;
                    if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType))
                    {
                        expectedSpn = string.Format(CultureInfo.InvariantCulture, "host/{0}", (string)identity.IdentityClaim.Resource);
                        Claim claim = CheckDnsEquivalence(claimSet, expectedSpn);
                        if (claim != null)
                        {
                            SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, claim, this.GetType());
                            return(true);
                        }
                    }

                    // Allow a Sid claim to support UPN, and SPN identities

                    // SID claims not available yet
                    //SecurityIdentifier identitySid = null;
                    //if (ClaimTypes.Sid.Equals(identity.IdentityClaim.ClaimType))
                    //{
                    //    throw ExceptionHelper.PlatformNotSupported("DefaultIdentityVerifier - ClaimTypes.Sid");
                    //}
                    //else if (ClaimTypes.Upn.Equals(identity.IdentityClaim.ClaimType))
                    //{
                    //    throw ExceptionHelper.PlatformNotSupported("DefaultIdentityVerifier - ClaimTypes.Upn");
                    //}
                    //else if (ClaimTypes.Spn.Equals(identity.IdentityClaim.ClaimType))
                    //{
                    //    throw ExceptionHelper.PlatformNotSupported("DefaultIdentityVerifier - ClaimTypes.Spn");
                    //}
                    //else if (ClaimTypes.Dns.Equals(identity.IdentityClaim.ClaimType))
                    //{
                    //    throw ExceptionHelper.PlatformNotSupported("DefaultIdentityVerifier - ClaimTypes.Dns");
                    //}
                    //if (identitySid != null)
                    //{
                    //    Claim claim = CheckSidEquivalence(identitySid, claimSet);
                    //    if (claim != null)
                    //    {
                    //        SecurityTraceRecordHelper.TraceIdentityVerificationSuccess(eventTraceActivity, identity, claim, this.GetType());
                    //        return true;
                    //    }
                    //}
                }
                SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity, authContext, this.GetType());
                if (WcfEventSource.Instance.SecurityIdentityVerificationFailureIsEnabled())
                {
                    WcfEventSource.Instance.SecurityIdentityVerificationFailure(eventTraceActivity);
                }

                return(false);
            }
        protected override async Task <Stream> OnInitiateUpgradeAsync(Stream stream, OutWrapper <SecurityMessageProperty> remoteSecurityWrapper)
        {
            if (WcfEventSource.Instance.SslOnInitiateUpgradeIsEnabled())
            {
                WcfEventSource.Instance.SslOnInitiateUpgrade();
            }

            // There is currently no way to convert a .Net X509Certificate2 to a UWP Certificate. The client certificate
            // needs to be provided by looking it up in the certificate store. E.g.
            //
            //     factory.Credentials.ClientCertificate.SetCertificate(
            //         StoreLocation.CurrentUser,
            //         StoreName.My,
            //         X509FindType.FindByThumbprint,
            //         clientCertThumb);
            //
            // The certificate is retrieved using .Net api's and UWP api's. An artifical X509Extension is used to attach the
            // UWP certificate to the .Net X509Certificate2. This is then retrieved at the point of usage to use with UWP
            // networking api's.

            Certificate clientCertificate = null;

            if (_clientToken != null)
            {
                foreach (var extension in _clientToken.Certificate.Extensions)
                {
                    var attachmentExtension =
                        extension as X509CertificateInitiatorClientCredential.X509UwpCertificateAttachmentExtension;
                    if (attachmentExtension != null && attachmentExtension.AttachedCertificate != null)
                    {
                        clientCertificate = attachmentExtension.AttachedCertificate;
                        break;
                    }
                }

                Contract.Assert(clientCertificate != null, "Missing UWP Certificate as an attachment to X509Certificate2");
            }

            try
            {
                // Fetch the underlying raw transport object. For UWP, this will be a StreamSocket
                var connectionStream = stream as ConnectionStream;
                Contract.Assert(connectionStream != null, "stream is either null or not a ConnectionStream");
                var rtStreamSocket = connectionStream.Connection.GetCoreTransport() as StreamSocket;
                Contract.Assert(rtStreamSocket != null, "Core transport is either null or not a StreamSocket");
                rtStreamSocket.Control.ClientCertificate = clientCertificate;

                // On CoreClr, we use SslStream which calls a callback with any problems with the server certificate, which
                // returns whether to accept the certificate or not. With SocketStream in UWP, any custom validation needs to
                // happen after the connection has successfully negotiated. Some certificate errors need to be set to be ignored
                // to allow the connection to be established so we can retrieve the server certificate and choose whether to
                // accept the server certificate or not.
                rtStreamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
                rtStreamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired);
                rtStreamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
                rtStreamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.IncompleteChain);
                rtStreamSocket.Control.IgnorableServerCertificateErrors.Add(
                    ChainValidationResult.RevocationInformationMissing);
                rtStreamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationFailure);

                // SocketStream doesn't take a bitwise field of accepted protocols, but instead accepts a value specifying the highest
                // protocol that can be negotiated. A check is made for each of the protocols in order to see if they've been requested
                // by the binding and set the protection level to the UWP equivalent. This will have the effect of protectionLevel being
                // set to the most secure protocol that was specified by client code. After the connection is established, if a protocol
                // was negotiated which the binding didn't request, the connection needs to be aborted. This could happen for example if
                // the requested SslProtocols was SslProtocols.Tls11 | SslProtocols.Tls12 and the server only supported SSL3 | Tls10. In
                // this case, SocketProtectionLevel would be set to SocketProtectionLevel.Tls12, which would mean Tls10, Tls11 and Tls12
                // are all acceptable protocols to negotiate. As the server is offering SSL3 | Tls10, the connection would be successfully
                // negotiated using Tls10 which isn't allowed according to the binding configuration.
                SocketProtectionLevel protectionLevel = SocketProtectionLevel.PlainSocket;
                if ((_parent.SslProtocols & SslProtocols.Tls) != SslProtocols.None)
                {
                    protectionLevel = SocketProtectionLevel.Tls10;
                }
                if ((_parent.SslProtocols & SslProtocols.Tls11) != SslProtocols.None)
                {
                    protectionLevel = SocketProtectionLevel.Tls11;
                }
                if ((_parent.SslProtocols & SslProtocols.Tls12) != SslProtocols.None)
                {
                    protectionLevel = SocketProtectionLevel.Tls12;
                }

                // With SslStream, the hostname provided in the server certificate is provided to the client and verified in the callback.
                // With UWP StreamSocket, the hostname needs to be provided to the call to UpgradeToSslAsync. The code to fetch the identity
                // lives in the callback for CoreClr but needs to be pulled into this method for UWP.
                EndpointAddress remoteAddress = RemoteAddress;
                if (remoteAddress.Identity == null && remoteAddress.Uri != Via)
                {
                    remoteAddress = new EndpointAddress(Via);
                }
                EndpointIdentity identity;
                if (!_parent.IdentityVerifier.TryGetIdentity(remoteAddress, out identity))
                {
                    SecurityTraceRecordHelper.TraceIdentityVerificationFailure(identity: identity, authContext: null, identityVerifier: GetType());
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(
                              new MessageSecurityException(SR.Format(SR.IdentityCheckFailedForOutgoingMessage, identity,
                                                                     remoteAddress)));
                }
                Contract.Assert(identity.IdentityClaim.ClaimType == ClaimTypes.Dns);
                string dnsHostName = identity.IdentityClaim.Resource as string;

                // This is the actual call to negotiate an SSL connection
                await rtStreamSocket.UpgradeToSslAsync(protectionLevel, new HostName(dnsHostName)).AsTask();

                // Verify that we didn't negotiate a protocol lower than the binding configuration specified. No need to check Tls12
                // as it will only be negotiated if Tls12 was actually specified.
                var negotiatedProtectionLevel = rtStreamSocket.Information.ProtectionLevel;
                if ((negotiatedProtectionLevel == SocketProtectionLevel.Tls11 && (_parent.SslProtocols & SslProtocols.Tls11) == SslProtocols.None) ||
                    (negotiatedProtectionLevel == SocketProtectionLevel.Tls10 && (_parent.SslProtocols & SslProtocols.Tls) == SslProtocols.None))
                {
                    // Need to dispose StreamSocket as normally SslStream wouldn't end up in a usable state in this situation. As
                    // post-upgrade validation is required in UWP, the connection needs to be Dispose'd to ensure it isn't used.
                    rtStreamSocket.Dispose();
                    throw new SecurityNegotiationException(SR.Format(SR.SSLProtocolNegotiationFailed, _parent.SslProtocols, negotiatedProtectionLevel));
                }

                X509Certificate2   serverCertificate = null;
                X509Certificate2[] chainCertificates = null;
                X509Chain          chain             = null;
                try
                {
                    // Convert the UWP Certificate object to a .Net X509Certificate2.
                    byte[] serverCertificateBlob =
                        rtStreamSocket.Information.ServerCertificate.GetCertificateBlob().ToArray();
                    serverCertificate = new X509Certificate2(serverCertificateBlob);

                    // The chain building and validation logic is done by SslStream in CoreClr. This section of code is based
                    // on the SslStream implementation to try to maintain behavior parity.
                    chain = new X509Chain();
                    chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
                    chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;

                    var serverIntermediateCertificates = rtStreamSocket.Information.ServerIntermediateCertificates;
                    chainCertificates = new X509Certificate2[serverIntermediateCertificates.Count];
                    for (int i = 0; i < chainCertificates.Length; i++)
                    {
                        chainCertificates[i] =
                            new X509Certificate2(serverIntermediateCertificates[i].GetCertificateBlob().ToArray());
                    }
                    chain.ChainPolicy.ExtraStore.AddRange(chainCertificates);

                    chain.Build(serverCertificate);
                    SslPolicyErrors policyErrors = SslPolicyErrors.None;
                    foreach (var serverCertificateError in rtStreamSocket.Information.ServerCertificateErrors)
                    {
                        if (serverCertificateError == ChainValidationResult.InvalidName)
                        {
                            policyErrors |= SslPolicyErrors.RemoteCertificateNameMismatch;
                            continue;
                        }
                        if (serverCertificateError == ChainValidationResult.IncompleteChain)
                        {
                            policyErrors |= SslPolicyErrors.RemoteCertificateChainErrors;
                        }
                    }

                    X509ChainStatus[] chainStatusArray = chain.ChainStatus;
                    if (chainStatusArray != null && chainStatusArray.Length != 0)
                    {
                        policyErrors |= SslPolicyErrors.RemoteCertificateChainErrors;
                    }

                    if (!ValidateRemoteCertificate(this, serverCertificate, chain, policyErrors))
                    {
                        // Need to dispose StreamSocket as normally SslStream wouldn't end up in a usable state in this situation. As
                        // post-upgrade validation is required in UWP, the connection needs to be Dispose'd to ensure it isn't used.
                        rtStreamSocket.Dispose();
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                  new SecurityNegotiationException(SR.ssl_io_cert_validation));
                    }
                }
                finally
                {
                    serverCertificate?.Dispose();
                    chain?.Dispose();
                    if (chainCertificates != null)
                    {
                        foreach (var chainCert in chainCertificates)
                        {
                            chainCert?.Dispose();
                        }
                    }
                }
            }
            catch (SecurityTokenValidationException tokenValidationException)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                          new SecurityNegotiationException(tokenValidationException.Message,
                                                           tokenValidationException));
            }
            catch (IOException ioException)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(
                                                                              SR.Format(SR.NegotiationFailedIO, ioException.Message), ioException));
            }
            catch (Exception exception)
            {
                // In NET Native the WinRT API's can throw the base Exception
                // class with an HRESULT indicating the issue.  However, custom
                // validation code can also throw Exception, and to be compatible
                // with the CoreCLR version, we must allow those exceptions to
                // propagate without wrapping them.  We use the simple heuristic
                // that if an HRESULT has been set to other than the default,
                // the exception should be wrapped in SecurityNegotiationException.
                if (exception.HResult == __HResults.COR_E_EXCEPTION)
                {
                    throw;
                }

                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(
                                                                              exception.Message, exception));
            }

            remoteSecurityWrapper.Value = _serverSecurity;

            return(stream);
        }
        void Initialize(TokenImpersonationLevel tokenImpersonationLevel, NetworkCredential networkCredential, SafeFreeCredentials credentialsHandle, ChannelBinding channelBinding)
        {
            bool ownCredentialsHandle         = false;
            SafeDeleteContext securityContext = null;

            try
            {
                if (credentialsHandle == null)
                {
                    if (networkCredential == null || networkCredential == CredentialCache.DefaultNetworkCredentials)
                    {
                        credentialsHandle = SspiWrapper.AcquireDefaultCredential("Kerberos", CredentialUse.Outbound);
                    }
                    else
                    {
                        AuthIdentityEx authIdentity = new AuthIdentityEx(networkCredential.UserName, networkCredential.Password, networkCredential.Domain);
                        credentialsHandle = SspiWrapper.AcquireCredentialsHandle("Kerberos", CredentialUse.Outbound, ref authIdentity);
                    }
                    ownCredentialsHandle = true;
                }

                SspiContextFlags fContextReq = SspiContextFlags.AllocateMemory
                                               | SspiContextFlags.Confidentiality
                                               | SspiContextFlags.ReplayDetect
                                               | SspiContextFlags.SequenceDetect;


                // we only accept Identity or Impersonation (Impersonation is default).
                if (tokenImpersonationLevel == TokenImpersonationLevel.Identification)
                {
                    fContextReq |= SspiContextFlags.InitIdentify;
                }

                SspiContextFlags contextFlags     = SspiContextFlags.Zero;
                SecurityBuffer   inSecurityBuffer = null;
                if (channelBinding != null)
                {
                    inSecurityBuffer = new SecurityBuffer(channelBinding);
                }
                SecurityBuffer outSecurityBuffer = new SecurityBuffer(0, BufferType.Token);

                int statusCode = SspiWrapper.InitializeSecurityContext(
                    credentialsHandle,
                    ref securityContext,
                    this.servicePrincipalName,
                    fContextReq,
                    Endianness.Native,
                    inSecurityBuffer,
                    outSecurityBuffer,
                    ref contextFlags);

                if (DiagnosticUtility.ShouldTraceInformation)
                {
                    SecurityTraceRecordHelper.TraceChannelBindingInformation(null, false, channelBinding);
                }

                if (statusCode != (int)SecurityStatus.OK)
                {
                    if (statusCode == (int)SecurityStatus.ContinueNeeded)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                  new SecurityTokenException(SR.GetString(SR.KerberosMultilegsNotSupported), new Win32Exception(statusCode)));
                    }
                    else
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                  new SecurityTokenException(SR.GetString(SR.FailInitializeSecurityContext), new Win32Exception(statusCode)));
                    }
                }

#if REMOVEGSS
                //
                // ... and strip GSS-framing from it
                //
                int offset = 0;
                int len    = outSecurityBuffer.token.Length;
                DEREncoding.VerifyTokenHeader(outSecurityBuffer.token, ref offset, ref len);
                this.apreq = SecurityUtils.CloneBuffer(outSecurityBuffer.token, offset, len);
#else
                this.apreq = outSecurityBuffer.token;
#endif

                // Expiration
                LifeSpan lifeSpan = (LifeSpan)SspiWrapper.QueryContextAttributes(securityContext, ContextAttribute.Lifespan);
                this.effectiveTime  = lifeSpan.EffectiveTimeUtc;
                this.expirationTime = lifeSpan.ExpiryTimeUtc;

                // SessionKey
                SecuritySessionKeyClass sessionKey = (SecuritySessionKeyClass)SspiWrapper.QueryContextAttributes(securityContext, ContextAttribute.SessionKey);
                this.symmetricSecurityKey = new InMemorySymmetricSecurityKey(sessionKey.SessionKey);
            }
            finally
            {
                if (securityContext != null)
                {
                    securityContext.Close();
                }

                if (ownCredentialsHandle && credentialsHandle != null)
                {
                    credentialsHandle.Close();
                }
            }
        }
示例#30
0
        Message ProcessRequestCore(Message request)
        {
            if (request == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("request");
            }
            Uri to = null;
            RequestSecurityToken         rst  = null;
            RequestSecurityTokenResponse rstr = null;
            string context              = null;
            bool   disposeRequest       = false;
            bool   isNegotiationFailure = true;
            T      negotiationState     = null;

            try
            {
                // validate the message size if needed
                if (this.maxMessageSize < int.MaxValue)
                {
                    string action = request.Headers.Action;
                    try
                    {
                        using (MessageBuffer buffer = request.CreateBufferedCopy(this.maxMessageSize))
                        {
                            request        = buffer.CreateMessage();
                            disposeRequest = true;
                        }
                    }
                    catch (QuotaExceededException e)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.SecurityNegotiationMessageTooLarge, action, this.maxMessageSize), e));
                    }
                }
                try
                {
                    to = request.Headers.To;
                    ParseMessageBody(request, out context, out rst, out rstr);
                    // check if there is existing state
                    if (context != null)
                    {
                        negotiationState = this.stateCache.GetState(context);
                    }
                    else
                    {
                        negotiationState = null;
                    }
                    bool       disposeState = false;
                    BodyWriter replyBody;
                    try
                    {
                        if (rst != null)
                        {
                            if (negotiationState != null)
                            {
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.NegotiationStateAlreadyPresent, context)));
                            }
                            replyBody = this.ProcessRequestSecurityToken(request, rst, out negotiationState);
                            lock (negotiationState.ThisLock)
                            {
                                if (negotiationState.IsNegotiationCompleted)
                                {
                                    // if session-sct add it to cache and add a redirect header
                                    if (!negotiationState.ServiceToken.IsCookieMode)
                                    {
                                        this.IssuedTokenCache.AddContext(negotiationState.ServiceToken);
                                    }
                                    this.OnTokenIssued(negotiationState.ServiceToken);
                                    SecurityTraceRecordHelper.TraceServiceSecurityNegotiationCompleted(request, this, negotiationState.ServiceToken);
                                    disposeState = true;
                                }
                                else
                                {
                                    this.stateCache.AddState(context, negotiationState);
                                    disposeState = false;
                                }
                                AddNegotiationChannelForIdleTracking();
                            }
                        }
                        else
                        {
                            if (negotiationState == null)
                            {
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.CannotFindNegotiationState, context)));
                            }
                            lock (negotiationState.ThisLock)
                            {
                                replyBody = this.ProcessRequestSecurityTokenResponse(negotiationState, request, rstr);
                                if (negotiationState.IsNegotiationCompleted)
                                {
                                    // if session-sct add it to cache and add a redirect header
                                    if (!negotiationState.ServiceToken.IsCookieMode)
                                    {
                                        this.IssuedTokenCache.AddContext(negotiationState.ServiceToken);
                                    }
                                    this.OnTokenIssued(negotiationState.ServiceToken);
                                    SecurityTraceRecordHelper.TraceServiceSecurityNegotiationCompleted(request, this, negotiationState.ServiceToken);
                                    disposeState = true;
                                }
                                else
                                {
                                    disposeState = false;
                                }
                            }
                        }

                        if (negotiationState.IsNegotiationCompleted && null != this.ListenUri)
                        {
                            if (AuditLevel.Success == (this.messageAuthenticationAuditLevel & AuditLevel.Success))
                            {
                                string primaryIdentity = negotiationState.GetRemoteIdentityName();
                                SecurityAuditHelper.WriteSecurityNegotiationSuccessEvent(this.auditLogLocation,
                                                                                         this.suppressAuditFailure, request, request.Headers.To, request.Headers.Action,
                                                                                         primaryIdentity, this.GetType().Name);
                            }
                        }
                        isNegotiationFailure = false;
                    }
                    catch (Exception exception)
                    {
                        if (Fx.IsFatal(exception))
                        {
                            throw;
                        }

                        if (PerformanceCounters.PerformanceCountersEnabled && null != this.ListenUri)
                        {
                            PerformanceCounters.AuthenticationFailed(request, this.ListenUri);
                        }
                        if (AuditLevel.Failure == (this.messageAuthenticationAuditLevel & AuditLevel.Failure))
                        {
                            try
                            {
                                string primaryIdentity = (negotiationState != null) ? negotiationState.GetRemoteIdentityName() : String.Empty;
                                SecurityAuditHelper.WriteSecurityNegotiationFailureEvent(this.auditLogLocation,
                                                                                         this.suppressAuditFailure, request, request.Headers.To, request.Headers.Action,
                                                                                         primaryIdentity, this.GetType().Name, exception);
                            }
#pragma warning suppress 56500
                            catch (Exception auditException)
                            {
                                if (Fx.IsFatal(auditException))
                                {
                                    throw;
                                }

                                DiagnosticUtility.TraceHandledException(auditException, TraceEventType.Error);
                            }
                        }

                        disposeState = true;
                        throw;
                    }
                    finally
                    {
                        if (disposeState)
                        {
                            if (negotiationState != null)
                            {
                                if (context != null)
                                {
                                    stateCache.RemoveState(context);
                                }
                                negotiationState.Dispose();
                            }
                        }
                    }

                    return(CreateReply(request, (replyBody is RequestSecurityTokenResponseCollection) ? RequestSecurityTokenResponseFinalAction : RequestSecurityTokenResponseAction, replyBody));
                }
                finally
                {
                    if (disposeRequest)
                    {
                        request.Close();
                    }
                }
            }
            finally
            {
                if (isNegotiationFailure)
                {
                    AddNegotiationChannelForIdleTracking();
                }
                else if (negotiationState != null && negotiationState.IsNegotiationCompleted)
                {
                    RemoveNegotiationChannelFromIdleTracking();
                }
            }
        }