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

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

namespace System.ServiceModel.Security 
{
    using System.Collections; 
    using System.Collections.ObjectModel; 
    using System.ServiceModel;
    using System.Xml; 
    using System.IdentityModel.Tokens;
    using System.IdentityModel.Selectors;
    using System.Collections.Generic;
    using System.ServiceModel.Security.Tokens; 

    class DerivedKeyCachingSecurityTokenSerializer : SecurityTokenSerializer 
    { 
        DerivedKeySecurityTokenCache[] cachedTokens;
        WSSecureConversation secureConversation; 
        SecurityTokenSerializer innerTokenSerializer;
        bool isInitiator;
        int indexToCache = 0;
        Object thisLock; 

        internal DerivedKeyCachingSecurityTokenSerializer(int cacheSize, bool isInitiator, WSSecureConversation secureConversation, SecurityTokenSerializer innerTokenSerializer) 
            : base() 
        {
            if (innerTokenSerializer == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("innerTokenSerializer");
            }
            if (secureConversation == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("secureConversation"); 
            } 
            if (cacheSize <= 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("cacheSize", SR.GetString(SR.ValueMustBeGreaterThanZero)));
            }
            this.cachedTokens = new DerivedKeySecurityTokenCache[cacheSize];
            this.isInitiator = isInitiator; 
            this.secureConversation = secureConversation;
            this.innerTokenSerializer = innerTokenSerializer; 
            this.thisLock = new Object(); 
        }
 
        protected override bool CanReadKeyIdentifierClauseCore(XmlReader reader)
        {
            return this.innerTokenSerializer.CanReadKeyIdentifierClause(reader);
        } 

        protected override bool CanReadKeyIdentifierCore(XmlReader reader) 
        { 
            return this.innerTokenSerializer.CanReadKeyIdentifier(reader);
        } 

        protected override bool CanReadTokenCore(XmlReader reader)
        {
            return this.innerTokenSerializer.CanReadToken(reader); 
        }
 
        protected override SecurityToken ReadTokenCore(XmlReader reader, SecurityTokenResolver tokenResolver) 
        {
            XmlDictionaryReader dictionaryReader = XmlDictionaryReader.CreateDictionaryReader(reader); 
            if (this.secureConversation.IsAtDerivedKeyToken(dictionaryReader))
            {
                string id;
                string derivationAlgorithm; 
                string label;
                int length; 
                byte[] nonce; 
                int offset;
                int generation; 
                SecurityKeyIdentifierClause tokenToDeriveIdentifier;
                SecurityToken tokenToDerive;
                this.secureConversation.ReadDerivedKeyTokenParameters(dictionaryReader, tokenResolver, out id, out derivationAlgorithm, out label,
                    out length, out nonce, out offset, out generation, out tokenToDeriveIdentifier, out tokenToDerive); 

                DerivedKeySecurityToken cachedToken = GetCachedToken(id, generation, offset, length, label, nonce, tokenToDerive, tokenToDeriveIdentifier, derivationAlgorithm); 
                if (cachedToken != null) 
                {
                    return cachedToken; 
                }

                lock (this.thisLock)
                { 
                    cachedToken = GetCachedToken(id, generation, offset, length, label, nonce, tokenToDerive, tokenToDeriveIdentifier, derivationAlgorithm);
                    if (cachedToken != null) 
                    { 
                        return cachedToken;
                    } 
                    SecurityToken result = this.secureConversation.CreateDerivedKeyToken(id, derivationAlgorithm, label, length, nonce, offset, generation, tokenToDeriveIdentifier, tokenToDerive)    as DerivedKeySecurityToken;
                    DerivedKeySecurityToken newToken = result as DerivedKeySecurityToken;
                    if (newToken != null)
                    { 
                        int pos = this.indexToCache;
                        if (this.indexToCache == int.MaxValue) 
                            this.indexToCache = 0; 
                        else
                            this.indexToCache = (++this.indexToCache) % this.cachedTokens.Length; 
                        this.cachedTokens[pos] = new DerivedKeySecurityTokenCache(newToken);
                    }
                    return result;
                } 
            }
            else 
            { 
                return this.innerTokenSerializer.ReadToken(reader, tokenResolver);
            } 
        }

        protected override bool CanWriteKeyIdentifierClauseCore(SecurityKeyIdentifierClause keyIdentifierClause)
        { 
            return this.innerTokenSerializer.CanWriteKeyIdentifierClause(keyIdentifierClause);
        } 
 
        protected override bool CanWriteKeyIdentifierCore(SecurityKeyIdentifier keyIdentifier)
        { 
            return this.innerTokenSerializer.CanWriteKeyIdentifier(keyIdentifier);
        }

        protected override bool CanWriteTokenCore(SecurityToken token) 
        {
            return this.innerTokenSerializer.CanWriteToken(token); 
        } 

        protected override SecurityKeyIdentifierClause ReadKeyIdentifierClauseCore(XmlReader reader) 
        {
            return this.innerTokenSerializer.ReadKeyIdentifierClause(reader);
        }
 
