298 lines
12 KiB
C#
298 lines
12 KiB
C#
|
//------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
namespace System.ServiceModel.Security
|
||
|
{
|
||
|
using System.Collections.Generic;
|
||
|
using System.ServiceModel.Channels;
|
||
|
using System.ServiceModel;
|
||
|
using System.ServiceModel.Description;
|
||
|
using System.IO;
|
||
|
using System.IdentityModel.Claims;
|
||
|
using System.IdentityModel.Policy;
|
||
|
using System.ServiceModel.Security.Tokens;
|
||
|
using System.Threading;
|
||
|
using System.Globalization;
|
||
|
using System.ServiceModel.Diagnostics;
|
||
|
using System.Xml;
|
||
|
|
||
|
using ISignatureValueSecurityElement = System.IdentityModel.ISignatureValueSecurityElement;
|
||
|
|
||
|
public abstract class SecurityVersion
|
||
|
{
|
||
|
readonly XmlDictionaryString headerName;
|
||
|
readonly XmlDictionaryString headerNamespace;
|
||
|
readonly XmlDictionaryString headerPrefix;
|
||
|
|
||
|
internal SecurityVersion(XmlDictionaryString headerName, XmlDictionaryString headerNamespace, XmlDictionaryString headerPrefix)
|
||
|
{
|
||
|
this.headerName = headerName;
|
||
|
this.headerNamespace = headerNamespace;
|
||
|
this.headerPrefix = headerPrefix;
|
||
|
}
|
||
|
|
||
|
internal XmlDictionaryString HeaderName
|
||
|
{
|
||
|
get { return this.headerName; }
|
||
|
}
|
||
|
|
||
|
internal XmlDictionaryString HeaderNamespace
|
||
|
{
|
||
|
get { return this.headerNamespace; }
|
||
|
}
|
||
|
|
||
|
internal XmlDictionaryString HeaderPrefix
|
||
|
{
|
||
|
get { return this.headerPrefix; }
|
||
|
}
|
||
|
|
||
|
internal abstract XmlDictionaryString FailedAuthenticationFaultCode
|
||
|
{
|
||
|
get;
|
||
|
}
|
||
|
|
||
|
internal abstract XmlDictionaryString InvalidSecurityTokenFaultCode
|
||
|
{
|
||
|
get;
|
||
|
}
|
||
|
|
||
|
internal abstract XmlDictionaryString InvalidSecurityFaultCode
|
||
|
{
|
||
|
get;
|
||
|
}
|
||
|
|
||
|
internal virtual bool SupportsSignatureConfirmation
|
||
|
{
|
||
|
get { return false; }
|
||
|
}
|
||
|
|
||
|
public static SecurityVersion WSSecurity10
|
||
|
{
|
||
|
get { return SecurityVersion10.Instance; }
|
||
|
}
|
||
|
|
||
|
public static SecurityVersion WSSecurity11
|
||
|
{
|
||
|
get { return SecurityVersion11.Instance; }
|
||
|
}
|
||
|
|
||
|
internal static SecurityVersion Default
|
||
|
{
|
||
|
get { return WSSecurity11; }
|
||
|
}
|
||
|
|
||
|
internal abstract ReceiveSecurityHeader CreateReceiveSecurityHeader(Message message,
|
||
|
string actor, bool mustUnderstand, bool relay,
|
||
|
SecurityStandardsManager standardsManager,
|
||
|
SecurityAlgorithmSuite algorithmSuite,
|
||
|
MessageDirection direction,
|
||
|
int headerIndex);
|
||
|
|
||
|
internal abstract SendSecurityHeader CreateSendSecurityHeader(Message message,
|
||
|
string actor, bool mustUnderstand, bool relay,
|
||
|
SecurityStandardsManager standardsManager,
|
||
|
SecurityAlgorithmSuite algorithmSuite,
|
||
|
MessageDirection direction);
|
||
|
|
||
|
internal bool DoesMessageContainSecurityHeader(Message message)
|
||
|
{
|
||
|
return message.Headers.FindHeader(this.HeaderName.Value, this.HeaderNamespace.Value) >= 0;
|
||
|
}
|
||
|
|
||
|
internal int FindIndexOfSecurityHeader(Message message, string[] actors)
|
||
|
{
|
||
|
return message.Headers.FindHeader(this.HeaderName.Value, this.HeaderNamespace.Value, actors);
|
||
|
|
||
|
}
|
||
|
|
||
|
internal virtual bool IsReaderAtSignatureConfirmation(XmlDictionaryReader reader)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
internal virtual ISignatureValueSecurityElement ReadSignatureConfirmation(XmlDictionaryReader reader)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
|
||
|
SR.GetString(SR.SignatureConfirmationNotSupported)));
|
||
|
}
|
||
|
|
||
|
// The security always look for Empty soap role. If not found, we will also look for Ultimate actors (next incl).
|
||
|
// In the future, till we support intermediary scenario, we should refactor this api to do not take actor parameter.
|
||
|
internal ReceiveSecurityHeader TryCreateReceiveSecurityHeader(Message message,
|
||
|
string actor,
|
||
|
SecurityStandardsManager standardsManager,
|
||
|
SecurityAlgorithmSuite algorithmSuite, MessageDirection direction)
|
||
|
{
|
||
|
int headerIndex = message.Headers.FindHeader(this.HeaderName.Value, this.HeaderNamespace.Value, actor);
|
||
|
if (headerIndex < 0 && String.IsNullOrEmpty(actor))
|
||
|
{
|
||
|
headerIndex = message.Headers.FindHeader(this.HeaderName.Value, this.HeaderNamespace.Value, message.Version.Envelope.UltimateDestinationActorValues);
|
||
|
}
|
||
|
|
||
|
if (headerIndex < 0)
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
MessageHeaderInfo headerInfo = message.Headers[headerIndex];
|
||
|
return CreateReceiveSecurityHeader(message,
|
||
|
headerInfo.Actor, headerInfo.MustUnderstand, headerInfo.Relay,
|
||
|
standardsManager, algorithmSuite,
|
||
|
direction, headerIndex);
|
||
|
}
|
||
|
|
||
|
internal virtual void WriteSignatureConfirmation(XmlDictionaryWriter writer, string id, byte[] signatureConfirmation)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
|
||
|
SR.GetString(SR.SignatureConfirmationNotSupported)));
|
||
|
}
|
||
|
|
||
|
internal void WriteStartHeader(XmlDictionaryWriter writer)
|
||
|
{
|
||
|
writer.WriteStartElement(this.HeaderPrefix.Value, this.HeaderName, this.HeaderNamespace);
|
||
|
}
|
||
|
|
||
|
class SecurityVersion10 : SecurityVersion
|
||
|
{
|
||
|
static readonly SecurityVersion10 instance = new SecurityVersion10();
|
||
|
|
||
|
protected SecurityVersion10()
|
||
|
: base(XD.SecurityJan2004Dictionary.Security, XD.SecurityJan2004Dictionary.Namespace, XD.SecurityJan2004Dictionary.Prefix)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public static SecurityVersion10 Instance
|
||
|
{
|
||
|
get { return instance; }
|
||
|
}
|
||
|
|
||
|
internal override XmlDictionaryString FailedAuthenticationFaultCode
|
||
|
{
|
||
|
get { return XD.SecurityJan2004Dictionary.FailedAuthenticationFaultCode; }
|
||
|
}
|
||
|
|
||
|
internal override XmlDictionaryString InvalidSecurityTokenFaultCode
|
||
|
{
|
||
|
get { return XD.SecurityJan2004Dictionary.InvalidSecurityTokenFaultCode; }
|
||
|
}
|
||
|
|
||
|
internal override XmlDictionaryString InvalidSecurityFaultCode
|
||
|
{
|
||
|
get { return XD.SecurityJan2004Dictionary.InvalidSecurityFaultCode; }
|
||
|
}
|
||
|
|
||
|
internal override SendSecurityHeader CreateSendSecurityHeader(Message message,
|
||
|
string actor, bool mustUnderstand, bool relay,
|
||
|
SecurityStandardsManager standardsManager,
|
||
|
SecurityAlgorithmSuite algorithmSuite,
|
||
|
MessageDirection direction)
|
||
|
{
|
||
|
return new WSSecurityOneDotZeroSendSecurityHeader(message, actor, mustUnderstand, relay, standardsManager, algorithmSuite, direction);
|
||
|
}
|
||
|
|
||
|
internal override ReceiveSecurityHeader CreateReceiveSecurityHeader(Message message,
|
||
|
string actor, bool mustUnderstand, bool relay,
|
||
|
SecurityStandardsManager standardsManager,
|
||
|
SecurityAlgorithmSuite algorithmSuite,
|
||
|
MessageDirection direction,
|
||
|
int headerIndex)
|
||
|
{
|
||
|
return new WSSecurityOneDotZeroReceiveSecurityHeader(
|
||
|
message,
|
||
|
actor, mustUnderstand, relay,
|
||
|
standardsManager,
|
||
|
algorithmSuite, headerIndex, direction);
|
||
|
}
|
||
|
|
||
|
public override string ToString()
|
||
|
{
|
||
|
return "WSSecurity10";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sealed class SecurityVersion11 : SecurityVersion10
|
||
|
{
|
||
|
static readonly SecurityVersion11 instance = new SecurityVersion11();
|
||
|
|
||
|
SecurityVersion11()
|
||
|
: base()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public new static SecurityVersion11 Instance
|
||
|
{
|
||
|
get { return instance; }
|
||
|
}
|
||
|
|
||
|
internal override bool SupportsSignatureConfirmation
|
||
|
{
|
||
|
get { return true; }
|
||
|
}
|
||
|
|
||
|
internal override ReceiveSecurityHeader CreateReceiveSecurityHeader(Message message,
|
||
|
string actor, bool mustUnderstand, bool relay,
|
||
|
SecurityStandardsManager standardsManager,
|
||
|
SecurityAlgorithmSuite algorithmSuite,
|
||
|
MessageDirection direction,
|
||
|
int headerIndex)
|
||
|
{
|
||
|
return new WSSecurityOneDotOneReceiveSecurityHeader(
|
||
|
message,
|
||
|
actor, mustUnderstand, relay,
|
||
|
standardsManager,
|
||
|
algorithmSuite, headerIndex, direction);
|
||
|
}
|
||
|
|
||
|
internal override SendSecurityHeader CreateSendSecurityHeader(Message message,
|
||
|
string actor, bool mustUnderstand, bool relay,
|
||
|
SecurityStandardsManager standardsManager,
|
||
|
SecurityAlgorithmSuite algorithmSuite, MessageDirection direction)
|
||
|
{
|
||
|
return new WSSecurityOneDotOneSendSecurityHeader(message, actor, mustUnderstand, relay, standardsManager, algorithmSuite, direction);
|
||
|
}
|
||
|
|
||
|
internal override bool IsReaderAtSignatureConfirmation(XmlDictionaryReader reader)
|
||
|
{
|
||
|
return reader.IsStartElement(XD.SecurityXXX2005Dictionary.SignatureConfirmation, XD.SecurityXXX2005Dictionary.Namespace);
|
||
|
}
|
||
|
|
||
|
internal override ISignatureValueSecurityElement ReadSignatureConfirmation(XmlDictionaryReader reader)
|
||
|
{
|
||
|
reader.MoveToStartElement(XD.SecurityXXX2005Dictionary.SignatureConfirmation, XD.SecurityXXX2005Dictionary.Namespace);
|
||
|
bool isEmptyElement = reader.IsEmptyElement;
|
||
|
string id = XmlHelper.GetRequiredNonEmptyAttribute(reader, XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace);
|
||
|
byte[] signatureValue = XmlHelper.GetRequiredBase64Attribute(reader, XD.SecurityXXX2005Dictionary.ValueAttribute, null);
|
||
|
reader.ReadStartElement();
|
||
|
if (!isEmptyElement)
|
||
|
{
|
||
|
reader.ReadEndElement();
|
||
|
}
|
||
|
return new SignatureConfirmationElement(id, signatureValue, this);
|
||
|
}
|
||
|
|
||
|
internal override void WriteSignatureConfirmation(XmlDictionaryWriter writer, string id, byte[] signature)
|
||
|
{
|
||
|
if (id == null)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("id");
|
||
|
}
|
||
|
if (signature == null)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("signature");
|
||
|
}
|
||
|
writer.WriteStartElement(XD.SecurityXXX2005Dictionary.Prefix.Value, XD.SecurityXXX2005Dictionary.SignatureConfirmation, XD.SecurityXXX2005Dictionary.Namespace);
|
||
|
writer.WriteAttributeString(XD.UtilityDictionary.Prefix.Value, XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace, id);
|
||
|
writer.WriteStartAttribute(XD.SecurityXXX2005Dictionary.ValueAttribute, null);
|
||
|
writer.WriteBase64(signature, 0, signature.Length);
|
||
|
writer.WriteEndAttribute();
|
||
|
writer.WriteEndElement();
|
||
|
}
|
||
|
|
||
|
public override string ToString()
|
||
|
{
|
||
|
return "WSSecurity11";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|