SecurityProtocol.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 / SecurityProtocol.cs / 1 / SecurityProtocol.cs

                            //---------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.ServiceModel.Security 
{
    using System.Diagnostics; 
    using System.Collections.Generic; 
    using System.ServiceModel;
    using System.ServiceModel.Description; 
    using System.Collections.ObjectModel;
    using System.IO;
    using System.IdentityModel.Selectors;
    using System.IdentityModel.Claims; 
    using System.IdentityModel.Policy;
    using System.IdentityModel.Tokens; 
    using System.Security.Cryptography; 
    using System.ServiceModel.Channels;
 
    using System.Text;
    using System.Xml;
    using System.Xml.Serialization;
    using System.ServiceModel.Diagnostics; 
    using System.ServiceModel.Security.Tokens;
 
    // See SecurityProtocolFactory for contracts on subclasses etc 

    // SecureOutgoingMessage and VerifyIncomingMessage take message as 
    // ref parameters (instead of taking a message and returning a
    // message) to reduce the likelihood that a caller will forget to
    // do the rest of the processing with the modified message object.
    // Especially, on the sender-side, not sending the modified 
    // message will result in sending it with an unencrypted body.
    // Correspondingly, the async versions have out parameters instead 
    // of simple return values. 
    abstract class SecurityProtocol : ISecurityCommunicationObject
    { 
        static ReadOnlyCollection emptyTokenProviders;

        ICollection channelSupportingTokenProviderSpecification;
        Dictionary> scopedSupportingTokenProviderSpecification; 
        Dictionary> mergedSupportingTokenProvidersMap;
        SecurityProtocolFactory factory; 
        EndpointAddress target; 
        Uri via;
        WrapperSecurityCommunicationObject communicationObject; 
        ChannelParameterCollection channelParameters;

        protected SecurityProtocol(SecurityProtocolFactory factory, EndpointAddress target, Uri via)
        { 
            this.factory = factory;
            this.target = target; 
            this.via = via; 
            this.communicationObject = new WrapperSecurityCommunicationObject(this);
        } 

        protected WrapperSecurityCommunicationObject CommunicationObject
        {
            get { return this.communicationObject; } 
        }
 
        public SecurityProtocolFactory SecurityProtocolFactory 
        {
            get { return this.factory; } 
        }

        public EndpointAddress Target
        { 
            get { return this.target; }
        } 
 
        public Uri Via
        { 
            get { return this.via; }
        }

        public ICollection ChannelSupportingTokenProviderSpecification 
        {
            get 
            { 
                return this.channelSupportingTokenProviderSpecification;
            } 
        }

        public Dictionary> ScopedSupportingTokenProviderSpecification
        { 
            get
            { 
                return this.scopedSupportingTokenProviderSpecification; 
            }
        } 

        static ReadOnlyCollection EmptyTokenProviders
        {
            get 
            {
                if (emptyTokenProviders == null) 
                { 
                    emptyTokenProviders = new ReadOnlyCollection(new List());
                } 
                return emptyTokenProviders;
            }
        }
 
        public ChannelParameterCollection ChannelParameters
        { 
            get 
            {
                return this.channelParameters; 
            }
            set
            {
                this.communicationObject.ThrowIfDisposedOrImmutable(); 
                this.channelParameters = value;
            } 
        } 

        // ISecurityCommunicationObject members 
        public TimeSpan DefaultOpenTimeout
        {
            get { return ServiceDefaults.OpenTimeout; }
        } 

        public TimeSpan DefaultCloseTimeout 
        { 
            get { return ServiceDefaults.CloseTimeout; }
        } 

        public IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new OperationWithTimeoutAsyncResult(new OperationWithTimeoutCallback(this.OnClose), timeout, callback, state); 
        }
 
        public IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            return new OperationWithTimeoutAsyncResult(new OperationWithTimeoutCallback(this.OnOpen), timeout, callback, state); 
        }

        public void OnClosed()
        { 
        }
 
        public void OnClosing() 
        {
        } 

        public void OnEndClose(IAsyncResult result)
        {
            OperationWithTimeoutAsyncResult.End(result); 
        }
 
        public void OnEndOpen(IAsyncResult result) 
        {
            OperationWithTimeoutAsyncResult.End(result); 
        }

        public void OnFaulted()
        { 
        }
 
        public void OnOpened() 
        {
        } 

        public void OnOpening()
        {
        } 

        internal IList GetSupportingTokenProviders(string action) 
        { 
            if (this.mergedSupportingTokenProvidersMap != null && this.mergedSupportingTokenProvidersMap.Count > 0)
            { 
                if (action != null && this.mergedSupportingTokenProvidersMap.ContainsKey(action))
                {
                    return this.mergedSupportingTokenProvidersMap[action];
                } 
                else if (this.mergedSupportingTokenProvidersMap.ContainsKey(MessageHeaders.WildcardAction))
                { 
                    return this.mergedSupportingTokenProvidersMap[MessageHeaders.WildcardAction]; 
                }
            } 
            // return null if the token providers list is empty - this gets a perf benefit since calling Count is expensive for an empty
            // ReadOnlyCollection
            return (this.channelSupportingTokenProviderSpecification == EmptyTokenProviders) ? null : (IList)this.channelSupportingTokenProviderSpecification;
        } 

        protected InitiatorServiceModelSecurityTokenRequirement CreateInitiatorSecurityTokenRequirement() 
        { 
            InitiatorServiceModelSecurityTokenRequirement requirement = new InitiatorServiceModelSecurityTokenRequirement();
            requirement.TargetAddress = this.Target; 
            requirement.Via = this.via;
            requirement.SecurityBindingElement = this.factory.SecurityBindingElement;
            requirement.SecurityAlgorithmSuite = this.factory.OutgoingAlgorithmSuite;
            requirement.MessageSecurityVersion = this.factory.MessageSecurityVersion.SecurityTokenVersion; 
            if (this.factory.PrivacyNoticeUri != null)
            { 
                requirement.Properties[ServiceModelSecurityTokenRequirement.PrivacyNoticeUriProperty] = this.factory.PrivacyNoticeUri; 
            }
            if (this.channelParameters != null) 
            {
                requirement.Properties[ServiceModelSecurityTokenRequirement.ChannelParametersCollectionProperty] = this.channelParameters;
            }
 
            requirement.Properties[ServiceModelSecurityTokenRequirement.PrivacyNoticeVersionProperty] = this.factory.PrivacyNoticeVersion;
 
            return requirement; 
        }
 
        InitiatorServiceModelSecurityTokenRequirement CreateInitiatorSecurityTokenRequirement(SecurityTokenParameters parameters, SecurityTokenAttachmentMode attachmentMode)
        {
            InitiatorServiceModelSecurityTokenRequirement requirement = CreateInitiatorSecurityTokenRequirement();
            parameters.InitializeSecurityTokenRequirement(requirement); 
            requirement.KeyUsage = SecurityKeyUsage.Signature;
            requirement.Properties[ServiceModelSecurityTokenRequirement.MessageDirectionProperty] = MessageDirection.Output; 
            requirement.Properties[ServiceModelSecurityTokenRequirement.SupportingTokenAttachmentModeProperty] = attachmentMode; 
            return requirement;
        } 

        void AddSupportingTokenProviders(SupportingTokenParameters supportingTokenParameters, bool isOptional, IList providerSpecList)
        {
            for (int i = 0; i < supportingTokenParameters.Endorsing.Count; ++i) 
            {
                SecurityTokenRequirement requirement = this.CreateInitiatorSecurityTokenRequirement(supportingTokenParameters.Endorsing[i], SecurityTokenAttachmentMode.Endorsing); 
                try 
                {
                    System.IdentityModel.Selectors.SecurityTokenProvider provider = this.factory.SecurityTokenManager.CreateSecurityTokenProvider(requirement); 
                    SupportingTokenProviderSpecification providerSpec = new SupportingTokenProviderSpecification(provider, SecurityTokenAttachmentMode.Endorsing, supportingTokenParameters.Endorsing[i]);
                    providerSpecList.Add(providerSpec);
                }
                catch (Exception e) 
                {
                    if (!isOptional || DiagnosticUtility.IsFatal(e)) 
                    { 
                        throw;
                    } 
                }
            }
            for (int i = 0; i < supportingTokenParameters.SignedEndorsing.Count; ++i)
            { 
                SecurityTokenRequirement requirement = this.CreateInitiatorSecurityTokenRequirement(supportingTokenParameters.SignedEndorsing[i], SecurityTokenAttachmentMode.SignedEndorsing);
                try 
                { 
                    System.IdentityModel.Selectors.SecurityTokenProvider provider = this.factory.SecurityTokenManager.CreateSecurityTokenProvider(requirement);
                    SupportingTokenProviderSpecification providerSpec = new SupportingTokenProviderSpecification(provider, SecurityTokenAttachmentMode.SignedEndorsing, supportingTokenParameters.SignedEndorsing[i]); 
                    providerSpecList.Add(providerSpec);
                }
                catch (Exception e)
                { 
                    if (!isOptional || DiagnosticUtility.IsFatal(e))
                    { 
                        throw; 
                    }
                } 
            }
            for (int i = 0; i < supportingTokenParameters.SignedEncrypted.Count; ++i)
            {
                SecurityTokenRequirement requirement = this.CreateInitiatorSecurityTokenRequirement(supportingTokenParameters.SignedEncrypted[i], SecurityTokenAttachmentMode.SignedEncrypted); 
                try
                { 
                    System.IdentityModel.Selectors.SecurityTokenProvider provider = this.factory.SecurityTokenManager.CreateSecurityTokenProvider(requirement); 
                    SupportingTokenProviderSpecification providerSpec = new SupportingTokenProviderSpecification(provider, SecurityTokenAttachmentMode.SignedEncrypted, supportingTokenParameters.SignedEncrypted[i]);
                    providerSpecList.Add(providerSpec); 
                }
                catch (Exception e)
                {
                    if (!isOptional || DiagnosticUtility.IsFatal(e)) 
                    {
                        throw; 
                    } 
                }
            } 
            for (int i = 0; i < supportingTokenParameters.Signed.Count; ++i)
            {
                SecurityTokenRequirement requirement = this.CreateInitiatorSecurityTokenRequirement(supportingTokenParameters.Signed[i], SecurityTokenAttachmentMode.Signed);
                try 
                {
                    System.IdentityModel.Selectors.SecurityTokenProvider provider = this.factory.SecurityTokenManager.CreateSecurityTokenProvider(requirement); 
                    SupportingTokenProviderSpecification providerSpec = new SupportingTokenProviderSpecification(provider, SecurityTokenAttachmentMode.Signed, supportingTokenParameters.Signed[i]); 
                    providerSpecList.Add(providerSpec);
                } 
                catch (Exception e)
                {
                    if (!isOptional || DiagnosticUtility.IsFatal(e))
                    { 
                        throw;
                    } 
                } 
            }
        } 

        void MergeSupportingTokenProviders(TimeSpan timeout)
        {
            if (this.ScopedSupportingTokenProviderSpecification.Count == 0) 
            {
                this.mergedSupportingTokenProvidersMap = null; 
            } 
            else
            { 
                TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
                this.factory.ExpectSupportingTokens = true;
                this.mergedSupportingTokenProvidersMap = new Dictionary>();
                foreach (string action in this.ScopedSupportingTokenProviderSpecification.Keys) 
                {
                    ICollection scopedProviders = this.ScopedSupportingTokenProviderSpecification[action]; 
                    if (scopedProviders == null || scopedProviders.Count == 0) 
                    {
                        continue; 
                    }
                    Collection mergedProviders = new Collection();
                    foreach (SupportingTokenProviderSpecification spec in this.channelSupportingTokenProviderSpecification)
                    { 
                        mergedProviders.Add(spec);
                    } 
                    foreach (SupportingTokenProviderSpecification spec in scopedProviders) 
                    {
                        SecurityUtils.OpenTokenProviderIfRequired(spec.TokenProvider, timeoutHelper.RemainingTime()); 
                        if (spec.SecurityTokenAttachmentMode == SecurityTokenAttachmentMode.Endorsing || spec.SecurityTokenAttachmentMode == SecurityTokenAttachmentMode.SignedEndorsing)
                        {
                            if (spec.TokenParameters.RequireDerivedKeys && !spec.TokenParameters.HasAsymmetricKey)
                            { 
                                this.factory.ExpectKeyDerivation = true;
                            } 
                        } 
                        mergedProviders.Add(spec);
                    } 
                    this.mergedSupportingTokenProvidersMap.Add(action, mergedProviders);
                }
            }
        } 

        public void Open(TimeSpan timeout) 
        { 
            this.communicationObject.Open(timeout);
        } 

        public IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this.communicationObject.BeginOpen(timeout, callback, state); 
        }
 
        public void EndOpen(IAsyncResult result) 
        {
            this.communicationObject.EndOpen(result); 
        }

        public virtual void OnOpen(TimeSpan timeout)
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            if (this.factory.ActAsInitiator) 
            { 
                this.channelSupportingTokenProviderSpecification = new Collection();
                this.scopedSupportingTokenProviderSpecification = new Dictionary>(); 

                AddSupportingTokenProviders(this.factory.SecurityBindingElement.EndpointSupportingTokenParameters, false, (IList)this.channelSupportingTokenProviderSpecification);
                AddSupportingTokenProviders(this.factory.SecurityBindingElement.OptionalEndpointSupportingTokenParameters, true, (IList)this.channelSupportingTokenProviderSpecification);
                foreach (string action in this.factory.SecurityBindingElement.OperationSupportingTokenParameters.Keys) 
                {
                    Collection providerSpecList = new Collection(); 
                    AddSupportingTokenProviders(this.factory.SecurityBindingElement.OperationSupportingTokenParameters[action], false, providerSpecList); 
                    this.scopedSupportingTokenProviderSpecification.Add(action, providerSpecList);
                } 
                foreach (string action in this.factory.SecurityBindingElement.OptionalOperationSupportingTokenParameters.Keys)
                {
                    Collection providerSpecList;
                    ICollection existingList; 
                    if (this.scopedSupportingTokenProviderSpecification.TryGetValue(action, out existingList))
                    { 
                        providerSpecList = ((Collection)existingList); 
                    }
                    else 
                    {
                        providerSpecList = new Collection();
                        this.scopedSupportingTokenProviderSpecification.Add(action, providerSpecList);
                    } 
                    this.AddSupportingTokenProviders(this.factory.SecurityBindingElement.OptionalOperationSupportingTokenParameters[action], true, providerSpecList);
                } 
 
                if (!this.channelSupportingTokenProviderSpecification.IsReadOnly)
                { 
                    if (this.channelSupportingTokenProviderSpecification.Count == 0)
                    {
                        this.channelSupportingTokenProviderSpecification = EmptyTokenProviders;
                    } 
                    else
                    { 
                        this.factory.ExpectSupportingTokens = true; 
                        foreach (SupportingTokenProviderSpecification tokenProviderSpec in this.channelSupportingTokenProviderSpecification)
                        { 
                            SecurityUtils.OpenTokenProviderIfRequired(tokenProviderSpec.TokenProvider, timeoutHelper.RemainingTime());
                            if (tokenProviderSpec.SecurityTokenAttachmentMode == SecurityTokenAttachmentMode.Endorsing || tokenProviderSpec.SecurityTokenAttachmentMode == SecurityTokenAttachmentMode.SignedEndorsing)
                            {
                                if (tokenProviderSpec.TokenParameters.RequireDerivedKeys && !tokenProviderSpec.TokenParameters.HasAsymmetricKey) 
                                {
                                    this.factory.ExpectKeyDerivation = true; 
                                } 
                            }
                        } 
                        this.channelSupportingTokenProviderSpecification =
                            new ReadOnlyCollection((Collection)this.channelSupportingTokenProviderSpecification);
                    }
                } 
                // create a merged map of the per operation supporting tokens
                MergeSupportingTokenProviders(timeoutHelper.RemainingTime()); 
            } 
        }
 
        public void Close(bool aborted, TimeSpan timeout)
        {
            if (aborted)
            { 
                this.communicationObject.Abort();
            } 
            else 
            {
                this.communicationObject.Close(timeout); 
            }
        }

        public virtual void OnAbort() 
        {
            if (this.factory.ActAsInitiator) 
            { 
                foreach (SupportingTokenProviderSpecification spec in this.channelSupportingTokenProviderSpecification)
                { 
                    SecurityUtils.AbortTokenProviderIfRequired(spec.TokenProvider);
                }
                foreach (string action in this.scopedSupportingTokenProviderSpecification.Keys)
                { 
                    ICollection supportingProviders = this.scopedSupportingTokenProviderSpecification[action];
                    foreach (SupportingTokenProviderSpecification spec in supportingProviders) 
                    { 
                        SecurityUtils.AbortTokenProviderIfRequired(spec.TokenProvider);
                    } 
                }
            }
        }
 
        public virtual void OnClose(TimeSpan timeout)
        { 
            if (this.factory.ActAsInitiator) 
            {
                TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
                foreach (SupportingTokenProviderSpecification spec in this.channelSupportingTokenProviderSpecification)
                {
                    SecurityUtils.CloseTokenProviderIfRequired(spec.TokenProvider, timeoutHelper.RemainingTime());
                } 
                foreach (string action in this.scopedSupportingTokenProviderSpecification.Keys)
                { 
                    ICollection supportingProviders = this.scopedSupportingTokenProviderSpecification[action]; 
                    foreach (SupportingTokenProviderSpecification spec in supportingProviders)
                    { 
                        SecurityUtils.CloseTokenProviderIfRequired(spec.TokenProvider, timeoutHelper.RemainingTime());
                    }
                }
            } 
        }
 
        public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            return this.communicationObject.BeginClose(timeout, callback, state); 
        }

        public void EndClose(IAsyncResult result)
        { 
            this.communicationObject.EndClose(result);
        } 
 
        static void SetSecurityHeaderId(SendSecurityHeader securityHeader, Message message)
        { 
            SecurityMessageProperty messageProperty = message.Properties.Security;
            if (messageProperty != null)
            {
                securityHeader.IdPrefix = messageProperty.SenderIdPrefix; 
            }
        } 
 
        void AddSupportingTokenSpecification(SecurityMessageProperty security, IList tokens, SecurityTokenAttachmentMode attachmentMode, IDictionary> tokenPoliciesMapping)
        { 
            if (tokens == null || tokens.Count == 0)
            {
                return;
            } 
            for (int i = 0; i < tokens.Count; ++i)
            { 
                security.IncomingSupportingTokens.Add(new SupportingTokenSpecification(tokens[i], tokenPoliciesMapping[tokens[i]], attachmentMode)); 
            }
        } 

        protected void AddSupportingTokenSpecification(SecurityMessageProperty security, IList basicTokens, IList endorsingTokens, IList signedEndorsingTokens, IList signedTokens, IDictionary> tokenPoliciesMapping)
        {
            AddSupportingTokenSpecification(security, basicTokens, SecurityTokenAttachmentMode.SignedEncrypted, tokenPoliciesMapping); 
            AddSupportingTokenSpecification(security, endorsingTokens, SecurityTokenAttachmentMode.Endorsing, tokenPoliciesMapping);
            AddSupportingTokenSpecification(security, signedEndorsingTokens, SecurityTokenAttachmentMode.SignedEndorsing, tokenPoliciesMapping); 
            AddSupportingTokenSpecification(security, signedTokens, SecurityTokenAttachmentMode.Signed, tokenPoliciesMapping); 
        }
 
        protected SendSecurityHeader CreateSendSecurityHeader(Message message, string actor, SecurityProtocolFactory factory)
        {
            return CreateSendSecurityHeader(message, actor, factory, true);
        } 

        protected SendSecurityHeader CreateSendSecurityHeaderForTransportProtocol(Message message, string actor, SecurityProtocolFactory factory) 
        { 
            return CreateSendSecurityHeader(message, actor, factory, false);
        } 

        SendSecurityHeader CreateSendSecurityHeader(Message message, string actor, SecurityProtocolFactory factory, bool requireMessageProtection)
        {
            MessageDirection transferDirection = factory.ActAsInitiator ? MessageDirection.Input : MessageDirection.Output; 
            SendSecurityHeader sendSecurityHeader = factory.StandardsManager.CreateSendSecurityHeader(
                message, 
                actor, true, false, 
                factory.OutgoingAlgorithmSuite, transferDirection);
            sendSecurityHeader.Layout = factory.SecurityHeaderLayout; 
            sendSecurityHeader.RequireMessageProtection = requireMessageProtection;
            SetSecurityHeaderId(sendSecurityHeader, message);
            if (factory.AddTimestamp)
            { 
                sendSecurityHeader.AddTimestamp(factory.TimestampValidityDuration);
            } 
            return sendSecurityHeader; 
        }
 
        internal void AddMessageSupportingTokens(Message message, ref IList supportingTokens)
        {
            SecurityMessageProperty supportingTokensProperty = message.Properties.Security;
            if (supportingTokensProperty != null && supportingTokensProperty.HasOutgoingSupportingTokens) 
            {
                if (supportingTokens == null) 
                { 
                    supportingTokens = new Collection();
                } 
                for (int i = 0; i < supportingTokensProperty.OutgoingSupportingTokens.Count; ++i)
                {
                    SupportingTokenSpecification spec = supportingTokensProperty.OutgoingSupportingTokens[i];
                    if (spec.SecurityTokenParameters == null) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.SenderSideSupportingTokensMustSpecifySecurityTokenParameters))); 
                    } 
                    supportingTokens.Add(spec);
                } 
            }
        }

        internal bool TryGetSupportingTokens(SecurityProtocolFactory factory, EndpointAddress target, Uri via, Message message, TimeSpan timeout, bool isBlockingCall, out IList supportingTokens) 
        {
            if (!factory.ActAsInitiator) 
            { 
                supportingTokens = null;
                return true; 
            }
            if (message == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message"); 
            }
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            supportingTokens = null; 
            IList supportingTokenProviders = this.GetSupportingTokenProviders(message.Headers.Action);
            if (supportingTokenProviders != null && supportingTokenProviders.Count > 0) 
            {
                // dont do anything if blocking is not allowed
                if (!isBlockingCall)
                { 
                    return false;
                } 
 
                supportingTokens = new Collection();
                for (int i = 0; i < supportingTokenProviders.Count; ++i) 
                {
                    SupportingTokenProviderSpecification spec = supportingTokenProviders[i];
                    SecurityToken supportingToken = spec.TokenProvider.GetToken(timeoutHelper.RemainingTime());
                    supportingTokens.Add(new SupportingTokenSpecification(supportingToken, EmptyReadOnlyCollection.Instance, spec.SecurityTokenAttachmentMode, spec.TokenParameters)); 
                }
            } 
            // add any runtime supporting tokens 
            AddMessageSupportingTokens(message, ref supportingTokens);
 
            return true;
        }

        protected IList GetSupportingTokenAuthenticatorsAndSetExpectationFlags(SecurityProtocolFactory factory, Message message, 
            ReceiveSecurityHeader securityHeader)
        { 
            if (factory.ActAsInitiator) 
            {
                return null; 
            }
            if (message == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message"); 
            }
            bool expectBasicTokens; 
            bool expectSignedTokens; 
            bool expectEndorsingTokens;
            IList authenticators = factory.GetSupportingTokenAuthenticators(message.Headers.Action, 
                out expectSignedTokens, out expectBasicTokens, out expectEndorsingTokens);
            securityHeader.ExpectBasicTokens = expectBasicTokens;
            securityHeader.ExpectEndorsingTokens = expectEndorsingTokens;
            securityHeader.ExpectSignedTokens = expectSignedTokens; 
            return authenticators;
        } 
 

        protected ReadOnlyCollection MergeOutOfBandResolvers(IList supportingAuthenticators, ReadOnlyCollection primaryResolvers) 
        {
            Collection outOfBandResolvers = null;
            if (supportingAuthenticators != null && supportingAuthenticators.Count > 0)
            { 
                for (int i = 0; i < supportingAuthenticators.Count; ++i)
                { 
                    if (supportingAuthenticators[i].TokenResolver != null) 
                    {
                        outOfBandResolvers = outOfBandResolvers ?? new Collection(); 
                        outOfBandResolvers.Add(supportingAuthenticators[i].TokenResolver);
                    }
                }
            } 
            if (outOfBandResolvers != null)
            { 
                if (primaryResolvers != null) 
                {
                    for (int i = 0; i < primaryResolvers.Count; ++i) 
                    {
                        outOfBandResolvers.Insert(0, primaryResolvers[i]);
                    }
                } 
                return new ReadOnlyCollection(outOfBandResolvers);
            } 
            else 
            {
                return primaryResolvers ?? EmptyReadOnlyCollection.Instance; 
            }
        }

 
        protected void AddSupportingTokens(SendSecurityHeader securityHeader, IList supportingTokens)
        { 
            if (supportingTokens != null) 
            {
                for (int i = 0; i < supportingTokens.Count; ++i) 
                {
                    SecurityToken token = supportingTokens[i].SecurityToken;
                    SecurityTokenParameters tokenParameters = supportingTokens[i].SecurityTokenParameters;
                    switch (supportingTokens[i].SecurityTokenAttachmentMode) 
                    {
                        case SecurityTokenAttachmentMode.Signed: 
                            securityHeader.AddSignedSupportingToken(token, tokenParameters); 
                            break;
                        case SecurityTokenAttachmentMode.Endorsing: 
                            securityHeader.AddEndorsingSupportingToken(token, tokenParameters);
                            break;
                        case SecurityTokenAttachmentMode.SignedEncrypted:
                            securityHeader.AddBasicSupportingToken(token, tokenParameters); 
                            break;
                        case SecurityTokenAttachmentMode.SignedEndorsing: 
                            securityHeader.AddSignedEndorsingSupportingToken(token, tokenParameters); 
                            break;
                        default: 
                            DiagnosticUtility.DebugAssert("Unknown token attachment mode " + supportingTokens[i].SecurityTokenAttachmentMode.ToString());
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.UnknownTokenAttachmentMode, supportingTokens[i].SecurityTokenAttachmentMode.ToString())));
                    }
                } 
            }
        } 
 
        public virtual IAsyncResult BeginSecureOutgoingMessage(Message message, TimeSpan timeout, AsyncCallback callback, object state)
        { 
            SecureOutgoingMessage(ref message, timeout);
            return new TypedCompletedAsyncResult(message, callback, state);
        }
 
        public virtual IAsyncResult BeginSecureOutgoingMessage(Message message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState, AsyncCallback callback, object state)
        { 
            SecurityProtocolCorrelationState newCorrelationState = SecureOutgoingMessage(ref message, timeout, correlationState); 
            return new TypedCompletedAsyncResult(message, newCorrelationState, callback, state);
        } 

        public virtual IAsyncResult BeginVerifyIncomingMessage(Message message, TimeSpan timeout, AsyncCallback callback, object state)
        {
            VerifyIncomingMessage(ref message, timeout); 
            return new TypedCompletedAsyncResult(message, callback, state);
        } 
 
        public virtual IAsyncResult BeginVerifyIncomingMessage(Message message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates, AsyncCallback callback, object state)
        { 
            SecurityProtocolCorrelationState newCorrelationState = VerifyIncomingMessage(ref message, timeout, correlationStates);
            return new TypedCompletedAsyncResult(message, newCorrelationState, callback, state);
        }
 
        public virtual void EndSecureOutgoingMessage(IAsyncResult result, out Message message)
        { 
            message = TypedCompletedAsyncResult.End(result); 
        }
 
        public virtual void EndSecureOutgoingMessage(IAsyncResult result, out Message message, out SecurityProtocolCorrelationState newCorrelationState)
        {
            message = TypedCompletedAsyncResult.End(result, out newCorrelationState);
        } 

        public virtual void EndVerifyIncomingMessage(IAsyncResult result, out Message message) 
        { 
            message = TypedCompletedAsyncResult.End(result);
        } 

        public virtual void EndVerifyIncomingMessage(IAsyncResult result, out Message message, out SecurityProtocolCorrelationState newCorrelationState)
        {
            message = TypedCompletedAsyncResult.End(result, out newCorrelationState); 
        }
 
        internal static SecurityToken GetToken(SecurityTokenProvider provider, EndpointAddress target, TimeSpan timeout) 
        {
            if (provider == null) 
            {
                // should this be an ArgumentNullException ?
                // throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("provider"));
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenProviderCannotGetTokensForTarget, target))); 
            }
 
            SecurityToken token = null; 

            try 
            {
                token = provider.GetToken(timeout);
            }
            catch (SecurityTokenException exception) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenProviderCannotGetTokensForTarget, target), exception)); 
            } 
            catch (SecurityNegotiationException sne)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.TokenProviderCannotGetTokensForTarget, target), sne));
            }

            return token; 
        }
 
        public abstract void SecureOutgoingMessage(ref Message message, TimeSpan timeout); 

        // subclasses that offer correlation should override this version 
        public virtual SecurityProtocolCorrelationState SecureOutgoingMessage(ref Message message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState)
        {
            SecureOutgoingMessage(ref message, timeout);
            return null; 
        }
 
        protected virtual void OnOutgoingMessageSecured(Message securedMessage) 
        {
            SecurityTraceRecordHelper.TraceOutgoingMessageSecured(this, securedMessage); 
        }

        protected virtual void OnSecureOutgoingMessageFailure(Message message)
        { 
            SecurityTraceRecordHelper.TraceSecureOutgoingMessageFailure(this, message);
        } 
 
        public abstract void VerifyIncomingMessage(ref Message message, TimeSpan timeout);
 
        // subclasses that offer correlation should override this version
        public virtual SecurityProtocolCorrelationState VerifyIncomingMessage(ref Message message, TimeSpan timeout, params SecurityProtocolCorrelationState[] correlationStates)
        {
            VerifyIncomingMessage(ref message, timeout); 
            return null;
        } 
 
        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, 
                    SecurityUtils.GetIdentityNamesFromContext(verifiedMessage.Properties.Security.ServiceSecurityContext.AuthorizationContext)); 
            }
        } 

        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 (DiagnosticUtility.IsFatal(auditException)) 
                        throw;
 
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(auditException, TraceEventType.Error); 
                }
            } 
        }

        protected abstract class GetSupportingTokensAsyncResult : AsyncResult
        { 
            static AsyncCallback getSupportingTokensCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(GetSupportingTokenCallback));
            SecurityProtocol binding; 
            Message message; 
            IList supportingTokens;
            int currentTokenProviderIndex = 0; 
            IList supportingTokenProviders;
            TimeoutHelper timeoutHelper;

            public GetSupportingTokensAsyncResult(Message m, SecurityProtocol binding, TimeSpan timeout, AsyncCallback callback, object state) 
                : base(callback, state)
            { 
                this.message = m; 
                this.binding = binding;
                this.timeoutHelper = new TimeoutHelper(timeout); 
            }

            protected IList SupportingTokens
            { 
                get { return this.supportingTokens; }
            } 
 
            protected abstract bool OnGetSupportingTokensDone(TimeSpan timeout);
 
            static void GetSupportingTokenCallback(IAsyncResult result)
            {
                if (result.CompletedSynchronously)
                { 
                    return;
                } 
                GetSupportingTokensAsyncResult self = (GetSupportingTokensAsyncResult)result.AsyncState; 
                bool completeSelf;
                Exception completionException = null; 
                try
                {
                    self.AddSupportingToken(result);
                    completeSelf = self.AddSupportingTokens(); 
                }
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e) 
                {
                    if (Diagnostics.ExceptionUtility.IsFatal(e)) 
                        throw;

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

            void AddSupportingToken(IAsyncResult result)
            { 
                SupportingTokenProviderSpecification spec = supportingTokenProviders[this.currentTokenProviderIndex];
                this.supportingTokens.Add(new SupportingTokenSpecification(spec.TokenProvider.EndGetToken(result), EmptyReadOnlyCollection.Instance, spec.SecurityTokenAttachmentMode, spec.TokenParameters)); 
                ++this.currentTokenProviderIndex; 
            }
 
            bool AddSupportingTokens()
            {
                while (this.currentTokenProviderIndex < supportingTokenProviders.Count)
                { 
                    SupportingTokenProviderSpecification spec = supportingTokenProviders[this.currentTokenProviderIndex];
                    IAsyncResult result = spec.TokenProvider.BeginGetToken(timeoutHelper.RemainingTime(), getSupportingTokensCallback, this); 
                    if (!result.CompletedSynchronously) 
                    {
                        return false; 
                    }
                    this.AddSupportingToken(result);
                }
                this.binding.AddMessageSupportingTokens(message, ref this.supportingTokens); 
                return this.OnGetSupportingTokensDone(timeoutHelper.RemainingTime());
            } 
 
            protected void Start()
            { 
                bool completeSelf;
                if (this.binding.TryGetSupportingTokens(this.binding.SecurityProtocolFactory, this.binding.Target, this.binding.Via, this.message, timeoutHelper.RemainingTime(), false, out supportingTokens))
                {
                    completeSelf = this.OnGetSupportingTokensDone(timeoutHelper.RemainingTime()); 
                }
                else 
                { 
                    this.supportingTokens = new Collection();
                    this.supportingTokenProviders = this.binding.GetSupportingTokenProviders(message.Headers.Action); 
                    if (!(this.supportingTokenProviders != null && this.supportingTokenProviders.Count > 0))
                    {
                        DiagnosticUtility.DebugAssert("There must be at least 1 supporting token provider");
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException("There must be at least 1 supporting token provider")); 
                    }
                    completeSelf = this.AddSupportingTokens(); 
                } 
                if (completeSelf)
                { 
                    base.Complete(true);
                }
            }
        } 
    }
} 

// 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