< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Security.ReceiveSecurityHeaderElementManager
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Security/ReceiveSecurityHeaderElementManager.cs
Line coverage
17%
Covered lines: 32
Uncovered lines: 151
Coverable lines: 183
Total lines: 458
Line coverage: 17.4%
Branch coverage
7%
Covered branches: 9
Total branches: 114
Branch coverage: 7.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Security/ReceiveSecurityHeaderElementManager.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Security.Cryptography.Xml;
 6using System.Xml;
 7using CoreWCF.Diagnostics;
 8using CoreWCF.IdentityModel;
 9using CoreWCF.IdentityModel.Tokens;
 10using CoreWCF.Runtime;
 11using ISignatureValueSecurityElement = CoreWCF.IdentityModel.ISignatureValueSecurityElement;
 12
 13namespace CoreWCF.Security
 14{
 15    internal interface ISignatureReaderProvider
 16    {
 17        XmlDictionaryReader GetReader(object callbackContext);
 18    }
 19
 20    internal sealed class ReceiveSecurityHeaderElementManager : ISignatureReaderProvider
 21    {
 22        private const int InitialCapacity = 8;
 23        private readonly ReceiveSecurityHeader _securityHeader;
 24        private ReceiveSecurityHeaderEntry[] _elements;
 25        private readonly string[] _headerIds;
 26        private string[] _predecryptionHeaderIds;
 27        private string _bodyId;
 28        private string _bodyContentId;
 29
 9430        public ReceiveSecurityHeaderElementManager(ReceiveSecurityHeader securityHeader)
 31        {
 9432            _securityHeader = securityHeader;
 9433            _elements = new ReceiveSecurityHeaderEntry[InitialCapacity];
 9434            if (securityHeader.RequireMessageProtection)
 35            {
 9436                _headerIds = new string[securityHeader.ProcessedMessage.Headers.Count];
 37            }
 9438        }
 39
 86640        public int Count { get; private set; }
 41
 042        public bool IsPrimaryTokenSigned { get; set; } = false;
 43
 44        public void AppendElement(
 45            ReceiveSecurityHeaderElementCategory elementCategory, object element,
 46            ReceiveSecurityHeaderBindingModes bindingMode, string id, TokenTracker supportingTokenTracker)
 47        {
 18148            if (id != null)
 49            {
 15950                VerifyIdUniquenessInSecurityHeader(id);
 51            }
 18152            EnsureCapacityToAdd();
 18153            _elements[Count++].SetElement(elementCategory, element, bindingMode, id, false, null, supportingTokenTracker
 18154        }
 55
 56        public void AppendSignature(SignedXml signedXml)
 57        {
 2358            AppendElement(ReceiveSecurityHeaderElementCategory.Signature, signedXml,
 2359                ReceiveSecurityHeaderBindingModes.Unknown, signedXml.Signature.Id, null);
 2360        }
 61
 62        public void AppendReferenceList(ReferenceList referenceList)
 63        {
 064            AppendElement(ReceiveSecurityHeaderElementCategory.ReferenceList, referenceList,
 065                ReceiveSecurityHeaderBindingModes.Unknown, null, null);
 066        }
 67
 68        public void AppendEncryptedData(EncryptedData encryptedData)
 69        {
 070            AppendElement(ReceiveSecurityHeaderElementCategory.EncryptedData, encryptedData,
 071                ReceiveSecurityHeaderBindingModes.Unknown, encryptedData.Id, null);
 072        }
 73
 74        public void AppendSignatureConfirmation(ISignatureValueSecurityElement signatureConfirmationElement)
 75        {
 076            AppendElement(ReceiveSecurityHeaderElementCategory.SignatureConfirmation, signatureConfirmationElement,
 077                ReceiveSecurityHeaderBindingModes.Unknown, signatureConfirmationElement.Id, null);
 078        }
 79
 80        public void AppendTimestamp(SecurityTimestamp timestamp)
 81        {
 9482            AppendElement(ReceiveSecurityHeaderElementCategory.Timestamp, timestamp,
 9483                ReceiveSecurityHeaderBindingModes.Unknown, timestamp.Id, null);
 9484        }
 85
 86        public void AppendSecurityTokenReference(SecurityKeyIdentifierClause strClause, string strId)
 87        {
 088            if (!string.IsNullOrEmpty(strId))
 89            {
 090                VerifyIdUniquenessInSecurityHeader(strId);
 091                AppendElement(ReceiveSecurityHeaderElementCategory.SecurityTokenReference, strClause, ReceiveSecurityHea
 92            }
 093        }
 94
 95        public void AppendToken(SecurityToken token, ReceiveSecurityHeaderBindingModes mode, TokenTracker supportingToke
 96        {
 6497            AppendElement(ReceiveSecurityHeaderElementCategory.Token, token,
 6498                mode, token.Id, supportingTokenTracker);
 6499        }
 100
 101        public void EnsureAllRequiredSecurityHeaderTargetsWereProtected()
 102        {
 103            Fx.Assert(_securityHeader.RequireMessageProtection, "security header protection checks should only be done f
 0104            for (int i = 0; i < Count; i++)
 105            {
 0106                GetElementEntry(i, out ReceiveSecurityHeaderEntry entry);
 0107                if (!entry.signed)
 108                {
 0109                    switch (entry.elementCategory)
 110                    {
 111                        case ReceiveSecurityHeaderElementCategory.Timestamp:
 112                        case ReceiveSecurityHeaderElementCategory.SignatureConfirmation:
 0113                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0114                                new MessageSecurityException(SR.Format(SR.RequiredSecurityHeaderElementNotSigned, entry.
 115                        case ReceiveSecurityHeaderElementCategory.Token:
 0116                            switch (entry.bindingMode)
 117                            {
 118                                case ReceiveSecurityHeaderBindingModes.Signed:
 119                                case ReceiveSecurityHeaderBindingModes.SignedEndorsing:
 120                                case ReceiveSecurityHeaderBindingModes.Basic:
 0121                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0122                                        new MessageSecurityException(SR.Format(SR.RequiredSecurityTokenNotSigned, entry.
 123                            }
 124                            break;
 125                    }
 126                }
 127
 0128                if (!entry.encrypted)
 129                {
 0130                    if (entry.elementCategory == ReceiveSecurityHeaderElementCategory.Token &&
 0131                        entry.bindingMode == ReceiveSecurityHeaderBindingModes.Basic)
 132                    {
 0133                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0134                            new MessageSecurityException(SR.Format(SR.RequiredSecurityTokenNotEncrypted, entry.element, 
 135                    }
 136                }
 137            }
 0138        }
 139
 140        private void EnsureCapacityToAdd()
 141        {
 181142            if (Count == _elements.Length)
 143            {
 0144                ReceiveSecurityHeaderEntry[] newElements = new ReceiveSecurityHeaderEntry[_elements.Length * 2];
 0145                Array.Copy(_elements, 0, newElements, 0, Count);
 0146                _elements = newElements;
 147            }
 181148        }
 149
 150        public object GetElement(int index)
 151        {
 152            Fx.Assert(0 <= index && index < Count, "");
 10153            return _elements[index].element;
 154        }
 155
 156        public T GetElement<T>(int index) where T : class
 157        {
 158            Fx.Assert(0 <= index && index < Count, "");
 0159            return (T)_elements[index].element;
 160        }
 161
 162        public void GetElementEntry(int index, out ReceiveSecurityHeaderEntry element)
 163        {
 164            Fx.Assert(0 <= index && index < Count, "index out of range");
 20165            element = _elements[index];
 20166        }
 167
 168        public ReceiveSecurityHeaderElementCategory GetElementCategory(int index)
 169        {
 170            Fx.Assert(0 <= index && index < Count, "index out of range");
 30171            return _elements[index].elementCategory;
 172        }
 173
 174        public void GetPrimarySignature(out XmlDictionaryReader reader, out string id)
 175        {
 0176            for (int i = 0; i < Count; i++)
 177            {
 0178                GetElementEntry(i, out ReceiveSecurityHeaderEntry entry);
 0179                if (entry.elementCategory == ReceiveSecurityHeaderElementCategory.Signature &&
 0180                    entry.bindingMode == ReceiveSecurityHeaderBindingModes.Primary)
 181                {
 0182                    reader = GetReader(i, false);
 0183                    id = entry.id;
 0184                    return;
 185                }
 186            }
 0187            reader = null;
 0188            id = null;
 0189            return;
 190        }
 191
 192        internal XmlDictionaryReader GetReader(int index, bool requiresEncryptedFormReader)
 193        {
 194            Fx.Assert(0 <= index && index < Count, "index out of range");
 0195            if (!requiresEncryptedFormReader)
 196            {
 0197                byte[] decryptedBuffer = _elements[index].decryptedBuffer;
 0198                if (decryptedBuffer != null)
 199                {
 0200                    return _securityHeader.CreateDecryptedReader(decryptedBuffer);
 201                }
 202            }
 0203            XmlDictionaryReader securityHeaderReader = _securityHeader.CreateSecurityHeaderReader();
 0204            securityHeaderReader.ReadStartElement();
 0205            for (int i = 0; securityHeaderReader.IsStartElement() && i < index; i++)
 206            {
 0207                securityHeaderReader.Skip();
 208            }
 0209            return securityHeaderReader;
 210        }
 211
 212        public XmlDictionaryReader GetSignatureVerificationReader(string id, bool requiresEncryptedFormReaderIfDecrypted
 213        {
 0214            for (int i = 0; i < Count; i++)
 215            {
 0216                GetElementEntry(i, out ReceiveSecurityHeaderEntry entry);
 0217                bool encryptedForm = entry.encrypted && requiresEncryptedFormReaderIfDecrypted;
 0218                bool isSignedToken = (entry.bindingMode == ReceiveSecurityHeaderBindingModes.Signed) || (entry.bindingMo
 0219                if (entry.MatchesId(id, encryptedForm))
 220                {
 0221                    SetSigned(i);
 0222                    if (!IsPrimaryTokenSigned)
 223                    {
 0224                        IsPrimaryTokenSigned = entry.bindingMode == ReceiveSecurityHeaderBindingModes.Primary && entry.e
 225                    }
 0226                    return GetReader(i, encryptedForm);
 227                }
 0228                else if (entry.MatchesId(id, isSignedToken))
 229                {
 0230                    SetSigned(i);
 0231                    if (!IsPrimaryTokenSigned)
 232                    {
 0233                        IsPrimaryTokenSigned = entry.bindingMode == ReceiveSecurityHeaderBindingModes.Primary && entry.e
 234                    }
 0235                    return GetReader(i, isSignedToken);
 236                }
 237            }
 0238            return null;
 239        }
 240
 241        private void OnDuplicateId(string id)
 242        {
 0243            throw TraceUtility.ThrowHelperError(
 0244                new MessageSecurityException(SR.Format(SR.DuplicateIdInMessageToBeVerified, id)), _securityHeader.Securi
 245        }
 246
 247        public void SetBindingMode(int index, ReceiveSecurityHeaderBindingModes bindingMode)
 248        {
 249            Fx.Assert(0 <= index && index < Count, "index out of range");
 23250            _elements[index].bindingMode = bindingMode;
 23251        }
 252
 253        public void SetElement(int index, object element)
 254        {
 255            Fx.Assert(0 <= index && index < Count, "");
 0256            _elements[index].element = element;
 0257        }
 258
 259        public void ReplaceHeaderEntry(int index, ReceiveSecurityHeaderEntry element)
 260        {
 261            Fx.Assert(0 <= index && index < Count, "");
 0262            _elements[index] = element;
 0263        }
 264
 265        public void SetElementAfterDecryption(
 266            int index,
 267            ReceiveSecurityHeaderElementCategory elementCategory, object element,
 268            ReceiveSecurityHeaderBindingModes bindingMode, string id, byte[] decryptedBuffer, TokenTracker supportingTok
 269        {
 270            Fx.Assert(0 <= index && index < Count, "index out of range");
 271            Fx.Assert(_elements[index].elementCategory == ReceiveSecurityHeaderElementCategory.EncryptedData, "Replaced 
 0272            if (id != null)
 273            {
 0274                VerifyIdUniquenessInSecurityHeader(id);
 275            }
 0276            _elements[index].PreserveIdBeforeDecryption();
 0277            _elements[index].SetElement(elementCategory, element, bindingMode, id, true, decryptedBuffer, supportingToke
 0278        }
 279
 280        public void SetSignatureAfterDecryption(int index, SignedXml signedXml, byte[] decryptedBuffer)
 281        {
 0282            SetElementAfterDecryption(index, ReceiveSecurityHeaderElementCategory.Signature,
 0283                                      signedXml, ReceiveSecurityHeaderBindingModes.Unknown, signedXml.SignedInfo.Id, dec
 0284        }
 285
 286        public void SetSignatureConfirmationAfterDecryption(int index, ISignatureValueSecurityElement signatureConfirmat
 287        {
 0288            SetElementAfterDecryption(index, ReceiveSecurityHeaderElementCategory.SignatureConfirmation,
 0289                                      signatureConfirmationElement, ReceiveSecurityHeaderBindingModes.Unknown, signature
 0290        }
 291
 292        internal void SetSigned(int index)
 293        {
 294            Fx.Assert(0 <= index && index < Count, "");
 0295            _elements[index].signed = true;
 0296            if (_elements[index].supportingTokenTracker != null)
 297            {
 0298                _elements[index].supportingTokenTracker.IsSigned = true;
 299            }
 0300        }
 301
 302        public void SetTimestampSigned(string id)
 303        {
 0304            for (int i = 0; i < Count; i++)
 305            {
 0306                if (_elements[i].elementCategory == ReceiveSecurityHeaderElementCategory.Timestamp &&
 0307                    _elements[i].id == id)
 308                {
 0309                    SetSigned(i);
 310                }
 311            }
 0312        }
 313
 314        public void SetTokenAfterDecryption(int index, SecurityToken token, ReceiveSecurityHeaderBindingModes mode, byte
 315        {
 0316            SetElementAfterDecryption(index, ReceiveSecurityHeaderElementCategory.Token, token, mode, token.Id, decrypte
 0317        }
 318
 319        internal bool TryGetTokenElementIndexFromStrId(string strId, out int index)
 320        {
 0321            index = -1;
 0322            SecurityKeyIdentifierClause strClause = null;
 0323            for (int position = 0; position < Count; position++)
 324            {
 0325                if (GetElementCategory(position) == ReceiveSecurityHeaderElementCategory.SecurityTokenReference)
 326                {
 0327                    strClause = GetElement(position) as SecurityKeyIdentifierClause;
 0328                    if (strClause.Id == strId)
 329                    {
 330                        break;
 331                    }
 332                }
 333            }
 334
 0335            if (strClause == null)
 336            {
 0337                return false;
 338            }
 339
 0340            for (int position = 0; position < Count; position++)
 341            {
 0342                if (GetElementCategory(position) == ReceiveSecurityHeaderElementCategory.Token)
 343                {
 0344                    SecurityToken token = GetElement(position) as SecurityToken;
 0345                    if (token.MatchesKeyIdentifierClause(strClause))
 346                    {
 0347                        index = position;
 0348                        return true;
 349                    }
 350                }
 351            }
 352
 0353            return false;
 354        }
 355
 356        public void VerifyUniquenessAndSetBodyId(string id)
 357        {
 0358            if (id != null)
 359            {
 0360                VerifyIdUniquenessInSecurityHeader(id);
 0361                VerifyIdUniquenessInMessageHeadersAndBody(id, _headerIds.Length);
 0362                _bodyId = id;
 363            }
 0364        }
 365
 366        public void VerifyUniquenessAndSetBodyContentId(string id)
 367        {
 0368            if (id != null)
 369            {
 0370                VerifyIdUniquenessInSecurityHeader(id);
 0371                VerifyIdUniquenessInMessageHeadersAndBody(id, _headerIds.Length);
 0372                _bodyContentId = id;
 373            }
 0374        }
 375
 376        public void VerifyUniquenessAndSetDecryptedHeaderId(string id, int headerIndex)
 377        {
 0378            if (id != null)
 379            {
 0380                VerifyIdUniquenessInSecurityHeader(id);
 0381                VerifyIdUniquenessInMessageHeadersAndBody(id, headerIndex);
 0382                if (_predecryptionHeaderIds == null)
 383                {
 0384                    _predecryptionHeaderIds = new string[_headerIds.Length];
 385                }
 0386                _predecryptionHeaderIds[headerIndex] = _headerIds[headerIndex];
 0387                _headerIds[headerIndex] = id;
 388            }
 0389        }
 390
 391        public void VerifyUniquenessAndSetHeaderId(string id, int headerIndex)
 392        {
 0393            if (id != null)
 394            {
 0395                VerifyIdUniquenessInSecurityHeader(id);
 0396                VerifyIdUniquenessInMessageHeadersAndBody(id, headerIndex);
 0397                _headerIds[headerIndex] = id;
 398            }
 0399        }
 400
 401        private void VerifyIdUniquenessInHeaderIdTable(string id, int headerCount, string[] headerIdTable)
 402        {
 0403            for (int i = 0; i < headerCount; i++)
 404            {
 0405                if (headerIdTable[i] == id)
 406                {
 0407                    OnDuplicateId(id);
 408                }
 409            }
 0410        }
 411
 412        private void VerifyIdUniquenessInSecurityHeader(string id)
 413        {
 414            Fx.Assert(id != null, "Uniqueness should only be tested for non-empty ids");
 450415            for (int i = 0; i < Count; i++)
 416            {
 66417                if (_elements[i].id == id || _elements[i].encryptedFormId == id)
 418                {
 0419                    OnDuplicateId(id);
 420                }
 421            }
 159422        }
 423
 424        private void VerifyIdUniquenessInMessageHeadersAndBody(string id, int headerCount)
 425        {
 426            Fx.Assert(id != null, "Uniqueness should only be tested for non-empty ids");
 0427            VerifyIdUniquenessInHeaderIdTable(id, headerCount, _headerIds);
 0428            if (_predecryptionHeaderIds != null)
 429            {
 0430                VerifyIdUniquenessInHeaderIdTable(id, headerCount, _predecryptionHeaderIds);
 431            }
 0432            if (_bodyId == id || _bodyContentId == id)
 433            {
 0434                OnDuplicateId(id);
 435            }
 0436        }
 437
 438        XmlDictionaryReader ISignatureReaderProvider.GetReader(object callbackContext)
 439        {
 0440            int index = (int)callbackContext;
 441            Fx.Assert(index < Count, "Invalid Context provided.");
 0442            return GetReader(index, false);
 443        }
 444
 445        public void VerifySignatureConfirmationWasFound()
 446        {
 0447            for (int i = 0; i < Count; i++)
 448            {
 0449                GetElementEntry(i, out ReceiveSecurityHeaderEntry entry);
 0450                if (entry.elementCategory == ReceiveSecurityHeaderElementCategory.SignatureConfirmation)
 451                {
 0452                    return;
 453                }
 454            }
 0455            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.SignatureConfirmat
 456        }
 457    }
 458}

Methods/Properties

.ctor(CoreWCF.Security.ReceiveSecurityHeader)
Count()
IsPrimaryTokenSigned()
AppendElement(CoreWCF.Security.ReceiveSecurityHeaderElementCategory,System.Object,CoreWCF.Security.ReceiveSecurityHeaderBindingModes,System.String,CoreWCF.Security.TokenTracker)
AppendSignature(System.Security.Cryptography.Xml.SignedXml)
AppendReferenceList(CoreWCF.Security.ReferenceList)
AppendEncryptedData(CoreWCF.Security.EncryptedData)
AppendSignatureConfirmation(CoreWCF.IdentityModel.ISignatureValueSecurityElement)
AppendTimestamp(CoreWCF.Security.SecurityTimestamp)
AppendSecurityTokenReference(CoreWCF.IdentityModel.SecurityKeyIdentifierClause,System.String)
AppendToken(CoreWCF.IdentityModel.Tokens.SecurityToken,CoreWCF.Security.ReceiveSecurityHeaderBindingModes,CoreWCF.Security.TokenTracker)
EnsureAllRequiredSecurityHeaderTargetsWereProtected()
EnsureCapacityToAdd()
GetElement(System.Int32)
GetElement(System.Int32)
GetElementEntry(System.Int32,CoreWCF.Security.ReceiveSecurityHeaderEntry&)
GetElementCategory(System.Int32)
GetPrimarySignature(System.Xml.XmlDictionaryReader&,System.String&)
GetReader(System.Int32,System.Boolean)
GetSignatureVerificationReader(System.String,System.Boolean)
OnDuplicateId(System.String)
SetBindingMode(System.Int32,CoreWCF.Security.ReceiveSecurityHeaderBindingModes)
SetElement(System.Int32,System.Object)
ReplaceHeaderEntry(System.Int32,CoreWCF.Security.ReceiveSecurityHeaderEntry)
SetElementAfterDecryption(System.Int32,CoreWCF.Security.ReceiveSecurityHeaderElementCategory,System.Object,CoreWCF.Security.ReceiveSecurityHeaderBindingModes,System.String,System.Byte[],CoreWCF.Security.TokenTracker)
SetSignatureAfterDecryption(System.Int32,System.Security.Cryptography.Xml.SignedXml,System.Byte[])
SetSignatureConfirmationAfterDecryption(System.Int32,CoreWCF.IdentityModel.ISignatureValueSecurityElement,System.Byte[])
SetSigned(System.Int32)
SetTimestampSigned(System.String)
SetTokenAfterDecryption(System.Int32,CoreWCF.IdentityModel.Tokens.SecurityToken,CoreWCF.Security.ReceiveSecurityHeaderBindingModes,System.Byte[],CoreWCF.Security.TokenTracker)
TryGetTokenElementIndexFromStrId(System.String,System.Int32&)
VerifyUniquenessAndSetBodyId(System.String)
VerifyUniquenessAndSetBodyContentId(System.String)
VerifyUniquenessAndSetDecryptedHeaderId(System.String,System.Int32)
VerifyUniquenessAndSetHeaderId(System.String,System.Int32)
VerifyIdUniquenessInHeaderIdTable(System.String,System.Int32,System.String[])
VerifyIdUniquenessInSecurityHeader(System.String)
VerifyIdUniquenessInMessageHeadersAndBody(System.String,System.Int32)
CoreWCF.Security.ISignatureReaderProvider.GetReader(System.Object)
VerifySignatureConfirmationWasFound()