| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907 |
- //----------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Security
- {
- using System.IdentityModel.Tokens;
- using System.IO;
- using System.Runtime;
- using System.Security.Cryptography;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Description;
- using System.ServiceModel.Diagnostics;
- using System.Xml;
- using ExclusiveCanonicalizationTransform = System.IdentityModel.ExclusiveCanonicalizationTransform;
- using HashStream = System.IdentityModel.HashStream;
- using IPrefixGenerator = System.IdentityModel.IPrefixGenerator;
- using ISecurityElement = System.IdentityModel.ISecurityElement;
- using ISignatureValueSecurityElement = System.IdentityModel.ISignatureValueSecurityElement;
- using PreDigestedSignedInfo = System.IdentityModel.PreDigestedSignedInfo;
- using Reference = System.IdentityModel.Reference;
- using SignedInfo = System.IdentityModel.SignedInfo;
- using SignedXml = System.IdentityModel.SignedXml;
- using StandardSignedInfo = System.IdentityModel.StandardSignedInfo;
- using System.ServiceModel.Security.Tokens;
- class WSSecurityOneDotZeroSendSecurityHeader : SendSecurityHeader
- {
- HashStream hashStream;
- PreDigestedSignedInfo signedInfo;
- SignedXml signedXml;
- SecurityKey signatureKey;
- MessagePartSpecification effectiveSignatureParts;
- SymmetricAlgorithm encryptingSymmetricAlgorithm;
- ReferenceList referenceList;
- SecurityKeyIdentifier encryptionKeyIdentifier;
- bool hasSignedEncryptedMessagePart;
- // For Transport Secrity we have to sign the 'To' header with the
- // supporting tokens.
- byte[] toHeaderHash = null;
- string toHeaderId = null;
- public WSSecurityOneDotZeroSendSecurityHeader(Message message, string actor, bool mustUnderstand, bool relay,
- SecurityStandardsManager standardsManager,
- SecurityAlgorithmSuite algorithmSuite,
- MessageDirection direction)
- : base(message, actor, mustUnderstand, relay, standardsManager, algorithmSuite, direction)
- {
- }
- protected string EncryptionAlgorithm
- {
- get { return this.AlgorithmSuite.DefaultEncryptionAlgorithm; }
- }
- protected XmlDictionaryString EncryptionAlgorithmDictionaryString
- {
- get { return this.AlgorithmSuite.DefaultEncryptionAlgorithmDictionaryString; }
- }
- protected override bool HasSignedEncryptedMessagePart
- {
- get
- {
- return this.hasSignedEncryptedMessagePart;
- }
- }
- void AddEncryptionReference(MessageHeader header, string headerId, IPrefixGenerator prefixGenerator, bool sign,
- out MemoryStream plainTextStream, out string encryptedDataId)
- {
- plainTextStream = new MemoryStream();
- XmlDictionaryWriter encryptingWriter = XmlDictionaryWriter.CreateTextWriter(plainTextStream);
- if (sign)
- {
- AddSignatureReference(header, headerId, prefixGenerator, encryptingWriter);
- }
- else
- {
- header.WriteHeader(encryptingWriter, this.Version);
- encryptingWriter.Flush();
- }
- encryptedDataId = this.GenerateId();
- referenceList.AddReferredId(encryptedDataId);
- }
- void AddSignatureReference(SecurityToken token, int position, SecurityTokenAttachmentMode mode)
- {
- SecurityKeyIdentifierClause keyIdentifierClause = null;
- bool strTransformEnabled = this.ShouldUseStrTransformForToken(token, position, mode, out keyIdentifierClause);
- AddTokenSignatureReference(token, keyIdentifierClause, strTransformEnabled);
- }
- void AddPrimaryTokenSignatureReference(SecurityToken token, SecurityTokenParameters securityTokenParameters)
- {
- // Currently we only support signing the primary token if the primary token is an issued token and protectTokens knob is set to true.
- // We will get rid of the below check when we support all token types.
- IssuedSecurityTokenParameters istp = securityTokenParameters as IssuedSecurityTokenParameters;
- if (istp == null)
- {
- return;
- }
- bool strTransformEnabled = istp != null && istp.UseStrTransform;
- SecurityKeyIdentifierClause keyIdentifierClause = null;
- // Only if the primary token is included in the message that we sign it because WCF at present does not resolve externally referenced tokens.
- // This means in the server's response
- if (ShouldSerializeToken(securityTokenParameters, this.MessageDirection))
- {
- if (strTransformEnabled)
- {
- keyIdentifierClause = securityTokenParameters.CreateKeyIdentifierClause(token, GetTokenReferenceStyle(securityTokenParameters));
- }
- AddTokenSignatureReference(token, keyIdentifierClause, strTransformEnabled);
- }
- }
- // Given a token and useStarTransform value this method adds apporopriate reference accordingly.
- // 1. If strTransform is disabled, it adds a reference to the token's id.
- // 2. Else if strtransform is enabled it adds a reference the security token's keyIdentifier's id.
- void AddTokenSignatureReference(SecurityToken token, SecurityKeyIdentifierClause keyIdentifierClause, bool strTransformEnabled)
- {
- if (!strTransformEnabled && token.Id == null)
- {
- throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.ElementToSignMustHaveId)), this.Message);
- }
- HashStream hashStream = TakeHashStream();
- XmlDictionaryWriter utf8Writer = TakeUtf8Writer();
- utf8Writer.StartCanonicalization(hashStream, false, null);
- this.StandardsManager.SecurityTokenSerializer.WriteToken(utf8Writer, token);
- utf8Writer.EndCanonicalization();
- if (strTransformEnabled)
- {
- if (keyIdentifierClause != null)
- {
- if (String.IsNullOrEmpty(keyIdentifierClause.Id))
- keyIdentifierClause.Id = SecurityUniqueId.Create().Value;
- this.ElementContainer.MapSecurityTokenToStrClause(token, keyIdentifierClause);
- this.signedInfo.AddReference(keyIdentifierClause.Id, hashStream.FlushHashAndGetValue(), true);
- }
- else
- throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenManagerCannotCreateTokenReference)), this.Message);
- }
- else
- this.signedInfo.AddReference(token.Id, hashStream.FlushHashAndGetValue());
- }
- void AddSignatureReference(SendSecurityHeaderElement[] elements)
- {
- if (elements != null)
- {
- for (int i = 0; i < elements.Length; ++i)
- {
- SecurityKeyIdentifierClause keyIdentifierClause = null;
- TokenElement signedEncryptedTokenElement = elements[i].Item as TokenElement;
- // signedEncryptedTokenElement can either be a TokenElement ( in SignThenEncrypt case) or EncryptedData ( in !SignThenEncryptCase)
- // STR-Transform does not make sense in !SignThenEncrypt case .
- // note: signedEncryptedTokenElement can also be SignatureConfirmation but we do not care about it here.
- bool useStrTransform = signedEncryptedTokenElement != null
- && SignThenEncrypt
- && this.ShouldUseStrTransformForToken(signedEncryptedTokenElement.Token,
- i,
- SecurityTokenAttachmentMode.SignedEncrypted,
- out keyIdentifierClause);
- if (!useStrTransform && elements[i].Id == null)
- {
- throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.ElementToSignMustHaveId)), this.Message);
- }
- HashStream hashStream = TakeHashStream();
- XmlDictionaryWriter utf8Writer = TakeUtf8Writer();
- utf8Writer.StartCanonicalization(hashStream, false, null);
- elements[i].Item.WriteTo(utf8Writer, ServiceModelDictionaryManager.Instance);
- utf8Writer.EndCanonicalization();
- if (useStrTransform)
- {
- if (keyIdentifierClause != null)
- {
- if (String.IsNullOrEmpty(keyIdentifierClause.Id))
- keyIdentifierClause.Id = SecurityUniqueId.Create().Value;
- this.ElementContainer.MapSecurityTokenToStrClause(signedEncryptedTokenElement.Token, keyIdentifierClause);
- this.signedInfo.AddReference(keyIdentifierClause.Id, hashStream.FlushHashAndGetValue(), true);
- }
- else
- throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenManagerCannotCreateTokenReference)), this.Message);
- }
- else
- this.signedInfo.AddReference(elements[i].Id, hashStream.FlushHashAndGetValue());
- }
- }
- }
- void AddSignatureReference(SecurityToken[] tokens, SecurityTokenAttachmentMode mode)
- {
- if (tokens != null)
- {
- for (int i = 0; i < tokens.Length; ++i)
- {
- AddSignatureReference(tokens[i], i, mode);
- }
- }
- }
- string GetSignatureHash(MessageHeader header, string headerId, IPrefixGenerator prefixGenerator, XmlDictionaryWriter writer, out byte[] hash)
- {
- HashStream hashStream = TakeHashStream();
- XmlDictionaryWriter effectiveWriter;
- XmlBuffer canonicalBuffer = null;
- if (writer.CanCanonicalize)
- {
- effectiveWriter = writer;
- }
- else
- {
- canonicalBuffer = new XmlBuffer(int.MaxValue);
- effectiveWriter = canonicalBuffer.OpenSection(XmlDictionaryReaderQuotas.Max);
- }
- effectiveWriter.StartCanonicalization(hashStream, false, null);
- header.WriteStartHeader(effectiveWriter, this.Version);
- if (headerId == null)
- {
- headerId = GenerateId();
- this.StandardsManager.IdManager.WriteIdAttribute(effectiveWriter, headerId);
- }
- header.WriteHeaderContents(effectiveWriter, this.Version);
- effectiveWriter.WriteEndElement();
- effectiveWriter.EndCanonicalization();
- effectiveWriter.Flush();
- if (!ReferenceEquals(effectiveWriter, writer))
- {
- Fx.Assert(canonicalBuffer != null, "Canonical buffer cannot be null.");
- canonicalBuffer.CloseSection();
- canonicalBuffer.Close();
- XmlDictionaryReader dicReader = canonicalBuffer.GetReader(0);
- writer.WriteNode(dicReader, false);
- dicReader.Close();
- }
- hash = hashStream.FlushHashAndGetValue();
- return headerId;
- }
- void AddSignatureReference(MessageHeader header, string headerId, IPrefixGenerator prefixGenerator, XmlDictionaryWriter writer)
- {
- byte[] hashValue;
- headerId = GetSignatureHash(header, headerId, prefixGenerator, writer, out hashValue);
- this.signedInfo.AddReference(headerId, hashValue);
- }
- void ApplySecurityAndWriteHeader(MessageHeader header, string headerId, XmlDictionaryWriter writer, IPrefixGenerator prefixGenerator)
- {
- if (!this.RequireMessageProtection && this.ShouldSignToHeader)
- {
- if ((header.Name == XD.AddressingDictionary.To.Value) &&
- (header.Namespace == this.Message.Version.Addressing.Namespace))
- {
- if (this.toHeaderHash == null)
- {
- byte[] headerHash;
- headerId = GetSignatureHash(header, headerId, prefixGenerator, writer, out headerHash);
- this.toHeaderHash = headerHash;
- this.toHeaderId = headerId;
- }
- else
- // More than one 'To' header is specified in the message.
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TransportSecuredMessageHasMoreThanOneToHeader)));
- return;
- }
- }
- MessagePartProtectionMode protectionMode = GetProtectionMode(header);
- MemoryStream plainTextStream;
- string encryptedDataId;
- switch (protectionMode)
- {
- case MessagePartProtectionMode.None:
- header.WriteHeader(writer, this.Version);
- return;
- case MessagePartProtectionMode.Sign:
- AddSignatureReference(header, headerId, prefixGenerator, writer);
- return;
- case MessagePartProtectionMode.SignThenEncrypt:
- AddEncryptionReference(header, headerId, prefixGenerator, true, out plainTextStream, out encryptedDataId);
- EncryptAndWriteHeader(header, encryptedDataId, plainTextStream, writer);
- this.hasSignedEncryptedMessagePart = true;
- return;
- case MessagePartProtectionMode.Encrypt:
- AddEncryptionReference(header, headerId, prefixGenerator, false, out plainTextStream, out encryptedDataId);
- EncryptAndWriteHeader(header, encryptedDataId, plainTextStream, writer);
- return;
- case MessagePartProtectionMode.EncryptThenSign:
- AddEncryptionReference(header, headerId, prefixGenerator, false, out plainTextStream, out encryptedDataId);
- EncryptedHeader encryptedHeader = EncryptHeader(
- header, this.encryptingSymmetricAlgorithm, this.encryptionKeyIdentifier, this.Version, encryptedDataId, plainTextStream);
- AddSignatureReference(encryptedHeader, encryptedDataId, prefixGenerator, writer);
- return;
- default:
- Fx.Assert("Invalid MessagePartProtectionMode");
- return;
- }
- }
- public override void ApplySecurityAndWriteHeaders(MessageHeaders headers, XmlDictionaryWriter writer, IPrefixGenerator prefixGenerator)
- {
- string[] headerIds;
- if (this.RequireMessageProtection || this.ShouldSignToHeader)
- {
- headerIds = headers.GetHeaderAttributes(UtilityStrings.IdAttribute,
- this.StandardsManager.IdManager.DefaultIdNamespaceUri);
- }
- else
- {
- headerIds = null;
- }
- for (int i = 0; i < headers.Count; i++)
- {
- MessageHeader header = headers.GetMessageHeader(i);
- if (this.Version.Addressing == AddressingVersion.None && header.Namespace == AddressingVersion.None.Namespace)
- {
- continue;
- }
- if (header != this)
- {
- ApplySecurityAndWriteHeader(header, headerIds == null ? null : headerIds[i], writer, prefixGenerator);
- }
- }
- }
- static bool CanCanonicalizeAndFragment(XmlDictionaryWriter writer)
- {
- if (!writer.CanCanonicalize)
- {
- return false;
- }
- IFragmentCapableXmlDictionaryWriter fragmentingWriter = writer as IFragmentCapableXmlDictionaryWriter;
- return fragmentingWriter != null && fragmentingWriter.CanFragment;
- }
- public override void ApplyBodySecurity(XmlDictionaryWriter writer, IPrefixGenerator prefixGenerator)
- {
- SecurityAppliedMessage message = this.SecurityAppliedMessage;
- EncryptedData encryptedData;
- HashStream hashStream;
- switch (message.BodyProtectionMode)
- {
- case MessagePartProtectionMode.None:
- return;
- case MessagePartProtectionMode.Sign:
- hashStream = TakeHashStream();
- if (CanCanonicalizeAndFragment(writer))
- {
- message.WriteBodyToSignWithFragments(hashStream, false, null, writer);
- }
- else
- {
- message.WriteBodyToSign(hashStream);
- }
- this.signedInfo.AddReference(message.BodyId, hashStream.FlushHashAndGetValue());
- return;
- case MessagePartProtectionMode.SignThenEncrypt:
- hashStream = TakeHashStream();
- encryptedData = CreateEncryptedDataForBody();
- if (CanCanonicalizeAndFragment(writer))
- {
- message.WriteBodyToSignThenEncryptWithFragments(hashStream, false, null, encryptedData, this.encryptingSymmetricAlgorithm, writer);
- }
- else
- {
- message.WriteBodyToSignThenEncrypt(hashStream, encryptedData, this.encryptingSymmetricAlgorithm);
- }
- this.signedInfo.AddReference(message.BodyId, hashStream.FlushHashAndGetValue());
- this.referenceList.AddReferredId(encryptedData.Id);
- this.hasSignedEncryptedMessagePart = true;
- return;
- case MessagePartProtectionMode.Encrypt:
- encryptedData = CreateEncryptedDataForBody();
- message.WriteBodyToEncrypt(encryptedData, this.encryptingSymmetricAlgorithm);
- this.referenceList.AddReferredId(encryptedData.Id);
- return;
- case MessagePartProtectionMode.EncryptThenSign:
- hashStream = TakeHashStream();
- encryptedData = CreateEncryptedDataForBody();
- message.WriteBodyToEncryptThenSign(hashStream, encryptedData, this.encryptingSymmetricAlgorithm);
- this.signedInfo.AddReference(message.BodyId, hashStream.FlushHashAndGetValue());
- this.referenceList.AddReferredId(encryptedData.Id);
- return;
- default:
- Fx.Assert("Invalid MessagePartProtectionMode");
- return;
- }
- }
- protected static MemoryStream CaptureToken(SecurityToken token, SecurityStandardsManager serializer)
- {
- MemoryStream stream = new MemoryStream();
- XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream);
- serializer.SecurityTokenSerializer.WriteToken(writer, token);
- writer.Flush();
- stream.Seek(0, SeekOrigin.Begin);
- return stream;
- }
- protected static MemoryStream CaptureSecurityElement(ISecurityElement element)
- {
- MemoryStream stream = new MemoryStream();
- XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream);
- element.WriteTo(writer, ServiceModelDictionaryManager.Instance);
- writer.Flush();
- stream.Seek(0, SeekOrigin.Begin);
- return stream;
- }
- protected override ISecurityElement CompleteEncryptionCore(
- SendSecurityHeaderElement primarySignature,
- SendSecurityHeaderElement[] basicTokens,
- SendSecurityHeaderElement[] signatureConfirmations,
- SendSecurityHeaderElement[] endorsingSignatures)
- {
- if (this.referenceList == null)
- {
- return null;
- }
- if (primarySignature != null && primarySignature.Item != null && primarySignature.MarkedForEncryption)
- {
- EncryptElement(primarySignature);
- }
- if (basicTokens != null)
- {
- for (int i = 0; i < basicTokens.Length; ++i)
- {
- if (basicTokens[i].MarkedForEncryption)
- EncryptElement(basicTokens[i]);
- }
- }
- if (signatureConfirmations != null)
- {
- for (int i = 0; i < signatureConfirmations.Length; ++i)
- {
- if (signatureConfirmations[i].MarkedForEncryption)
- EncryptElement(signatureConfirmations[i]);
- }
- }
- if (endorsingSignatures != null)
- {
- for (int i = 0; i < endorsingSignatures.Length; ++i)
- {
- if (endorsingSignatures[i].MarkedForEncryption)
- EncryptElement(endorsingSignatures[i]);
- }
- }
- try
- {
- return this.referenceList.DataReferenceCount > 0 ? this.referenceList : null;
- }
- finally
- {
- this.referenceList = null;
- this.encryptingSymmetricAlgorithm = null;
- this.encryptionKeyIdentifier = null;
- }
- }
- protected override ISignatureValueSecurityElement CompletePrimarySignatureCore(
- SendSecurityHeaderElement[] signatureConfirmations,
- SecurityToken[] signedEndorsingTokens,
- SecurityToken[] signedTokens,
- SendSecurityHeaderElement[] basicTokens, bool isPrimarySignature)
- {
- if (this.signedXml == null)
- {
- return null;
- }
- SecurityTimestamp timestamp = this.Timestamp;
- if (timestamp != null)
- {
- if (timestamp.Id == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TimestampToSignHasNoId)));
- }
- HashStream hashStream = TakeHashStream();
- this.StandardsManager.WSUtilitySpecificationVersion.WriteTimestampCanonicalForm(
- hashStream, timestamp, this.signedInfo.ResourcePool.TakeEncodingBuffer());
- signedInfo.AddReference(timestamp.Id, hashStream.FlushHashAndGetValue());
- }
- if ((this.ShouldSignToHeader) && (this.signatureKey is AsymmetricSecurityKey) && (this.Version.Addressing != AddressingVersion.None))
- {
- if (this.toHeaderHash != null)
- signedInfo.AddReference(this.toHeaderId, this.toHeaderHash);
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TransportSecurityRequireToHeader)));
- }
- AddSignatureReference(signatureConfirmations);
- if (isPrimarySignature && this.ShouldProtectTokens)
- {
- AddPrimaryTokenSignatureReference(this.ElementContainer.SourceSigningToken, this.SigningTokenParameters);
- }
- if (this.RequireMessageProtection)
- {
- AddSignatureReference(signedEndorsingTokens, SecurityTokenAttachmentMode.SignedEndorsing);
- AddSignatureReference(signedTokens, SecurityTokenAttachmentMode.Signed);
- AddSignatureReference(basicTokens);
- }
- if (this.signedInfo.ReferenceCount == 0)
- {
- throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoPartsOfMessageMatchedPartsToSign)), this.Message);
- }
- try
- {
- this.signedXml.ComputeSignature(this.signatureKey);
- return this.signedXml;
- }
- finally
- {
- this.hashStream = null;
- this.signedInfo = null;
- this.signedXml = null;
- this.signatureKey = null;
- this.effectiveSignatureParts = null;
- }
- }
- EncryptedData CreateEncryptedData()
- {
- EncryptedData encryptedData = new EncryptedData();
- encryptedData.SecurityTokenSerializer = this.StandardsManager.SecurityTokenSerializer;
- encryptedData.KeyIdentifier = this.encryptionKeyIdentifier;
- encryptedData.EncryptionMethod = this.EncryptionAlgorithm;
- encryptedData.EncryptionMethodDictionaryString = this.EncryptionAlgorithmDictionaryString;
- return encryptedData;
- }
- EncryptedData CreateEncryptedData(MemoryStream stream, string id, bool typeElement)
- {
- EncryptedData encryptedData = CreateEncryptedData();
- encryptedData.Id = id;
- encryptedData.SetUpEncryption(this.encryptingSymmetricAlgorithm, new ArraySegment<byte>(stream.GetBuffer(), 0, (int) stream.Length));
- if (typeElement)
- {
- encryptedData.Type = EncryptedData.ElementType;
- }
- return encryptedData;
- }
- EncryptedData CreateEncryptedDataForBody()
- {
- EncryptedData encryptedData = CreateEncryptedData();
- encryptedData.Type = EncryptedData.ContentType;
- return encryptedData;
- }
- void EncryptAndWriteHeader(MessageHeader plainTextHeader, string id, MemoryStream stream, XmlDictionaryWriter writer)
- {
- EncryptedHeader encryptedHeader = EncryptHeader(
- plainTextHeader,
- this.encryptingSymmetricAlgorithm, this.encryptionKeyIdentifier, this.Version,
- id, stream);
- encryptedHeader.WriteHeader(writer, this.Version);
- }
- void EncryptElement(SendSecurityHeaderElement element)
- {
- string id = GenerateId();
- ISecurityElement encryptedElement = CreateEncryptedData(CaptureSecurityElement(element.Item), id, true);
- this.referenceList.AddReferredId(id);
- element.Replace(id, encryptedElement);
- }
- protected virtual EncryptedHeader EncryptHeader(MessageHeader plainTextHeader, SymmetricAlgorithm algorithm,
- SecurityKeyIdentifier keyIdentifier, MessageVersion version, string id, MemoryStream stream)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.HeaderEncryptionNotSupportedInWsSecurityJan2004, plainTextHeader.Name, plainTextHeader.Namespace)));
- }
- HashStream TakeHashStream()
- {
- HashStream hashStream = null;
- if (this.hashStream == null)
- {
- this.hashStream = hashStream = new HashStream(CryptoHelper.CreateHashAlgorithm(this.AlgorithmSuite.DefaultDigestAlgorithm));
- }
- else
- {
- hashStream = this.hashStream;;
- hashStream.Reset();
- }
- return hashStream;
- }
- XmlDictionaryWriter TakeUtf8Writer()
- {
- return this.signedInfo.ResourcePool.TakeUtf8Writer();
- }
- MessagePartProtectionMode GetProtectionMode(MessageHeader header)
- {
- if (!this.RequireMessageProtection)
- {
- return MessagePartProtectionMode.None;
- }
- bool sign = this.signedInfo != null && this.effectiveSignatureParts.IsHeaderIncluded(header);
- bool encrypt = this.referenceList != null && this.EncryptionParts.IsHeaderIncluded(header);
- return MessagePartProtectionModeHelper.GetProtectionMode(sign, encrypt, this.SignThenEncrypt);
- }
- protected override void StartEncryptionCore(SecurityToken token, SecurityKeyIdentifier keyIdentifier)
- {
- this.encryptingSymmetricAlgorithm = SecurityUtils.GetSymmetricAlgorithm(this.EncryptionAlgorithm, token);
- if (this.encryptingSymmetricAlgorithm == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(
- SR.GetString(SR.UnableToCreateSymmetricAlgorithmFromToken, this.EncryptionAlgorithm)));
- }
- this.encryptionKeyIdentifier = keyIdentifier;
- this.referenceList = new ReferenceList();
- }
- protected override void StartPrimarySignatureCore(SecurityToken token,
- SecurityKeyIdentifier keyIdentifier,
- MessagePartSpecification signatureParts,
- bool generateTargettableSignature)
- {
- SecurityAlgorithmSuite suite = this.AlgorithmSuite;
- string canonicalizationAlgorithm = suite.DefaultCanonicalizationAlgorithm;
- XmlDictionaryString canonicalizationAlgorithmDictionaryString = suite.DefaultCanonicalizationAlgorithmDictionaryString;
- if (canonicalizationAlgorithm != SecurityAlgorithms.ExclusiveC14n)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new MessageSecurityException(SR.GetString(SR.UnsupportedCanonicalizationAlgorithm, suite.DefaultCanonicalizationAlgorithm)));
- }
- string signatureAlgorithm;
- XmlDictionaryString signatureAlgorithmDictionaryString;
- suite.GetSignatureAlgorithmAndKey(token, out signatureAlgorithm, out this.signatureKey, out signatureAlgorithmDictionaryString);
- string digestAlgorithm = suite.DefaultDigestAlgorithm;
- XmlDictionaryString digestAlgorithmDictionaryString = suite.DefaultDigestAlgorithmDictionaryString;
- this.signedInfo = new PreDigestedSignedInfo(ServiceModelDictionaryManager.Instance, canonicalizationAlgorithm, canonicalizationAlgorithmDictionaryString, digestAlgorithm, digestAlgorithmDictionaryString, signatureAlgorithm, signatureAlgorithmDictionaryString);
- this.signedXml = new SignedXml(this.signedInfo, ServiceModelDictionaryManager.Instance, this.StandardsManager.SecurityTokenSerializer);
- if (keyIdentifier != null)
- {
- this.signedXml.Signature.KeyIdentifier = keyIdentifier;
- }
- if (generateTargettableSignature)
- {
- this.signedXml.Id = GenerateId();
- }
- this.effectiveSignatureParts = signatureParts;
- this.hashStream = this.signedInfo.ResourcePool.TakeHashStream(digestAlgorithm);
- }
- protected override ISignatureValueSecurityElement CreateSupportingSignature(SecurityToken token, SecurityKeyIdentifier identifier)
- {
- StartPrimarySignatureCore(token, identifier, MessagePartSpecification.NoParts, false);
- return CompletePrimarySignatureCore(null, null, null, null, false);
- }
- protected override ISignatureValueSecurityElement CreateSupportingSignature(SecurityToken token, SecurityKeyIdentifier identifier, ISecurityElement elementToSign)
- {
- SecurityAlgorithmSuite algorithmSuite = this.AlgorithmSuite;
- string signatureAlgorithm;
- XmlDictionaryString signatureAlgorithmDictionaryString;
- SecurityKey signatureKey;
- algorithmSuite.GetSignatureAlgorithmAndKey(token, out signatureAlgorithm, out signatureKey, out signatureAlgorithmDictionaryString);
- SignedXml signedXml = new SignedXml(ServiceModelDictionaryManager.Instance, this.StandardsManager.SecurityTokenSerializer);
- SignedInfo signedInfo = signedXml.Signature.SignedInfo;
- signedInfo.CanonicalizationMethod = algorithmSuite.DefaultCanonicalizationAlgorithm;
- signedInfo.CanonicalizationMethodDictionaryString = algorithmSuite.DefaultCanonicalizationAlgorithmDictionaryString;
- signedInfo.SignatureMethod = signatureAlgorithm;
- signedInfo.SignatureMethodDictionaryString = signatureAlgorithmDictionaryString;
- if (elementToSign.Id == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ElementToSignMustHaveId)));
- }
- Reference reference = new Reference(ServiceModelDictionaryManager.Instance, "#" + elementToSign.Id, elementToSign);
- reference.DigestMethod = algorithmSuite.DefaultDigestAlgorithm;
- reference.DigestMethodDictionaryString = algorithmSuite.DefaultDigestAlgorithmDictionaryString;
- reference.AddTransform(new ExclusiveCanonicalizationTransform());
- ((StandardSignedInfo)signedInfo).AddReference(reference);
- signedXml.ComputeSignature(signatureKey);
- if (identifier != null)
- {
- signedXml.Signature.KeyIdentifier = identifier;
- }
- return signedXml;
- }
- protected override void WriteSecurityTokenReferencyEntry(XmlDictionaryWriter writer, SecurityToken securityToken, SecurityTokenParameters securityTokenParameters)
- {
- SecurityKeyIdentifierClause keyIdentifierClause = null;
- // Given a token this method writes its corresponding security token reference entry in the security header
- // 1. If the token parameters is an issuedSecurityTokenParamter
- // 2. If UseStrTransform is enabled on it.
- IssuedSecurityTokenParameters issuedSecurityTokenParameters = securityTokenParameters as IssuedSecurityTokenParameters;
- if (issuedSecurityTokenParameters == null || !issuedSecurityTokenParameters.UseStrTransform)
- return;
- if (this.ElementContainer.TryGetIdentifierClauseFromSecurityToken(securityToken, out keyIdentifierClause))
- {
- if (keyIdentifierClause != null && !String.IsNullOrEmpty(keyIdentifierClause.Id))
- {
- WrappedXmlDictionaryWriter wrappedLocalWriter = new WrappedXmlDictionaryWriter(writer, keyIdentifierClause.Id);
- this.StandardsManager.SecurityTokenSerializer.WriteKeyIdentifierClause(wrappedLocalWriter, keyIdentifierClause);
- }
- else
- throw TraceUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.TokenManagerCannotCreateTokenReference)), this.Message);
- }
- }
- }
- class WrappedXmlDictionaryWriter : XmlDictionaryWriter
- {
- XmlDictionaryWriter innerWriter;
- int index;
- bool insertId;
- bool isStrReferenceElement;
- string id;
- public WrappedXmlDictionaryWriter(XmlDictionaryWriter writer, string id)
- {
- this.innerWriter = writer;
- this.index = 0;
- this.insertId = false;
- this.isStrReferenceElement = false;
- this.id = id;
- }
- public override void WriteStartAttribute(string prefix, string localName, string namespaceUri)
- {
- if (isStrReferenceElement && this.insertId && localName == XD.UtilityDictionary.IdAttribute.Value)
- {
- // This means the serializer is already writing the Id out, so we don't write it again.
- this.insertId = false;
- }
- this.innerWriter.WriteStartAttribute(prefix, localName, namespaceUri);
- }
- public override void WriteStartElement(string prefix, string localName, string namespaceUri)
- {
- if (isStrReferenceElement && this.insertId)
- {
- if (id != null)
- {
- this.innerWriter.WriteAttributeString(XD.UtilityDictionary.Prefix.Value, XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace, id);
- }
- isStrReferenceElement = false;
- this.insertId = false;
- }
- index++;
- if (index == 1 && localName == XD.SecurityJan2004Dictionary.SecurityTokenReference.Value)
- {
- this.insertId = true;
- isStrReferenceElement = true;
- }
- this.innerWriter.WriteStartElement(prefix, localName, namespaceUri);
- }
- // Below methods simply call into innerWritter
- public override void Close()
- {
- this.innerWriter.Close();
- }
- public override void Flush()
- {
- this.innerWriter.Flush();
- }
- public override string LookupPrefix(string ns)
- {
- return this.innerWriter.LookupPrefix(ns);
- }
- public override void WriteBase64(byte[] buffer, int index, int count)
- {
- this.innerWriter.WriteBase64(buffer, index, count);
- }
- public override void WriteCData(string text)
- {
- this.innerWriter.WriteCData(text);
- }
- public override void WriteCharEntity(char ch)
- {
- this.innerWriter.WriteCharEntity(ch);
- }
- public override void WriteChars(char[] buffer, int index, int count)
- {
- this.innerWriter.WriteChars(buffer, index, count);
- }
- public override void WriteComment(string text)
- {
- this.innerWriter.WriteComment(text);
- }
- public override void WriteDocType(string name, string pubid, string sysid, string subset)
- {
- this.innerWriter.WriteDocType(name, pubid, sysid, subset);
- }
- public override void WriteEndAttribute()
- {
- this.innerWriter.WriteEndAttribute();
- }
- public override void WriteEndDocument()
- {
- this.innerWriter.WriteEndDocument();
- }
- public override void WriteEndElement()
- {
- this.innerWriter.WriteEndElement();
- }
- public override void WriteEntityRef(string name)
- {
- this.innerWriter.WriteEntityRef(name);
- }
- public override void WriteFullEndElement()
- {
- this.innerWriter.WriteFullEndElement();
- }
- public override void WriteProcessingInstruction(string name, string text)
- {
- this.innerWriter.WriteProcessingInstruction(name, text);
- }
- public override void WriteRaw(string data)
- {
- this.innerWriter.WriteRaw(data);
- }
- public override void WriteRaw(char[] buffer, int index, int count)
- {
- this.innerWriter.WriteRaw(buffer, index, count);
- }
- public override void WriteStartDocument(bool standalone)
- {
- this.innerWriter.WriteStartDocument(standalone);
- }
- public override void WriteStartDocument()
- {
- this.innerWriter.WriteStartDocument();
- }
- public override WriteState WriteState
- {
- get { return this.innerWriter.WriteState; }
- }
- public override void WriteString(string text)
- {
- this.innerWriter.WriteString(text);
- }
- public override void WriteSurrogateCharEntity(char lowChar, char highChar)
- {
- this.innerWriter.WriteSurrogateCharEntity(lowChar, highChar);
- }
- public override void WriteWhitespace(string ws)
- {
- this.innerWriter.WriteWhitespace(ws);
- }
- }
- }
|