You've already forked linux-packaging-mono
Imported Upstream version 4.0.0~alpha1
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
456
external/referencesource/System.ServiceModel/System/ServiceModel/Security/SecurityAppliedMessage.cs
vendored
Normal file
456
external/referencesource/System.ServiceModel/System/ServiceModel/Security/SecurityAppliedMessage.cs
vendored
Normal file
@ -0,0 +1,456 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Security
|
||||
{
|
||||
using System.IO;
|
||||
using System.Runtime;
|
||||
using System.Security.Cryptography;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Security.Tokens;
|
||||
using System.Xml;
|
||||
using System.IdentityModel.Tokens;
|
||||
using System.Collections.Generic;
|
||||
using IPrefixGenerator = System.IdentityModel.IPrefixGenerator;
|
||||
using ISecurityElement = System.IdentityModel.ISecurityElement;
|
||||
using XmlAttributeHolder = System.IdentityModel.XmlAttributeHolder;
|
||||
|
||||
sealed class SecurityAppliedMessage : DelegatingMessage
|
||||
{
|
||||
string bodyId;
|
||||
bool bodyIdInserted;
|
||||
string bodyPrefix = MessageStrings.Prefix;
|
||||
XmlBuffer fullBodyBuffer;
|
||||
ISecurityElement encryptedBodyContent;
|
||||
XmlAttributeHolder[] bodyAttributes;
|
||||
bool delayedApplicationHandled;
|
||||
readonly MessagePartProtectionMode bodyProtectionMode;
|
||||
BodyState state = BodyState.Created;
|
||||
readonly SendSecurityHeader securityHeader;
|
||||
MemoryStream startBodyFragment;
|
||||
MemoryStream endBodyFragment;
|
||||
byte[] fullBodyFragment;
|
||||
int fullBodyFragmentLength;
|
||||
|
||||
public SecurityAppliedMessage(Message messageToProcess, SendSecurityHeader securityHeader, bool signBody, bool encryptBody)
|
||||
: base(messageToProcess)
|
||||
{
|
||||
Fx.Assert(!(messageToProcess is SecurityAppliedMessage), "SecurityAppliedMessage should not be wrapped");
|
||||
this.securityHeader = securityHeader;
|
||||
this.bodyProtectionMode = MessagePartProtectionModeHelper.GetProtectionMode(signBody, encryptBody, securityHeader.SignThenEncrypt);
|
||||
}
|
||||
|
||||
public string BodyId
|
||||
{
|
||||
get { return this.bodyId; }
|
||||
}
|
||||
|
||||
public MessagePartProtectionMode BodyProtectionMode
|
||||
{
|
||||
get { return this.bodyProtectionMode; }
|
||||
}
|
||||
|
||||
internal byte[] PrimarySignatureValue
|
||||
{
|
||||
get { return this.securityHeader.PrimarySignatureValue; }
|
||||
}
|
||||
|
||||
Exception CreateBadStateException(string operation)
|
||||
{
|
||||
return new InvalidOperationException(SR.GetString(SR.MessageBodyOperationNotValidInBodyState,
|
||||
operation, this.state));
|
||||
}
|
||||
|
||||
void EnsureUniqueSecurityApplication()
|
||||
{
|
||||
if (this.delayedApplicationHandled)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.DelayedSecurityApplicationAlreadyCompleted)));
|
||||
}
|
||||
this.delayedApplicationHandled = true;
|
||||
}
|
||||
|
||||
protected override void OnBodyToString(XmlDictionaryWriter writer)
|
||||
{
|
||||
if (this.state == BodyState.Created || this.fullBodyFragment != null)
|
||||
{
|
||||
base.OnBodyToString(writer);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnWriteBodyContents(writer);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnClose()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.InnerMessage.Close();
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.fullBodyBuffer = null;
|
||||
this.bodyAttributes = null;
|
||||
this.encryptedBodyContent = null;
|
||||
this.state = BodyState.Disposed;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnWriteStartBody(XmlDictionaryWriter writer)
|
||||
{
|
||||
if (this.startBodyFragment != null || this.fullBodyFragment != null)
|
||||
{
|
||||
WriteStartInnerMessageWithId(writer);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.state)
|
||||
{
|
||||
case BodyState.Created:
|
||||
case BodyState.Encrypted:
|
||||
this.InnerMessage.WriteStartBody(writer);
|
||||
return;
|
||||
case BodyState.Signed:
|
||||
case BodyState.EncryptedThenSigned:
|
||||
XmlDictionaryReader reader = fullBodyBuffer.GetReader(0);
|
||||
writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
|
||||
writer.WriteAttributes(reader, false);
|
||||
reader.Close();
|
||||
return;
|
||||
case BodyState.SignedThenEncrypted:
|
||||
writer.WriteStartElement(this.bodyPrefix, XD.MessageDictionary.Body, this.Version.Envelope.DictionaryNamespace);
|
||||
if (this.bodyAttributes != null)
|
||||
{
|
||||
XmlAttributeHolder.WriteAttributes(this.bodyAttributes, writer);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBadStateException("OnWriteStartBody"));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
|
||||
{
|
||||
switch (this.state)
|
||||
{
|
||||
case BodyState.Created:
|
||||
this.InnerMessage.WriteBodyContents(writer);
|
||||
return;
|
||||
case BodyState.Signed:
|
||||
case BodyState.EncryptedThenSigned:
|
||||
XmlDictionaryReader reader = fullBodyBuffer.GetReader(0);
|
||||
reader.ReadStartElement();
|
||||
while (reader.NodeType != XmlNodeType.EndElement)
|
||||
writer.WriteNode(reader, false);
|
||||
reader.ReadEndElement();
|
||||
reader.Close();
|
||||
return;
|
||||
case BodyState.Encrypted:
|
||||
case BodyState.SignedThenEncrypted:
|
||||
this.encryptedBodyContent.WriteTo(writer, ServiceModelDictionaryManager.Instance);
|
||||
break;
|
||||
default:
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBadStateException("OnWriteBodyContents"));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnWriteMessage(XmlDictionaryWriter writer)
|
||||
{
|
||||
// For Kerb one shot, the channel binding will be need to be fished out of the message, cached and added to the
|
||||
// token before calling ISC.
|
||||
|
||||
AttachChannelBindingTokenIfFound();
|
||||
|
||||
EnsureUniqueSecurityApplication();
|
||||
|
||||
MessagePrefixGenerator prefixGenerator = new MessagePrefixGenerator(writer);
|
||||
this.securityHeader.StartSecurityApplication();
|
||||
|
||||
this.Headers.Add(this.securityHeader);
|
||||
|
||||
this.InnerMessage.WriteStartEnvelope(writer);
|
||||
|
||||
this.Headers.RemoveAt(this.Headers.Count - 1);
|
||||
|
||||
this.securityHeader.ApplyBodySecurity(writer, prefixGenerator);
|
||||
|
||||
this.InnerMessage.WriteStartHeaders(writer);
|
||||
this.securityHeader.ApplySecurityAndWriteHeaders(this.Headers, writer, prefixGenerator);
|
||||
|
||||
this.securityHeader.RemoveSignatureEncryptionIfAppropriate();
|
||||
|
||||
this.securityHeader.CompleteSecurityApplication();
|
||||
this.securityHeader.WriteHeader(writer, this.Version);
|
||||
writer.WriteEndElement();
|
||||
|
||||
if (this.fullBodyFragment != null)
|
||||
{
|
||||
((IFragmentCapableXmlDictionaryWriter) writer).WriteFragment(this.fullBodyFragment, 0, this.fullBodyFragmentLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.startBodyFragment != null)
|
||||
{
|
||||
((IFragmentCapableXmlDictionaryWriter) writer).WriteFragment(this.startBodyFragment.GetBuffer(), 0, (int) this.startBodyFragment.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnWriteStartBody(writer);
|
||||
}
|
||||
|
||||
OnWriteBodyContents(writer);
|
||||
|
||||
if (this.endBodyFragment != null)
|
||||
{
|
||||
((IFragmentCapableXmlDictionaryWriter) writer).WriteFragment(this.endBodyFragment.GetBuffer(), 0, (int) this.endBodyFragment.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
void AttachChannelBindingTokenIfFound()
|
||||
{
|
||||
ChannelBindingMessageProperty cbmp = null;
|
||||
ChannelBindingMessageProperty.TryGet(this.InnerMessage, out cbmp);
|
||||
|
||||
if (cbmp != null)
|
||||
{
|
||||
if (this.securityHeader.ElementContainer != null && this.securityHeader.ElementContainer.EndorsingSupportingTokens != null)
|
||||
{
|
||||
foreach (SecurityToken token in this.securityHeader.ElementContainer.EndorsingSupportingTokens)
|
||||
{
|
||||
ProviderBackedSecurityToken pbst = token as ProviderBackedSecurityToken;
|
||||
if (pbst != null)
|
||||
{
|
||||
pbst.ChannelBinding = cbmp.ChannelBinding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetBodyId()
|
||||
{
|
||||
this.bodyId = this.InnerMessage.GetBodyAttribute(
|
||||
UtilityStrings.IdAttribute,
|
||||
this.securityHeader.StandardsManager.IdManager.DefaultIdNamespaceUri);
|
||||
if (this.bodyId == null)
|
||||
{
|
||||
this.bodyId = this.securityHeader.GenerateId();
|
||||
this.bodyIdInserted = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBodyToEncrypt(EncryptedData encryptedData, SymmetricAlgorithm algorithm)
|
||||
{
|
||||
encryptedData.Id = this.securityHeader.GenerateId();
|
||||
|
||||
BodyContentHelper helper = new BodyContentHelper();
|
||||
XmlDictionaryWriter encryptingWriter = helper.CreateWriter();
|
||||
this.InnerMessage.WriteBodyContents(encryptingWriter);
|
||||
encryptedData.SetUpEncryption(algorithm, helper.ExtractResult());
|
||||
this.encryptedBodyContent = encryptedData;
|
||||
|
||||
this.state = BodyState.Encrypted;
|
||||
}
|
||||
|
||||
public void WriteBodyToEncryptThenSign(Stream canonicalStream, EncryptedData encryptedData, SymmetricAlgorithm algorithm)
|
||||
{
|
||||
encryptedData.Id = this.securityHeader.GenerateId();
|
||||
SetBodyId();
|
||||
|
||||
XmlDictionaryWriter encryptingWriter = XmlDictionaryWriter.CreateTextWriter(Stream.Null);
|
||||
// The XmlSerializer body formatter would add a
|
||||
// document declaration to the body fragment when a fresh writer
|
||||
// is provided. Hence, insert a dummy element here and capture
|
||||
// the body contents as a fragment.
|
||||
encryptingWriter.WriteStartElement("a");
|
||||
MemoryStream ms = new MemoryStream();
|
||||
((IFragmentCapableXmlDictionaryWriter)encryptingWriter).StartFragment(ms, true);
|
||||
|
||||
this.InnerMessage.WriteBodyContents(encryptingWriter);
|
||||
((IFragmentCapableXmlDictionaryWriter)encryptingWriter).EndFragment();
|
||||
encryptingWriter.WriteEndElement();
|
||||
ms.Flush();
|
||||
encryptedData.SetUpEncryption(algorithm, new ArraySegment<byte>(ms.GetBuffer(), 0, (int) ms.Length));
|
||||
|
||||
this.fullBodyBuffer = new XmlBuffer(int.MaxValue);
|
||||
XmlDictionaryWriter canonicalWriter = this.fullBodyBuffer.OpenSection(XmlDictionaryReaderQuotas.Max);
|
||||
|
||||
canonicalWriter.StartCanonicalization(canonicalStream, false, null);
|
||||
WriteStartInnerMessageWithId(canonicalWriter);
|
||||
encryptedData.WriteTo(canonicalWriter, ServiceModelDictionaryManager.Instance);
|
||||
canonicalWriter.WriteEndElement();
|
||||
canonicalWriter.EndCanonicalization();
|
||||
canonicalWriter.Flush();
|
||||
|
||||
this.fullBodyBuffer.CloseSection();
|
||||
this.fullBodyBuffer.Close();
|
||||
|
||||
this.state = BodyState.EncryptedThenSigned;
|
||||
}
|
||||
|
||||
public void WriteBodyToSign(Stream canonicalStream)
|
||||
{
|
||||
SetBodyId();
|
||||
|
||||
this.fullBodyBuffer = new XmlBuffer(int.MaxValue);
|
||||
XmlDictionaryWriter canonicalWriter = this.fullBodyBuffer.OpenSection(XmlDictionaryReaderQuotas.Max);
|
||||
canonicalWriter.StartCanonicalization(canonicalStream, false, null);
|
||||
WriteInnerMessageWithId(canonicalWriter);
|
||||
canonicalWriter.EndCanonicalization();
|
||||
canonicalWriter.Flush();
|
||||
this.fullBodyBuffer.CloseSection();
|
||||
this.fullBodyBuffer.Close();
|
||||
|
||||
this.state = BodyState.Signed;
|
||||
}
|
||||
|
||||
public void WriteBodyToSignThenEncrypt(Stream canonicalStream, EncryptedData encryptedData, SymmetricAlgorithm algorithm)
|
||||
{
|
||||
XmlBuffer buffer = new XmlBuffer(int.MaxValue);
|
||||
XmlDictionaryWriter fragmentingWriter = buffer.OpenSection(XmlDictionaryReaderQuotas.Max);
|
||||
WriteBodyToSignThenEncryptWithFragments(canonicalStream, false, null, encryptedData, algorithm, fragmentingWriter);
|
||||
((IFragmentCapableXmlDictionaryWriter)fragmentingWriter).WriteFragment(this.startBodyFragment.GetBuffer(), 0, (int)this.startBodyFragment.Length);
|
||||
((IFragmentCapableXmlDictionaryWriter)fragmentingWriter).WriteFragment(this.endBodyFragment.GetBuffer(), 0, (int)this.endBodyFragment.Length);
|
||||
buffer.CloseSection();
|
||||
buffer.Close();
|
||||
|
||||
this.startBodyFragment = null;
|
||||
this.endBodyFragment = null;
|
||||
|
||||
XmlDictionaryReader reader = buffer.GetReader(0);
|
||||
reader.MoveToContent();
|
||||
this.bodyPrefix = reader.Prefix;
|
||||
if (reader.HasAttributes)
|
||||
{
|
||||
this.bodyAttributes = XmlAttributeHolder.ReadAttributes(reader);
|
||||
}
|
||||
reader.Close();
|
||||
}
|
||||
|
||||
public void WriteBodyToSignThenEncryptWithFragments(
|
||||
Stream stream, bool includeComments, string[] inclusivePrefixes,
|
||||
EncryptedData encryptedData, SymmetricAlgorithm algorithm, XmlDictionaryWriter writer)
|
||||
{
|
||||
IFragmentCapableXmlDictionaryWriter fragmentingWriter = (IFragmentCapableXmlDictionaryWriter) writer;
|
||||
|
||||
SetBodyId();
|
||||
encryptedData.Id = this.securityHeader.GenerateId();
|
||||
|
||||
this.startBodyFragment = new MemoryStream();
|
||||
BufferedOutputStream bodyContentFragment = new BufferManagerOutputStream(SR.XmlBufferQuotaExceeded, 1024, int.MaxValue, this.securityHeader.StreamBufferManager);
|
||||
this.endBodyFragment = new MemoryStream();
|
||||
|
||||
writer.StartCanonicalization(stream, includeComments, inclusivePrefixes);
|
||||
|
||||
fragmentingWriter.StartFragment(this.startBodyFragment, false);
|
||||
WriteStartInnerMessageWithId(writer);
|
||||
fragmentingWriter.EndFragment();
|
||||
|
||||
fragmentingWriter.StartFragment(bodyContentFragment, true);
|
||||
this.InnerMessage.WriteBodyContents(writer);
|
||||
fragmentingWriter.EndFragment();
|
||||
|
||||
fragmentingWriter.StartFragment(this.endBodyFragment, false);
|
||||
writer.WriteEndElement();
|
||||
fragmentingWriter.EndFragment();
|
||||
|
||||
writer.EndCanonicalization();
|
||||
|
||||
int bodyLength;
|
||||
byte[] bodyBuffer = bodyContentFragment.ToArray(out bodyLength);
|
||||
|
||||
encryptedData.SetUpEncryption(algorithm, new ArraySegment<byte>(bodyBuffer, 0, bodyLength));
|
||||
this.encryptedBodyContent = encryptedData;
|
||||
|
||||
this.state = BodyState.SignedThenEncrypted;
|
||||
}
|
||||
|
||||
public void WriteBodyToSignWithFragments(Stream stream, bool includeComments, string[] inclusivePrefixes, XmlDictionaryWriter writer)
|
||||
{
|
||||
IFragmentCapableXmlDictionaryWriter fragmentingWriter = (IFragmentCapableXmlDictionaryWriter) writer;
|
||||
|
||||
SetBodyId();
|
||||
BufferedOutputStream fullBodyFragment = new BufferManagerOutputStream(SR.XmlBufferQuotaExceeded, 1024, int.MaxValue, this.securityHeader.StreamBufferManager);
|
||||
writer.StartCanonicalization(stream, includeComments, inclusivePrefixes);
|
||||
fragmentingWriter.StartFragment(fullBodyFragment, false);
|
||||
WriteStartInnerMessageWithId(writer);
|
||||
this.InnerMessage.WriteBodyContents(writer);
|
||||
writer.WriteEndElement();
|
||||
fragmentingWriter.EndFragment();
|
||||
writer.EndCanonicalization();
|
||||
|
||||
this.fullBodyFragment = fullBodyFragment.ToArray(out this.fullBodyFragmentLength);
|
||||
|
||||
this.state = BodyState.Signed;
|
||||
}
|
||||
|
||||
void WriteInnerMessageWithId(XmlDictionaryWriter writer)
|
||||
{
|
||||
WriteStartInnerMessageWithId(writer);
|
||||
this.InnerMessage.WriteBodyContents(writer);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
void WriteStartInnerMessageWithId(XmlDictionaryWriter writer)
|
||||
{
|
||||
this.InnerMessage.WriteStartBody(writer);
|
||||
if (this.bodyIdInserted)
|
||||
{
|
||||
this.securityHeader.StandardsManager.IdManager.WriteIdAttribute(writer, this.bodyId);
|
||||
}
|
||||
}
|
||||
|
||||
enum BodyState
|
||||
{
|
||||
Created,
|
||||
Signed,
|
||||
SignedThenEncrypted,
|
||||
EncryptedThenSigned,
|
||||
Encrypted,
|
||||
Disposed,
|
||||
}
|
||||
|
||||
struct BodyContentHelper
|
||||
{
|
||||
MemoryStream stream;
|
||||
XmlDictionaryWriter writer;
|
||||
|
||||
public XmlDictionaryWriter CreateWriter()
|
||||
{
|
||||
this.stream = new MemoryStream();
|
||||
this.writer = XmlDictionaryWriter.CreateTextWriter(stream);
|
||||
return this.writer;
|
||||
}
|
||||
|
||||
public ArraySegment<byte> ExtractResult()
|
||||
{
|
||||
this.writer.Flush();
|
||||
return new ArraySegment<byte>(this.stream.GetBuffer(), 0, (int) this.stream.Length);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class MessagePrefixGenerator : IPrefixGenerator
|
||||
{
|
||||
XmlWriter writer;
|
||||
|
||||
public MessagePrefixGenerator(XmlWriter writer)
|
||||
{
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
public string GetPrefix(string namespaceUri, int depth, bool isForAttribute)
|
||||
{
|
||||
return this.writer.LookupPrefix(namespaceUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user