| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel
- {
- using System.Runtime;
- using System.Runtime.CompilerServices;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Security;
- using System.ServiceModel.Security.Tokens;
- using System.ComponentModel;
- public class MessageSecurityOverHttp
- {
- internal const MessageCredentialType DefaultClientCredentialType = MessageCredentialType.Windows;
- internal const bool DefaultNegotiateServiceCredential = true;
- MessageCredentialType clientCredentialType;
- bool negotiateServiceCredential;
- SecurityAlgorithmSuite algorithmSuite;
- bool wasAlgorithmSuiteSet;
- public MessageSecurityOverHttp()
- {
- clientCredentialType = DefaultClientCredentialType;
- negotiateServiceCredential = DefaultNegotiateServiceCredential;
- algorithmSuite = SecurityAlgorithmSuite.Default;
- }
- public MessageCredentialType ClientCredentialType
- {
- get { return this.clientCredentialType; }
- set
- {
- if (!MessageCredentialTypeHelper.IsDefined(value))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
- }
- this.clientCredentialType = value;
- }
- }
- public bool NegotiateServiceCredential
- {
- get { return this.negotiateServiceCredential; }
- set { this.negotiateServiceCredential = value; }
- }
- public SecurityAlgorithmSuite AlgorithmSuite
- {
- get { return this.algorithmSuite; }
- set
- {
- if (value == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
- }
- this.algorithmSuite = value;
- wasAlgorithmSuiteSet = true;
- }
- }
- internal bool WasAlgorithmSuiteSet
- {
- get { return this.wasAlgorithmSuiteSet; }
- }
- protected virtual bool IsSecureConversationEnabled()
- {
- return true;
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- internal SecurityBindingElement CreateSecurityBindingElement(bool isSecureTransportMode, bool isReliableSession, MessageSecurityVersion version)
- {
- if (isReliableSession && !this.IsSecureConversationEnabled())
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SecureConversationRequiredByReliableSession)));
- }
- SecurityBindingElement result;
- SecurityBindingElement oneShotSecurity;
- bool isKerberosSelected = false;
- bool emitBspAttributes = true;
- if (isSecureTransportMode)
- {
- switch (this.clientCredentialType)
- {
- case MessageCredentialType.None:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ClientCredentialTypeMustBeSpecifiedForMixedMode)));
- case MessageCredentialType.UserName:
- oneShotSecurity = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
- break;
- case MessageCredentialType.Certificate:
- oneShotSecurity = SecurityBindingElement.CreateCertificateOverTransportBindingElement();
- break;
- case MessageCredentialType.Windows:
- oneShotSecurity = SecurityBindingElement.CreateSspiNegotiationOverTransportBindingElement(true);
- break;
- case MessageCredentialType.IssuedToken:
- oneShotSecurity = SecurityBindingElement.CreateIssuedTokenOverTransportBindingElement(IssuedSecurityTokenParameters.CreateInfoCardParameters(new SecurityStandardsManager(new WSSecurityTokenSerializer(emitBspAttributes)), this.algorithmSuite));
- break;
- default:
- Fx.Assert("unknown ClientCredentialType");
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
- }
- if (this.IsSecureConversationEnabled())
- {
- result = SecurityBindingElement.CreateSecureConversationBindingElement(oneShotSecurity, true);
- }
- else
- {
- result = oneShotSecurity;
- }
- }
- else
- {
- if (negotiateServiceCredential)
- {
- switch (this.clientCredentialType)
- {
- case MessageCredentialType.None:
- oneShotSecurity = SecurityBindingElement.CreateSslNegotiationBindingElement(false, true);
- break;
- case MessageCredentialType.UserName:
- oneShotSecurity = SecurityBindingElement.CreateUserNameForSslBindingElement(true);
- break;
- case MessageCredentialType.Certificate:
- oneShotSecurity = SecurityBindingElement.CreateSslNegotiationBindingElement(true, true);
- break;
- case MessageCredentialType.Windows:
- oneShotSecurity = SecurityBindingElement.CreateSspiNegotiationBindingElement(true);
- break;
- case MessageCredentialType.IssuedToken:
- oneShotSecurity = SecurityBindingElement.CreateIssuedTokenForSslBindingElement(IssuedSecurityTokenParameters.CreateInfoCardParameters(new SecurityStandardsManager(new WSSecurityTokenSerializer(emitBspAttributes)), this.algorithmSuite), true);
- break;
- default:
- Fx.Assert("unknown ClientCredentialType");
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
- }
- }
- else
- {
- switch (this.clientCredentialType)
- {
- case MessageCredentialType.None:
- oneShotSecurity = SecurityBindingElement.CreateAnonymousForCertificateBindingElement();
- break;
- case MessageCredentialType.UserName:
- oneShotSecurity = SecurityBindingElement.CreateUserNameForCertificateBindingElement();
- break;
- case MessageCredentialType.Certificate:
- oneShotSecurity = SecurityBindingElement.CreateMutualCertificateBindingElement();
- break;
- case MessageCredentialType.Windows:
- oneShotSecurity = SecurityBindingElement.CreateKerberosBindingElement();
- isKerberosSelected = true;
- break;
- case MessageCredentialType.IssuedToken:
- oneShotSecurity = SecurityBindingElement.CreateIssuedTokenForCertificateBindingElement(IssuedSecurityTokenParameters.CreateInfoCardParameters(new SecurityStandardsManager(new WSSecurityTokenSerializer(emitBspAttributes)), this.algorithmSuite));
- break;
- default:
- Fx.Assert("unknown ClientCredentialType");
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
- }
- }
- if (this.IsSecureConversationEnabled())
- {
- result = SecurityBindingElement.CreateSecureConversationBindingElement(oneShotSecurity, true);
- }
- else
- {
- result = oneShotSecurity;
- }
- }
- // set the algorithm suite and issued token params if required
- if (wasAlgorithmSuiteSet || (!isKerberosSelected))
- {
- result.DefaultAlgorithmSuite = oneShotSecurity.DefaultAlgorithmSuite = this.AlgorithmSuite;
- }
- else if (isKerberosSelected)
- {
- result.DefaultAlgorithmSuite = oneShotSecurity.DefaultAlgorithmSuite = SecurityAlgorithmSuite.KerberosDefault;
- }
- result.IncludeTimestamp = true;
- oneShotSecurity.MessageSecurityVersion = version;
- result.MessageSecurityVersion = version;
- if (!isReliableSession)
- {
- result.LocalServiceSettings.ReconnectTransportOnFailure = false;
- result.LocalClientSettings.ReconnectTransportOnFailure = false;
- }
- else
- {
- result.LocalServiceSettings.ReconnectTransportOnFailure = true;
- result.LocalClientSettings.ReconnectTransportOnFailure = true;
- }
- if (this.IsSecureConversationEnabled())
- {
- // issue the transition SCT for a short duration only
- oneShotSecurity.LocalServiceSettings.IssuedCookieLifetime = SpnegoTokenAuthenticator.defaultServerIssuedTransitionTokenLifetime;
- }
- return result;
- }
- internal static bool TryCreate<TSecurity>(SecurityBindingElement sbe, bool isSecureTransportMode, bool isReliableSession, out TSecurity messageSecurity)
- where TSecurity : MessageSecurityOverHttp
- {
- Fx.Assert(null != sbe, string.Empty);
- messageSecurity = null;
- // do not check local settings: sbe.LocalServiceSettings and sbe.LocalClientSettings
- if (!sbe.IncludeTimestamp)
- {
- return false;
- }
- // Do not check MessageSecurityVersion: it maybe changed by the wrapper element and gets checked later in the SecuritySection.AreBindingsMatching()
- if (sbe.SecurityHeaderLayout != SecurityProtocolFactory.defaultSecurityHeaderLayout)
- {
- return false;
- }
- bool negotiateServiceCredential = DefaultNegotiateServiceCredential;
- MessageCredentialType clientCredentialType;
- SecurityAlgorithmSuite algorithmSuite = SecurityAlgorithmSuite.Default;
- bool isSecureConversation;
- SecurityBindingElement bootstrapSecurity;
- if (!SecurityBindingElement.IsSecureConversationBinding(sbe, true, out bootstrapSecurity))
- {
- isSecureConversation = false;
- bootstrapSecurity = sbe;
- }
- else
- {
- isSecureConversation = true;
- }
- if (!isSecureConversation && typeof(TSecurity).Equals(typeof(MessageSecurityOverHttp)))
- {
- return false;
- }
- if (!isSecureConversation && isReliableSession)
- {
- return false;
- }
- if (isSecureTransportMode && !(bootstrapSecurity is TransportSecurityBindingElement))
- {
- return false;
- }
- IssuedSecurityTokenParameters infocardParameters;
- if (isSecureTransportMode)
- {
- if (SecurityBindingElement.IsUserNameOverTransportBinding(bootstrapSecurity))
- {
- clientCredentialType = MessageCredentialType.UserName;
- }
- else if (SecurityBindingElement.IsCertificateOverTransportBinding(bootstrapSecurity))
- {
- clientCredentialType = MessageCredentialType.Certificate;
- }
- else if (SecurityBindingElement.IsSspiNegotiationOverTransportBinding(bootstrapSecurity, true))
- {
- clientCredentialType = MessageCredentialType.Windows;
- }
- else if (SecurityBindingElement.IsIssuedTokenOverTransportBinding(bootstrapSecurity, out infocardParameters))
- {
- if (!IssuedSecurityTokenParameters.IsInfoCardParameters(
- infocardParameters,
- new SecurityStandardsManager(
- sbe.MessageSecurityVersion,
- new WSSecurityTokenSerializer(
- sbe.MessageSecurityVersion.SecurityVersion,
- sbe.MessageSecurityVersion.TrustVersion,
- sbe.MessageSecurityVersion.SecureConversationVersion,
- true,
- null, null, null))))
- {
- return false;
- }
- clientCredentialType = MessageCredentialType.IssuedToken;
- }
- else
- {
- // the standard binding does not support None client credential type in mixed mode
- return false;
- }
- }
- else
- {
- if (SecurityBindingElement.IsSslNegotiationBinding(bootstrapSecurity, false, true))
- {
- negotiateServiceCredential = true;
- clientCredentialType = MessageCredentialType.None;
- }
- else if (SecurityBindingElement.IsUserNameForSslBinding(bootstrapSecurity, true))
- {
- negotiateServiceCredential = true;
- clientCredentialType = MessageCredentialType.UserName;
- }
- else if (SecurityBindingElement.IsSslNegotiationBinding(bootstrapSecurity, true, true))
- {
- negotiateServiceCredential = true;
- clientCredentialType = MessageCredentialType.Certificate;
- }
- else if (SecurityBindingElement.IsSspiNegotiationBinding(bootstrapSecurity, true))
- {
- negotiateServiceCredential = true;
- clientCredentialType = MessageCredentialType.Windows;
- }
- else if (SecurityBindingElement.IsIssuedTokenForSslBinding(bootstrapSecurity, true, out infocardParameters))
- {
- if (!IssuedSecurityTokenParameters.IsInfoCardParameters(
- infocardParameters,
- new SecurityStandardsManager(
- sbe.MessageSecurityVersion,
- new WSSecurityTokenSerializer(
- sbe.MessageSecurityVersion.SecurityVersion,
- sbe.MessageSecurityVersion.TrustVersion,
- sbe.MessageSecurityVersion.SecureConversationVersion,
- true,
- null, null, null))))
- {
- return false;
- }
- negotiateServiceCredential = true;
- clientCredentialType = MessageCredentialType.IssuedToken;
- }
- else if (SecurityBindingElement.IsUserNameForCertificateBinding(bootstrapSecurity))
- {
- negotiateServiceCredential = false;
- clientCredentialType = MessageCredentialType.UserName;
- }
- else if (SecurityBindingElement.IsMutualCertificateBinding(bootstrapSecurity))
- {
- negotiateServiceCredential = false;
- clientCredentialType = MessageCredentialType.Certificate;
- }
- else if (SecurityBindingElement.IsKerberosBinding(bootstrapSecurity))
- {
- negotiateServiceCredential = false;
- clientCredentialType = MessageCredentialType.Windows;
- }
- else if (SecurityBindingElement.IsIssuedTokenForCertificateBinding(bootstrapSecurity, out infocardParameters))
- {
- if (!IssuedSecurityTokenParameters.IsInfoCardParameters(
- infocardParameters,
- new SecurityStandardsManager(
- sbe.MessageSecurityVersion,
- new WSSecurityTokenSerializer(
- sbe.MessageSecurityVersion.SecurityVersion,
- sbe.MessageSecurityVersion.TrustVersion,
- sbe.MessageSecurityVersion.SecureConversationVersion,
- true,
- null, null, null))))
- {
- return false;
- }
- negotiateServiceCredential = false;
- clientCredentialType = MessageCredentialType.IssuedToken;
- }
- else if (SecurityBindingElement.IsAnonymousForCertificateBinding(bootstrapSecurity))
- {
- negotiateServiceCredential = false;
- clientCredentialType = MessageCredentialType.None;
- }
- else
- {
- return false;
- }
- }
- // Do not check any Local* settings
- // Do not check DefaultAlgorithmSuite: is it often changed after the Security element is created, it will verified by SecuritySectionBase.AreBindingsMatching().
- if (typeof(NonDualMessageSecurityOverHttp).Equals(typeof(TSecurity)))
- {
- messageSecurity = (TSecurity)(object)new NonDualMessageSecurityOverHttp();
- ((NonDualMessageSecurityOverHttp)(object)messageSecurity).EstablishSecurityContext = isSecureConversation;
- }
- else
- {
- messageSecurity = (TSecurity)(object)new MessageSecurityOverHttp();
- }
- messageSecurity.ClientCredentialType = clientCredentialType;
- messageSecurity.NegotiateServiceCredential = negotiateServiceCredential;
- messageSecurity.AlgorithmSuite = sbe.DefaultAlgorithmSuite;
- return true;
- }
- internal bool InternalShouldSerialize()
- {
- return this.ShouldSerializeAlgorithmSuite()
- || this.ShouldSerializeClientCredentialType()
- || ShouldSerializeNegotiateServiceCredential();
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool ShouldSerializeAlgorithmSuite()
- {
- return this.AlgorithmSuite != SecurityAlgorithmSuite.Default;
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool ShouldSerializeClientCredentialType()
- {
- return this.ClientCredentialType != DefaultClientCredentialType;
- }
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool ShouldSerializeNegotiateServiceCredential()
- {
- return this.NegotiateServiceCredential != DefaultNegotiateServiceCredential;
- }
- }
- }
|