diff --git a/eng/build.ps1 b/eng/build.ps1 index 3c3f6e74730..c599d160ff2 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -143,6 +143,7 @@ foreach ($argument in $PSBoundParameters.Keys) "allconfigurations" { $arguments += " /p:BuildAllConfigurations=true" } "arch" { $arguments += " /p:ArchGroup=$($PSBoundParameters[$argument]) /p:TargetArchitecture=$($PSBoundParameters[$argument])" } "properties" { $arguments += " " + $properties } + "testscope" { if ($testscope -eq "outerloop" -or $testscope -eq "all") { $arguments += " /p:IntegrationTest=true" }} default { $arguments += " /p:$argument=$($PSBoundParameters[$argument])" } } } diff --git a/src/System.Private.ServiceModel/src/Resources/Strings.resx b/src/System.Private.ServiceModel/src/Resources/Strings.resx index 09d15d6449e..34dcff2a7d3 100644 --- a/src/System.Private.ServiceModel/src/Resources/Strings.resx +++ b/src/System.Private.ServiceModel/src/Resources/Strings.resx @@ -2499,4 +2499,13 @@ BasicHttp binding requires that BasicHttpBinding.Security.Message.ClientCredentialType be equivalent to the BasicHttpMessageCredentialType.Certificate credential type for secure messages. Select Transport or TransportWithMessageCredential security for UserName credentials. - \ No newline at end of file + + The SecurityContextSecurityToken does not have a cookie. + + + The SecurityContextSecurityToken does not have a context-id. + + + The SecurityContextSecurityToken with context-id={0} (key generation-id={1}) is not registered. + + diff --git a/src/System.Private.ServiceModel/src/System.Private.ServiceModel.sln b/src/System.Private.ServiceModel/src/System.Private.ServiceModel.sln index 33921b6f539..15d7643e0e1 100644 --- a/src/System.Private.ServiceModel/src/System.Private.ServiceModel.sln +++ b/src/System.Private.ServiceModel/src/System.Private.ServiceModel.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.329 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29806.167 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Private.ServiceModel", "System.Private.ServiceModel.csproj", "{9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.ServiceModel", "System.Private.ServiceModel.csproj", "{9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,18 +15,18 @@ Global uap-Windows_NT-Release|Any CPU = uap-Windows_NT-Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Unix-Debug|Any CPU.ActiveCfg = netstandard-Unix-Debug|Any CPU - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Unix-Debug|Any CPU.Build.0 = netstandard-Unix-Debug|Any CPU - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Unix-Release|Any CPU.ActiveCfg = netstandard-Unix-Release|Any CPU - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Unix-Release|Any CPU.Build.0 = netstandard-Unix-Release|Any CPU - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Windows_NT-Debug|Any CPU.ActiveCfg = netstandard-Windows_NT-Debug|Any CPU - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Windows_NT-Debug|Any CPU.Build.0 = netstandard-Windows_NT-Debug|Any CPU - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Windows_NT-Release|Any CPU.ActiveCfg = netstandard-Windows_NT-Release|Any CPU - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Windows_NT-Release|Any CPU.Build.0 = netstandard-Windows_NT-Release|Any CPU - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.uap-Windows_NT-Debug|Any CPU.ActiveCfg = uap-Windows_NT-Debug|Any CPU - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.uap-Windows_NT-Debug|Any CPU.Build.0 = uap-Windows_NT-Debug|Any CPU - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.uap-Windows_NT-Release|Any CPU.ActiveCfg = uap-Windows_NT-Release|Any CPU - {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.uap-Windows_NT-Release|Any CPU.Build.0 = uap-Windows_NT-Release|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Unix-Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Unix-Debug|Any CPU.Build.0 = Debug|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Unix-Release|Any CPU.ActiveCfg = Release|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Unix-Release|Any CPU.Build.0 = Release|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Windows_NT-Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Windows_NT-Debug|Any CPU.Build.0 = Debug|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Windows_NT-Release|Any CPU.ActiveCfg = Release|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.netstandard-Windows_NT-Release|Any CPU.Build.0 = Release|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.uap-Windows_NT-Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.uap-Windows_NT-Debug|Any CPU.Build.0 = Debug|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.uap-Windows_NT-Release|Any CPU.ActiveCfg = Release|Any CPU + {9E50E7BF-CD6E-4269-A6DD-59FD0BD6C0FD}.uap-Windows_NT-Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/SctClaimDictionary.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/SctClaimDictionary.cs new file mode 100644 index 00000000000..c750303227a --- /dev/null +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/SctClaimDictionary.cs @@ -0,0 +1,169 @@ +// 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.Xml; + +namespace System.ServiceModel.Security +{ + sealed class SctClaimDictionary : XmlDictionary + { + private SctClaimDictionary() + { + SecurityContextSecurityToken = Add("SecurityContextSecurityToken"); + Version = Add("Version"); + ContextId = Add("ContextId"); + Id = Add("Id"); + Key = Add("Key"); + IsCookieMode = Add("IsCookieMode"); + ServiceContractId = Add("ServiceContractId"); + EffectiveTime = Add("EffectiveTime"); + ExpiryTime = Add("ExpiryTime"); + KeyGeneration = Add("KeyGeneration"); + KeyEffectiveTime = Add("KeyEffectiveTime"); + KeyExpiryTime = Add("KeyExpiryTime"); + Claim = Add("Claim"); + ClaimSets = Add("ClaimSets"); + ClaimSet = Add("ClaimSet"); + Identities = Add("Identities"); + PrimaryIdentity = Add("PrimaryIdentity"); + PrimaryIssuer = Add("PrimaryIssuer"); + + X509CertificateClaimSet = Add("X509CertificateClaimSet"); + SystemClaimSet = Add("SystemClaimSet"); + WindowsClaimSet = Add("WindowsClaimSet"); + AnonymousClaimSet = Add("AnonymousClaimSet"); + + BinaryClaim = Add("BinaryClaim"); + DnsClaim = Add("DnsClaim"); + GenericIdentity = Add("GenericIdentity"); + AuthenticationType = Add("AuthenticationType"); + Right = Add("Right"); + HashClaim = Add("HashClaim"); + MailAddressClaim = Add("MailAddressClaim"); + NameClaim = Add("NameClaim"); + RsaClaim = Add("RsaClaim"); + SpnClaim = Add("SpnClaim"); + SystemClaim = Add("SystemClaim"); + UpnClaim = Add("UpnClaim"); + UrlClaim = Add("UrlClaim"); + WindowsSidClaim = Add("WindowsSidClaim"); + DenyOnlySidClaim = Add("DenyOnlySidClaim"); + WindowsSidIdentity = Add("WindowsSidIdentity"); + X500DistinguishedNameClaim = Add("X500DistinguishedClaim"); + X509ThumbprintClaim = Add("X509ThumbprintClaim"); + + Name = Add("Name"); + Sid = Add("Sid"); + Value = Add("Value"); + NullValue = Add("Null"); + GenericXmlSecurityToken = Add("GenericXmlSecurityToken"); + TokenType = Add("TokenType"); + InternalTokenReference = Add("InternalTokenReference"); + ExternalTokenReference = Add("ExternalTokenReference"); + TokenXml = Add("TokenXml"); + EmptyString = Add(string.Empty); + } + + public static SctClaimDictionary Instance { get; } = new SctClaimDictionary(); + + public XmlDictionaryString Claim { get; } + + public XmlDictionaryString ClaimSets { get; } + + public XmlDictionaryString ClaimSet { get; } + + public XmlDictionaryString PrimaryIssuer { get; } + + public XmlDictionaryString Identities { get; } + + public XmlDictionaryString PrimaryIdentity { get; } + + public XmlDictionaryString X509CertificateClaimSet { get; } + + public XmlDictionaryString SystemClaimSet { get; } + + public XmlDictionaryString WindowsClaimSet { get; } + + public XmlDictionaryString AnonymousClaimSet { get; } + + public XmlDictionaryString ContextId { get; } + + public XmlDictionaryString BinaryClaim { get; } + + public XmlDictionaryString DnsClaim { get; } + + public XmlDictionaryString GenericIdentity { get; } + + public XmlDictionaryString AuthenticationType { get; } + + public XmlDictionaryString Right { get; } + + public XmlDictionaryString HashClaim { get; } + + public XmlDictionaryString MailAddressClaim { get; } + + public XmlDictionaryString NameClaim { get; } + + public XmlDictionaryString RsaClaim { get; } + + public XmlDictionaryString SpnClaim { get; } + + public XmlDictionaryString SystemClaim { get; } + + public XmlDictionaryString UpnClaim { get; } + + public XmlDictionaryString UrlClaim { get; } + + public XmlDictionaryString WindowsSidClaim { get; } + + public XmlDictionaryString DenyOnlySidClaim { get; } + + public XmlDictionaryString WindowsSidIdentity { get; } + + public XmlDictionaryString X500DistinguishedNameClaim { get; } + + public XmlDictionaryString X509ThumbprintClaim { get; } + + public XmlDictionaryString EffectiveTime { get; } + + public XmlDictionaryString ExpiryTime { get; } + + public XmlDictionaryString Id { get; } + + public XmlDictionaryString IsCookieMode { get; } + + public XmlDictionaryString Key { get; } + + public XmlDictionaryString Sid { get; } + + public XmlDictionaryString Name { get; } + + public XmlDictionaryString NullValue { get; } + + public XmlDictionaryString SecurityContextSecurityToken { get; } + + public XmlDictionaryString ServiceContractId { get; } + + public XmlDictionaryString Value { get; } + + public XmlDictionaryString Version { get; } + + public XmlDictionaryString GenericXmlSecurityToken { get; } + + public XmlDictionaryString TokenType { get; } + + public XmlDictionaryString TokenXml { get; } + + public XmlDictionaryString InternalTokenReference { get; } + + public XmlDictionaryString ExternalTokenReference { get; } + + public XmlDictionaryString EmptyString { get; } + + public XmlDictionaryString KeyGeneration { get; } + + public XmlDictionaryString KeyEffectiveTime { get; } + + public XmlDictionaryString KeyExpiryTime { get; } + } +} diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/SecurityStandardsManager.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/SecurityStandardsManager.cs index d1a6790a7e4..6b1c74eb504 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/SecurityStandardsManager.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/SecurityStandardsManager.cs @@ -35,7 +35,7 @@ public SecurityStandardsManager(MessageSecurityVersion messageSecurityVersion, S _tokenSerializer = tokenSerializer ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(tokenSerializer)); if (messageSecurityVersion.SecureConversationVersion == SecureConversationVersion.WSSecureConversation13) { - throw ExceptionHelper.PlatformNotSupported(); + SecureConversationDriver = new WSSecureConversationDec2005.DriverDec2005(); } else { @@ -55,7 +55,7 @@ public SecurityStandardsManager(MessageSecurityVersion messageSecurityVersion, S TrustDriver = null; if (messageSecurityVersion.MessageSecurityTokenVersion.TrustVersion == TrustVersion.WSTrust13) { - throw ExceptionHelper.PlatformNotSupported(); + TrustDriver = new WSTrustDec2005.DriverDec2005(this); } else { diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/ISecurityContextSecurityTokenCache.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/ISecurityContextSecurityTokenCache.cs index 2f6c8043f41..c8ef7d29bbf 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/ISecurityContextSecurityTokenCache.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/ISecurityContextSecurityTokenCache.cs @@ -8,7 +8,7 @@ namespace System.ServiceModel.Security.Tokens { - public interface ISecurityContextSecurityTokenCache + internal interface ISecurityContextSecurityTokenCache { void AddContext(SecurityContextSecurityToken token); bool TryAddContext(SecurityContextSecurityToken token); diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/IssuedSecurityTokenParameters.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/IssuedSecurityTokenParameters.cs index 9f3ac63b9a2..c5c2098efd2 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/IssuedSecurityTokenParameters.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/IssuedSecurityTokenParameters.cs @@ -101,11 +101,6 @@ public SecurityKeyType KeyType set { SecurityKeyTypeHelper.Validate(value); - if(value == SecurityKeyType.BearerKey) - { - throw ExceptionHelper.PlatformNotSupported(); - } - _keyType = value; } } diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/SecurityContextCookieSerializer.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/SecurityContextCookieSerializer.cs deleted file mode 100644 index 58f72848be8..00000000000 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/SecurityContextCookieSerializer.cs +++ /dev/null @@ -1,35 +0,0 @@ -// 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.Collections.Generic; -using System.Collections.ObjectModel; -using System.IdentityModel.Policy; -using System.Xml; -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace System.ServiceModel.Security.Tokens -{ - internal struct SecurityContextCookieSerializer - { - private const int SupportedPersistanceVersion = 1; - - private SecurityStateEncoder _securityStateEncoder; - private IList _knownTypes; - - public SecurityContextCookieSerializer(SecurityStateEncoder securityStateEncoder, IList knownTypes) - { - _securityStateEncoder = securityStateEncoder ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(securityStateEncoder)); - _knownTypes = knownTypes ?? new List(); - } - - public byte[] CreateCookieFromSecurityContext(UniqueId contextId, string id, byte[] key, DateTime tokenEffectiveTime, - DateTime tokenExpirationTime, UniqueId keyGeneration, DateTime keyEffectiveTime, DateTime keyExpirationTime, - ReadOnlyCollection authorizationPolicies) - { - throw ExceptionHelper.PlatformNotSupported(); - } - } -} diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/SecurityContextSecurityToken.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/SecurityContextSecurityToken.cs index 438f4cc2095..fa4e44548ef 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/SecurityContextSecurityToken.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/SecurityContextSecurityToken.cs @@ -2,7 +2,6 @@ // 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.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; @@ -12,40 +11,17 @@ namespace System.ServiceModel.Security.Tokens { - public class SecurityContextSecurityToken : SecurityToken, TimeBoundedCache.IExpirableItem, IDisposable + internal class SecurityContextSecurityToken : SecurityToken, TimeBoundedCache.IExpirableItem, IDisposable { private UniqueId _keyGeneration = null; private DateTime _tokenEffectiveTime; private DateTime _tokenExpirationTime; private byte[] _key; - private string _keyString; private ReadOnlyCollection _authorizationPolicies; private ReadOnlyCollection _securityKeys; private string _id; private bool _disposed = false; - public SecurityContextSecurityToken(UniqueId contextId, byte[] key, DateTime validFrom, DateTime validTo) - : this(contextId, SecurityUtils.GenerateId(), key, validFrom, validTo) - { } - - public SecurityContextSecurityToken(UniqueId contextId, string id, byte[] key, DateTime validFrom, DateTime validTo) - : this(contextId, id, key, validFrom, validTo, null) - { } - - public SecurityContextSecurityToken(UniqueId contextId, string id, byte[] key, DateTime validFrom, DateTime validTo, ReadOnlyCollection authorizationPolicies) - : base() - { - _id = id; - Initialize(contextId, key, validFrom, validTo, authorizationPolicies, false, null, validFrom, validTo); - } - - public SecurityContextSecurityToken(UniqueId contextId, string id, byte[] key, DateTime validFrom, DateTime validTo, UniqueId keyGeneration, DateTime keyEffectiveTime, DateTime keyExpirationTime, ReadOnlyCollection authorizationPolicies) - : base() - { - _id = id; - Initialize(contextId, key, validFrom, validTo, authorizationPolicies, false, keyGeneration, keyEffectiveTime, keyExpirationTime); - } - internal SecurityContextSecurityToken(SecurityContextSecurityToken sourceToken, string id) : this(sourceToken, id, sourceToken._key, sourceToken._keyGeneration, sourceToken.KeyEffectiveTime, sourceToken.KeyExpirationTime, sourceToken.AuthorizationPolicies) { @@ -60,29 +36,6 @@ internal SecurityContextSecurityToken(SecurityContextSecurityToken sourceToken, BootstrapMessageProperty = (sourceToken.BootstrapMessageProperty == null) ? null : (SecurityMessageProperty)sourceToken.BootstrapMessageProperty.CreateCopy(); } - internal SecurityContextSecurityToken(UniqueId contextId, string id, byte[] key, DateTime validFrom, DateTime validTo, ReadOnlyCollection authorizationPolicies, bool isCookieMode, byte[] cookieBlob) - : this(contextId, id, key, validFrom, validTo, authorizationPolicies, isCookieMode, cookieBlob, null, validFrom, validTo) - { - } - - internal SecurityContextSecurityToken(UniqueId contextId, string id, byte[] key, DateTime validFrom, DateTime validTo, ReadOnlyCollection authorizationPolicies, bool isCookieMode, byte[] cookieBlob, - UniqueId keyGeneration, DateTime keyEffectiveTime, DateTime keyExpirationTime) - : base() - { - _id = id; - Initialize(contextId, key, validFrom, validTo, authorizationPolicies, isCookieMode, keyGeneration, keyEffectiveTime, keyExpirationTime); - CookieBlob = cookieBlob; - } - - private SecurityContextSecurityToken(SecurityContextSecurityToken from) - { - ReadOnlyCollection authorizationPolicies = System.IdentityModel.SecurityUtils.CloneAuthorizationPoliciesIfNecessary(from._authorizationPolicies); - _id = from._id; - Initialize(from.ContextId, from._key, from._tokenEffectiveTime, from._tokenExpirationTime, authorizationPolicies, from.IsCookieMode, from._keyGeneration, from.KeyEffectiveTime, from.KeyExpirationTime); - CookieBlob = from.CookieBlob; - BootstrapMessageProperty = (from.BootstrapMessageProperty == null) ? null : (SecurityMessageProperty)from.BootstrapMessageProperty.CreateCopy(); - } - /// /// Gets or Sets the SecurityMessageProperty extracted from /// the Bootstrap message. This will contain the original tokens @@ -168,22 +121,6 @@ DateTime TimeBoundedCache.IExpirableItem.ExpirationTime } } - internal string GetBase64KeyString() - { - if (_keyString == null) - { - _keyString = Convert.ToBase64String(_key); - } - return _keyString; - } - - internal byte[] GetKeyBytes() - { - byte[] retval = new byte[_key.Length]; - Buffer.BlockCopy(_key, 0, retval, 0, _key.Length); - return retval; - } - public override string ToString() { return String.Format(CultureInfo.CurrentCulture, "SecurityContextSecurityToken(Identifier='{0}', KeyGeneration='{1}')", ContextId, _keyGeneration); @@ -228,31 +165,6 @@ private void Initialize(UniqueId contextId, byte[] key, DateTime validFrom, Date IsCookieMode = isCookieMode; } - public static SecurityContextSecurityToken CreateCookieSecurityContextToken(UniqueId contextId, string id, byte[] key, - DateTime validFrom, DateTime validTo, ReadOnlyCollection authorizationPolicies, SecurityStateEncoder securityStateEncoder) - { - return CreateCookieSecurityContextToken(contextId, id, key, validFrom, validTo, null, validFrom, validTo, authorizationPolicies, securityStateEncoder); - } - - - public static SecurityContextSecurityToken CreateCookieSecurityContextToken(UniqueId contextId, string id, byte[] key, - DateTime validFrom, DateTime validTo, UniqueId keyGeneration, DateTime keyEffectiveTime, - DateTime keyExpirationTime, ReadOnlyCollection authorizationPolicies, SecurityStateEncoder securityStateEncoder) - { - SecurityContextCookieSerializer cookieSerializer = new SecurityContextCookieSerializer(securityStateEncoder, null); - byte[] cookieBlob = cookieSerializer.CreateCookieFromSecurityContext(contextId, id, key, validFrom, validTo, keyGeneration, - keyEffectiveTime, keyExpirationTime, authorizationPolicies); - - return new SecurityContextSecurityToken(contextId, id, key, validFrom, validTo, - authorizationPolicies, true, cookieBlob, keyGeneration, keyEffectiveTime, keyExpirationTime); - } - - internal SecurityContextSecurityToken Clone() - { - ThrowIfDisposed(); - return new SecurityContextSecurityToken(this); - } - public void Dispose() { if (!_disposed) diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/SecurityContextTokenValidationException.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/SecurityContextTokenValidationException.cs new file mode 100644 index 00000000000..663ecda3fa4 --- /dev/null +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/Tokens/SecurityContextTokenValidationException.cs @@ -0,0 +1,33 @@ +// 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.IdentityModel.Tokens; +using System.Runtime.Serialization; + +namespace System.ServiceModel.Security.Tokens +{ + [Serializable] + class SecurityContextTokenValidationException : SecurityTokenValidationException + { + public SecurityContextTokenValidationException() + : base() + { + } + + public SecurityContextTokenValidationException(string message) + : base(message) + { + } + + public SecurityContextTokenValidationException(string message, Exception innerException) + : base(message, innerException) + { + } + + protected SecurityContextTokenValidationException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/TrustDriver.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/TrustDriver.cs index 3339f796d0b..d0a5d248f3b 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/TrustDriver.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/TrustDriver.cs @@ -140,8 +140,5 @@ public abstract GenericXmlSecurityToken GetIssuedToken(RequestSecurityTokenRespo // RSTR Collection method public abstract void WriteRequestSecurityTokenResponseCollection(RequestSecurityTokenResponseCollection rstrCollection, XmlWriter writer); - - // Federation proxy creation - public abstract IChannelFactory CreateFederationProxy(EndpointAddress address, Binding binding, KeyedByTypeCollection channelBehaviors); } } diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecureConversation.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecureConversation.cs index df987e6ae59..ef15f02af4c 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecureConversation.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecureConversation.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; +using System.Runtime; using System.ServiceModel.Security.Tokens; using System.Xml; using TokenEntry = System.ServiceModel.Security.WSSecurityTokenSerializer.TokenEntry; @@ -300,6 +301,209 @@ public override void WriteTokenCore(XmlDictionaryWriter writer, SecurityToken to } } + protected abstract class SecurityContextTokenEntry : TokenEntry + { + public SecurityContextTokenEntry(WSSecureConversation parent, SecurityStateEncoder securityStateEncoder, IList knownClaimTypes) + { + Parent = parent; + } + + protected WSSecureConversation Parent { get; } + + protected override XmlDictionaryString LocalName { get { return Parent.SerializerDictionary.SecurityContextToken; } } + protected override XmlDictionaryString NamespaceUri { get { return Parent.SerializerDictionary.Namespace; } } + protected override Type[] GetTokenTypesCore() { return new Type[] { typeof(SecurityContextSecurityToken) }; } + public override string TokenTypeUri { get { return Parent.SerializerDictionary.SecurityContextTokenType.Value; } } + protected override string ValueTypeUri { get { return null; } } + + public override SecurityKeyIdentifierClause CreateKeyIdentifierClauseFromTokenXmlCore(XmlElement issuedTokenXml, + SecurityTokenReferenceStyle tokenReferenceStyle) + { + + TokenReferenceStyleHelper.Validate(tokenReferenceStyle); + + switch (tokenReferenceStyle) + { + case SecurityTokenReferenceStyle.Internal: + return CreateDirectReference(issuedTokenXml, UtilityStrings.IdAttribute, UtilityStrings.Namespace, typeof(SecurityContextSecurityToken)); + case SecurityTokenReferenceStyle.External: + UniqueId contextId = null; + UniqueId generation = null; + foreach (XmlNode node in issuedTokenXml.ChildNodes) + { + XmlElement element = node as XmlElement; + if (element != null) + { + if (element.LocalName == Parent.SerializerDictionary.Identifier.Value && element.NamespaceURI == Parent.SerializerDictionary.Namespace.Value) + { + contextId = XmlHelper.ReadTextElementAsUniqueId(element); + } + else if (CanReadGeneration(element)) + { + generation = ReadGeneration(element); + } + } + } + return new SecurityContextKeyIdentifierClause(contextId, generation); + default: + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("tokenReferenceStyle")); + } + } + + protected abstract bool CanReadGeneration(XmlDictionaryReader reader); + protected abstract bool CanReadGeneration(XmlElement element); + protected abstract UniqueId ReadGeneration(XmlDictionaryReader reader); + protected abstract UniqueId ReadGeneration(XmlElement element); + + SecurityContextSecurityToken TryResolveSecurityContextToken(UniqueId contextId, UniqueId generation, string id, SecurityTokenResolver tokenResolver, out ISecurityContextSecurityTokenCache sctCache) + { + SecurityContextSecurityToken cachedSct = null; + sctCache = null; + if (tokenResolver is ISecurityContextSecurityTokenCache) + { + sctCache = ((ISecurityContextSecurityTokenCache)tokenResolver); + cachedSct = sctCache.GetContext(contextId, generation); + } + else if (tokenResolver is AggregateSecurityHeaderTokenResolver) + { + // We will see if we have a ISecurityContextSecurityTokenCache in the + // AggregateTokenResolver. We will hold the reference to the first sctCache + // we find. + AggregateSecurityHeaderTokenResolver aggregateTokenResolve = tokenResolver as AggregateSecurityHeaderTokenResolver; + for (int i = 0; i < aggregateTokenResolve.TokenResolvers.Count; ++i) + { + ISecurityContextSecurityTokenCache oobTokenResolver = aggregateTokenResolve.TokenResolvers[i] as ISecurityContextSecurityTokenCache; + if (oobTokenResolver == null) + { + continue; + } + if (sctCache == null) + { + sctCache = oobTokenResolver; + } + cachedSct = oobTokenResolver.GetContext(contextId, generation); + if (cachedSct != null) + { + break; + } + } + } + if (cachedSct == null) + { + return null; + } + else if (cachedSct.Id == id) + { + return cachedSct; + } + else + { + return new SecurityContextSecurityToken(cachedSct, id); + } + } + + public override SecurityToken ReadTokenCore(XmlDictionaryReader reader, SecurityTokenResolver tokenResolver) + { + UniqueId contextId = null; + byte[] encodedCookie = null; + UniqueId generation = null; + bool isCookieMode = false; + + Fx.Assert(reader.NodeType == XmlNodeType.Element, ""); + + // check if there is an id + string id = reader.GetAttribute(XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace); + + SecurityContextSecurityToken sct = null; + + // There needs to be at least a contextId in here. + reader.ReadFullStartElement(); + reader.MoveToStartElement(Parent.SerializerDictionary.Identifier, Parent.SerializerDictionary.Namespace); + contextId = reader.ReadElementContentAsUniqueId(); + if (CanReadGeneration(reader)) + { + generation = ReadGeneration(reader); + } + if (reader.IsStartElement(Parent.SerializerDictionary.Cookie, XD.DotNetSecurityDictionary.Namespace)) + { + isCookieMode = true; + ISecurityContextSecurityTokenCache sctCache; + sct = TryResolveSecurityContextToken(contextId, generation, id, tokenResolver, out sctCache); + if (sct == null) + { + encodedCookie = reader.ReadElementContentAsBase64(); + if (encodedCookie != null) + { + throw new PlatformNotSupportedException(); + // Ultimately depends on ProtectedData which isn't available cross platform + // I believe this is server side only code but too complicated to reason about + // to know for sure. + } + } + else + { + reader.Skip(); + } + } + reader.ReadEndElement(); + + if (contextId == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.NoSecurityContextIdentifier)); + } + + if (sct == null && !isCookieMode) + { + ISecurityContextSecurityTokenCache sctCache; + sct = TryResolveSecurityContextToken(contextId, generation, id, tokenResolver, out sctCache); + } + if (sct == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityContextTokenValidationException(SR.Format(SR.SecurityContextNotRegistered, contextId, generation))); + } + return sct; + } + + protected virtual void WriteGeneration(XmlDictionaryWriter writer, SecurityContextSecurityToken sct) + { + } + + public override void WriteTokenCore(XmlDictionaryWriter writer, SecurityToken token) + { + SecurityContextSecurityToken sct = (token as SecurityContextSecurityToken); + + // serialize the name and any wsu:Id attribute + writer.WriteStartElement(Parent.SerializerDictionary.Prefix.Value, Parent.SerializerDictionary.SecurityContextToken, Parent.SerializerDictionary.Namespace); + if (sct.Id != null) + { + writer.WriteAttributeString(XD.UtilityDictionary.Prefix.Value, XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace, sct.Id); + } + + // serialize the context id + writer.WriteStartElement(Parent.SerializerDictionary.Prefix.Value, Parent.SerializerDictionary.Identifier, Parent.SerializerDictionary.Namespace); + XmlHelper.WriteStringAsUniqueId(writer, sct.ContextId); + writer.WriteEndElement(); + + WriteGeneration(writer, sct); + + // if cookie-mode, then it must have a cookie + if (sct.IsCookieMode) + { + if (sct.CookieBlob == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.NoCookieInSct)); + } + + // if the token has a cookie, write it out + writer.WriteStartElement(XD.DotNetSecurityDictionary.Prefix.Value, Parent.SerializerDictionary.Cookie, XD.DotNetSecurityDictionary.Namespace); + writer.WriteBase64(sct.CookieBlob, 0, sct.CookieBlob.Length); + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + } + } + public abstract class Driver : SecureConversationDriver { public Driver() diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecureConversationDec2005.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecureConversationDec2005.cs new file mode 100644 index 00000000000..6a73cbfd9e7 --- /dev/null +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecureConversationDec2005.cs @@ -0,0 +1,152 @@ +// 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.Collections.Generic; +using System.IdentityModel.Tokens; +using System.ServiceModel.Security.Tokens; +using System.Text; +using System.Xml; + +namespace System.ServiceModel.Security +{ + class WSSecureConversationDec2005 : WSSecureConversation + { + SecurityStateEncoder _securityStateEncoder; + IList _knownClaimTypes; + + public WSSecureConversationDec2005(WSSecurityTokenSerializer tokenSerializer, SecurityStateEncoder securityStateEncoder, IEnumerable knownTypes, + int maxKeyDerivationOffset, int maxKeyDerivationLabelLength, int maxKeyDerivationNonceLength) + : base(tokenSerializer, maxKeyDerivationOffset, maxKeyDerivationLabelLength, maxKeyDerivationNonceLength) + { + if (securityStateEncoder != null) + { + _securityStateEncoder = securityStateEncoder; + } + else + { + //throw new PlatformNotSupportedException(); + //this.securityStateEncoder = new DataProtectionSecurityStateEncoder(); + } + + _knownClaimTypes = new List(); + if (knownTypes != null) + { + // Clone this collection. + foreach (Type knownType in knownTypes) + { + _knownClaimTypes.Add(knownType); + } + } + } + + public override SecureConversationDictionary SerializerDictionary + { + get { return DXD.SecureConversationDec2005Dictionary; } + } + + public override void PopulateTokenEntries(IList tokenEntryList) + { + base.PopulateTokenEntries(tokenEntryList); + tokenEntryList.Add(new SecurityContextTokenEntryDec2005(this, _securityStateEncoder, _knownClaimTypes)); + } + + public override string DerivationAlgorithm + { + get + { + return SecurityAlgorithms.Psha1KeyDerivationDec2005; + } + } + + class SecurityContextTokenEntryDec2005 : SecurityContextTokenEntry + { + public SecurityContextTokenEntryDec2005(WSSecureConversationDec2005 parent, SecurityStateEncoder securityStateEncoder, IList knownClaimTypes) + : base(parent, securityStateEncoder, knownClaimTypes) + { + } + + protected override bool CanReadGeneration(XmlDictionaryReader reader) + { + return reader.IsStartElement(DXD.SecureConversationDec2005Dictionary.Instance, DXD.SecureConversationDec2005Dictionary.Namespace); + } + + protected override bool CanReadGeneration(XmlElement element) + { + return (element.LocalName == DXD.SecureConversationDec2005Dictionary.Instance.Value && + element.NamespaceURI == DXD.SecureConversationDec2005Dictionary.Namespace.Value); + } + + protected override UniqueId ReadGeneration(XmlDictionaryReader reader) + { + return reader.ReadElementContentAsUniqueId(); + } + + protected override UniqueId ReadGeneration(XmlElement element) + { + return XmlHelper.ReadTextElementAsUniqueId(element); + } + + protected override void WriteGeneration(XmlDictionaryWriter writer, SecurityContextSecurityToken sct) + { + // serialize the generation + if (sct.KeyGeneration != null) + { + writer.WriteStartElement(DXD.SecureConversationDec2005Dictionary.Prefix.Value, + DXD.SecureConversationDec2005Dictionary.Instance, + DXD.SecureConversationDec2005Dictionary.Namespace); + XmlHelper.WriteStringAsUniqueId(writer, sct.KeyGeneration); + writer.WriteEndElement(); + } + } + } + + public class DriverDec2005 : Driver + { + public DriverDec2005() + { + } + + protected override SecureConversationDictionary DriverDictionary + { + get { return DXD.SecureConversationDec2005Dictionary; } + } + + public override XmlDictionaryString CloseAction + { + get { return DXD.SecureConversationDec2005Dictionary.RequestSecurityContextClose; } + } + + public override XmlDictionaryString CloseResponseAction + { + get { return DXD.SecureConversationDec2005Dictionary.RequestSecurityContextCloseResponse; } + } + + public override bool IsSessionSupported + { + get { return true; } + } + + public override XmlDictionaryString RenewAction + { + get { return DXD.SecureConversationDec2005Dictionary.RequestSecurityContextRenew; } + } + + public override XmlDictionaryString RenewResponseAction + { + get { return DXD.SecureConversationDec2005Dictionary.RequestSecurityContextRenewResponse; } + } + + public override XmlDictionaryString Namespace + { + get { return DXD.SecureConversationDec2005Dictionary.Namespace; } + } + + public override string TokenTypeUri + { + get { return DXD.SecureConversationDec2005Dictionary.SecurityContextTokenType.Value; } + } + } + } +} diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecureConversationFeb2005.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecureConversationFeb2005.cs index 847f4533923..7e615094079 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecureConversationFeb2005.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecureConversationFeb2005.cs @@ -4,19 +4,33 @@ using System.Collections.Generic; +using System.ServiceModel.Security.Tokens; using System.Xml; namespace System.ServiceModel.Security { internal class WSSecureConversationFeb2005 : WSSecureConversation { + SecurityStateEncoder _securityStateEncoder; + IList _knownClaimTypes; + public WSSecureConversationFeb2005(WSSecurityTokenSerializer tokenSerializer, SecurityStateEncoder securityStateEncoder, IEnumerable knownTypes, int maxKeyDerivationOffset, int maxKeyDerivationLabelLength, int maxKeyDerivationNonceLength) : base(tokenSerializer, maxKeyDerivationOffset, maxKeyDerivationLabelLength, maxKeyDerivationNonceLength) { if (securityStateEncoder != null) { - throw ExceptionHelper.PlatformNotSupported(); + _securityStateEncoder = securityStateEncoder; + } + + _knownClaimTypes = new List(); + if (knownTypes != null) + { + // Clone this collection. + foreach (Type knownType in knownTypes) + { + _knownClaimTypes.Add(knownType); + } } } @@ -25,6 +39,53 @@ public override SecureConversationDictionary SerializerDictionary get { return XD.SecureConversationFeb2005Dictionary; } } + public override void PopulateTokenEntries(IList tokenEntryList) + { + base.PopulateTokenEntries(tokenEntryList); + tokenEntryList.Add(new SecurityContextTokenEntryFeb2005(this, _securityStateEncoder, _knownClaimTypes)); + } + + class SecurityContextTokenEntryFeb2005 : SecurityContextTokenEntry + { + public SecurityContextTokenEntryFeb2005(WSSecureConversationFeb2005 parent, SecurityStateEncoder securityStateEncoder, IList knownClaimTypes) + : base(parent, securityStateEncoder, knownClaimTypes) + { + } + + protected override bool CanReadGeneration(XmlDictionaryReader reader) + { + return reader.IsStartElement(DXD.SecureConversationDec2005Dictionary.Instance, XD.SecureConversationFeb2005Dictionary.Namespace); + } + + protected override bool CanReadGeneration(XmlElement element) + { + return (element.LocalName == DXD.SecureConversationDec2005Dictionary.Instance.Value && + element.NamespaceURI == XD.SecureConversationFeb2005Dictionary.Namespace.Value); + } + + protected override UniqueId ReadGeneration(XmlDictionaryReader reader) + { + return reader.ReadElementContentAsUniqueId(); + } + + protected override UniqueId ReadGeneration(XmlElement element) + { + return XmlHelper.ReadTextElementAsUniqueId(element); + } + + protected override void WriteGeneration(XmlDictionaryWriter writer, SecurityContextSecurityToken sct) + { + // serialize the generation + if (sct.KeyGeneration != null) + { + writer.WriteStartElement(XD.SecureConversationFeb2005Dictionary.Prefix.Value, DXD.SecureConversationDec2005Dictionary.Instance, + XD.SecureConversationFeb2005Dictionary.Namespace); + XmlHelper.WriteStringAsUniqueId(writer, sct.KeyGeneration); + writer.WriteEndElement(); + } + } + } + public class DriverFeb2005 : Driver { public DriverFeb2005() diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecurityTokenSerializer.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecurityTokenSerializer.cs index 3700261a378..eb8a1242cb9 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecurityTokenSerializer.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSSecurityTokenSerializer.cs @@ -98,7 +98,7 @@ public WSSecurityTokenSerializer(SecurityVersion securityVersion, TrustVersion t } else if (secureConversationVersion == SecureConversationVersion.WSSecureConversation13) { - throw new PlatformNotSupportedException(nameof(SecureConversationVersion.WSSecureConversation13)); + _secureConversation = new WSSecureConversationDec2005(this, securityStateEncoder, knownTypes, maximumKeyDerivationOffset, maximumKeyDerivationLabelLength, maximumKeyDerivationNonceLength); } else { @@ -126,7 +126,8 @@ public WSSecurityTokenSerializer(SecurityVersion securityVersion, TrustVersion t } else if (trustVersion == TrustVersion.WSTrust13) { - throw ExceptionHelper.PlatformNotSupported(nameof(TrustVersion.WSTrust13)); + _serializerEntries.Add(new WSTrustDec2005(this)); + trustDictionary = new IdentityModel.TrustDec2005Dictionary(new CollectionDictionary(DXD.TrustDec2005Dictionary.Dec2005DictionaryString)); } else { diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSTrustDec2005.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSTrustDec2005.cs new file mode 100644 index 00000000000..1d16c65e1c4 --- /dev/null +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSTrustDec2005.cs @@ -0,0 +1,65 @@ +// 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.Xml; + +namespace System.ServiceModel.Security +{ + class WSTrustDec2005 : WSTrustFeb2005 + { + public WSTrustDec2005(WSSecurityTokenSerializer tokenSerializer) + : base(tokenSerializer) + { + } + + public override TrustDictionary SerializerDictionary + { + get { return DXD.TrustDec2005Dictionary; } + } + + public class DriverDec2005 : DriverFeb2005 + { + public DriverDec2005(SecurityStandardsManager standardsManager) + : base(standardsManager) + { + } + + public override TrustDictionary DriverDictionary + { + get + { + return DXD.TrustDec2005Dictionary; + } + } + + public override XmlDictionaryString RequestSecurityTokenResponseFinalAction + { + get + { + return DXD.TrustDec2005Dictionary.RequestSecurityTokenCollectionIssuanceFinalResponse; + } + } + + internal virtual bool IsSecondaryParametersElement(XmlElement element) + { + return ((element.LocalName == DXD.TrustDec2005Dictionary.SecondaryParameters.Value) && + (element.NamespaceURI == DXD.TrustDec2005Dictionary.Namespace.Value)); + } + + public virtual XmlElement CreateKeyWrapAlgorithmElement(string keyWrapAlgorithm) + { + if (keyWrapAlgorithm == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(keyWrapAlgorithm)); + } + + XmlDocument doc = new XmlDocument(); + XmlElement result = doc.CreateElement(DXD.TrustDec2005Dictionary.Prefix.Value, DXD.TrustDec2005Dictionary.KeyWrapAlgorithm.Value, + DXD.TrustDec2005Dictionary.Namespace.Value); + result.AppendChild(doc.CreateTextNode(keyWrapAlgorithm)); + return result; + } + } + } +} diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSTrustFeb2005.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSTrustFeb2005.cs index 8b2fea3ce7a..72bf5a12fe5 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSTrustFeb2005.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/WSTrustFeb2005.cs @@ -2,11 +2,7 @@ // 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.Collections.Generic; using System.IdentityModel.Tokens; -using System.ServiceModel.Channels; -using System.ServiceModel.Description; -using System.ServiceModel.Dispatcher; using System.ServiceModel.Security.Tokens; using System.Xml; @@ -220,116 +216,6 @@ protected override void WriteTargets(RequestSecurityToken rst, XmlDictionaryWrit writer.WriteEndElement(); } } - - // this is now the abstract in WSTrust - public override IChannelFactory CreateFederationProxy(EndpointAddress address, Binding binding, KeyedByTypeCollection channelBehaviors) - { - if (channelBehaviors == null) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(channelBehaviors)); - } - - ChannelFactory result = new ChannelFactory(binding, address); - SetProtectionLevelForFederation(result.Endpoint.Contract.Operations); - // remove the default client credentials that gets added to channel factories - result.Endpoint.Behaviors.Remove(); - for (int i = 0; i < channelBehaviors.Count; ++i) - { - result.Endpoint.Behaviors.Add(channelBehaviors[i]); - } - // add a behavior that removes the UI channel initializer added by the client credentials since there should be no UI - // initializer popped up as part of obtaining the federation token (the UI should already have been popped up for the main channel) - result.Endpoint.Behaviors.Add(new InteractiveInitializersRemovingBehavior()); - - return new RequestChannelFactory(result); - } - - [ServiceContract] - internal interface IWsTrustFeb2005SecurityTokenService - { - [OperationContract(IsOneWay = false, - Action = TrustFeb2005Strings.RequestSecurityTokenIssuance, - ReplyAction = TrustFeb2005Strings.RequestSecurityTokenIssuanceResponse)] - [FaultContract(typeof(string), Action = "*", ProtectionLevel = System.Net.Security.ProtectionLevel.Sign)] - Message RequestToken(Message message); - } - - public class InteractiveInitializersRemovingBehavior : IEndpointBehavior - { - public void Validate(ServiceEndpoint serviceEndpoint) { } - public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters) { } - public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher) { } - public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior) - { - // it is very unlikely that InteractiveChannelInitializers will be null, this is defensive in case ClientRuntime every has a - // bug. I am OK with this as ApplyingClientBehavior is a one-time channel setup. - if (behavior != null && behavior.InteractiveChannelInitializers != null) - { - // clear away any interactive initializer - behavior.InteractiveChannelInitializers.Clear(); - } - } - } - - public class RequestChannelFactory : ChannelFactoryBase, IChannelFactory - { - private ChannelFactory _innerChannelFactory; - - public RequestChannelFactory(ChannelFactory innerChannelFactory) - { - _innerChannelFactory = innerChannelFactory; - } - - public IRequestChannel CreateChannel(EndpointAddress address) - { - return _innerChannelFactory.CreateChannel(address); - } - - public IRequestChannel CreateChannel(EndpointAddress address, Uri via) - { - return _innerChannelFactory.CreateChannel(address, via); - } - - protected override void OnAbort() - { - _innerChannelFactory.Abort(); - } - - protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) - { - return _innerChannelFactory.BeginOpen(timeout, callback, state); - } - - protected override void OnEndOpen(IAsyncResult result) - { - _innerChannelFactory.EndOpen(result); - } - - protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) - { - return _innerChannelFactory.BeginClose(timeout, callback, state); - } - - protected override void OnEndClose(IAsyncResult result) - { - _innerChannelFactory.EndClose(result); - } - - protected override void OnClose(TimeSpan timeout) - { - _innerChannelFactory.Close(timeout); - } - - protected override void OnOpen(TimeSpan timeout) - { - _innerChannelFactory.Open(timeout); - } - - public override T GetProperty() - { - return _innerChannelFactory.GetProperty(); - } - } } } } diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/XmlHelper.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/XmlHelper.cs index af59da17f3f..fa77b3f1d78 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/Security/XmlHelper.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Security/XmlHelper.cs @@ -409,5 +409,10 @@ static public UniqueId ReadElementStringAsUniqueId(XmlDictionaryReader reader) reader.ReadEndElement(); return id; } + + static public UniqueId ReadTextElementAsUniqueId(XmlElement element) + { + return new UniqueId(ReadTextElementAsTrimmedString(element)); + } } } diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/WS2007HttpBinding.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/WS2007HttpBinding.cs new file mode 100644 index 00000000000..8f65df1bc53 --- /dev/null +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/WS2007HttpBinding.cs @@ -0,0 +1,40 @@ +// 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.ServiceModel.Channels; + +namespace System.ServiceModel +{ + public class WS2007HttpBinding : WSHttpBinding + { + static readonly MessageSecurityVersion WS2007MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10; + + public WS2007HttpBinding() + : base() + { + HttpsTransport.MessageSecurityVersion = WS2007MessageSecurityVersion; + } + + public WS2007HttpBinding(SecurityMode securityMode) + : this(securityMode, false) + { + } + + public WS2007HttpBinding(SecurityMode securityMode, bool reliableSessionEnabled) + : base(securityMode, reliableSessionEnabled) + { + HttpsTransport.MessageSecurityVersion = WS2007MessageSecurityVersion; + } + + internal WS2007HttpBinding(WSHttpSecurity security, bool reliableSessionEnabled) + : base(security, reliableSessionEnabled) + { + HttpsTransport.MessageSecurityVersion = WS2007MessageSecurityVersion; + } + + protected override SecurityBindingElement CreateMessageSecurity() + { + return Security.CreateMessageSecurity(false, WS2007MessageSecurityVersion); + } + } +} diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/XD.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/XD.cs index 60a263fedd8..6042902f3c4 100644 --- a/src/System.Private.ServiceModel/src/System/ServiceModel/XD.cs +++ b/src/System.Private.ServiceModel/src/System/ServiceModel/XD.cs @@ -19,6 +19,7 @@ internal static class XD private static Addressing10Dictionary s_addressing10Dictionary; private static Addressing200408Dictionary s_addressing200408Dictionary; private static AddressingNoneDictionary s_addressingNoneDictionary; + private static DotNetSecurityDictionary s_dotNetSecurityDictionary; private static MessageDictionary s_messageDictionary; private static Message11Dictionary s_message11Dictionary; private static Message12Dictionary s_message12Dictionary; @@ -95,6 +96,16 @@ static public AddressingNoneDictionary AddressingNoneDictionary } } + static public DotNetSecurityDictionary DotNetSecurityDictionary + { + get + { + if (s_dotNetSecurityDictionary == null) + s_dotNetSecurityDictionary = new DotNetSecurityDictionary(Dictionary); + return s_dotNetSecurityDictionary; + } + } + static public MessageDictionary MessageDictionary { get @@ -1070,6 +1081,18 @@ internal static class DotNetSecurityStrings public const string SecureConversationCancelNotAllowedFault = "SecureConversationCancellationNotAllowed"; } + class DotNetSecurityDictionary + { + public XmlDictionaryString Namespace; + public XmlDictionaryString Prefix; + + public DotNetSecurityDictionary(ServiceModelDictionary dictionary) + { + Namespace = dictionary.CreateString(ServiceModelStringsVersion1.String162, 162); + Prefix = dictionary.CreateString(ServiceModelStringsVersion1.String163, 163); + } + } + internal static class ExclusiveC14NStrings { // Main dictionary strings diff --git a/src/System.Private.ServiceModel/tests/Common/Scenarios/Endpoints.cs b/src/System.Private.ServiceModel/tests/Common/Scenarios/Endpoints.cs index 96b6f4cb743..4314a7cd800 100644 --- a/src/System.Private.ServiceModel/tests/Common/Scenarios/Endpoints.cs +++ b/src/System.Private.ServiceModel/tests/Common/Scenarios/Endpoints.cs @@ -375,6 +375,22 @@ public static string Https_SecModeTransWithMessCred_ClientCredTypeUserName } } + public static string Https2007_SecModeTransWithMessCred_ClientCredTypeCert + { + get + { + return GetEndpointAddress("HttpsTransSecMessCredsCert.svc//https2007-message-credentials-cert", protocol: "https"); + } + } + + public static string Https2007_SecModeTransWithMessCred_ClientCredTypeUserName + { + get + { + return GetEndpointAddress("HttpsTransSecMessCredsUserName.svc//https2007-message-credentials-username", protocol: "https"); + } + } + public static string BasicHttps_SecModeTransWithMessCred_ClientCredTypeCert { get diff --git a/src/System.Private.ServiceModel/tests/Scenarios/Binding/WS/TransportWithMessageCredentialSecurity/WS2007HttpTransportWithMessageCredentialsSecurityTests.cs b/src/System.Private.ServiceModel/tests/Scenarios/Binding/WS/TransportWithMessageCredentialSecurity/WS2007HttpTransportWithMessageCredentialsSecurityTests.cs new file mode 100644 index 00000000000..4a84f970b1f --- /dev/null +++ b/src/System.Private.ServiceModel/tests/Scenarios/Binding/WS/TransportWithMessageCredentialSecurity/WS2007HttpTransportWithMessageCredentialsSecurityTests.cs @@ -0,0 +1,109 @@ +// 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.Collections.Generic; +using System.Security.Cryptography.X509Certificates; +using System.ServiceModel; +using System.Text; +using Infrastructure.Common; +using Xunit; + +public class WS2007HttpTransportWithMessageCredentialsSecurityTests : ConditionalWcfTest +{ + [WcfFact] + [Issue(2870, OS = OSID.AnyOSX)] + [Condition(nameof(Root_Certificate_Installed), + nameof(Client_Certificate_Installed), + nameof(SSL_Available))] + [OuterLoop] + public static void Https_SecModeTransWithMessCred_CertClientCredential_Succeeds() + { + string clientCertThumb = null; + EndpointAddress endpointAddress = null; + string testString = "Hello"; + ChannelFactory factory = null; + IWcfService serviceProxy = null; + + try + { + // *** SETUP *** \\ + WS2007HttpBinding binding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential); + binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate; + endpointAddress = new EndpointAddress(new Uri(Endpoints.Https2007_SecModeTransWithMessCred_ClientCredTypeCert)); + clientCertThumb = ServiceUtilHelper.ClientCertificate.Thumbprint; + + factory = new ChannelFactory(binding, endpointAddress); + factory.Credentials.ClientCertificate.SetCertificate( + StoreLocation.CurrentUser, + StoreName.My, + X509FindType.FindByThumbprint, + clientCertThumb); + + serviceProxy = factory.CreateChannel(); + + // *** EXECUTE *** \\ + string result = serviceProxy.Echo(testString); + + // *** VALIDATE *** \\ + Assert.Equal(testString, result); + + // *** CLEANUP *** \\ + ((ICommunicationObject)serviceProxy).Close(); + factory.Close(); + } + finally + { + // *** ENSURE CLEANUP *** \\ + ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory); + } + } + + [WcfFact] + [Condition(nameof(Root_Certificate_Installed), + nameof(SSL_Available))] + [OuterLoop] + public static void Https_SecModeTransWithMessCred_UserNameClientCredential_Succeeds() + { + string testString = "Hello"; + string result = null; + string username = null; + string password = null; + EndpointAddress endpointAddress = null; + ChannelFactory factory = null; + IWcfService serviceProxy = null; + + try + { + // *** SETUP *** \\ + WS2007HttpBinding binding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential); + binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName; + endpointAddress = new EndpointAddress(new Uri(Endpoints.Https2007_SecModeTransWithMessCred_ClientCredTypeUserName)); + + factory = new ChannelFactory(binding, endpointAddress); + username = Guid.NewGuid().ToString("n").Substring(0, 8); + char[] usernameArr = username.ToCharArray(); + Array.Reverse(usernameArr); + password = new string(usernameArr); + factory.Credentials.UserName.UserName = username; + factory.Credentials.UserName.Password = password; + + serviceProxy = factory.CreateChannel(); + + // *** EXECUTE *** \\ + result = serviceProxy.Echo(testString); + + // *** VALIDATE *** \\ + Assert.Equal(testString, result); + + // *** CLEANUP *** \\ + ((ICommunicationObject)serviceProxy).Close(); + factory.Close(); + } + finally + { + // *** ENSURE CLEANUP *** \\ + ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory); + } + } +} diff --git a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/HttpsTransportSecurityMessageCredentialsCertTestServiceHost.cs b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/HttpsTransportSecurityMessageCredentialsCertTestServiceHost.cs index 0f4423b8c09..000ab1a0e5e 100644 --- a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/HttpsTransportSecurityMessageCredentialsCertTestServiceHost.cs +++ b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/HttpsTransportSecurityMessageCredentialsCertTestServiceHost.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Security; @@ -12,13 +13,24 @@ namespace WcfService [TestServiceDefinition(Schema = ServiceSchema.HTTPS, BasePath = "HttpsTransSecMessCredsCert.svc")] internal class HttpsTransportSecurityMessageCredentialsCertTestServiceHost : TestServiceHostBase { - protected override string Address { get { return "https-message-credentials-cert"; } } + protected override IList GetBindings() + { + return new List { GetWSHttpBinding(), GetWS2007HttpBinding() }; + } - protected override Binding GetBinding() + private Binding GetWSHttpBinding() { WSHttpBinding binding = new WSHttpBinding(SecurityMode.TransportWithMessageCredential); binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate; + binding.Name = "https-message-credentials-cert"; + return binding; + } + private Binding GetWS2007HttpBinding() + { + WS2007HttpBinding binding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential); + binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate; + binding.Name = "https2007-message-credentials-cert"; return binding; } diff --git a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/HttpsTransportSecurityMessageCredentialsUsernameTestServiceHost.cs b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/HttpsTransportSecurityMessageCredentialsUsernameTestServiceHost.cs index 7275b11db08..4e33eb0e070 100644 --- a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/HttpsTransportSecurityMessageCredentialsUsernameTestServiceHost.cs +++ b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/HttpsTransportSecurityMessageCredentialsUsernameTestServiceHost.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Channels; @@ -11,7 +12,26 @@ namespace WcfService [TestServiceDefinition(Schema = ServiceSchema.HTTPS, BasePath = "HttpsTransSecMessCredsUserName.svc")] internal class HttpsTransportSecurityMessageCredentialsUserNameTestServiceHost : TestServiceHostBase { - protected override string Address { get { return "https-message-credentials-username"; } } + protected override IList GetBindings() + { + return new List { GetWSHttpBinding(), GetWS2007HttpBinding() }; + } + + private Binding GetWSHttpBinding() + { + WSHttpBinding binding = new WSHttpBinding(SecurityMode.TransportWithMessageCredential); + binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName; + binding.Name = "https-message-credentials-username"; + return binding; + } + + private Binding GetWS2007HttpBinding() + { + WS2007HttpBinding binding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential); + binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName; + binding.Name = "https2007-message-credentials-username"; + return binding; + } protected override Binding GetBinding() { diff --git a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/TestServiceHostBase.cs b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/TestServiceHostBase.cs index 54c630fca1e..8ba10595730 100644 --- a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/TestServiceHostBase.cs +++ b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/TestServiceHostBase.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections; +using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; @@ -11,16 +13,27 @@ namespace WcfService { public abstract class TestServiceHostBase : ServiceHost { + private const string EmptyAddress = "___"; protected static int SixtyFourMB = 64 * 1024 * 1024; - protected abstract string Address { get; } - protected abstract Binding GetBinding(); + protected virtual string Address { get { throw new NotImplementedException("Must override Address if not overriding GetBindings"); } } + protected virtual Binding GetBinding() { throw new NotImplementedException("Must override either GetBinding or GetBindings"); } + + protected virtual IList GetBindings() + { + var singleBinding = GetBinding(); + singleBinding.Name = string.IsNullOrEmpty(Address) ? EmptyAddress : Address; + return new List { singleBinding }; + } public TestServiceHostBase(Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses) { - ServiceEndpoint endpoint = this.AddServiceEndpoint(typeof(ContractType), GetBinding(), Address); + foreach(var binding in GetBindings()) + { + AddServiceEndpoint(typeof(ContractType), binding, binding.Name == EmptyAddress ? "" : binding.Name); + } } //Overriding ApplyConfiguration() allows us to diff --git a/src/System.ServiceModel.Http/ref/System.ServiceModel.Http.cs b/src/System.ServiceModel.Http/ref/System.ServiceModel.Http.cs index c26b3427697..d21d1e9eb53 100644 --- a/src/System.ServiceModel.Http/ref/System.ServiceModel.Http.cs +++ b/src/System.ServiceModel.Http/ref/System.ServiceModel.Http.cs @@ -173,6 +173,13 @@ public WSHttpBinding(System.ServiceModel.SecurityMode securityMode, bool reliabl protected override System.ServiceModel.Channels.TransportBindingElement GetTransport() { return default(System.ServiceModel.Channels.TransportBindingElement); } protected override System.ServiceModel.Channels.SecurityBindingElement CreateMessageSecurity() { return default(System.ServiceModel.Channels.SecurityBindingElement); } } + public class WS2007HttpBinding : WSHttpBinding + { + public WS2007HttpBinding() { } + public WS2007HttpBinding(System.ServiceModel.SecurityMode securityMode) { } + public WS2007HttpBinding(System.ServiceModel.SecurityMode securityMode, bool reliableSessionEnabled) { } + protected override System.ServiceModel.Channels.SecurityBindingElement CreateMessageSecurity() { return default(System.ServiceModel.Channels.SecurityBindingElement); } + } public sealed partial class WSHttpSecurity { public WSHttpSecurity() { } diff --git a/src/System.ServiceModel.Security/ref/System.ServiceModel.Security.cs b/src/System.ServiceModel.Security/ref/System.ServiceModel.Security.cs index f8c803677c8..b8ee16daeb6 100644 --- a/src/System.ServiceModel.Security/ref/System.ServiceModel.Security.cs +++ b/src/System.ServiceModel.Security/ref/System.ServiceModel.Security.cs @@ -22,6 +22,7 @@ internal MessageSecurityVersion() { } public static System.ServiceModel.MessageSecurityVersion WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10 { get { return default; } } public static System.ServiceModel.MessageSecurityVersion WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11 { get { return default; } } public static System.ServiceModel.MessageSecurityVersion WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10 { get { return default; } } + public static System.ServiceModel.MessageSecurityVersion WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10 { get { return default; } } } public partial class SpnEndpointIdentity : System.ServiceModel.EndpointIdentity { @@ -103,6 +104,7 @@ internal SecureConversationVersion() { } public System.Xml.XmlDictionaryString Namespace { get { return default; } } public System.Xml.XmlDictionaryString Prefix { get { return default; } } public static System.ServiceModel.Security.SecureConversationVersion WSSecureConversationFeb2005 { get { return default; } } + public static System.ServiceModel.Security.SecureConversationVersion WSSecureConversation13 { get { return default; } } } public abstract partial class SecurityAlgorithmSuite { @@ -125,6 +127,7 @@ internal SecurityPolicyVersion() { } public string Namespace { get { return default; } } public string Prefix { get { return default; } } public static System.ServiceModel.Security.SecurityPolicyVersion WSSecurityPolicy11 { get { return default; } } + public static System.ServiceModel.Security.SecurityPolicyVersion WSSecurityPolicy12 { get { return default; } } } public abstract partial class SecurityVersion { @@ -139,6 +142,7 @@ internal TrustVersion() { } public System.Xml.XmlDictionaryString Namespace { get { return default; } } public System.Xml.XmlDictionaryString Prefix { get { return default; } } public static System.ServiceModel.Security.TrustVersion WSTrustFeb2005 { get { return default; } } + public static System.ServiceModel.Security.TrustVersion WSTrust13 { get { return default; } } } } namespace System.ServiceModel.Security.Tokens