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

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

namespace System.ServiceModel.Security 
{
    using System.Collections.Generic; 
    using System.ServiceModel; 
    using System.ServiceModel.Description;
    using System.Collections.ObjectModel; 
    using System.IO;
    using System.IdentityModel.Claims;
    using System.IdentityModel.Policy;
    using System.IdentityModel.Tokens; 
    using System.IdentityModel.Selectors;
    using System.Security.Cryptography; 
    using System.ServiceModel.Security.Tokens; 
    using System.ServiceModel.Channels;
    using System.ServiceModel.Diagnostics; 
    using System.Text;
    using System.Xml;
    using System.Xml.Serialization;
 
    sealed class SymmetricSecurityProtocol : MessageSecurityProtocol
    { 
        SecurityTokenProvider initiatorSymmetricTokenProvider; 
        SecurityTokenProvider initiatorAsymmetricTokenProvider;
        SecurityTokenAuthenticator initiatorTokenAuthenticator; 

        public SymmetricSecurityProtocol(SymmetricSecurityProtocolFactory factory,
            EndpointAddress target, Uri via)
            : base(factory, target, via) 
        {
        } 
 
        SymmetricSecurityProtocolFactory Factory
        { 
            get { return (SymmetricSecurityProtocolFactory)base.MessageSecurityProtocolFactory; }
        }

        public SecurityTokenProvider InitiatorSymmetricTokenProvider 
        {
            get 
            { 
                this.CommunicationObject.ThrowIfNotOpened();
                return this.initiatorSymmetricTokenProvider; 
            }
        }

        public SecurityTokenProvider InitiatorAsymmetricTokenProvider 
        {
            get 
            { 
                this.CommunicationObject.ThrowIfNotOpened();
                return this.initiatorAsymmetricTokenProvider; 
            }
        }

        public SecurityTokenAuthenticator InitiatorTokenAuthenticator 
        {
            get 
            { 

                this.CommunicationObject.ThrowIfNotOpened(); 
                return this.initiatorTokenAuthenticator;
            }
        }
 
        InitiatorServiceModelSecurityTokenRequirement CreateInitiatorTokenRequirement()
        { 
            InitiatorServiceModelSecurityTokenRequirement tokenRequirement = CreateInitiatorSecurityTokenRequirement(); 
            this.Factory.SecurityTokenParameters.InitializeSecurityTokenRequirement(tokenRequirement);
            tokenRequirement.KeyUsage = this.Factory.SecurityTokenParameters.HasAsymmetricKey ? SecurityKeyUsage.Exchange : SecurityKeyUsage.Signature; 
            tokenRequirement.Properties[ServiceModelSecurityTokenRequirement.MessageDirectionProperty] = MessageDirection.Output;
            if (this.Factory.SecurityTokenParameters.HasAsymmetricKey)
            {
                tokenRequirement.IsOutOfBandToken = true; 
            }
            return tokenRequirement; 
        } 

        public override void OnOpen(TimeSpan timeout) 
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            base.OnOpen(timeoutHelper.RemainingTime());
            if (this.Factory.ActAsInitiator) 
            {
                // 1. Create a token requirement for the provider 
                InitiatorServiceModelSecurityTokenRequirement tokenProviderRequirement = CreateInitiatorTokenRequirement(); 

                // 2. Create a provider 
                SecurityTokenProvider tokenProvider = this.Factory.SecurityTokenManager.CreateSecurityTokenProvider(tokenProviderRequirement);
                SecurityUtils.OpenTokenProviderIfRequired(tokenProvider, timeoutHelper.RemainingTime());
                if (this.Factory.SecurityTokenParameters.HasAsymmetricKey)
                { 
                    this.initiatorAsymmetricTokenProvider = tokenProvider;
                } 
                else 
                {
                    this.initiatorSymmetricTokenProvider = tokenProvider; 
                }

                // 3. Create a token requirement for authenticator
                InitiatorServiceModelSecurityTokenRequirement tokenAuthenticatorRequirement = CreateInitiatorTokenRequirement(); 

                // 4. Create authenticator (we dont support out of band resolvers on the client side 
                SecurityTokenResolver outOfBandTokenResolver; 
                this.initiatorTokenAuthenticator = this.Factory.SecurityTokenManager.CreateSecurityTokenAuthenticator(tokenAuthenticatorRequirement, out outOfBandTokenResolver);
                SecurityUtils.OpenTokenAuthenticatorIfRequired(this.initiatorTokenAuthenticator, timeoutHelper.RemainingTime()); 
            }
        }

