IssuanceTokenProviderBase.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Security / IssuanceTokenProviderBase.cs / 1 / IssuanceTokenProviderBase.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.ServiceModel.Security
{ 
    using System.IdentityModel.Claims;
    using System.ServiceModel; 
    using System.IdentityModel.Policy; 
    using System.IdentityModel.Tokens;
    using System.Security.Principal; 
    using System.Security.Cryptography.X509Certificates;
    using System.ServiceModel.Security.Tokens;
    using System.Collections.Generic;
    using System.Collections.ObjectModel; 
    using System.ServiceModel.Channels;
    using System.Net; 
    using System.Globalization; 
    using System.Diagnostics;
    using System.Runtime.Serialization; 
    using System.Runtime.InteropServices;
    using System.ServiceModel.Diagnostics;
    using System.Xml;
 
    /*
     * IssuanceTokenProviderBase is a base class for token providers that fetch tokens from 
     * another party. 
     * This class manages caching of tokens, async messaging, concurrency
     */ 
    abstract class IssuanceTokenProviderBase : CommunicationObjectSecurityTokenProvider
        where T : IssuanceTokenProviderState
    {
        internal const string defaultClientMaxTokenCachingTimeString = "10675199.02:48:05.4775807"; 
        internal const bool defaultClientCacheTokens = true;
        internal const int defaultServiceTokenValidityThresholdPercentage = 60; 
 
        // if an issuer is explicitly specified it will be used otherwise target is the issuer
        EndpointAddress issuerAddress; 
        // the target service's address and via
        EndpointAddress targetAddress;
        Uri via = null;
 
        // This controls whether the token provider caches the service tokens it obtains
        bool cacheServiceTokens = defaultClientCacheTokens; 
        // This is a fudge factor that controls how long the client can use a service token 
        int serviceTokenValidityThresholdPercentage = defaultServiceTokenValidityThresholdPercentage;
        // the maximum time that the client is willing to cache service tokens 
        TimeSpan maxServiceTokenCachingTime;

        SecurityStandardsManager standardsManager;
        SecurityAlgorithmSuite algorithmSuite; 
        ChannelProtectionRequirements applicationProtectionRequirements;
        SecurityToken cachedToken; 
        Object thisLock = new Object(); 

        string sctUri; 

        protected IssuanceTokenProviderBase() : base()
        {
            this.cacheServiceTokens = defaultClientCacheTokens; 
            this.serviceTokenValidityThresholdPercentage = defaultServiceTokenValidityThresholdPercentage;
            this.maxServiceTokenCachingTime = DefaultClientMaxTokenCachingTime; 
            this.standardsManager = null; 
        }
 
        // settings
        public EndpointAddress IssuerAddress
        {
            get 
            {
                return this.issuerAddress; 
            } 
            set
            { 
                this.CommunicationObject.ThrowIfDisposedOrImmutable();
                this.issuerAddress = value;
            }
        } 

        public EndpointAddress TargetAddress 
        { 
            get
            { 
                return this.targetAddress;
            }
            set
            { 
                this.CommunicationObject.ThrowIfDisposedOrImmutable();
                this.targetAddress = value; 
            } 
        }
 
        public bool CacheServiceTokens
        {
            get
            { 
                return this.cacheServiceTokens;
            } 
            set 
            {
                this.CommunicationObject.ThrowIfDisposedOrImmutable(); 
                this.cacheServiceTokens = value;
            }
        }
 
        internal static TimeSpan DefaultClientMaxTokenCachingTime
        { 
            get 
            {
                DiagnosticUtility.DebugAssert(TimeSpan.Parse(defaultClientMaxTokenCachingTimeString) == TimeSpan.MaxValue, "TimeSpan value not correct"); 
                return TimeSpan.MaxValue;
            }
        }
 
        public int ServiceTokenValidityThresholdPercentage
        { 
            get 
            {
                return this.serviceTokenValidityThresholdPercentage; 
            }
            set
            {
                this.CommunicationObject.ThrowIfDisposedOrImmutable(); 
                if (value <= 0 || value > 100)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.ValueMustBeInRange, 1, 100))); 
                }
                this.serviceTokenValidityThresholdPercentage = value; 
            }
        }

        public SecurityAlgorithmSuite SecurityAlgorithmSuite 
        {
            get 
            { 
                return this.algorithmSuite;
            } 
            set
            {
                this.CommunicationObject.ThrowIfDisposedOrImmutable();
                this.algorithmSuite = value; 
            }
        } 
 
        public TimeSpan MaxServiceTokenCachingTime
        { 
            get
            {
                return this.maxServiceTokenCachingTime;
            } 
            set
            { 
                this.CommunicationObject.ThrowIfDisposedOrImmutable(); 
                if (value <= TimeSpan.Zero)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.TimeSpanMustbeGreaterThanTimeSpanZero)));
                }

                if (TimeoutHelper.IsTooLarge(value)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, 
                        SR.GetString(SR.SFxTimeoutOutOfRangeTooBig))); 
                }
 
                this.maxServiceTokenCachingTime = value;
            }
        }
 

        public SecurityStandardsManager StandardsManager 
        { 
            get
            { 
                if (this.standardsManager == null)
                    return SecurityStandardsManager.DefaultInstance;
                return this.standardsManager;
            } 
            set
            { 
                this.CommunicationObject.ThrowIfDisposedOrImmutable(); 
                this.standardsManager = value;
            } 
        }

        public ChannelProtectionRequirements ApplicationProtectionRequirements
        { 
            get
            { 
                return this.applicationProtectionRequirements; 
            }
            set 
            {
                this.CommunicationObject.ThrowIfDisposedOrImmutable();
                this.applicationProtectionRequirements = value;
            } 
        }
 
        public Uri Via 
        {
            get 
            {
                return this.via;
            }
            set 
            {
                this.CommunicationObject.ThrowIfDisposedOrImmutable(); 
                this.via = value; 
            }
        } 

        public override bool SupportsTokenCancellation
        {
            get 
            {
                return true; 
            } 
        }
 
        protected Object ThisLock
        {
            get { return this.thisLock; }
        } 

        protected virtual bool IsMultiLegNegotiation 
        { 
            get { return true; }
        } 

        protected abstract MessageVersion MessageVersion
        {
            get; 
        }
 
        protected abstract bool RequiresManualReplyAddressing 
        {
            get; 
        }

        public abstract XmlDictionaryString RequestSecurityTokenAction
        { 
            get;
        } 
 
        public abstract XmlDictionaryString RequestSecurityTokenResponseAction
        { 
            get;
        }

        protected string SecurityContextTokenUri 
        {
            get 
            { 
                ThrowIfCreated();
                return this.sctUri; 
            }
        }

        protected void ThrowIfCreated() 
        {
            CommunicationState state = this.CommunicationObject.State; 
            if (state == CommunicationState.Created) 
            {
                Exception e = new InvalidOperationException(SR.GetString(SR.CommunicationObjectCannotBeUsed, this.GetType().ToString(), state.ToString())); 
                throw TraceUtility.ThrowHelperError(e, Guid.Empty, this);
            }
        }
 
        protected void ThrowIfClosedOrCreated()
        { 
            this.CommunicationObject.ThrowIfClosed(); 
            ThrowIfCreated();
        } 

        // ISecurityCommunicationObject methods
        public override void OnOpen(TimeSpan timeout)
        { 
            if (this.targetAddress == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TargetAddressIsNotSet, this.GetType()))); 
            }
            if (this.SecurityAlgorithmSuite == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SecurityAlgorithmSuiteNotSet, this.GetType())));
            }
            this.sctUri = this.StandardsManager.SecureConversationDriver.TokenTypeUri; 
        }
 
        // helper methods 
        protected void EnsureEndpointAddressDoesNotRequireEncryption(EndpointAddress target)
        { 
          if (this.ApplicationProtectionRequirements == null
                || this.ApplicationProtectionRequirements.OutgoingEncryptionParts == null)
            {
                return; 
            }
            MessagePartSpecification channelEncryptionParts = this.ApplicationProtectionRequirements.OutgoingEncryptionParts.ChannelParts; 
            if (channelEncryptionParts == null) 
            {
                return; 
            }
            for (int i = 0; i < this.targetAddress.Headers.Count; ++i)
            {
                AddressHeader header = target.Headers[i]; 
                if (channelEncryptionParts.IsHeaderIncluded(header.Name, header.Namespace))
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.SecurityNegotiationCannotProtectConfidentialEndpointHeader, target, header.Name, header.Namespace))); 
                }
            } 
        }

        DateTime GetServiceTokenEffectiveExpirationTime(SecurityToken serviceToken)
        { 
            // if the token never expires, return the max date time
            // else return effective expiration time 
            if (serviceToken.ValidTo.ToUniversalTime() >= SecurityUtils.MaxUtcDateTime) 
            {
                return serviceToken.ValidTo; 
            }

            TimeSpan interval = serviceToken.ValidTo.ToUniversalTime() - serviceToken.ValidFrom.ToUniversalTime();
            long serviceTokenTicksInterval = interval.Ticks; 
            long effectiveTicksInterval = Convert.ToInt64((double) this.ServiceTokenValidityThresholdPercentage / 100.0 * (double) serviceTokenTicksInterval, NumberFormatInfo.InvariantInfo);
            DateTime effectiveExpirationTime = TimeoutHelper.Add(serviceToken.ValidFrom.ToUniversalTime(), new TimeSpan(effectiveTicksInterval)); 
            DateTime maxCachingTime = TimeoutHelper.Add(serviceToken.ValidFrom.ToUniversalTime(), this.MaxServiceTokenCachingTime); 
            if (effectiveExpirationTime <= maxCachingTime)
            { 
                return effectiveExpirationTime;
            }
            else
            { 
                return maxCachingTime;
            } 
        } 

        bool IsServiceTokenTimeValid(SecurityToken serviceToken) 
        {
            DateTime effectiveExpirationTime = GetServiceTokenEffectiveExpirationTime(serviceToken);
            return (DateTime.UtcNow <= effectiveExpirationTime);
        } 

        SecurityToken GetCurrentServiceToken() 
        { 
            if (this.CacheServiceTokens && this.cachedToken != null && IsServiceTokenTimeValid(cachedToken))
            { 
                return this.cachedToken;
            }
            else
            { 
                return null;
            } 
        } 

        static protected void ThrowIfFault(Message message, EndpointAddress target) 
        {
            SecurityUtils.ThrowIfNegotiationFault(message, target);
        }
 
        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 TypedCompletedAsyncResult(token, callback, state); 
                } 
                else
                { 
                    asyncResult = BeginNegotiation(timeout, callback, state);
                }
            }
            return asyncResult; 
        }
 
        protected override SecurityToken EndGetTokenCore(IAsyncResult result) 
        {
            if (result is TypedCompletedAsyncResult) 
            {
                return TypedCompletedAsyncResult.End(result);
            }
            else 
            {
                return this.EndNegotiation(result); 
            } 
        }
 
        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;
        } 

        protected override void CancelTokenCore(TimeSpan timeout, SecurityToken token)
        {
            if (this.CacheServiceTokens) 
            {
                lock (ThisLock) 
                { 
                    if (Object.ReferenceEquals(token, this.cachedToken))
                    { 
                        this.cachedToken = null;
                    }
                }
            } 
        }
 
        // Negotiation state creation methods 
        protected abstract bool CreateNegotiationStateCompletesSynchronously(EndpointAddress target, Uri via);
        protected abstract IAsyncResult BeginCreateNegotiationState(EndpointAddress target, Uri via, TimeSpan timeout, AsyncCallback callback, object state); 
        protected abstract T CreateNegotiationState(EndpointAddress target, Uri via, TimeSpan timeout);
        protected abstract T EndCreateNegotiationState(IAsyncResult result);

        // Negotiation message processing methods 
        protected abstract BodyWriter GetFirstOutgoingMessageBody(T negotiationState, out MessageProperties properties);
        protected abstract BodyWriter GetNextOutgoingMessageBody(Message incomingMessage, T negotiationState); 
        protected abstract bool WillInitializeChannelFactoriesCompleteSynchronously(EndpointAddress target); 
        protected abstract void InitializeChannelFactories(EndpointAddress target, TimeSpan timeout);
        protected abstract IAsyncResult BeginInitializeChannelFactories(EndpointAddress target, TimeSpan timeout, AsyncCallback callback, object state); 
        protected abstract void EndInitializeChannelFactories(IAsyncResult result);
        protected abstract IRequestChannel CreateClientChannel(EndpointAddress target, Uri via);

        void PrepareRequest(Message nextMessage) 
        {
            RequestReplyCorrelator.PrepareRequest(nextMessage); 
            if (this.RequiresManualReplyAddressing) 
            {
                // if we are on HTTP, we need to explicitly add a reply-to header for interop 
                nextMessage.Headers.ReplyTo = EndpointAddress.AnonymousAddress;
            }
        }
 
        /*
        *   Negotiation consists of the following steps (some may be async in the async case): 
        *   1. Create negotiation state 
        *   2. Initialize channel factories
        *   3. Create an channel 
        *   4. Open the channel
        *   5. Create the next message to send to server
        *   6. Send the message and get reply
        *   8. Process incoming message and get next outgoing message. 
        *   9. If no outgoing message, then negotiation is over. Go to step 11.
        *   10. Goto step 6 
        *   11. Close the IRequest channel and complete 
        */
        protected SecurityToken DoNegotiation(TimeSpan timeout) 
        {
            ThrowIfClosedOrCreated();
            SecurityTraceRecordHelper.TraceBeginSecurityNegotiation(this, this.targetAddress);
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            IRequestChannel rstChannel = null;
            T negotiationState = null; 
            TimeSpan timeLeft = timeout; 
            int legs = 1;
            try 
            {
                negotiationState = this.CreateNegotiationState(this.targetAddress, this.via, timeoutHelper.RemainingTime());
                InitializeNegotiationState(negotiationState);
                this.InitializeChannelFactories(negotiationState.RemoteAddress, timeoutHelper.RemainingTime()); 
                rstChannel = this.CreateClientChannel(negotiationState.RemoteAddress, this.via);
                rstChannel.Open(timeoutHelper.RemainingTime()); 
                Message nextOutgoingMessage = null; 
                Message incomingMessage = null;
                SecurityToken serviceToken = null; 
                for (; ; )
                {
                    nextOutgoingMessage = this.GetNextOutgoingMessage(incomingMessage, negotiationState);
                    if (incomingMessage != null) 
                    {
                        incomingMessage.Close(); 
                    } 
                    if (nextOutgoingMessage != null)
                    { 
                        using (nextOutgoingMessage)
                        {
                            TraceUtility.ProcessOutgoingMessage(nextOutgoingMessage);
                            timeLeft = timeoutHelper.RemainingTime(); 
                            incomingMessage = rstChannel.Request(nextOutgoingMessage, timeLeft);
                            if (incomingMessage == null) 
                            { 
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.FailToRecieveReplyFromNegotiation)));
                            } 
                            TraceUtility.ProcessIncomingMessage(incomingMessage);
                        }
                        legs += 2;
                    } 
                    else
                    { 
                        if (!negotiationState.IsNegotiationCompleted) 
                        {
                            throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.NoNegotiationMessageToSend)), incomingMessage); 
                        }

                        try
                        { 
                            rstChannel.Close(timeoutHelper.RemainingTime());
                        } 
                        catch (CommunicationException e) 
                        {
                            if (DiagnosticUtility.ShouldTraceInformation) 
                            {
                                DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                            }
 
                            rstChannel.Abort();
                        } 
                        catch (TimeoutException e) 
                        {
                            if (DiagnosticUtility.ShouldTraceInformation) 
                            {
                                DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                            }
 
                            rstChannel.Abort();
                        } 
 
                        rstChannel = null;
                        this.ValidateAndCacheServiceToken(negotiationState); 
                        serviceToken = negotiationState.ServiceToken;
                        SecurityTraceRecordHelper.TraceEndSecurityNegotiation(this, serviceToken, this.targetAddress);
                        break;
                    } 
                }
                return serviceToken; 
            } 
            catch (Exception e)
            { 
                if (DiagnosticUtility.IsFatal(e))
                {
                    throw;
                } 

                if (e is TimeoutException) 
                { 
                    e = new TimeoutException(SR.GetString(SR.ClientSecurityNegotiationTimeout, timeout, legs, timeLeft), e);
                } 
                EndpointAddress temp = (negotiationState == null) ? null : negotiationState.RemoteAddress;
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WrapExceptionIfRequired(e, temp, this.issuerAddress ));
            }
            finally 
            {
                Cleanup(rstChannel, negotiationState); 
            } 
        }
 
        void InitializeNegotiationState(T negotiationState)
        {
            negotiationState.TargetAddress = this.targetAddress;
            if (negotiationState.Context == null && this.IsMultiLegNegotiation) 
            {
                negotiationState.Context = SecurityUtils.GenerateId(); 
            } 
            if (this.IssuerAddress != null)
            { 
                negotiationState.RemoteAddress = this.IssuerAddress;
            }
            else
            { 
                negotiationState.RemoteAddress = negotiationState.TargetAddress;
            } 
        } 

        Message GetNextOutgoingMessage(Message incomingMessage, T negotiationState) 
        {
            BodyWriter nextMessageBody;
            MessageProperties nextMessageProperties = null;
            if (incomingMessage == null) 
            {
                nextMessageBody = this.GetFirstOutgoingMessageBody(negotiationState, out nextMessageProperties); 
            } 
            else
            { 
                nextMessageBody = this.GetNextOutgoingMessageBody(incomingMessage, negotiationState);
            }
            if (nextMessageBody != null)
            { 
                Message nextMessage;
                if (incomingMessage == null) 
                { 
                    nextMessage = Message.CreateMessage(this.MessageVersion, ActionHeader.Create(this.RequestSecurityTokenAction, this.MessageVersion.Addressing), nextMessageBody);
                } 
                else
                {
                    nextMessage = Message.CreateMessage(this.MessageVersion, ActionHeader.Create(this.RequestSecurityTokenResponseAction, this.MessageVersion.Addressing), nextMessageBody);
                } 
                if (nextMessageProperties != null)
                { 
                    nextMessage.Properties.CopyProperties(nextMessageProperties); 
                }
                PrepareRequest(nextMessage); 
                return nextMessage;
            }
            else
            { 
                return null;
            } 
        } 

        void Cleanup(IChannel rstChannel, T negotiationState) 
        {
            if (negotiationState != null)
            {
                negotiationState.Dispose(); 
            }
            if (rstChannel != null) 
            { 
                rstChannel.Abort();
            } 
        }

        protected IAsyncResult BeginNegotiation(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            ThrowIfClosedOrCreated();
            SecurityTraceRecordHelper.TraceBeginSecurityNegotiation(this, this.targetAddress); 
            return new SecurityNegotiationAsyncResult(this, timeout, callback, state); 
        }
 
        protected SecurityToken EndNegotiation(IAsyncResult result)
        {
            SecurityToken token = SecurityNegotiationAsyncResult.End(result);
            SecurityTraceRecordHelper.TraceEndSecurityNegotiation(this, token, this.targetAddress); 
            return token;
        } 
 
        protected virtual void ValidateKeySize(GenericXmlSecurityToken issuedToken)
        { 
            if (this.SecurityAlgorithmSuite == null)
            {
                return;
            } 
            ReadOnlyCollection issuedKeys = issuedToken.SecurityKeys;
            if (issuedKeys != null && issuedKeys.Count == 1) 
            { 
                SymmetricSecurityKey symmetricKey = issuedKeys[0] as SymmetricSecurityKey;
                if (symmetricKey != null) 
                {
                    if (this.SecurityAlgorithmSuite.IsSymmetricKeyLengthSupported(symmetricKey.KeySize))
                    {
                        return; 
                    }
                    else 
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.InvalidIssuedTokenKeySize, symmetricKey.KeySize)));
                    } 
                }
            }
            else
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.CannotObtainIssuedTokenKeySize)));
            } 
        } 

        static bool ShouldWrapException(Exception e) 
        {
            return (e is System.ComponentModel.Win32Exception
                || e is XmlException
                || e is InvalidOperationException 
                || e is ArgumentException
                || e is QuotaExceededException 
                || e is System.Security.SecurityException 
                || e is System.Security.Cryptography.CryptographicException
                || e is SecurityTokenException); 
        }

        static Exception WrapExceptionIfRequired(Exception e, EndpointAddress targetAddress, EndpointAddress issuerAddress)
        { 
            if (ShouldWrapException(e))
            { 
                Uri targetUri; 
                if (targetAddress != null)
                { 
                    targetUri = targetAddress.Uri;
                }
                else
                { 
                    targetUri = null;
                } 
 
                Uri issuerUri;
                if (issuerAddress != null) 
                {
                    issuerUri = issuerAddress.Uri;
                }
                else 
                {
                    issuerUri = targetUri; 
                } 

                // => issuerUri != null 
                if (targetUri != null)
                {
                    e = new SecurityNegotiationException(SR.GetString(SR.SoapSecurityNegotiationFailedForIssuerAndTarget, issuerUri, targetUri), e);
                } 
                else
                { 
                    e = new SecurityNegotiationException(SR.GetString(SR.SoapSecurityNegotiationFailed), e); 
                }
            } 
            return e;
        }

        void ValidateAndCacheServiceToken(T negotiationState) 
        {
            this.ValidateKeySize(negotiationState.ServiceToken); 
            lock (ThisLock) 
            {
                if (this.CacheServiceTokens) 
                {
                    this.cachedToken = negotiationState.ServiceToken;
                }
            } 
        }
 
        class SecurityNegotiationAsyncResult : AsyncResult 
        {
            static AsyncCallback createNegotiationStateCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(CreateNegotiationStateCallback)); 
            static AsyncCallback initializeChannelFactoriesCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(InitializeChannelFactoriesCallback));
            static AsyncCallback closeChannelCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(CloseChannelCallback));
            static AsyncCallback sendRequestCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(SendRequestCallback));
            static AsyncCallback openChannelCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OpenChannelCallback)); 

            TimeSpan timeout; 
            TimeoutHelper timeoutHelper; 
            SecurityToken serviceToken;
            IssuanceTokenProviderBase tokenProvider; 
            IRequestChannel rstChannel;
            T negotiationState;
            Message nextOutgoingMessage;
            EndpointAddress target; 
            EndpointAddress issuer;
            Uri via; 
 
            public SecurityNegotiationAsyncResult(IssuanceTokenProviderBase tokenProvider, TimeSpan timeout, AsyncCallback callback, object state)
                : base(callback, state) 
            {
                this.timeout = timeout;
                timeoutHelper = new TimeoutHelper(timeout);
                this.tokenProvider = tokenProvider; 
                this.target = tokenProvider.targetAddress;
                this.issuer = tokenProvider.issuerAddress; 
                this.via = tokenProvider.via; 
                bool completeSelf = false;
                try 
                {
                    completeSelf = this.StartNegotiation();
                }
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e)) 
                    {
                        throw; 
                    }
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(this.OnSyncNegotiationFailure(e));
                }
                if (completeSelf) 
                {
                    this.OnNegotiationComplete(); 
                    Complete(true); 
                }
            } 

            bool StartNegotiation()
            {
                if (this.tokenProvider.CreateNegotiationStateCompletesSynchronously(this.target, this.via)) 
                {
                    this.negotiationState = this.tokenProvider.CreateNegotiationState(target, this.via, timeoutHelper.RemainingTime()); 
                } 
                else
                { 
                    IAsyncResult createStateResult = this.tokenProvider.BeginCreateNegotiationState(target, this.via, timeoutHelper.RemainingTime(), createNegotiationStateCallback, this);
                    if (!createStateResult.CompletedSynchronously)
                    {
                        return false; 
                    }
                    this.negotiationState = this.tokenProvider.EndCreateNegotiationState(createStateResult); 
                } 
                return this.OnCreateStateComplete();
            } 

            static void CreateNegotiationStateCallback(IAsyncResult result)
            {
                if (result.CompletedSynchronously) 
                {
                    return; 
                } 
                SecurityNegotiationAsyncResult self = (SecurityNegotiationAsyncResult)result.AsyncState;
                bool completeSelf = false; 
                Exception completionException = null;
                try
                {
                    self.negotiationState = self.tokenProvider.EndCreateNegotiationState(result); 
                    completeSelf = self.OnCreateStateComplete();
                    if (completeSelf) 
                    { 
                        self.OnNegotiationComplete();
                    } 
                }
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e)
                { 
                    if (Diagnostics.ExceptionUtility.IsFatal(e))
                        throw; 
 
                    completeSelf = true;
                    completionException = self.OnAsyncNegotiationFailure(e); 
                }
                if (completeSelf)
                {
                    self.Complete(false, completionException); 
                }
            } 
 
            bool OnCreateStateComplete()
            { 
                this.tokenProvider.InitializeNegotiationState(negotiationState);
                return InitializeChannelFactories();
            }
 
            bool InitializeChannelFactories()
            { 
                if (this.tokenProvider.WillInitializeChannelFactoriesCompleteSynchronously(negotiationState.RemoteAddress)) 
                {
                    this.tokenProvider.InitializeChannelFactories(negotiationState.RemoteAddress, timeoutHelper.RemainingTime()); 
                }
                else
                {
                    IAsyncResult result = this.tokenProvider.BeginInitializeChannelFactories(negotiationState.RemoteAddress, timeoutHelper.RemainingTime(), initializeChannelFactoriesCallback, this); 
                    if (!result.CompletedSynchronously)
                    { 
                        return false; 
                    }
                    this.tokenProvider.EndInitializeChannelFactories(result); 
                }
                return this.OnChannelFactoriesInitialized();
            }
 
            static void InitializeChannelFactoriesCallback(IAsyncResult result)
            { 
                if (result.CompletedSynchronously) 
                {
                    return; 
                }

                SecurityNegotiationAsyncResult self = (SecurityNegotiationAsyncResult)result.AsyncState;
                bool completeSelf = false; 
                Exception completionException = null;
                try 
                { 
                    self.tokenProvider.EndInitializeChannelFactories(result);
                    completeSelf = self.OnChannelFactoriesInitialized(); 
                    if (completeSelf)
                    {
                        self.OnNegotiationComplete();
                    } 
                }
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e) 
                {
                    if (Diagnostics.ExceptionUtility.IsFatal(e)) 
                        throw;

                    completeSelf = true;
                    completionException = self.OnAsyncNegotiationFailure(e); 
                }
                if (completeSelf) 
                { 
                    self.Complete(false, completionException);
                } 
            }

            bool OnChannelFactoriesInitialized()
            { 
                this.rstChannel = this.tokenProvider.CreateClientChannel(negotiationState.RemoteAddress, this.via);
                this.nextOutgoingMessage = null; 
                return this.OnRequestChannelCreated(); 
            }
 
            bool OnRequestChannelCreated()
            {
                IAsyncResult result = rstChannel.BeginOpen(timeoutHelper.RemainingTime(), openChannelCallback, this);
                if (!result.CompletedSynchronously) 
                {
                    return false; 
                } 
                rstChannel.EndOpen(result);
                return this.OnRequestChannelOpened(); 
            }

            static void OpenChannelCallback(IAsyncResult result)
            { 
                if (result.CompletedSynchronously)
                { 
                    return; 
                }
                SecurityNegotiationAsyncResult self = (SecurityNegotiationAsyncResult)result.AsyncState; 
                bool completeSelf = false;
                Exception completionException = null;
                try
                { 
                    self.rstChannel.EndOpen(result);
                    completeSelf = self.OnRequestChannelOpened(); 
                    if (completeSelf) 
                    {
                        self.OnNegotiationComplete(); 
                    }
                }
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e) 
                {
                    if (Diagnostics.ExceptionUtility.IsFatal(e)) 
                        throw; 

                    completeSelf = true; 
                    completionException = self.OnAsyncNegotiationFailure(e);
                }
                if (completeSelf)
                { 
                    self.Complete(false, completionException);
                } 
            } 

            bool OnRequestChannelOpened() 
            {
                return this.SendRequest();
            }
 
            bool SendRequest()
            { 
                if (this.nextOutgoingMessage == null) 
                {
                    return this.DoNegotiation(null); 
                }
                else
                {
                    this.tokenProvider.PrepareRequest(this.nextOutgoingMessage); 
                    bool closeMessage = true;
                    Message incomingMessage = null; 
 
                    IAsyncResult result = null;
                    try 
                    {
                        result = this.rstChannel.BeginRequest(this.nextOutgoingMessage, timeoutHelper.RemainingTime(), sendRequestCallback, this);

                        if (!result.CompletedSynchronously) 
                        {
                            closeMessage = false; 
                            return false; 
                        }
 

                        incomingMessage = rstChannel.EndRequest(result);
                    }
                    finally 
                    {
                        if (closeMessage && this.nextOutgoingMessage != null) 
                        { 
                            this.nextOutgoingMessage.Close();
                        } 
                    }

                    using (incomingMessage)
                    { 
                        if (incomingMessage == null)
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.FailToRecieveReplyFromNegotiation))); 
                        }
                        return this.DoNegotiation(incomingMessage); 
                    }
                }
            }
 
            static void SendRequestCallback(IAsyncResult result)
            { 
                if (result.CompletedSynchronously) 
                {
                    return; 
                }
                SecurityNegotiationAsyncResult self = (SecurityNegotiationAsyncResult)result.AsyncState;
                bool completeSelf = false;
                Exception completionException = null; 
                try
                { 
                    Message incomingMessage = null; 
                    try
                    { 
                        incomingMessage = self.rstChannel.EndRequest(result);
                    }
                    finally
                    { 
                        if (self.nextOutgoingMessage != null)
                        { 
                            self.nextOutgoingMessage.Close(); 
                        }
                    } 

                    using (incomingMessage)
                    {
                        if (incomingMessage == null) 
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.FailToRecieveReplyFromNegotiation))); 
                        } 
                        completeSelf = self.DoNegotiation(incomingMessage);
                    } 

                    if (completeSelf)
                    {
                        self.OnNegotiationComplete(); 
                    }
                } 
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                { 
                    if (Diagnostics.ExceptionUtility.IsFatal(e))
                        throw;

                    completeSelf = true; 
                    completionException = self.OnAsyncNegotiationFailure(e);
                } 
                if (completeSelf) 
                {
                    self.Complete(false, completionException); 
                }
            }

            bool DoNegotiation(Message incomingMessage) 
            {
                this.nextOutgoingMessage = this.tokenProvider.GetNextOutgoingMessage(incomingMessage, this.negotiationState); 
                if (this.nextOutgoingMessage != null) 
                {
                    return SendRequest(); 
                }
                else
                {
                    if (!negotiationState.IsNegotiationCompleted) 
                    {
                        throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.NoNegotiationMessageToSend)), incomingMessage); 
                    } 
                    return this.CloseRequestChannel();
                } 
            }

            bool CloseRequestChannel()
            { 
                IAsyncResult result = rstChannel.BeginClose(timeoutHelper.RemainingTime(), closeChannelCallback, this);
                if (!result.CompletedSynchronously) 
                { 
                    return false;
                } 
                rstChannel.EndClose(result);
                return true;
            }
 
            static void CloseChannelCallback(IAsyncResult result)
            { 
                if (result.CompletedSynchronously) 
                {
                    return; 
                }
                SecurityNegotiationAsyncResult self = (SecurityNegotiationAsyncResult)result.AsyncState;
                bool completeSelf = false;
                Exception completionException = null; 
                try
                { 
                    self.rstChannel.EndClose(result); 
                    self.OnNegotiationComplete();
                    completeSelf = true; 
                }
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e)
                { 
                    if (Diagnostics.ExceptionUtility.IsFatal(e))
                        throw; 
                    completeSelf = true; 
                    completionException = self.OnAsyncNegotiationFailure(e);
                } 
                if (completeSelf)
                {
                    self.Complete(false, completionException);
                } 
            }
 
            void Cleanup() 
            {
                this.tokenProvider.Cleanup(this.rstChannel, this.negotiationState); 
                this.rstChannel = null;
                this.negotiationState = null;
            }
 
            Exception OnAsyncNegotiationFailure(Exception e)
            { 
                EndpointAddress pinnedEpr = null; 
                try
                { 
                    pinnedEpr = (this.negotiationState == null) ? null : this.negotiationState.RemoteAddress;
                    Cleanup();
                }
                catch (CommunicationException ex) 
                {
                    if (DiagnosticUtility.ShouldTraceInformation) 
                    { 
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(ex, TraceEventType.Information);
                    } 
                }

                return IssuanceTokenProviderBase.WrapExceptionIfRequired(e, pinnedEpr, this.issuer);
            } 

            Exception OnSyncNegotiationFailure(Exception e) 
            { 
                EndpointAddress pinnedTarget = (this.negotiationState == null) ? null : this.negotiationState.RemoteAddress;
                return IssuanceTokenProviderBase.WrapExceptionIfRequired(e, pinnedTarget, this.issuer); 
            }

            void OnNegotiationComplete()
            { 
                using (negotiationState)
                { 
                    SecurityToken token = negotiationState.ServiceToken; 
                    this.tokenProvider.ValidateAndCacheServiceToken(negotiationState);
                    this.serviceToken = token; 
                }
            }

            public static SecurityToken End(IAsyncResult result) 
            {
                SecurityNegotiationAsyncResult self = AsyncResult.End(result); 
                return self.serviceToken; 
            }
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK