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

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

namespace System.ServiceModel.Security 
{
    using System.ServiceModel.Channels; 
    using System.ServiceModel; 
    using System.Diagnostics;
    using System.IdentityModel.Tokens; 
    using System.ServiceModel.Diagnostics;
    using System.Xml;

    using SignedXml = System.IdentityModel.SignedXml; 
    using ISignatureValueSecurityElement = System.IdentityModel.ISignatureValueSecurityElement;
    using ISignatureReaderProvider = System.IdentityModel.ISignatureReaderProvider; 
 
    sealed class ReceiveSecurityHeaderElementManager : ISignatureReaderProvider
    { 
        const int InitialCapacity = 8;
        readonly ReceiveSecurityHeader securityHeader;
        ReceiveSecurityHeaderEntry[] elements;
        int count; 
        readonly string[] headerIds;
        string[] predecryptionHeaderIds; 
        string bodyId; 
        string bodyContentId;
 
        public ReceiveSecurityHeaderElementManager(ReceiveSecurityHeader securityHeader)
        {
            this.securityHeader = securityHeader;
            this.elements = new ReceiveSecurityHeaderEntry[InitialCapacity]; 
            if (securityHeader.RequireMessageProtection)
            { 
                this.headerIds = new string[securityHeader.ProcessedMessage.Headers.Count]; 
            }
        } 

        public int Count
        {
            get { return this.count; } 
        }
 
        public void AppendElement( 
            ReceiveSecurityHeaderElementCategory elementCategory, object element,
            ReceiveSecurityHeaderBindingModes bindingMode, string id, TokenTracker supportingTokenTracker) 
        {
            if (id != null)
            {
                VerifyIdUniquenessInSecurityHeader(id); 
            }
            EnsureCapacityToAdd(); 
            this.elements[this.count++].SetElement(elementCategory, element, bindingMode, id, false, null, supportingTokenTracker); 
        }
 
        public void AppendSignature(SignedXml signedXml)
        {
            AppendElement(ReceiveSecurityHeaderElementCategory.Signature, signedXml,
                ReceiveSecurityHeaderBindingModes.Unknown, signedXml.Id, null); 
        }
 
        public void AppendReferenceList(ReferenceList referenceList) 
        {
            AppendElement(ReceiveSecurityHeaderElementCategory.ReferenceList, referenceList, 
                ReceiveSecurityHeaderBindingModes.Unknown, null, null);
        }

        public void AppendEncryptedData(EncryptedData encryptedData) 
        {
            AppendElement(ReceiveSecurityHeaderElementCategory.EncryptedData, encryptedData, 
                ReceiveSecurityHeaderBindingModes.Unknown, encryptedData.Id, null); 
        }
 
        public void AppendSignatureConfirmation(ISignatureValueSecurityElement signatureConfirmationElement)
        {
            AppendElement(ReceiveSecurityHeaderElementCategory.SignatureConfirmation, signatureConfirmationElement,
                ReceiveSecurityHeaderBindingModes.Unknown, signatureConfirmationElement.Id, null); 
        }
 
        public void AppendTimestamp(SecurityTimestamp timestamp) 
        {
            AppendElement(ReceiveSecurityHeaderElementCategory.Timestamp, timestamp, 
                ReceiveSecurityHeaderBindingModes.Unknown, timestamp.Id, null);
        }

        public void AppendToken(SecurityToken token, ReceiveSecurityHeaderBindingModes mode, TokenTracker supportingTokenTracker) 
        {
            AppendElement(ReceiveSecurityHeaderElementCategory.Token, token, 
                mode, token.Id, supportingTokenTracker); 
        }
 
        public void EnsureAllRequiredSecurityHeaderTargetsWereProtected()
        {
            DiagnosticUtility.DebugAssert(this.securityHeader.RequireMessageProtection, "security header protection checks should only be done for message security");
            ReceiveSecurityHeaderEntry entry; 
            for (int i = 0; i < this.count; i++)
            { 
                GetElementEntry(i, out entry); 
                if (!entry.signed)
                { 
                    switch (entry.elementCategory)
                    {
                        case ReceiveSecurityHeaderElementCategory.Timestamp:
                        case ReceiveSecurityHeaderElementCategory.SignatureConfirmation: 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                new MessageSecurityException(SR.GetString(SR.RequiredSecurityHeaderElementNotSigned, entry.elementCategory, entry.id))); 
                        case ReceiveSecurityHeaderElementCategory.Token: 
                            switch (entry.bindingMode)
                            { 
                                case ReceiveSecurityHeaderBindingModes.Signed:
                                case ReceiveSecurityHeaderBindingModes.SignedEndorsing:
                                case ReceiveSecurityHeaderBindingModes.Basic:
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                                        new MessageSecurityException(SR.GetString(SR.RequiredSecurityTokenNotSigned, entry.element, entry.bindingMode)));
                            } 
                            break; 
                    }
                } 