        protected override SecurityKeyIdentifier ReadKeyIdentifierCore(XmlReader reader)
        { 
            return this.innerTokenSerializer.ReadKeyIdentifier(reader); 
        }
 
        protected override void WriteKeyIdentifierClauseCore(XmlWriter writer, SecurityKeyIdentifierClause keyIdentifierClause)
        {
            this.innerTokenSerializer.WriteKeyIdentifierClause(writer, keyIdentifierClause);
        } 

        protected override void WriteKeyIdentifierCore(XmlWriter writer, SecurityKeyIdentifier keyIdentifier) 
        { 
            this.innerTokenSerializer.WriteKeyIdentifier(writer, keyIdentifier);
        } 

        protected override void WriteTokenCore(XmlWriter writer, SecurityToken token)
        {
            this.innerTokenSerializer.WriteToken(writer, token); 
        }
 
        bool IsMatch(DerivedKeySecurityTokenCache cachedToken, string id, int generation, int offset, int length, 
            string label, byte[] nonce, SecurityToken tokenToDerive, string derivationAlgorithm)
        { 
            if ((cachedToken.Generation == generation)
                && (cachedToken.Offset == offset)
                && (cachedToken.Length == length)
                && (cachedToken.Label == label) 
                && (cachedToken.KeyDerivationAlgorithm == derivationAlgorithm))
            { 
                if (!cachedToken.IsSourceKeyEqual(tokenToDerive)) 
                {
                    return false; 
                }
                // since derived key token keys are delay initialized during security processing, it may be possible
                // that the cached derived key token does not have its keys initialized as yet. If so return false for
                // the match so that the framework doesnt try to reference a null key. 
                return (CryptoHelper.IsEqual(cachedToken.Nonce, nonce) && (cachedToken.SecurityKeys != null));
            } 
            else 
            {
                return false; 
            }
        }

        DerivedKeySecurityToken GetCachedToken(string id, int generation, int offset, int length, 
            string label, byte[] nonce, SecurityToken tokenToDerive, SecurityKeyIdentifierClause tokenToDeriveIdentifier, string derivationAlgorithm)
        { 
            for (int i = 0; i < this.cachedTokens.Length; ++i) 
            {
                DerivedKeySecurityTokenCache cachedToken = this.cachedTokens[i]; 
                if (cachedToken != null && IsMatch(cachedToken, id, generation, offset, length,
                    label, nonce, tokenToDerive, derivationAlgorithm))
                {
                    DerivedKeySecurityToken token = new DerivedKeySecurityToken(generation, offset, length, label, nonce, tokenToDerive, 
                        tokenToDeriveIdentifier, derivationAlgorithm, id);
                    token.InitializeDerivedKey(cachedToken.SecurityKeys); 
                    return token; 
                }
            } 
            return null;
        }

        class DerivedKeySecurityTokenCache 
        {
            byte[] keyToDerive; 
            int generation; 
            int offset;
            int length; 
            string label;
            string keyDerivationAlgorithm;
            byte[] nonce;
            ReadOnlyCollection keys; 
            DerivedKeySecurityToken cachedToken;
 
            public DerivedKeySecurityTokenCache(DerivedKeySecurityToken cachedToken) 
            {
                this.keyToDerive = ((SymmetricSecurityKey)cachedToken.TokenToDerive.SecurityKeys[0]).GetSymmetricKey(); 
                this.generation = cachedToken.Generation;
                this.offset = cachedToken.Offset;
                this.length = cachedToken.Length;
                this.label = cachedToken.Label; 
                this.keyDerivationAlgorithm = cachedToken.KeyDerivationAlgorithm;
                this.nonce = cachedToken.Nonce; 
                this.cachedToken = cachedToken; 
            }
 
            public int Generation
            {
                get { return this.generation; }
            } 

            public int Offset 
            { 
                get { return this.offset; }
            } 

            public int Length
            {
                get { return this.length; } 
            }
 
            public string Label 
            {
                get { return this.label; } 
            }

            public string KeyDerivationAlgorithm
            { 
                get { return this.keyDerivationAlgorithm; }
            } 
 
            public byte[] Nonce
            { 
                get { return this.nonce; }
            }

            public ReadOnlyCollection SecurityKeys 
            {
                get 
                { 
                    // we would need to hold onto the cached token till a hit is obtained because of
                    // the delay initialization of derived key crypto by the security header. 
                    lock (this)
                    {
                        if (this.keys == null)
                        { 
                            ReadOnlyCollection computedKeys;
                            if (this.cachedToken.TryGetSecurityKeys(out computedKeys)) 
                            { 
                                this.keys = computedKeys;
                                this.cachedToken = null; 
                            }
                        }
                    }
                    return this.keys; 
                }
            } 
 
            public bool IsSourceKeyEqual(SecurityToken token)
            { 
                if (token.SecurityKeys.Count != 1)
                {
                    return false;
                } 
                SymmetricSecurityKey key = token.SecurityKeys[0] as SymmetricSecurityKey;
                if (key == null) 
                { 
                    return false;
                } 
                return CryptoHelper.IsEqual(this.keyToDerive, key.GetSymmetricKey());
            }
        }
    } 
}

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