|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Net.Security;
using System.Runtime;
using System.Security.Authentication.ExtendedProtection;
using System.ServiceModel;
using System.ServiceModel.Diagnostics;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Security.Tokens;
using System.Text;
using Microsoft.Xml;
namespace System.ServiceModel.Channels
{
public abstract class SecurityBindingElement : BindingElement
{
internal static readonly SecurityAlgorithmSuite defaultDefaultAlgorithmSuite = SecurityAlgorithmSuite.Default;
internal const bool defaultIncludeTimestamp = true;
internal const bool defaultAllowInsecureTransport = false;
internal const MessageProtectionOrder defaultMessageProtectionOrder = MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature;
internal const bool defaultRequireSignatureConfirmation = false;
internal const bool defaultEnableUnsecuredResponse = false;
internal const bool defaultProtectTokens = false;
private SecurityAlgorithmSuite _defaultAlgorithmSuite;
private SupportingTokenParameters _endpointSupportingTokenParameters;
private SupportingTokenParameters _optionalEndpointSupportingTokenParameters;
private bool _includeTimestamp;
private SecurityKeyEntropyMode _keyEntropyMode;
private Dictionary<string, SupportingTokenParameters> _operationSupportingTokenParameters;
private Dictionary<string, SupportingTokenParameters> _optionalOperationSupportingTokenParameters;
private LocalClientSecuritySettings _localClientSettings;
private LocalServiceSecuritySettings _localServiceSettings;
private MessageSecurityVersion _messageSecurityVersion;
private SecurityHeaderLayout _securityHeaderLayout;
private long _maxReceivedMessageSize = TransportDefaults.MaxReceivedMessageSize;
private XmlDictionaryReaderQuotas _readerQuotas;
private bool _doNotEmitTrust = false; // true if user create a basic http standard binding, the custombinding equivalent will not set this flag
private bool _supportsExtendedProtectionPolicy;
private bool _allowInsecureTransport;
private bool _enableUnsecuredResponse;
private bool _protectTokens = defaultProtectTokens;
internal SecurityBindingElement()
: base()
{
_messageSecurityVersion = MessageSecurityVersion.Default;
_keyEntropyMode = SecurityKeyEntropyMode.CombinedEntropy; //TODO:? AcceleratedTokenProvider.defaultKeyEntropyMode;
_includeTimestamp = defaultIncludeTimestamp;
_defaultAlgorithmSuite = defaultDefaultAlgorithmSuite;
_localClientSettings = new LocalClientSecuritySettings();
_localServiceSettings = new LocalServiceSecuritySettings();
_endpointSupportingTokenParameters = new SupportingTokenParameters();
_optionalEndpointSupportingTokenParameters = new SupportingTokenParameters();
_operationSupportingTokenParameters = new Dictionary<string, SupportingTokenParameters>();
_optionalOperationSupportingTokenParameters = new Dictionary<string, SupportingTokenParameters>();
_securityHeaderLayout = SecurityProtocolFactory.defaultSecurityHeaderLayout;
_allowInsecureTransport = defaultAllowInsecureTransport;
_enableUnsecuredResponse = defaultEnableUnsecuredResponse;
_protectTokens = defaultProtectTokens;
}
internal SecurityBindingElement(SecurityBindingElement elementToBeCloned)
: base(elementToBeCloned)
{
if (elementToBeCloned == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("elementToBeCloned");
_defaultAlgorithmSuite = elementToBeCloned._defaultAlgorithmSuite;
_includeTimestamp = elementToBeCloned._includeTimestamp;
_keyEntropyMode = elementToBeCloned._keyEntropyMode;
_messageSecurityVersion = elementToBeCloned._messageSecurityVersion;
_securityHeaderLayout = elementToBeCloned._securityHeaderLayout;
_endpointSupportingTokenParameters = elementToBeCloned._endpointSupportingTokenParameters.Clone();
_optionalEndpointSupportingTokenParameters = elementToBeCloned._optionalEndpointSupportingTokenParameters.Clone();
_operationSupportingTokenParameters = new Dictionary<string, SupportingTokenParameters>();
foreach (string key in elementToBeCloned._operationSupportingTokenParameters.Keys)
{
_operationSupportingTokenParameters[key] = (SupportingTokenParameters)elementToBeCloned._operationSupportingTokenParameters[key].Clone();
}
_optionalOperationSupportingTokenParameters = new Dictionary<string, SupportingTokenParameters>();
foreach (string key in elementToBeCloned._optionalOperationSupportingTokenParameters.Keys)
{
_optionalOperationSupportingTokenParameters[key] = (SupportingTokenParameters)elementToBeCloned._optionalOperationSupportingTokenParameters[key].Clone();
}
_localClientSettings = elementToBeCloned._localClientSettings.Clone();
_localServiceSettings = elementToBeCloned._localServiceSettings.Clone();
_maxReceivedMessageSize = elementToBeCloned._maxReceivedMessageSize;
_readerQuotas = elementToBeCloned._readerQuotas;
_doNotEmitTrust = elementToBeCloned._doNotEmitTrust;
_allowInsecureTransport = elementToBeCloned._allowInsecureTransport;
_enableUnsecuredResponse = elementToBeCloned._enableUnsecuredResponse;
_supportsExtendedProtectionPolicy = elementToBeCloned._supportsExtendedProtectionPolicy;
_protectTokens = elementToBeCloned._protectTokens;
}
internal bool SupportsExtendedProtectionPolicy
{
get { return _supportsExtendedProtectionPolicy; }
set { _supportsExtendedProtectionPolicy = value; }
}
public SupportingTokenParameters EndpointSupportingTokenParameters
{
get
{
return _endpointSupportingTokenParameters;
}
}
public SupportingTokenParameters OptionalEndpointSupportingTokenParameters
{
get
{
return _optionalEndpointSupportingTokenParameters;
}
}
public IDictionary<string, SupportingTokenParameters> OperationSupportingTokenParameters
{
get
{
return _operationSupportingTokenParameters;
}
}
public IDictionary<string, SupportingTokenParameters> OptionalOperationSupportingTokenParameters
{
get
{
return _optionalOperationSupportingTokenParameters;
}
}
public SecurityHeaderLayout SecurityHeaderLayout
{
get
{
return _securityHeaderLayout;
}
set
{
if (!SecurityHeaderLayoutHelper.IsDefined(value))
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
_securityHeaderLayout = value;
}
}
public MessageSecurityVersion MessageSecurityVersion
{
get
{
return _messageSecurityVersion;
}
set
{
if (value == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
_messageSecurityVersion = value;
}
}
public bool EnableUnsecuredResponse
{
get
{
return _enableUnsecuredResponse;
}
set
{
_enableUnsecuredResponse = value;
}
}
public bool IncludeTimestamp
{
get
{
return _includeTimestamp;
}
set
{
_includeTimestamp = value;
}
}
public bool AllowInsecureTransport
{
get
{
return _allowInsecureTransport;
}
set
{
_allowInsecureTransport = value;
}
}
public SecurityAlgorithmSuite DefaultAlgorithmSuite
{
get
{
return _defaultAlgorithmSuite;
}
set
{
if (value == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
_defaultAlgorithmSuite = value;
}
}
public bool ProtectTokens
{
get
{
return _protectTokens;
}
set
{
_protectTokens = value;
}
}
public LocalClientSecuritySettings LocalClientSettings
{
get
{
return _localClientSettings;
}
}
public LocalServiceSecuritySettings LocalServiceSettings
{
get
{
return _localServiceSettings;
}
}
public SecurityKeyEntropyMode KeyEntropyMode
{
get
{
return _keyEntropyMode;
}
set
{
if (!SecurityKeyEntropyModeHelper.IsDefined(value))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
}
_keyEntropyMode = value;
}
}
internal virtual bool SessionMode
{
get { return false; }
}
internal virtual bool SupportsDuplex
{
get { return false; }
}
internal virtual bool SupportsRequestReply
{
get { return false; }
}
internal long MaxReceivedMessageSize
{
get { return _maxReceivedMessageSize; }
set { _maxReceivedMessageSize = value; }
}
internal bool DoNotEmitTrust
{
get { return _doNotEmitTrust; }
set { _doNotEmitTrust = value; }
}
internal XmlDictionaryReaderQuotas ReaderQuotas
{
get { return _readerQuotas; }
set { _readerQuotas = value; }
}
private void GetSupportingTokensCapabilities(ICollection<SecurityTokenParameters> parameters, out bool supportsClientAuth, out bool supportsWindowsIdentity)
{
supportsClientAuth = false;
supportsWindowsIdentity = false;
foreach (SecurityTokenParameters p in parameters)
{
if (p.SupportsClientAuthentication)
supportsClientAuth = true;
if (p.SupportsClientWindowsIdentity)
supportsWindowsIdentity = true;
}
}
private void GetSupportingTokensCapabilities(SupportingTokenParameters requirements, out bool supportsClientAuth, out bool supportsWindowsIdentity)
{
supportsClientAuth = false;
supportsWindowsIdentity = false;
bool tmpSupportsClientAuth;
bool tmpSupportsWindowsIdentity;
this.GetSupportingTokensCapabilities(requirements.Endorsing, out tmpSupportsClientAuth, out tmpSupportsWindowsIdentity);
supportsClientAuth = supportsClientAuth || tmpSupportsClientAuth;
supportsWindowsIdentity = supportsWindowsIdentity || tmpSupportsWindowsIdentity;
this.GetSupportingTokensCapabilities(requirements.SignedEndorsing, out tmpSupportsClientAuth, out tmpSupportsWindowsIdentity);
supportsClientAuth = supportsClientAuth || tmpSupportsClientAuth;
supportsWindowsIdentity = supportsWindowsIdentity || tmpSupportsWindowsIdentity;
this.GetSupportingTokensCapabilities(requirements.SignedEncrypted, out tmpSupportsClientAuth, out tmpSupportsWindowsIdentity);
supportsClientAuth = supportsClientAuth || tmpSupportsClientAuth;
supportsWindowsIdentity = supportsWindowsIdentity || tmpSupportsWindowsIdentity;
}
internal void GetSupportingTokensCapabilities(out bool supportsClientAuth, out bool supportsWindowsIdentity)
{
this.GetSupportingTokensCapabilities(this.EndpointSupportingTokenParameters, out supportsClientAuth, out supportsWindowsIdentity);
}
public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
{
throw new NotImplementedException();
}
protected abstract IChannelFactory<TChannel> BuildChannelFactoryCore<TChannel>(BindingContext context);
public override bool CanBuildChannelFactory<TChannel>(BindingContext context)
{
throw new NotImplementedException();
}
private bool CanBuildSessionChannelFactory<TChannel>(BindingContext context)
{
if (!(context.CanBuildInnerChannelFactory<IRequestChannel>()
|| context.CanBuildInnerChannelFactory<IRequestSessionChannel>()
|| context.CanBuildInnerChannelFactory<IDuplexChannel>()
|| context.CanBuildInnerChannelFactory<IDuplexSessionChannel>()))
{
return false;
}
if (typeof(TChannel) == typeof(IRequestSessionChannel))
{
return (context.CanBuildInnerChannelFactory<IRequestChannel>() || context.CanBuildInnerChannelFactory<IRequestSessionChannel>());
}
else if (typeof(TChannel) == typeof(IDuplexSessionChannel))
{
return (context.CanBuildInnerChannelFactory<IDuplexChannel>() || context.CanBuildInnerChannelFactory<IDuplexSessionChannel>());
}
else
{
return false;
}
}
public virtual void SetKeyDerivation(bool requireDerivedKeys)
{
this.EndpointSupportingTokenParameters.SetKeyDerivation(requireDerivedKeys);
this.OptionalEndpointSupportingTokenParameters.SetKeyDerivation(requireDerivedKeys);
foreach (SupportingTokenParameters t in this.OperationSupportingTokenParameters.Values)
t.SetKeyDerivation(requireDerivedKeys);
foreach (SupportingTokenParameters t in this.OptionalOperationSupportingTokenParameters.Values)
{
t.SetKeyDerivation(requireDerivedKeys);
}
}
internal virtual bool IsSetKeyDerivation(bool requireDerivedKeys)
{
if (!this.EndpointSupportingTokenParameters.IsSetKeyDerivation(requireDerivedKeys))
return false;
if (!this.OptionalEndpointSupportingTokenParameters.IsSetKeyDerivation(requireDerivedKeys))
return false;
foreach (SupportingTokenParameters t in this.OperationSupportingTokenParameters.Values)
{
if (!t.IsSetKeyDerivation(requireDerivedKeys))
return false;
}
foreach (SupportingTokenParameters t in this.OptionalOperationSupportingTokenParameters.Values)
{
if (!t.IsSetKeyDerivation(requireDerivedKeys))
return false;
}
return true;
}
internal ChannelProtectionRequirements GetProtectionRequirements(AddressingVersion addressing, ProtectionLevel defaultProtectionLevel)
{
if (addressing == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("addressing");
ChannelProtectionRequirements result = new ChannelProtectionRequirements();
ProtectionLevel supportedRequestProtectionLevel = this.GetIndividualProperty<ISecurityCapabilities>().SupportedRequestProtectionLevel;
ProtectionLevel supportedResponseProtectionLevel = this.GetIndividualProperty<ISecurityCapabilities>().SupportedResponseProtectionLevel;
bool canSupportMoreThanTheDefault =
(ProtectionLevelHelper.IsStrongerOrEqual(supportedRequestProtectionLevel, defaultProtectionLevel)
&& ProtectionLevelHelper.IsStrongerOrEqual(supportedResponseProtectionLevel, defaultProtectionLevel));
if (canSupportMoreThanTheDefault)
{
MessagePartSpecification signedParts = new MessagePartSpecification();
MessagePartSpecification encryptedParts = new MessagePartSpecification();
if (defaultProtectionLevel != ProtectionLevel.None)
{
signedParts.IsBodyIncluded = true;
if (defaultProtectionLevel == ProtectionLevel.EncryptAndSign)
{
encryptedParts.IsBodyIncluded = true;
}
}
signedParts.MakeReadOnly();
encryptedParts.MakeReadOnly();
if (addressing.FaultAction != null)
{
// Addressing faults
result.IncomingSignatureParts.AddParts(signedParts, addressing.FaultAction);
result.OutgoingSignatureParts.AddParts(signedParts, addressing.FaultAction);
result.IncomingEncryptionParts.AddParts(encryptedParts, addressing.FaultAction);
result.OutgoingEncryptionParts.AddParts(encryptedParts, addressing.FaultAction);
}
if (addressing.DefaultFaultAction != null)
{
// Faults that do not specify a particular action
result.IncomingSignatureParts.AddParts(signedParts, addressing.DefaultFaultAction);
result.OutgoingSignatureParts.AddParts(signedParts, addressing.DefaultFaultAction);
result.IncomingEncryptionParts.AddParts(encryptedParts, addressing.DefaultFaultAction);
result.OutgoingEncryptionParts.AddParts(encryptedParts, addressing.DefaultFaultAction);
}
// Infrastructure faults
result.IncomingSignatureParts.AddParts(signedParts, FaultCodeConstants.Actions.NetDispatcher);
result.OutgoingSignatureParts.AddParts(signedParts, FaultCodeConstants.Actions.NetDispatcher);
result.IncomingEncryptionParts.AddParts(encryptedParts, FaultCodeConstants.Actions.NetDispatcher);
result.OutgoingEncryptionParts.AddParts(encryptedParts, FaultCodeConstants.Actions.NetDispatcher);
}
return result;
}
public override T GetProperty<T>(BindingContext context)
{
if (context == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
}
if (typeof(T) == typeof(ISecurityCapabilities))
{
return (T)(object)GetSecurityCapabilities(context);
}
else if (typeof(T) == typeof(IdentityVerifier))
{
return (T)(object)_localClientSettings.IdentityVerifier;
}
else
{
return context.GetInnerProperty<T>();
}
}
internal abstract ISecurityCapabilities GetIndividualISecurityCapabilities();
private ISecurityCapabilities GetSecurityCapabilities(BindingContext context)
{
ISecurityCapabilities thisSecurityCapability = this.GetIndividualISecurityCapabilities();
ISecurityCapabilities lowerSecurityCapability = context.GetInnerProperty<ISecurityCapabilities>();
if (lowerSecurityCapability == null)
{
return thisSecurityCapability;
}
else
{
bool supportsClientAuth = thisSecurityCapability.SupportsClientAuthentication;
bool supportsClientWindowsIdentity = thisSecurityCapability.SupportsClientWindowsIdentity;
bool supportsServerAuth = thisSecurityCapability.SupportsServerAuthentication || lowerSecurityCapability.SupportsServerAuthentication;
ProtectionLevel requestProtectionLevel = ProtectionLevelHelper.Max(thisSecurityCapability.SupportedRequestProtectionLevel, lowerSecurityCapability.SupportedRequestProtectionLevel);
ProtectionLevel responseProtectionLevel = ProtectionLevelHelper.Max(thisSecurityCapability.SupportedResponseProtectionLevel, lowerSecurityCapability.SupportedResponseProtectionLevel);
return new SecurityCapabilities(supportsClientAuth, supportsServerAuth, supportsClientWindowsIdentity, requestProtectionLevel, responseProtectionLevel);
}
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsMutualCertificateBinding() method.
static public SecurityBindingElement CreateMutualCertificateBindingElement()
{
return CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11);
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsMutualCertificateBinding(SecurityBindingElement sbe)
{
return IsMutualCertificateBinding(sbe, false);
}
static public AsymmetricSecurityBindingElement CreateCertificateSignatureBindingElement()
{
AsymmetricSecurityBindingElement result;
result = new AsymmetricSecurityBindingElement(
new X509SecurityTokenParameters( // recipient
X509KeyIdentifierClauseType.Any,
SecurityTokenInclusionMode.Never, false),
new X509SecurityTokenParameters( // initiator
X509KeyIdentifierClauseType.Any,
SecurityTokenInclusionMode.AlwaysToRecipient, false));
// this is a one way binding so the client cannot detect replays
result.IsCertificateSignatureBinding = true;
result.LocalClientSettings.DetectReplays = false;
result.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
return result;
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsMutualCertificateBinding() method.
static public SecurityBindingElement CreateMutualCertificateBindingElement(MessageSecurityVersion version)
{
return CreateMutualCertificateBindingElement(version, false);
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsMutualCertificateBinding() method.
static public SecurityBindingElement CreateMutualCertificateBindingElement(MessageSecurityVersion version, bool allowSerializedSigningTokenOnReply)
{
if (version == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("version");
}
SecurityBindingElement result;
if (version.SecurityVersion == SecurityVersion.WSSecurity10)
{
result = new AsymmetricSecurityBindingElement(
new X509SecurityTokenParameters( // recipient
X509KeyIdentifierClauseType.Any,
SecurityTokenInclusionMode.Never,
false),
new X509SecurityTokenParameters( // initiator
X509KeyIdentifierClauseType.Any,
SecurityTokenInclusionMode.AlwaysToRecipient, false),
allowSerializedSigningTokenOnReply);
}
else
{
result = new SymmetricSecurityBindingElement(
new X509SecurityTokenParameters( // protection
X509KeyIdentifierClauseType.Thumbprint,
SecurityTokenInclusionMode.Never));
result.EndpointSupportingTokenParameters.Endorsing.Add(
new X509SecurityTokenParameters(
X509KeyIdentifierClauseType.Thumbprint,
SecurityTokenInclusionMode.AlwaysToRecipient,
false));
((SymmetricSecurityBindingElement)result).RequireSignatureConfirmation = true;
}
result.MessageSecurityVersion = version;
return result;
}
// this method reverses CreateMutualCertificateDuplexBindingElement() logic
internal static bool IsMutualCertificateDuplexBinding(SecurityBindingElement sbe)
{
// Do not check MessageSecurityVersion: it maybe changed by the wrapper element and gets checked later in the SecuritySection.AreBindingsMatching()
AsymmetricSecurityBindingElement asbe = sbe as AsymmetricSecurityBindingElement;
if (asbe != null)
{
X509SecurityTokenParameters recipient = asbe.RecipientTokenParameters as X509SecurityTokenParameters;
if (recipient == null || (recipient.X509ReferenceStyle != X509KeyIdentifierClauseType.Any && recipient.X509ReferenceStyle != X509KeyIdentifierClauseType.Thumbprint) || recipient.InclusionMode != SecurityTokenInclusionMode.AlwaysToInitiator)
return false;
X509SecurityTokenParameters initiator = asbe.InitiatorTokenParameters as X509SecurityTokenParameters;
if (initiator == null || (initiator.X509ReferenceStyle != X509KeyIdentifierClauseType.Any && initiator.X509ReferenceStyle != X509KeyIdentifierClauseType.Thumbprint) || initiator.InclusionMode != SecurityTokenInclusionMode.AlwaysToRecipient)
return false;
if (!sbe.EndpointSupportingTokenParameters.IsEmpty())
return false;
return true;
}
else
{
return false;
}
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsMutualCertificateBinding(SecurityBindingElement sbe, bool allowSerializedSigningTokenOnReply)
{
// Do not check MessageSecurityVersion: it maybe changed by the wrapper element and gets checked later in the SecuritySection.AreBindingsMatching()
AsymmetricSecurityBindingElement asbe = sbe as AsymmetricSecurityBindingElement;
if (asbe != null)
{
X509SecurityTokenParameters recipient = asbe.RecipientTokenParameters as X509SecurityTokenParameters;
if (recipient == null || recipient.X509ReferenceStyle != X509KeyIdentifierClauseType.Any || recipient.InclusionMode != SecurityTokenInclusionMode.Never)
return false;
X509SecurityTokenParameters initiator = asbe.InitiatorTokenParameters as X509SecurityTokenParameters;
if (initiator == null || initiator.X509ReferenceStyle != X509KeyIdentifierClauseType.Any || initiator.InclusionMode != SecurityTokenInclusionMode.AlwaysToRecipient)
return false;
if (!sbe.EndpointSupportingTokenParameters.IsEmpty())
return false;
}
else
{
SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
if (ssbe == null)
return false;
X509SecurityTokenParameters x509Parameters = ssbe.ProtectionTokenParameters as X509SecurityTokenParameters;
if (x509Parameters == null || x509Parameters.X509ReferenceStyle != X509KeyIdentifierClauseType.Thumbprint || x509Parameters.InclusionMode != SecurityTokenInclusionMode.Never)
return false;
SupportingTokenParameters parameters = sbe.EndpointSupportingTokenParameters;
if (parameters.Signed.Count != 0 || parameters.SignedEncrypted.Count != 0 || parameters.Endorsing.Count != 1 || parameters.SignedEndorsing.Count != 0)
return false;
x509Parameters = parameters.Endorsing[0] as X509SecurityTokenParameters;
if (x509Parameters == null || x509Parameters.X509ReferenceStyle != X509KeyIdentifierClauseType.Thumbprint || x509Parameters.InclusionMode != SecurityTokenInclusionMode.AlwaysToRecipient)
return false;
if (!ssbe.RequireSignatureConfirmation)
return false;
}
return true;
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsAnonymousForCertificateBinding() method.
static public SymmetricSecurityBindingElement CreateAnonymousForCertificateBindingElement()
{
SymmetricSecurityBindingElement result;
result = new SymmetricSecurityBindingElement(
new X509SecurityTokenParameters( // protection
X509KeyIdentifierClauseType.Thumbprint,
SecurityTokenInclusionMode.Never));
result.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11;
result.RequireSignatureConfirmation = true;
return result;
}
// this method reverses CreateAnonymousForCertificateBindingElement() logic
internal static bool IsAnonymousForCertificateBinding(SecurityBindingElement sbe)
{
SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
if (ssbe == null)
return false;
if (!ssbe.RequireSignatureConfirmation)
return false;
// Do not check MessageSecurityVersion: it maybe changed by the wrapper element and gets checked later in the SecuritySection.AreBindingsMatching()
X509SecurityTokenParameters x509Parameters = ssbe.ProtectionTokenParameters as X509SecurityTokenParameters;
if (x509Parameters == null || x509Parameters.X509ReferenceStyle != X509KeyIdentifierClauseType.Thumbprint || x509Parameters.InclusionMode != SecurityTokenInclusionMode.Never)
return false;
if (!sbe.EndpointSupportingTokenParameters.IsEmpty())
return false;
return true;
}
static public AsymmetricSecurityBindingElement CreateMutualCertificateDuplexBindingElement()
{
return CreateMutualCertificateDuplexBindingElement(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11);
}
static public AsymmetricSecurityBindingElement CreateMutualCertificateDuplexBindingElement(MessageSecurityVersion version)
{
if (version == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("version");
}
AsymmetricSecurityBindingElement result;
if (version.SecurityVersion == SecurityVersion.WSSecurity10)
{
result = new AsymmetricSecurityBindingElement(
new X509SecurityTokenParameters( // recipient
X509KeyIdentifierClauseType.Any,
SecurityTokenInclusionMode.AlwaysToInitiator,
false),
new X509SecurityTokenParameters( // initiator
X509KeyIdentifierClauseType.Any,
SecurityTokenInclusionMode.AlwaysToRecipient,
false));
}
else
{
result = new AsymmetricSecurityBindingElement(
new X509SecurityTokenParameters( // recipient
X509KeyIdentifierClauseType.Thumbprint,
SecurityTokenInclusionMode.AlwaysToInitiator,
false),
new X509SecurityTokenParameters( // initiator
X509KeyIdentifierClauseType.Thumbprint,
SecurityTokenInclusionMode.AlwaysToRecipient,
false));
}
result.MessageSecurityVersion = version;
return result;
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsUserNameForCertificateBinding() method.
static public SymmetricSecurityBindingElement CreateUserNameForCertificateBindingElement()
{
SymmetricSecurityBindingElement result = new SymmetricSecurityBindingElement(
new X509SecurityTokenParameters(
X509KeyIdentifierClauseType.Thumbprint,
SecurityTokenInclusionMode.Never));
result.EndpointSupportingTokenParameters.SignedEncrypted.Add(
new UserNameSecurityTokenParameters());
result.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11;
return result;
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsUserNameForCertificateBinding(SecurityBindingElement sbe)
{
// Do not check MessageSecurityVersion: it maybe changed by the wrapper element and gets checked later in the SecuritySection.AreBindingsMatching()
SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
if (ssbe == null)
return false;
X509SecurityTokenParameters x509Parameters = ssbe.ProtectionTokenParameters as X509SecurityTokenParameters;
if (x509Parameters == null || x509Parameters.X509ReferenceStyle != X509KeyIdentifierClauseType.Thumbprint || x509Parameters.InclusionMode != SecurityTokenInclusionMode.Never)
return false;
SupportingTokenParameters parameters = sbe.EndpointSupportingTokenParameters;
if (parameters.Signed.Count != 0 || parameters.SignedEncrypted.Count != 1 || parameters.Endorsing.Count != 0 || parameters.SignedEndorsing.Count != 0)
return false;
UserNameSecurityTokenParameters userNameParameters = parameters.SignedEncrypted[0] as UserNameSecurityTokenParameters;
if (userNameParameters == null)
return false;
return true;
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsKerberosBinding() method.
static public SymmetricSecurityBindingElement CreateKerberosBindingElement()
{
SymmetricSecurityBindingElement result = new SymmetricSecurityBindingElement(
new KerberosSecurityTokenParameters());
result.DefaultAlgorithmSuite = SecurityAlgorithmSuite.KerberosDefault;
return result;
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsKerberosBinding(SecurityBindingElement sbe)
{
// do not check DefaultAlgorithmSuite match: it is often changed by the caller of CreateKerberosBindingElement
SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
if (ssbe == null)
return false;
KerberosSecurityTokenParameters parameters = ssbe.ProtectionTokenParameters as KerberosSecurityTokenParameters;
if (parameters == null)
return false;
if (!sbe.EndpointSupportingTokenParameters.IsEmpty())
return false;
return true;
}
static public SymmetricSecurityBindingElement CreateSspiNegotiationBindingElement()
{
return CreateSspiNegotiationBindingElement(SspiSecurityTokenParameters.defaultRequireCancellation);
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsSspiNegotiationBinding() method.
static public SymmetricSecurityBindingElement CreateSspiNegotiationBindingElement(bool requireCancellation)
{
SymmetricSecurityBindingElement result = new SymmetricSecurityBindingElement(
new SspiSecurityTokenParameters(requireCancellation));
return result;
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsSspiNegotiationBinding(SecurityBindingElement sbe, bool requireCancellation)
{
SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
if (ssbe == null)
return false;
if (!sbe.EndpointSupportingTokenParameters.IsEmpty())
return false;
SspiSecurityTokenParameters sspiParameters = ssbe.ProtectionTokenParameters as SspiSecurityTokenParameters;
if (sspiParameters == null)
return false;
return sspiParameters.RequireCancellation == requireCancellation;
}
static public SymmetricSecurityBindingElement CreateSslNegotiationBindingElement(bool requireClientCertificate)
{
return CreateSslNegotiationBindingElement(requireClientCertificate, SslSecurityTokenParameters.defaultRequireCancellation);
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsSslNegotiationBinding() method.
static public SymmetricSecurityBindingElement CreateSslNegotiationBindingElement(bool requireClientCertificate, bool requireCancellation)
{
SymmetricSecurityBindingElement result = new SymmetricSecurityBindingElement(
new SslSecurityTokenParameters(requireClientCertificate, requireCancellation));
return result;
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsSslNegotiationBinding(SecurityBindingElement sbe, bool requireClientCertificate, bool requireCancellation)
{
SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
if (ssbe == null)
return false;
if (!sbe.EndpointSupportingTokenParameters.IsEmpty())
return false;
SslSecurityTokenParameters sslParameters = ssbe.ProtectionTokenParameters as SslSecurityTokenParameters;
if (sslParameters == null)
return false;
return sslParameters.RequireClientCertificate == requireClientCertificate && sslParameters.RequireCancellation == requireCancellation;
}
static public SymmetricSecurityBindingElement CreateIssuedTokenBindingElement(IssuedSecurityTokenParameters issuedTokenParameters)
{
if (issuedTokenParameters == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("issuedTokenParameters");
if (issuedTokenParameters.KeyType != SecurityKeyType.SymmetricKey)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SRServiceModel.IssuedTokenAuthenticationModeRequiresSymmetricIssuedKey);
SymmetricSecurityBindingElement result = new SymmetricSecurityBindingElement(issuedTokenParameters);
return result;
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsIssuedTokenForCertificateBinding() method.
static public SymmetricSecurityBindingElement CreateIssuedTokenForCertificateBindingElement(IssuedSecurityTokenParameters issuedTokenParameters)
{
if (issuedTokenParameters == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("issuedTokenParameters");
SymmetricSecurityBindingElement result = new SymmetricSecurityBindingElement(
new X509SecurityTokenParameters(
X509KeyIdentifierClauseType.Thumbprint,
SecurityTokenInclusionMode.Never));
if (issuedTokenParameters.KeyType == SecurityKeyType.BearerKey)
{
result.EndpointSupportingTokenParameters.SignedEncrypted.Add(issuedTokenParameters);
result.MessageSecurityVersion = MessageSecurityVersion.WSSXDefault;
}
else
{
result.EndpointSupportingTokenParameters.Endorsing.Add(issuedTokenParameters);
result.MessageSecurityVersion = MessageSecurityVersion.Default;
}
result.RequireSignatureConfirmation = true;
return result;
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsIssuedTokenForCertificateBinding(SecurityBindingElement sbe, out IssuedSecurityTokenParameters issuedTokenParameters)
{
issuedTokenParameters = null;
SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
if (ssbe == null)
return false;
if (!ssbe.RequireSignatureConfirmation)
return false;
// Do not check MessageSecurityVersion: it maybe changed by the wrapper element and gets checked later in the SecuritySection.AreBindingsMatching()
X509SecurityTokenParameters x509Parameters = ssbe.ProtectionTokenParameters as X509SecurityTokenParameters;
if (x509Parameters == null || x509Parameters.X509ReferenceStyle != X509KeyIdentifierClauseType.Thumbprint || x509Parameters.InclusionMode != SecurityTokenInclusionMode.Never)
return false;
SupportingTokenParameters parameters = ssbe.EndpointSupportingTokenParameters;
if (parameters.Signed.Count != 0 || (parameters.SignedEncrypted.Count == 0 && parameters.Endorsing.Count == 0) || parameters.SignedEndorsing.Count != 0)
return false;
if ((parameters.SignedEncrypted.Count == 1) && (parameters.Endorsing.Count == 0))
{
issuedTokenParameters = parameters.SignedEncrypted[0] as IssuedSecurityTokenParameters;
if (issuedTokenParameters != null && issuedTokenParameters.KeyType != SecurityKeyType.BearerKey)
return false;
}
else if ((parameters.Endorsing.Count == 1) && (parameters.SignedEncrypted.Count == 0))
{
issuedTokenParameters = parameters.Endorsing[0] as IssuedSecurityTokenParameters;
if (issuedTokenParameters != null && (issuedTokenParameters.KeyType != SecurityKeyType.SymmetricKey && issuedTokenParameters.KeyType != SecurityKeyType.AsymmetricKey))
return false;
}
return (issuedTokenParameters != null);
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsIssuedTokenForSslBinding() method.
static public SymmetricSecurityBindingElement CreateIssuedTokenForSslBindingElement(IssuedSecurityTokenParameters issuedTokenParameters)
{
return CreateIssuedTokenForSslBindingElement(issuedTokenParameters, SslSecurityTokenParameters.defaultRequireCancellation);
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsIssuedTokenForSslBinding(SecurityBindingElement sbe, out IssuedSecurityTokenParameters issuedTokenParameters)
{
return IsIssuedTokenForSslBinding(sbe, SslSecurityTokenParameters.defaultRequireCancellation, out issuedTokenParameters);
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsIssuedTokenForSslBinding() method.
static public SymmetricSecurityBindingElement CreateIssuedTokenForSslBindingElement(IssuedSecurityTokenParameters issuedTokenParameters, bool requireCancellation)
{
if (issuedTokenParameters == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("issuedTokenParameters");
SymmetricSecurityBindingElement result = new SymmetricSecurityBindingElement(
new SslSecurityTokenParameters(false, requireCancellation));
if (issuedTokenParameters.KeyType == SecurityKeyType.BearerKey)
{
result.EndpointSupportingTokenParameters.SignedEncrypted.Add(issuedTokenParameters);
result.MessageSecurityVersion = MessageSecurityVersion.WSSXDefault;
}
else
{
result.EndpointSupportingTokenParameters.Endorsing.Add(issuedTokenParameters);
result.MessageSecurityVersion = MessageSecurityVersion.Default;
}
result.RequireSignatureConfirmation = true;
return result;
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsIssuedTokenForSslBinding(SecurityBindingElement sbe, bool requireCancellation, out IssuedSecurityTokenParameters issuedTokenParameters)
{
issuedTokenParameters = null;
SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
if (ssbe == null)
return false;
if (!ssbe.RequireSignatureConfirmation)
return false;
// Do not check MessageSecurityVersion: it maybe changed by the wrapper element and gets checked later in the SecuritySection.AreBindingsMatching()
SslSecurityTokenParameters sslParameters = ssbe.ProtectionTokenParameters as SslSecurityTokenParameters;
if (sslParameters == null)
return false;
if (sslParameters.RequireClientCertificate || sslParameters.RequireCancellation != requireCancellation)
return false;
SupportingTokenParameters parameters = ssbe.EndpointSupportingTokenParameters;
if (parameters.Signed.Count != 0 || (parameters.SignedEncrypted.Count == 0 && parameters.Endorsing.Count == 0) || parameters.SignedEndorsing.Count != 0)
return false;
if ((parameters.SignedEncrypted.Count == 1) && (parameters.Endorsing.Count == 0))
{
issuedTokenParameters = parameters.SignedEncrypted[0] as IssuedSecurityTokenParameters;
if (issuedTokenParameters != null && issuedTokenParameters.KeyType != SecurityKeyType.BearerKey)
return false;
}
else if ((parameters.Endorsing.Count == 1) && (parameters.SignedEncrypted.Count == 0))
{
issuedTokenParameters = parameters.Endorsing[0] as IssuedSecurityTokenParameters;
if (issuedTokenParameters != null && (issuedTokenParameters.KeyType != SecurityKeyType.SymmetricKey && issuedTokenParameters.KeyType != SecurityKeyType.AsymmetricKey))
return false;
}
return (issuedTokenParameters != null);
}
static public SymmetricSecurityBindingElement CreateUserNameForSslBindingElement()
{
return CreateUserNameForSslBindingElement(SslSecurityTokenParameters.defaultRequireCancellation);
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsUserNameForSslBinding() method.
static public SymmetricSecurityBindingElement CreateUserNameForSslBindingElement(bool requireCancellation)
{
SymmetricSecurityBindingElement result = new SymmetricSecurityBindingElement(
new SslSecurityTokenParameters(false, requireCancellation));
result.EndpointSupportingTokenParameters.SignedEncrypted.Add(
new UserNameSecurityTokenParameters());
result.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11;
return result;
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsUserNameForSslBinding(SecurityBindingElement sbe, bool requireCancellation)
{
// Do not check MessageSecurityVersion: it maybe changed by the wrapper element and gets checked later in the SecuritySection.AreBindingsMatching()
SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
if (ssbe == null)
return false;
SupportingTokenParameters parameters = sbe.EndpointSupportingTokenParameters;
if (parameters.Signed.Count != 0 || parameters.SignedEncrypted.Count != 1 || parameters.Endorsing.Count != 0 || parameters.SignedEndorsing.Count != 0)
return false;
if (!(parameters.SignedEncrypted[0] is UserNameSecurityTokenParameters))
return false;
SslSecurityTokenParameters sslParameters = ssbe.ProtectionTokenParameters as SslSecurityTokenParameters;
if (sslParameters == null)
return false;
return sslParameters.RequireCancellation == requireCancellation && !sslParameters.RequireClientCertificate;
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsUserNameOverTransportBinding() method.
static public TransportSecurityBindingElement CreateUserNameOverTransportBindingElement()
{
TransportSecurityBindingElement result = new TransportSecurityBindingElement();
result.EndpointSupportingTokenParameters.SignedEncrypted.Add(
new UserNameSecurityTokenParameters());
result.IncludeTimestamp = true;
result.LocalClientSettings.DetectReplays = false;
result.LocalServiceSettings.DetectReplays = false;
return result;
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsUserNameOverTransportBinding(SecurityBindingElement sbe)
{
// do not check local settings: sbe.LocalServiceSettings and sbe.LocalClientSettings
if (!sbe.IncludeTimestamp)
return false;
if (!(sbe is TransportSecurityBindingElement))
return false;
SupportingTokenParameters parameters = sbe.EndpointSupportingTokenParameters;
if (parameters.Signed.Count != 0 || parameters.SignedEncrypted.Count != 1 || parameters.Endorsing.Count != 0 || parameters.SignedEndorsing.Count != 0)
return false;
UserNameSecurityTokenParameters userNameParameters = parameters.SignedEncrypted[0] as UserNameSecurityTokenParameters;
if (userNameParameters == null)
return false;
return true;
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsCertificateOverTransportBinding() method.
static public TransportSecurityBindingElement CreateCertificateOverTransportBindingElement()
{
return CreateCertificateOverTransportBindingElement(MessageSecurityVersion.Default);
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsCertificateOverTransportBinding() method.
static public TransportSecurityBindingElement CreateCertificateOverTransportBindingElement(MessageSecurityVersion version)
{
if (version == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("version");
}
X509KeyIdentifierClauseType x509ReferenceType;
if (version.SecurityVersion == SecurityVersion.WSSecurity10)
{
x509ReferenceType = X509KeyIdentifierClauseType.Any;
}
else
{
x509ReferenceType = X509KeyIdentifierClauseType.Thumbprint;
}
TransportSecurityBindingElement result = new TransportSecurityBindingElement();
X509SecurityTokenParameters x509Parameters = new X509SecurityTokenParameters(
x509ReferenceType,
SecurityTokenInclusionMode.AlwaysToRecipient,
false);
result.EndpointSupportingTokenParameters.Endorsing.Add(
x509Parameters
);
result.IncludeTimestamp = true;
result.LocalClientSettings.DetectReplays = false;
result.LocalServiceSettings.DetectReplays = false;
result.MessageSecurityVersion = version;
return result;
}
// this method reverses CreateMutualCertificateBindingElement() logic
internal static bool IsCertificateOverTransportBinding(SecurityBindingElement sbe)
{
// do not check local settings: sbe.LocalServiceSettings and sbe.LocalClientSettings
if (!sbe.IncludeTimestamp)
return false;
if (!(sbe is TransportSecurityBindingElement))
return false;
SupportingTokenParameters parameters = sbe.EndpointSupportingTokenParameters;
if (parameters.Signed.Count != 0 || parameters.SignedEncrypted.Count != 0 || parameters.Endorsing.Count != 1 || parameters.SignedEndorsing.Count != 0)
return false;
X509SecurityTokenParameters x509Parameters = parameters.Endorsing[0] as X509SecurityTokenParameters;
if (x509Parameters == null)
return false;
if (x509Parameters.InclusionMode != SecurityTokenInclusionMode.AlwaysToRecipient)
return false;
return x509Parameters.X509ReferenceStyle == X509KeyIdentifierClauseType.Any || x509Parameters.X509ReferenceStyle == X509KeyIdentifierClauseType.Thumbprint;
}
static public TransportSecurityBindingElement CreateKerberosOverTransportBindingElement()
{
TransportSecurityBindingElement result = new TransportSecurityBindingElement();
KerberosSecurityTokenParameters kerberosParameters = new KerberosSecurityTokenParameters();
kerberosParameters.RequireDerivedKeys = false;
result.EndpointSupportingTokenParameters.Endorsing.Add(
kerberosParameters);
result.IncludeTimestamp = true;
result.LocalClientSettings.DetectReplays = false;
result.LocalServiceSettings.DetectReplays = false;
result.DefaultAlgorithmSuite = SecurityAlgorithmSuite.KerberosDefault;
result.SupportsExtendedProtectionPolicy = true;
return result;
}
#if NO
// this is reversing of the CreateKerberosOverTransportBindingElement() logic
static bool IsKerberosOverTransportBinding(SecurityBindingElement sbe)
{
if (sbe.DefaultAlgorithmSuite != SecurityAlgorithmSuite.KerberosDefault)
return false;
// do not check local settings: sbe.LocalServiceSettings and sbe.LocalClientSettings
if (!sbe.IncludeTimestamp)
return false;
if (!(sbe is TransportSecurityBindingElement))
return false;
SupportingTokenParameters parameters = sbe.EndpointSupportingTokenParameters;
if (parameters.Signed.Count != 0 || parameters.SignedEncrypted.Count != 0 || parameters.Endorsing.Count != 1 || parameters.SignedEndorsing.Count != 0)
return false;
KerberosSecurityTokenParameters kerberosParameters = parameters.Endorsing[0] as KerberosSecurityTokenParameters;
if (kerberosParameters == null)
return false;
if (kerberosParameters.RequireDerivedKeys)
return false;
return true;
}
#endif
static public TransportSecurityBindingElement CreateSspiNegotiationOverTransportBindingElement()
{
return CreateSspiNegotiationOverTransportBindingElement(true);
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsSspiNegotiationOverTransportBinding() method.
static public TransportSecurityBindingElement CreateSspiNegotiationOverTransportBindingElement(bool requireCancellation)
{
TransportSecurityBindingElement result = new TransportSecurityBindingElement();
SspiSecurityTokenParameters sspiParameters = new SspiSecurityTokenParameters(requireCancellation);
sspiParameters.RequireDerivedKeys = false;
result.EndpointSupportingTokenParameters.Endorsing.Add(
sspiParameters);
result.IncludeTimestamp = true;
result.LocalClientSettings.DetectReplays = false;
result.LocalServiceSettings.DetectReplays = false;
result.SupportsExtendedProtectionPolicy = true;
return result;
}
// this method reverses CreateSspiNegotiationOverTransportBindingElement() logic
internal static bool IsSspiNegotiationOverTransportBinding(SecurityBindingElement sbe, bool requireCancellation)
{
// do not check local settings: sbe.LocalServiceSettings and sbe.LocalClientSettings
if (!sbe.IncludeTimestamp)
return false;
SupportingTokenParameters parameters = sbe.EndpointSupportingTokenParameters;
if (parameters.Signed.Count != 0 || parameters.SignedEncrypted.Count != 0 || parameters.Endorsing.Count != 1 || parameters.SignedEndorsing.Count != 0)
return false;
SspiSecurityTokenParameters sspiParameters = parameters.Endorsing[0] as SspiSecurityTokenParameters;
if (sspiParameters == null)
return false;
if (sspiParameters.RequireDerivedKeys)
return false;
if (sspiParameters.RequireCancellation != requireCancellation)
return false;
if (!(sbe is TransportSecurityBindingElement))
return false;
return true;
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsIssuedTokenOverTransportBinding() method.
static public TransportSecurityBindingElement CreateIssuedTokenOverTransportBindingElement(IssuedSecurityTokenParameters issuedTokenParameters)
{
if (issuedTokenParameters == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("issuedTokenParameters");
issuedTokenParameters.RequireDerivedKeys = false;
TransportSecurityBindingElement result = new TransportSecurityBindingElement();
if (issuedTokenParameters.KeyType == SecurityKeyType.BearerKey)
{
result.EndpointSupportingTokenParameters.Signed.Add(issuedTokenParameters);
result.MessageSecurityVersion = MessageSecurityVersion.WSSXDefault;
}
else
{
result.EndpointSupportingTokenParameters.Endorsing.Add(issuedTokenParameters);
result.MessageSecurityVersion = MessageSecurityVersion.Default;
}
result.LocalClientSettings.DetectReplays = false;
result.LocalServiceSettings.DetectReplays = false;
result.IncludeTimestamp = true;
return result;
}
// this method reverses CreateIssuedTokenOverTransportBindingElement() logic
internal static bool IsIssuedTokenOverTransportBinding(SecurityBindingElement sbe, out IssuedSecurityTokenParameters issuedTokenParameters)
{
issuedTokenParameters = null;
if (!(sbe is TransportSecurityBindingElement))
return false;
if (!sbe.IncludeTimestamp)
return false;
// do not check local settings: sbe.LocalServiceSettings and sbe.LocalClientSettings
SupportingTokenParameters parameters = sbe.EndpointSupportingTokenParameters;
if (parameters.SignedEncrypted.Count != 0 || (parameters.Signed.Count == 0 && parameters.Endorsing.Count == 0) || parameters.SignedEndorsing.Count != 0)
return false;
if ((parameters.Signed.Count == 1) && (parameters.Endorsing.Count == 0))
{
issuedTokenParameters = parameters.Signed[0] as IssuedSecurityTokenParameters;
if (issuedTokenParameters != null && issuedTokenParameters.KeyType != SecurityKeyType.BearerKey)
return false;
}
else if ((parameters.Endorsing.Count == 1) && (parameters.Signed.Count == 0))
{
issuedTokenParameters = parameters.Endorsing[0] as IssuedSecurityTokenParameters;
if (issuedTokenParameters != null && (issuedTokenParameters.KeyType != SecurityKeyType.SymmetricKey && issuedTokenParameters.KeyType != SecurityKeyType.AsymmetricKey))
return false;
}
if (issuedTokenParameters == null)
return false;
if (issuedTokenParameters.RequireDerivedKeys)
return false;
return true;
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsSecureConversationBinding() method.
static public SecurityBindingElement CreateSecureConversationBindingElement(SecurityBindingElement bootstrapSecurity)
{
return CreateSecureConversationBindingElement(bootstrapSecurity, SecureConversationSecurityTokenParameters.defaultRequireCancellation, null);
}
// this method reverses CreateSecureConversationBindingElement() logic
internal static bool IsSecureConversationBinding(SecurityBindingElement sbe, out SecurityBindingElement bootstrapSecurity)
{
return IsSecureConversationBinding(sbe, SecureConversationSecurityTokenParameters.defaultRequireCancellation, out bootstrapSecurity);
}
static public SecurityBindingElement CreateSecureConversationBindingElement(SecurityBindingElement bootstrapSecurity, bool requireCancellation)
{
return CreateSecureConversationBindingElement(bootstrapSecurity, requireCancellation, null);
}
// If any changes are made to this method, please make sure that they are
// reflected in the corresponding IsSecureConversationBinding() method.
static public SecurityBindingElement CreateSecureConversationBindingElement(SecurityBindingElement bootstrapSecurity, bool requireCancellation, ChannelProtectionRequirements bootstrapProtectionRequirements)
{
if (bootstrapSecurity == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bootstrapBinding");
SecurityBindingElement result;
if (bootstrapSecurity is TransportSecurityBindingElement)
{
// there is no need to do replay detection or key derivation for transport bindings
TransportSecurityBindingElement primary = new TransportSecurityBindingElement();
SecureConversationSecurityTokenParameters scParameters = new SecureConversationSecurityTokenParameters(
bootstrapSecurity,
requireCancellation,
bootstrapProtectionRequirements);
scParameters.RequireDerivedKeys = false;
primary.EndpointSupportingTokenParameters.Endorsing.Add(
scParameters);
primary.LocalClientSettings.DetectReplays = false;
primary.LocalServiceSettings.DetectReplays = false;
primary.IncludeTimestamp = true;
result = primary;
}
else // Symmetric- or AsymmetricSecurityBindingElement
{
SymmetricSecurityBindingElement primary = new SymmetricSecurityBindingElement(
new SecureConversationSecurityTokenParameters(
bootstrapSecurity,
requireCancellation,
bootstrapProtectionRequirements));
// there is no need for signature confirmation on the steady state binding
primary.RequireSignatureConfirmation = false;
result = primary;
}
return result;
}
// this method reverses CreateSecureConversationBindingElement() logic
internal static bool IsSecureConversationBinding(SecurityBindingElement sbe, bool requireCancellation, out SecurityBindingElement bootstrapSecurity)
{
bootstrapSecurity = null;
SymmetricSecurityBindingElement ssbe = sbe as SymmetricSecurityBindingElement;
if (ssbe != null)
{
if (ssbe.RequireSignatureConfirmation)
return false;
SecureConversationSecurityTokenParameters parameters = ssbe.ProtectionTokenParameters as SecureConversationSecurityTokenParameters;
if (parameters == null)
return false;
if (parameters.RequireCancellation != requireCancellation)
return false;
bootstrapSecurity = parameters.BootstrapSecurityBindingElement;
}
else
{
if (!sbe.IncludeTimestamp)
return false;
// do not check local settings: sbe.LocalServiceSettings and sbe.LocalClientSettings
if (!(sbe is TransportSecurityBindingElement))
return false;
SupportingTokenParameters parameters = sbe.EndpointSupportingTokenParameters;
if (parameters.Signed.Count != 0 || parameters.SignedEncrypted.Count != 0 || parameters.Endorsing.Count != 1 || parameters.SignedEndorsing.Count != 0)
return false;
SecureConversationSecurityTokenParameters scParameters = parameters.Endorsing[0] as SecureConversationSecurityTokenParameters;
if (scParameters == null)
return false;
if (scParameters.RequireCancellation != requireCancellation)
return false;
bootstrapSecurity = scParameters.BootstrapSecurityBindingElement;
}
if (bootstrapSecurity != null && bootstrapSecurity.SecurityHeaderLayout != SecurityProtocolFactory.defaultSecurityHeaderLayout)
return false;
return bootstrapSecurity != null;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "{0}:", this.GetType().ToString()));
sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "DefaultAlgorithmSuite: {0}", _defaultAlgorithmSuite.ToString()));
sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "IncludeTimestamp: {0}", _includeTimestamp.ToString()));
sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "KeyEntropyMode: {0}", _keyEntropyMode.ToString()));
sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "MessageSecurityVersion: {0}", this.MessageSecurityVersion.ToString()));
sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "SecurityHeaderLayout: {0}", _securityHeaderLayout.ToString()));
sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "ProtectTokens: {0}", _protectTokens.ToString()));
sb.AppendLine("EndpointSupportingTokenParameters:");
sb.AppendLine(" " + this.EndpointSupportingTokenParameters.ToString().Trim().Replace("\n", "\n "));
sb.AppendLine("OptionalEndpointSupportingTokenParameters:");
sb.AppendLine(" " + this.OptionalEndpointSupportingTokenParameters.ToString().Trim().Replace("\n", "\n "));
if (_operationSupportingTokenParameters.Count == 0)
{
sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "OperationSupportingTokenParameters: none"));
}
else
{
foreach (string requestAction in this.OperationSupportingTokenParameters.Keys)
{
sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "OperationSupportingTokenParameters[\"{0}\"]:", requestAction));
sb.AppendLine(" " + this.OperationSupportingTokenParameters[requestAction].ToString().Trim().Replace("\n", "\n "));
}
}
if (_optionalOperationSupportingTokenParameters.Count == 0)
{
sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "OptionalOperationSupportingTokenParameters: none"));
}
else
{
foreach (string requestAction in this.OptionalOperationSupportingTokenParameters.Keys)
{
sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "OptionalOperationSupportingTokenParameters[\"{0}\"]:", requestAction));
sb.AppendLine(" " + this.OptionalOperationSupportingTokenParameters[requestAction].ToString().Trim().Replace("\n", "\n "));
}
}
return sb.ToString().Trim();
}
internal static ChannelProtectionRequirements ComputeProtectionRequirements(SecurityBindingElement security, BindingParameterCollection parameterCollection, BindingElementCollection bindingElements, bool isForService)
{
if (parameterCollection == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameterCollection");
if (bindingElements == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bindingElements");
if (security == null)
{
return null;
}
ChannelProtectionRequirements result = null;
if ((security is SymmetricSecurityBindingElement) || (security is AsymmetricSecurityBindingElement))
{
result = new ChannelProtectionRequirements();
ChannelProtectionRequirements contractRequirements = parameterCollection.Find<ChannelProtectionRequirements>();
if (contractRequirements != null)
result.Add(contractRequirements);
AddBindingProtectionRequirements(result, bindingElements, !isForService);
}
return result;
}
private static void AddBindingProtectionRequirements(ChannelProtectionRequirements requirements, BindingElementCollection bindingElements, bool isForChannel)
{
// Gather custom requirements from bindingElements
CustomBinding binding = new CustomBinding(bindingElements);
BindingContext context = new BindingContext(binding, new BindingParameterCollection());
// In theory, we can just do
// context.GetInnerProperty<ChannelProtectionRequirements>()
// but that relies on each binding element to correctly union-up its own requirements with
// those of the rest of the stack. So instead, we ask each BE individually, and we do the
// work of combining the results. This protects us against this scenario: someone authors "FooBE"
// with a a GetProperty implementation that always returns null (oops), and puts FooBE on the
// top of the stack, and so FooBE "hides" important protection requirements that inner BEs
// require, resulting in an insecure binding.
foreach (BindingElement bindingElement in bindingElements)
{
if (bindingElement != null)
{
// ask each element individually for its requirements
context.RemainingBindingElements.Clear();
context.RemainingBindingElements.Add(bindingElement);
ChannelProtectionRequirements s = context.GetInnerProperty<ChannelProtectionRequirements>();
if (s != null)
{
//if (isForChannel)
//{
// requirements.Add(s.CreateInverse());
//}
//else
//{
requirements.Add(s);
//}
}
}
}
}
internal override bool IsMatch(BindingElement b)
{
if (b == null)
return false;
SecurityBindingElement security = b as SecurityBindingElement;
if (security == null)
return false;
return System.ServiceModel.Configuration.SecurityElement.AreBindingsMatching(this, security);
}
private static void AddAssertionIfNotNull(PolicyConversionContext policyContext, XmlElement assertion)
{
if (policyContext != null && assertion != null)
{
policyContext.GetBindingAssertions().Add(assertion);
}
}
private static void AddAssertionIfNotNull(PolicyConversionContext policyContext, Collection<XmlElement> assertions)
{
if (policyContext != null && assertions != null)
{
PolicyAssertionCollection existingAssertions = policyContext.GetBindingAssertions();
for (int i = 0; i < assertions.Count; ++i)
existingAssertions.Add(assertions[i]);
}
}
private static void AddAssertionIfNotNull(PolicyConversionContext policyContext, OperationDescription operation, XmlElement assertion)
{
if (policyContext != null && assertion != null)
{
policyContext.GetOperationBindingAssertions(operation).Add(assertion);
}
}
private static void AddAssertionIfNotNull(PolicyConversionContext policyContext, OperationDescription operation, Collection<XmlElement> assertions)
{
if (policyContext != null && assertions != null)
{
PolicyAssertionCollection existingAssertions = policyContext.GetOperationBindingAssertions(operation);
for (int i = 0; i < assertions.Count; ++i)
existingAssertions.Add(assertions[i]);
}
}
private static void AddAssertionIfNotNull(PolicyConversionContext policyContext, MessageDescription message, XmlElement assertion)
{
if (policyContext != null && assertion != null)
{
policyContext.GetMessageBindingAssertions(message).Add(assertion);
}
}
private static void AddAssertionIfNotNull(PolicyConversionContext policyContext, FaultDescription message, XmlElement assertion)
{
if (policyContext != null && assertion != null)
{
policyContext.GetFaultBindingAssertions(message).Add(assertion);
}
}
}
}
|