                if (!entry.encrypted)
                {
                    if (entry.elementCategory == ReceiveSecurityHeaderElementCategory.Token && 
                        entry.bindingMode == ReceiveSecurityHeaderBindingModes.Basic)
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            new MessageSecurityException(SR.GetString(SR.RequiredSecurityTokenNotEncrypted, entry.element, entry.bindingMode)));
                    } 
                }
            }
        }
 
        void EnsureCapacityToAdd()
        { 
            if (this.count == this.elements.Length) 
            {
                ReceiveSecurityHeaderEntry[] newElements = new ReceiveSecurityHeaderEntry[this.elements.Length * 2]; 
                Array.Copy(this.elements, 0, newElements, 0, this.count);
                this.elements = newElements;
            }
        } 

        public object GetElement(int index) 
        { 
            DiagnosticUtility.DebugAssert(0 <= index && index < this.count, "");
            return this.elements[index].element; 
        }

        public T GetElement(int index) where T : class
        { 
            DiagnosticUtility.DebugAssert(0 <= index && index < this.count, "");
            return (T) this.elements[index].element; 
        } 

        public void GetElementEntry(int index, out ReceiveSecurityHeaderEntry element) 
        {
            DiagnosticUtility.DebugAssert(0 <= index && index < this.count, "index out of range");
            element = this.elements[index];
        } 

        public ReceiveSecurityHeaderElementCategory GetElementCategory(int index) 
        { 
            DiagnosticUtility.DebugAssert(0 <= index && index < this.count, "index out of range");
            return this.elements[index].elementCategory; 
        }

        public void GetPrimarySignature(out XmlDictionaryReader reader, out string id)
        { 
            ReceiveSecurityHeaderEntry entry;
            for (int i = 0; i < this.count; i++) 
            { 
                GetElementEntry(i, out entry);
                if (entry.elementCategory == ReceiveSecurityHeaderElementCategory.Signature && 
                    entry.bindingMode == ReceiveSecurityHeaderBindingModes.Primary)
                {
                    reader = GetReader(i, false);
                    id = entry.id; 
                    return;
                } 
            } 
            reader = null;
            id = null; 
            return;
        }

        internal XmlDictionaryReader GetReader(int index, bool requiresEncryptedFormReader) 
        {
            DiagnosticUtility.DebugAssert(0 <= index && index < this.count, "index out of range"); 
            if (!requiresEncryptedFormReader) 
            {
                byte[] decryptedBuffer = this.elements[index].decryptedBuffer; 
                if (decryptedBuffer != null)
                {
                    return this.securityHeader.CreateDecryptedReader(decryptedBuffer);
                } 
            }
            XmlDictionaryReader securityHeaderReader = this.securityHeader.CreateSecurityHeaderReader(); 
            securityHeaderReader.ReadStartElement(); 
            for (int i = 0; securityHeaderReader.IsStartElement() && i < index; i++)
            { 
                securityHeaderReader.Skip();
            }
            return securityHeaderReader;
        } 

        public XmlDictionaryReader GetSignatureVerificationReader(string id, bool requiresEncryptedFormReaderIfDecrypted) 
        { 
            ReceiveSecurityHeaderEntry entry;
            for (int i = 0; i < this.count; i++) 
            {
                GetElementEntry(i, out entry);
                bool encryptedForm = entry.encrypted && requiresEncryptedFormReaderIfDecrypted;
                if (entry.MatchesId(id, encryptedForm)) 
                {
                    SetSigned(i); 
                    return GetReader(i, encryptedForm); 
                }
            } 
            return null;
        }

        void OnDuplicateId(string id) 
        {
            throw TraceUtility.ThrowHelperError( 
                new MessageSecurityException(SR.GetString(SR.DuplicateIdInMessageToBeVerified, id)), this.securityHeader.SecurityVerifiedMessage); 
        }
 
        public void SetBindingMode(int index, ReceiveSecurityHeaderBindingModes bindingMode)
        {
            DiagnosticUtility.DebugAssert(0 <= index && index < this.count, "index out of range");
            this.elements[index].bindingMode = bindingMode; 
        }
 
        public void SetElement(int index, object element) 
        {
            DiagnosticUtility.DebugAssert(0 <= index && index < this.count, ""); 
            this.elements[index].element = element;
        }

        public void ReplaceHeaderEntry(int index, ReceiveSecurityHeaderEntry element) 
        {
            DiagnosticUtility.DebugAssert(0 <= index && index < this.count, ""); 
            this.elements[index] = element; 
        }
 
        public void SetElementAfterDecryption(
            int index,
            ReceiveSecurityHeaderElementCategory elementCategory, object element,
            ReceiveSecurityHeaderBindingModes bindingMode, string id, byte[] decryptedBuffer, TokenTracker supportingTokenTracker) 
        {
            DiagnosticUtility.DebugAssert(0 <= index && index < this.count, "index out of range"); 
            DiagnosticUtility.DebugAssert(this.elements[index].elementCategory == ReceiveSecurityHeaderElementCategory.EncryptedData, "Replaced item must be EncryptedData"); 
            if (id != null)
            { 
                VerifyIdUniquenessInSecurityHeader(id);
            }
            this.elements[index].PreserveIdBeforeDecryption();
            this.elements[index].SetElement(elementCategory, element, bindingMode, id, true, decryptedBuffer, supportingTokenTracker); 
        }
 
        public void SetSignatureAfterDecryption(int index, SignedXml signedXml, byte[] decryptedBuffer) 
        {
            SetElementAfterDecryption(index, ReceiveSecurityHeaderElementCategory.Signature, 
                                      signedXml, ReceiveSecurityHeaderBindingModes.Unknown, signedXml.Id, decryptedBuffer, null);
        }

        public void SetSignatureConfirmationAfterDecryption(int index, ISignatureValueSecurityElement signatureConfirmationElement, byte[] decryptedBuffer) 
        {
            SetElementAfterDecryption(index, ReceiveSecurityHeaderElementCategory.SignatureConfirmation, 
                                      signatureConfirmationElement, ReceiveSecurityHeaderBindingModes.Unknown, signatureConfirmationElement.Id, decryptedBuffer, null); 
        }
 
        void SetSigned(int index)
        {
            DiagnosticUtility.DebugAssert(0 <= index && index < this.count, "");
            this.elements[index].signed = true; 
            if (this.elements[index].supportingTokenTracker != null)
            { 
                this.elements[index].supportingTokenTracker.IsSigned = true; 
            }
        } 

        public void SetTimestampSigned(string id)
        {
            for (int i = 0; i < this.count; i++) 
            {
                if (this.elements[i].elementCategory == ReceiveSecurityHeaderElementCategory.Timestamp && 
                    this.elements[i].id == id) 
                {
                    SetSigned(i); 
                }
            }
        }
 
        public void SetTokenAfterDecryption(int index, SecurityToken token, ReceiveSecurityHeaderBindingModes mode, byte[] decryptedBuffer, TokenTracker supportingTokenTracker)
        { 
            SetElementAfterDecryption(index, ReceiveSecurityHeaderElementCategory.Token, token, mode, token.Id, decryptedBuffer, supportingTokenTracker); 
        }
 
        public void VerifyUniquenessAndSetBodyId(string id)
        {
            if (id != null)
            { 
                VerifyIdUniquenessInSecurityHeader(id);
                VerifyIdUniquenessInMessageHeadersAndBody(id, this.headerIds.Length); 
                this.bodyId = id; 
            }
        } 

        public void VerifyUniquenessAndSetBodyContentId(string id)
        {
            if (id != null) 
            {
                VerifyIdUniquenessInSecurityHeader(id); 
                VerifyIdUniquenessInMessageHeadersAndBody(id, this.headerIds.Length); 
                this.bodyContentId = id;
            } 
        }

        public void VerifyUniquenessAndSetDecryptedHeaderId(string id, int headerIndex)
        { 
            if (id != null)
            { 
                VerifyIdUniquenessInSecurityHeader(id); 
                VerifyIdUniquenessInMessageHeadersAndBody(id, headerIndex);
                if (this.predecryptionHeaderIds == null) 
                {
                    this.predecryptionHeaderIds = new string[headerIds.Length];
                }
                this.predecryptionHeaderIds[headerIndex] = this.headerIds[headerIndex]; 
                this.headerIds[headerIndex] = id;
            } 
        } 

        public void VerifyUniquenessAndSetHeaderId(string id, int headerIndex) 
        {
            if (id != null)
            {
                VerifyIdUniquenessInSecurityHeader(id); 
                VerifyIdUniquenessInMessageHeadersAndBody(id, headerIndex);
                this.headerIds[headerIndex] = id; 
            } 
        }
 
        void VerifyIdUniquenessInHeaderIdTable(string id, int headerCount, string[] headerIdTable)
        {
            for (int i = 0; i < headerCount; i++)
            { 
                if (headerIdTable[i] == id)
                { 
                    OnDuplicateId(id); 
                }
            } 
        }

        void VerifyIdUniquenessInSecurityHeader(string id)
        { 
            DiagnosticUtility.DebugAssert(id != null, "Uniqueness should only be tested for non-empty ids");
            for (int i = 0; i < this.count; i++) 
            { 
                if (this.elements[i].id == id || this.elements[i].encryptedFormId == id)
                { 
                    OnDuplicateId(id);
                }
            }
        } 

        void VerifyIdUniquenessInMessageHeadersAndBody(string id, int headerCount) 
        { 
            DiagnosticUtility.DebugAssert(id != null, "Uniqueness should only be tested for non-empty ids");
            VerifyIdUniquenessInHeaderIdTable(id, headerCount, this.headerIds); 
            if (this.predecryptionHeaderIds != null)
            {
                VerifyIdUniquenessInHeaderIdTable(id, headerCount, this.predecryptionHeaderIds);
            } 
            if (this.bodyId == id || this.bodyContentId == id)
            { 
                OnDuplicateId(id); 
            }
        } 

        XmlDictionaryReader ISignatureReaderProvider.GetReader(object callbackContext)
        {
            int index = (int)callbackContext; 
            DiagnosticUtility.DebugAssert(index < this.Count, "Invalid Context provided.");
            return GetReader(index, false); 
        } 
    }
} 

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