        public override void OnAbort() 
        {
            if (this.Factory.ActAsInitiator) 
            { 
                SecurityTokenProvider provider = this.initiatorSymmetricTokenProvider ?? this.initiatorAsymmetricTokenProvider;
                if (provider != null) 
                {
                    SecurityUtils.AbortTokenProviderIfRequired(provider);
                }
                if (this.initiatorTokenAuthenticator != null) 
                {
                    SecurityUtils.AbortTokenAuthenticatorIfRequired(this.initiatorTokenAuthenticator); 
                } 
            }
            base.OnAbort(); 
        }

        public override void OnClose(TimeSpan timeout)
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            if (this.Factory.ActAsInitiator) 
            { 
                SecurityTokenProvider provider = this.initiatorSymmetricTokenProvider ?? this.initiatorAsymmetricTokenProvider;
                if (provider != null) 
                {
                    SecurityUtils.CloseTokenProviderIfRequired(provider, timeoutHelper.RemainingTime());
                }
                if (this.initiatorTokenAuthenticator != null) 
                {
                    SecurityUtils.CloseTokenAuthenticatorIfRequired(this.initiatorTokenAuthenticator, timeoutHelper.RemainingTime()); 
                } 
            }
            base.OnClose(timeoutHelper.RemainingTime()); 
        }


        SecurityTokenProvider GetTokenProvider() 
        {
            if (this.Factory.ActAsInitiator) 
            { 
                return (this.initiatorSymmetricTokenProvider ?? this.initiatorAsymmetricTokenProvider);
            } 
            else
            {
                return this.Factory.RecipientAsymmetricTokenProvider;
            } 
        }
 
        protected override IAsyncResult BeginSecureOutgoingMessageCore(Message message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState, AsyncCallback callback, object state) 
        {
            SecurityToken token; 
            SecurityTokenParameters tokenParameters;
            IList supportingTokens;
            SecurityToken prerequisiteWrappingToken;
            SecurityProtocolCorrelationState newCorrelationState; 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            if (TryGetTokenSynchronouslyForOutgoingSecurity(message, correlationState, false, timeoutHelper.RemainingTime(), out token, out tokenParameters, out prerequisiteWrappingToken, out supportingTokens, out newCorrelationState)) 
            { 
                SetUpDelayedSecurityExecution(ref message, prerequisiteWrappingToken, token, tokenParameters, supportingTokens, GetSignatureConfirmationCorrelationState(correlationState, newCorrelationState));
                return new TypedCompletedAsyncResult(message, newCorrelationState, callback, state); 
            }
            else
            {
                if (this.Factory.ActAsInitiator != true) 
                {
                    DiagnosticUtility.DebugAssert("Unexpected code path for server security application"); 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ProtocolMustBeInitiator, this.GetType().ToString()))); 
                }
                SecurityTokenProvider provider = GetTokenProvider(); 
                return new SecureOutgoingMessageAsyncResult(message, this, provider, this.Factory.ApplyConfidentiality, this.initiatorTokenAuthenticator, correlationState, timeoutHelper.RemainingTime(), callback, state);
            }
        }
 
        protected override SecurityProtocolCorrelationState SecureOutgoingMessageCore(ref Message message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState)
        { 
            SecurityToken token; 
            SecurityTokenParameters tokenParameters;
            IList supportingTokens; 
            SecurityToken prerequisiteWrappingToken;
            SecurityProtocolCorrelationState newCorrelationState;
            TryGetTokenSynchronouslyForOutgoingSecurity(message, correlationState, true, timeout, out token, out tokenParameters, out prerequisiteWrappingToken, out supportingTokens, out newCorrelationState);
            SetUpDelayedSecurityExecution(ref message, prerequisiteWrappingToken, token, tokenParameters, supportingTokens, GetSignatureConfirmationCorrelationState(correlationState, newCorrelationState)); 
            return newCorrelationState;
        } 
 
        void SetUpDelayedSecurityExecution(ref Message message,
            SecurityToken prerequisiteToken, 
            SecurityToken primaryToken,
            SecurityTokenParameters primaryTokenParameters,
            IList supportingTokens,
            SecurityProtocolCorrelationState correlationState 
        )
        { 
            string actor = string.Empty; 
            SendSecurityHeader securityHeader = ConfigureSendSecurityHeader(message, actor, supportingTokens, correlationState);
            if (prerequisiteToken != null) 
            {
                securityHeader.AddPrerequisiteToken(prerequisiteToken);
            }
            if (this.Factory.ApplyIntegrity || securityHeader.HasSignedTokens) 
            {
                if (!this.Factory.ApplyIntegrity) 
                { 
                    securityHeader.SignatureParts = MessagePartSpecification.NoParts;
                } 
                securityHeader.SetSigningToken(primaryToken, primaryTokenParameters);
            }
            if (Factory.ApplyConfidentiality || securityHeader.HasEncryptedTokens)
            { 
                if (!this.Factory.ApplyConfidentiality)
                { 
                    securityHeader.EncryptionParts = MessagePartSpecification.NoParts; 
                }
                securityHeader.SetEncryptionToken(primaryToken, primaryTokenParameters); 
            }
            message = securityHeader.SetupExecution();
        }
 
        protected override void EndSecureOutgoingMessageCore(IAsyncResult result, out Message message, out SecurityProtocolCorrelationState newCorrelationState)
        { 
            if (result is TypedCompletedAsyncResult) 
            {
                message = TypedCompletedAsyncResult.End(result, out newCorrelationState); 
            }
            else
            {
                message = SecureOutgoingMessageAsyncResult.End(result, out newCorrelationState); 
            }
        } 
 
        WrappedKeySecurityToken CreateWrappedKeyToken(SecurityToken wrappingToken, SecurityTokenParameters wrappingTokenParameters, SecurityTokenReferenceStyle wrappingTokenReferenceStyle)
        { 
            int keyLength = Math.Max(128, this.Factory.OutgoingAlgorithmSuite.DefaultSymmetricKeyLength);
            CryptoHelper.ValidateSymmetricKeyLength(keyLength, this.Factory.OutgoingAlgorithmSuite);
            byte[] key = new byte[keyLength / 8];
            CryptoHelper.FillRandomBytes(key); 
            string tokenId = SecurityUtils.GenerateId();
            string wrappingAlgorithm = this.Factory.OutgoingAlgorithmSuite.DefaultAsymmetricKeyWrapAlgorithm; 
            SecurityKeyIdentifierClause clause = wrappingTokenParameters.CreateKeyIdentifierClause(wrappingToken, wrappingTokenReferenceStyle); 
            SecurityKeyIdentifier identifier = new SecurityKeyIdentifier();
            identifier.Add(clause); 
            return new WrappedKeySecurityToken(tokenId, key, wrappingAlgorithm, wrappingToken, identifier);
        }

        SecurityToken GetInitiatorToken(SecurityToken providerToken, 
            Message message,
            TimeSpan timeout, 
            out SecurityTokenParameters tokenParameters, 
            out SecurityToken prerequisiteWrappingToken)
        { 
            tokenParameters = null;
            prerequisiteWrappingToken = null;
            SecurityToken token;
            if (this.Factory.SecurityTokenParameters.HasAsymmetricKey) 
            {
                SecurityToken asymmetricToken = providerToken; 
                // non-Indigo server implementations might require the wrapping token to be included in the message 
                bool isAsymmetricTokenInMessage = SendSecurityHeader.ShouldSerializeToken(this.Factory.SecurityTokenParameters, MessageDirection.Input);
                if (isAsymmetricTokenInMessage) 
                {
                    prerequisiteWrappingToken = asymmetricToken;
                }
                token = CreateWrappedKeyToken(asymmetricToken, this.Factory.SecurityTokenParameters, (isAsymmetricTokenInMessage) ? SecurityTokenReferenceStyle.Internal : SecurityTokenReferenceStyle.External); 
            }
            else 
            { 
                token = providerToken;
            } 

            tokenParameters = this.Factory.GetProtectionTokenParameters();
            return token;
        } 

        // try to get the token if it can be obtained within the 
        // synchronous requirements of the call; return true iff a 
        // token not required OR a token is required AND has been
        // obtained within the specified synchronous requirements. 
        bool TryGetTokenSynchronouslyForOutgoingSecurity(Message message, SecurityProtocolCorrelationState correlationState, bool isBlockingCall, TimeSpan timeout, out SecurityToken token, out SecurityTokenParameters tokenParameters, out SecurityToken prerequisiteWrappingToken, out IList supportingTokens, out SecurityProtocolCorrelationState newCorrelationState)
        {
            SymmetricSecurityProtocolFactory factory = this.Factory;
            supportingTokens = null; 
            prerequisiteWrappingToken = null;
            token = null; 
            tokenParameters = null; 
            newCorrelationState = null;
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            if (factory.ApplyIntegrity || factory.ApplyConfidentiality)
            {
                if (factory.ActAsInitiator)
                { 
                    if (!isBlockingCall || !TryGetSupportingTokens(factory, this.Target, this.Via, message, timeoutHelper.RemainingTime(), isBlockingCall, out supportingTokens))
                    { 
                        return false; 
                    }
                    SecurityTokenProvider provider = GetTokenProvider(); 
                    SecurityToken providerToken = GetTokenAndEnsureOutgoingIdentity(provider, factory.ApplyConfidentiality, timeoutHelper.RemainingTime(), this.initiatorTokenAuthenticator);
                    token = GetInitiatorToken(providerToken, message, timeoutHelper.RemainingTime(), out tokenParameters, out prerequisiteWrappingToken);
                    newCorrelationState = GetCorrelationState(token);
                } 
                else
                { 
                    token = GetCorrelationToken(correlationState); 
                    tokenParameters = this.Factory.GetProtectionTokenParameters();
                } 
            }
            return true;
        }
 
        SecurityToken GetCorrelationToken(SecurityProtocolCorrelationState[] correlationStates, out SecurityTokenParameters correlationTokenParameters)
        { 
            SecurityToken token = GetCorrelationToken(correlationStates); 
            correlationTokenParameters = this.Factory.GetProtectionTokenParameters();
            return token; 
        }

        void EnsureWrappedToken(SecurityToken token, Message message)
        { 
            if (!(token is WrappedKeySecurityToken))
            { 
                throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.IncomingSigningTokenMustBeAnEncryptedKey)), message); 
            }
        } 

        protected override SecurityProtocolCorrelationState VerifyIncomingMessageCore(ref Message message, string actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
        {
            SymmetricSecurityProtocolFactory factory = this.Factory; 
            IList supportingAuthenticators;
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            ReceiveSecurityHeader securityHeader = ConfigureReceiveSecurityHeader(message, string.Empty, correlationStates, out supportingAuthenticators); 
            SecurityToken requiredReplySigningToken = null;
            if (this.Factory.ActAsInitiator) 
            {
                // set the outofband protection token
                SecurityTokenParameters outOfBandTokenParameters;
                SecurityToken outOfBandToken = GetCorrelationToken(correlationStates, out outOfBandTokenParameters); 
                securityHeader.ConfigureSymmetricBindingClientReceiveHeader(outOfBandToken, outOfBandTokenParameters);
                requiredReplySigningToken = outOfBandToken; 
            } 
            else
            { 
                if (factory.RecipientSymmetricTokenAuthenticator != null)
                {
                    securityHeader.ConfigureSymmetricBindingServerReceiveHeader(this.Factory.RecipientSymmetricTokenAuthenticator, this.Factory.SecurityTokenParameters, supportingAuthenticators);
                } 
                else
                { 
                    securityHeader.ConfigureSymmetricBindingServerReceiveHeader(this.Factory.RecipientAsymmetricTokenProvider.GetToken(timeoutHelper.RemainingTime()), this.Factory.SecurityTokenParameters, supportingAuthenticators); 
                    securityHeader.WrappedKeySecurityTokenAuthenticator = this.Factory.WrappedKeySecurityTokenAuthenticator;
                } 
                securityHeader.ConfigureOutOfBandTokenResolver(MergeOutOfBandResolvers(supportingAuthenticators, this.Factory.RecipientOutOfBandTokenResolverList));
            }

            ProcessSecurityHeader(securityHeader, ref message, requiredReplySigningToken, timeoutHelper.RemainingTime(), correlationStates); 
            SecurityToken signingToken = securityHeader.SignatureToken;
            if (factory.RequireIntegrity) 
            { 
                if (factory.SecurityTokenParameters.HasAsymmetricKey)
                { 
                    // enforce that the signing token is a wrapped key token
                    EnsureWrappedToken(signingToken, message);
                }
                else 
                {
                    EnsureNonWrappedToken(signingToken, message); 
                } 

                if (factory.ActAsInitiator) 
                {
                    if (!factory.SecurityTokenParameters.HasAsymmetricKey)
                    {
                        ReadOnlyCollection signingTokenPolicies = this.initiatorTokenAuthenticator.ValidateToken(signingToken); 
                        DoIdentityCheckAndAttachInitiatorSecurityProperty(message, signingToken, signingTokenPolicies);
                    } 
                    else 
                    {
                        SecurityToken wrappingToken = (signingToken as WrappedKeySecurityToken).WrappingToken; 
                        ReadOnlyCollection wrappingTokenPolicies = this.initiatorTokenAuthenticator.ValidateToken(wrappingToken);
                        DoIdentityCheckAndAttachInitiatorSecurityProperty(message, signingToken, wrappingTokenPolicies);
                    }
                } 
                else
                { 
                    AttachRecipientSecurityProperty(message, signingToken, this.Factory.SecurityTokenParameters.HasAsymmetricKey, securityHeader.BasicSupportingTokens, securityHeader.EndorsingSupportingTokens, securityHeader.SignedEndorsingSupportingTokens, 
                        securityHeader.SignedSupportingTokens, securityHeader.SecurityTokenAuthorizationPoliciesMapping);
                } 
            }
            return GetCorrelationState(signingToken, securityHeader);
        }
 
        sealed class SecureOutgoingMessageAsyncResult : GetOneTokenAndSetUpSecurityAsyncResult
        { 
            SymmetricSecurityProtocol symmetricBinding; 

            public SecureOutgoingMessageAsyncResult(Message m, SymmetricSecurityProtocol binding, SecurityTokenProvider provider, 
                bool doIdentityChecks, SecurityTokenAuthenticator identityCheckAuthenticator, SecurityProtocolCorrelationState correlationState, TimeSpan timeout, AsyncCallback callback, object state)
                : base(m, binding, provider, doIdentityChecks, identityCheckAuthenticator, correlationState, timeout, callback, state)
            {
                symmetricBinding = binding; 
                Start();
            } 
 
            protected override void OnGetTokenDone(ref Message message, SecurityToken providerToken, TimeSpan timeout)
            { 
                SecurityTokenParameters tokenParameters;
                SecurityToken prerequisiteWrappingToken;
                SecurityToken token = symmetricBinding.GetInitiatorToken(providerToken, message, timeout, out tokenParameters, out prerequisiteWrappingToken);
                this.SetCorrelationToken(token); 
                symmetricBinding.SetUpDelayedSecurityExecution(ref message, prerequisiteWrappingToken, token, tokenParameters, this.SupportingTokens, Binding.GetSignatureConfirmationCorrelationState(OldCorrelationState, NewCorrelationState));
            } 
        } 
    }
} 

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