| File: FrameworkFork\System.ServiceModel\System\ServiceModel\MessageSecurityOverHttp.cs | Web Access |
| Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib) |
// 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. 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; private MessageCredentialType _clientCredentialType; private bool _negotiateServiceCredential; private SecurityAlgorithmSuite _algorithmSuite; private bool _wasAlgorithmSuiteSet; public MessageSecurityOverHttp() { _clientCredentialType = DefaultClientCredentialType; _negotiateServiceCredential = DefaultNegotiateServiceCredential; _algorithmSuite = SecurityAlgorithmSuite.Default; } public MessageCredentialType ClientCredentialType { get { return _clientCredentialType; } set { if (!MessageCredentialTypeHelper.IsDefined(value)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value")); } _clientCredentialType = value; } } public bool NegotiateServiceCredential { get { return _negotiateServiceCredential; } set { _negotiateServiceCredential = value; } } public SecurityAlgorithmSuite AlgorithmSuite { get { return _algorithmSuite; } set { if (value == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); } _algorithmSuite = value; _wasAlgorithmSuiteSet = true; } } internal bool WasAlgorithmSuiteSet { get { return _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(SRServiceModel.SecureConversationRequiredByReliableSession)); } SecurityBindingElement result; SecurityBindingElement oneShotSecurity; bool isKerberosSelected = false; bool emitBspAttributes = true; if (isSecureTransportMode) { switch (_clientCredentialType) { case MessageCredentialType.None: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRServiceModel.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: // TODO: IssuedSecurityTokenParameters.CreateInfoCardParameters(new SecurityStandardsManager(new WSSecurityTokenSerializer(emitBspAttributes)), this.algorithmSuite)); oneShotSecurity = SecurityBindingElement.CreateIssuedTokenOverTransportBindingElement(null); 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 (_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(null, false); // TODO: IssuedSecurityTokenParameters.CreateInfoCardParameters(new SecurityStandardsManager(new WSSecurityTokenSerializer(emitBspAttributes)), this.algorithmSuite), true); break; default: Fx.Assert("unknown ClientCredentialType"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); } } else { switch (_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(null); // TODO: 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 = TimeSpan.Parse("00:15:00", System.Globalization.CultureInfo.InvariantCulture); ; // TODO: 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; } } }