//----------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.ServiceModel.Security.Tokens { using System.Collections.ObjectModel; using System.Globalization; using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; using System.Runtime; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Security; using System.Text; using System.Xml; public class IssuedSecurityTokenParameters : SecurityTokenParameters { const string wsidPrefix = "wsid"; const string wsidNamespace = "http://schemas.xmlsoap.org/ws/2005/05/identity"; static readonly string wsidPPIClaim = String.Format(CultureInfo.InvariantCulture, "{0}/claims/privatepersonalidentifier", wsidNamespace); internal const SecurityKeyType defaultKeyType = SecurityKeyType.SymmetricKey; internal const bool defaultUseStrTransform = false; internal struct AlternativeIssuerEndpoint { public EndpointAddress IssuerAddress; public EndpointAddress IssuerMetadataAddress; public Binding IssuerBinding; } Collection additionalRequestParameters = new Collection(); Collection alternativeIssuerEndpoints = new Collection(); MessageSecurityVersion defaultMessageSecurityVersion; EndpointAddress issuerAddress; EndpointAddress issuerMetadataAddress; Binding issuerBinding; int keySize; SecurityKeyType keyType = defaultKeyType; Collection claimTypeRequirements = new Collection(); bool useStrTransform = defaultUseStrTransform; string tokenType; protected IssuedSecurityTokenParameters(IssuedSecurityTokenParameters other) : base(other) { this.defaultMessageSecurityVersion = other.defaultMessageSecurityVersion; this.issuerAddress = other.issuerAddress; this.keyType = other.keyType; this.tokenType = other.tokenType; this.keySize = other.keySize; this.useStrTransform = other.useStrTransform; foreach (XmlElement parameter in other.additionalRequestParameters) { this.additionalRequestParameters.Add((XmlElement)parameter.Clone()); } foreach (ClaimTypeRequirement c in other.claimTypeRequirements) { this.claimTypeRequirements.Add(c); } if (other.issuerBinding != null) { this.issuerBinding = new CustomBinding(other.issuerBinding); } this.issuerMetadataAddress = other.issuerMetadataAddress; } public IssuedSecurityTokenParameters() : this(null, null, null) { // empty } public IssuedSecurityTokenParameters(string tokenType) : this(tokenType, null, null) { // empty } public IssuedSecurityTokenParameters(string tokenType, EndpointAddress issuerAddress) : this(tokenType, issuerAddress, null) { // empty } public IssuedSecurityTokenParameters(string tokenType, EndpointAddress issuerAddress, Binding issuerBinding) : base() { this.tokenType = tokenType; this.issuerAddress = issuerAddress; this.issuerBinding = issuerBinding; } internal protected override bool HasAsymmetricKey { get { return this.KeyType == SecurityKeyType.AsymmetricKey; } } public Collection AdditionalRequestParameters { get { return this.additionalRequestParameters; } } public MessageSecurityVersion DefaultMessageSecurityVersion { get { return this.defaultMessageSecurityVersion; } set { defaultMessageSecurityVersion = value; } } internal Collection AlternativeIssuerEndpoints { get { return this.alternativeIssuerEndpoints; } } public EndpointAddress IssuerAddress { get { return this.issuerAddress; } set { this.issuerAddress = value; } } public EndpointAddress IssuerMetadataAddress { get { return this.issuerMetadataAddress; } set { this.issuerMetadataAddress = value; } } public Binding IssuerBinding { get { return this.issuerBinding; } set { this.issuerBinding = value; } } public SecurityKeyType KeyType { get { return this.keyType; } set { SecurityKeyTypeHelper.Validate(value); this.keyType = value; } } public int KeySize { get { return this.keySize; } set { if (value < 0) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.ValueMustBeNonNegative))); this.keySize = value; } } public bool UseStrTransform { get { return this.useStrTransform; } set { this.useStrTransform = value; } } public Collection ClaimTypeRequirements { get { return this.claimTypeRequirements; } } public string TokenType { get { return this.tokenType; } set { this.tokenType = value; } } internal protected override bool SupportsClientAuthentication { get { return true; } } internal protected override bool SupportsServerAuthentication { get { return true; } } internal protected override bool SupportsClientWindowsIdentity { get { return false; } } protected override SecurityTokenParameters CloneCore() { return new IssuedSecurityTokenParameters(this); } internal protected override SecurityKeyIdentifierClause CreateKeyIdentifierClause(SecurityToken token, SecurityTokenReferenceStyle referenceStyle) { if (token is GenericXmlSecurityToken) return base.CreateGenericXmlTokenKeyIdentifierClause(token, referenceStyle); else return this.CreateKeyIdentifierClause(token, referenceStyle); } internal void SetRequestParameters(Collection requestParameters, TrustDriver trustDriver) { if (requestParameters == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("requestParameters"); if (trustDriver == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("trustDriver"); Collection unknownRequestParameters = new Collection(); foreach (XmlElement element in requestParameters) { int keySize; string tokenType; SecurityKeyType keyType; Collection requiredClaims; if (trustDriver.TryParseKeySizeElement(element, out keySize)) this.keySize = keySize; else if (trustDriver.TryParseKeyTypeElement(element, out keyType)) this.KeyType = keyType; else if (trustDriver.TryParseTokenTypeElement(element, out tokenType)) this.TokenType = tokenType; // Only copy RP policy to client policy for TrustFeb2005 else if (trustDriver.StandardsManager.TrustVersion == TrustVersion.WSTrustFeb2005) { if (trustDriver.TryParseRequiredClaimsElement(element, out requiredClaims)) { Collection unrecognizedRequiredClaims = new Collection(); foreach (XmlElement claimRequirement in requiredClaims) { if (claimRequirement.LocalName == "ClaimType" && claimRequirement.NamespaceURI == wsidNamespace) { string claimValue = claimRequirement.GetAttribute("Uri", string.Empty); if (!string.IsNullOrEmpty(claimValue)) { ClaimTypeRequirement claimTypeRequirement; string optional = claimRequirement.GetAttribute("Optional", string.Empty); if (String.IsNullOrEmpty(optional)) { claimTypeRequirement = new ClaimTypeRequirement(claimValue); } else { claimTypeRequirement = new ClaimTypeRequirement(claimValue, XmlConvert.ToBoolean(optional)); } this.claimTypeRequirements.Add(claimTypeRequirement); } } else { unrecognizedRequiredClaims.Add(claimRequirement); } } if (unrecognizedRequiredClaims.Count > 0) unknownRequestParameters.Add(trustDriver.CreateRequiredClaimsElement(unrecognizedRequiredClaims)); } else { unknownRequestParameters.Add(element); } } } unknownRequestParameters = trustDriver.ProcessUnknownRequestParameters(unknownRequestParameters, requestParameters); if (unknownRequestParameters.Count > 0) { for (int i = 0; i < unknownRequestParameters.Count; ++i) this.AdditionalRequestParameters.Add(unknownRequestParameters[i]); } } public Collection CreateRequestParameters(MessageSecurityVersion messageSecurityVersion, SecurityTokenSerializer securityTokenSerializer) { return CreateRequestParameters(SecurityUtils.CreateSecurityStandardsManager(messageSecurityVersion, securityTokenSerializer).TrustDriver); } internal Collection CreateRequestParameters(TrustDriver driver) { if (driver == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("driver"); Collection result = new Collection(); if (this.tokenType != null) { result.Add(driver.CreateTokenTypeElement(tokenType)); } result.Add(driver.CreateKeyTypeElement(this.keyType)); if (this.keySize != 0) { result.Add(driver.CreateKeySizeElement(keySize)); } if (this.claimTypeRequirements.Count > 0) { Collection claimsElements = new Collection(); XmlDocument doc = new XmlDocument(); foreach (ClaimTypeRequirement claimType in this.claimTypeRequirements) { XmlElement element = doc.CreateElement(wsidPrefix, "ClaimType", wsidNamespace); XmlAttribute attr = doc.CreateAttribute("Uri"); attr.Value = claimType.ClaimType; element.Attributes.Append(attr); if (claimType.IsOptional != ClaimTypeRequirement.DefaultIsOptional) { attr = doc.CreateAttribute("Optional"); attr.Value = XmlConvert.ToString(claimType.IsOptional); element.Attributes.Append(attr); } claimsElements.Add(element); } result.Add(driver.CreateRequiredClaimsElement(claimsElements)); } if (this.additionalRequestParameters.Count > 0) { Collection trustNormalizedParameters = NormalizeAdditionalParameters(this.additionalRequestParameters, driver, (this.claimTypeRequirements.Count > 0)); foreach (XmlElement parameter in trustNormalizedParameters) { result.Add(parameter); } } return result; } private Collection NormalizeAdditionalParameters(Collection additionalParameters, TrustDriver driver, bool clientSideClaimTypeRequirementsSpecified) { // Ensure STS trust version is one of the currently supported versions: Feb 05 / Trust 1.3 Fx.Assert(((driver.StandardsManager.TrustVersion == TrustVersion.WSTrustFeb2005) || (driver.StandardsManager.TrustVersion == TrustVersion.WSTrust13)), "Unsupported trust version specified for the STS."); // We have a mismatch. Make a local copy of additionalParameters for making any potential modifications // as part of normalization Collection tmpCollection = new Collection(); foreach (XmlElement e in additionalParameters) { tmpCollection.Add(e); } // 1. For Trust 1.3 EncryptionAlgorithm, CanonicalizationAlgorithm and KeyWrapAlgorithm should not be // specified as top-level element if "SecondaryParameters" element already specifies this. if (driver.StandardsManager.TrustVersion == TrustVersion.WSTrust13) { Fx.Assert(driver.GetType() == typeof(WSTrustDec2005.DriverDec2005), "Invalid Trust Driver specified for Trust 1.3."); XmlElement encryptionAlgorithmElement = null; XmlElement canonicalizationAlgorithmElement = null; XmlElement keyWrapAlgorithmElement = null; XmlElement secondaryParameter = null; for (int i = 0; i < tmpCollection.Count; ++i) { string algorithm; if (driver.IsEncryptionAlgorithmElement(tmpCollection[i], out algorithm)) { encryptionAlgorithmElement = tmpCollection[i]; } else if (driver.IsCanonicalizationAlgorithmElement(tmpCollection[i], out algorithm)) { canonicalizationAlgorithmElement = tmpCollection[i]; } else if (driver.IsKeyWrapAlgorithmElement(tmpCollection[i], out algorithm)) { keyWrapAlgorithmElement = tmpCollection[i]; } else if (((WSTrustDec2005.DriverDec2005)driver).IsSecondaryParametersElement(tmpCollection[i])) { secondaryParameter = tmpCollection[i]; } } if (secondaryParameter != null) { foreach (XmlNode node in secondaryParameter.ChildNodes) { XmlElement child = node as XmlElement; if (child != null) { string algorithm = null; if (driver.IsEncryptionAlgorithmElement(child, out algorithm) && (encryptionAlgorithmElement != null)) { tmpCollection.Remove(encryptionAlgorithmElement); } else if (driver.IsCanonicalizationAlgorithmElement(child, out algorithm) && (canonicalizationAlgorithmElement != null)) { tmpCollection.Remove(canonicalizationAlgorithmElement); } else if (driver.IsKeyWrapAlgorithmElement(child, out algorithm) && (keyWrapAlgorithmElement != null)) { tmpCollection.Remove(keyWrapAlgorithmElement); } } } } } // 2. Check for Mismatch. // a. Trust Feb 2005 -> Trust 1.3. do the following, // (i) Copy EncryptionAlgorithm and CanonicalizationAlgorithm as the top-level elements. // Note, this is in contradiction to step 1. But we don't have a choice here as we cannot say from the // Additional Parameters section in the config what came from the service and what came from the client. // (ii) Convert SignWith and EncryptWith elements to Trust 1.3 namespace. // b. For Trust 1.3 -> Trust Feb 2005, do the following, // (i) Find EncryptionAlgorithm, CanonicalizationAlgorithm from inside the "SecondaryParameters" element. // If found, then promote these as the top-level elements replacing the existing values. // (ii) Convert the SignWith and EncryptWith elements to the Trust Feb 2005 namespace and drop the KeyWrapAlgorithm // element. // make an optimistic check to detect mismatched trust-versions between STS and RP bool mismatch = (((driver.StandardsManager.TrustVersion == TrustVersion.WSTrustFeb2005) && !CollectionContainsElementsWithTrustNamespace(additionalParameters, TrustFeb2005Strings.Namespace)) || ((driver.StandardsManager.TrustVersion == TrustVersion.WSTrust13) && !CollectionContainsElementsWithTrustNamespace(additionalParameters, TrustDec2005Strings.Namespace))); // if no mismatch, return unmodified collection if (!mismatch) { return tmpCollection; } // 2.a // If we are talking to a Trust 1.3 STS, replace any Feb '05 algorithm parameters with their Trust 1.3 counterparts if (driver.StandardsManager.TrustVersion == TrustVersion.WSTrust13) { SecurityStandardsManager trustFeb2005StandardsManager = SecurityStandardsManager.DefaultInstance; // the following cast is guaranteed to succeed WSTrustFeb2005.DriverFeb2005 trustFeb2005Driver = (WSTrustFeb2005.DriverFeb2005)trustFeb2005StandardsManager.TrustDriver; for (int i = 0; i < tmpCollection.Count; i++) { string algorithmParameter = string.Empty; if (trustFeb2005Driver.IsSignWithElement(tmpCollection[i], out algorithmParameter)) { tmpCollection[i] = driver.CreateSignWithElement(algorithmParameter); } else if (trustFeb2005Driver.IsEncryptWithElement(tmpCollection[i], out algorithmParameter)) { tmpCollection[i] = driver.CreateEncryptWithElement(algorithmParameter); } else if (trustFeb2005Driver.IsEncryptionAlgorithmElement(tmpCollection[i], out algorithmParameter)) { tmpCollection[i] = driver.CreateEncryptionAlgorithmElement(algorithmParameter); } else if (trustFeb2005Driver.IsCanonicalizationAlgorithmElement(tmpCollection[i], out algorithmParameter)) { tmpCollection[i] = driver.CreateCanonicalizationAlgorithmElement(algorithmParameter); } } } else { // 2.b // We are talking to a Feb 05 STS. Filter out any SecondaryParameters element. Collection childrenToPromote = null; WSSecurityTokenSerializer trust13Serializer = new WSSecurityTokenSerializer(SecurityVersion.WSSecurity11, TrustVersion.WSTrust13, SecureConversationVersion.WSSecureConversation13, true, null, null, null); SecurityStandardsManager trust13StandardsManager = new SecurityStandardsManager(MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12, trust13Serializer); // the following cast is guaranteed to succeed WSTrustDec2005.DriverDec2005 trust13Driver = (WSTrustDec2005.DriverDec2005)trust13StandardsManager.TrustDriver; foreach (XmlElement parameter in tmpCollection) { // check if SecondaryParameters is present if (trust13Driver.IsSecondaryParametersElement(parameter)) { childrenToPromote = new Collection(); // walk SecondaryParameters and collect any 'non-standard' children foreach (XmlNode innerNode in parameter.ChildNodes) { XmlElement innerElement = innerNode as XmlElement; if ((innerElement != null) && CanPromoteToRoot(innerElement, trust13Driver, clientSideClaimTypeRequirementsSpecified)) { childrenToPromote.Add(innerElement); } } // remove SecondaryParameters element tmpCollection.Remove(parameter); // we are done - break out of the loop break; } } // Probe of standard Trust elements and remember them. if ((childrenToPromote != null) && (childrenToPromote.Count > 0)) { XmlElement encryptionElement = null; string encryptionAlgorithm = String.Empty; XmlElement canonicalizationElement = null; string canonicalizationAlgoritm = String.Empty; XmlElement requiredClaimsElement = null; Collection requiredClaims = null; Collection processedElements = new Collection(); foreach (XmlElement e in childrenToPromote) { if ((encryptionElement == null) && trust13Driver.IsEncryptionAlgorithmElement(e, out encryptionAlgorithm)) { encryptionElement = driver.CreateEncryptionAlgorithmElement(encryptionAlgorithm); processedElements.Add(e); } else if ((canonicalizationElement == null) && trust13Driver.IsCanonicalizationAlgorithmElement(e, out canonicalizationAlgoritm)) { canonicalizationElement = driver.CreateCanonicalizationAlgorithmElement(canonicalizationAlgoritm); processedElements.Add(e); } else if ((requiredClaimsElement == null) && trust13Driver.TryParseRequiredClaimsElement(e, out requiredClaims)) { requiredClaimsElement = driver.CreateRequiredClaimsElement(requiredClaims); processedElements.Add(e); } } for (int i = 0; i < processedElements.Count; ++i) { childrenToPromote.Remove(processedElements[i]); } XmlElement keyWrapAlgorithmElement = null; // Replace the appropriate elements. for (int i = 0; i < tmpCollection.Count; ++i) { string algorithmParameter; Collection reqClaims; if (trust13Driver.IsSignWithElement(tmpCollection[i], out algorithmParameter)) { tmpCollection[i] = driver.CreateSignWithElement(algorithmParameter); } else if (trust13Driver.IsEncryptWithElement(tmpCollection[i], out algorithmParameter)) { tmpCollection[i] = driver.CreateEncryptWithElement(algorithmParameter); } else if (trust13Driver.IsEncryptionAlgorithmElement(tmpCollection[i], out algorithmParameter) && (encryptionElement != null)) { tmpCollection[i] = encryptionElement; encryptionElement = null; } else if (trust13Driver.IsCanonicalizationAlgorithmElement(tmpCollection[i], out algorithmParameter) && (canonicalizationElement != null)) { tmpCollection[i] = canonicalizationElement; canonicalizationElement = null; } else if (trust13Driver.IsKeyWrapAlgorithmElement(tmpCollection[i], out algorithmParameter) && (keyWrapAlgorithmElement == null)) { keyWrapAlgorithmElement = tmpCollection[i]; } else if (trust13Driver.TryParseRequiredClaimsElement(tmpCollection[i], out reqClaims) && (requiredClaimsElement != null)) { tmpCollection[i] = requiredClaimsElement; requiredClaimsElement = null; } } if (keyWrapAlgorithmElement != null) { // Remove KeyWrapAlgorithmElement as this is not define in Trust Feb 2005. tmpCollection.Remove(keyWrapAlgorithmElement); } // Add the remaining elements to the additionaParameters list to the end. if (encryptionElement != null) tmpCollection.Add(encryptionElement); if (canonicalizationElement != null) tmpCollection.Add(canonicalizationElement); if (requiredClaimsElement != null) tmpCollection.Add(requiredClaimsElement); if (childrenToPromote.Count > 0) { // There are some non-standard elements. Just bump them to the top-level element. for (int i = 0; i < childrenToPromote.Count; ++i) { tmpCollection.Add(childrenToPromote[i]); } } } } return tmpCollection; } private bool CollectionContainsElementsWithTrustNamespace(Collection collection, string trustNamespace) { for (int i = 0; i < collection.Count; i++) { if ((collection[i] != null) && (collection[i].NamespaceURI == trustNamespace)) { return true; } } return false; } private bool CanPromoteToRoot(XmlElement innerElement, WSTrustDec2005.DriverDec2005 trust13Driver, bool clientSideClaimTypeRequirementsSpecified) { SecurityKeyType dummyOutParamForKeyType; int dummyOutParamForKeySize; string dummyStringOutParam; Collection dummyOutParamForRequiredClaims = null; // check if SecondaryParameters has claim requirements specified if (trust13Driver.TryParseRequiredClaimsElement(innerElement, out dummyOutParamForRequiredClaims)) { // if client has not specified any claim requirements, promote claim requirements // in SecondaryParameters to root level (and subsequently fix up the trust namespace) return !clientSideClaimTypeRequirementsSpecified; } // KeySize, KeyType and TokenType were converted to top-level property values when the WSDL was // imported, so drop it here. We check for EncryptWith and SignWith as these are Client specific algorithm values and we // don't have to promote the service specified values. KeyWrapAlgorithm was never sent in the RST // in V1 and hence we are dropping it here as well. return (!trust13Driver.TryParseKeyTypeElement(innerElement, out dummyOutParamForKeyType) && !trust13Driver.TryParseKeySizeElement(innerElement, out dummyOutParamForKeySize) && !trust13Driver.TryParseTokenTypeElement(innerElement, out dummyStringOutParam) && !trust13Driver.IsSignWithElement(innerElement, out dummyStringOutParam) && !trust13Driver.IsEncryptWithElement(innerElement, out dummyStringOutParam) && !trust13Driver.IsKeyWrapAlgorithmElement(innerElement, out dummyStringOutParam)); } internal void AddAlgorithmParameters(SecurityAlgorithmSuite algorithmSuite, SecurityStandardsManager standardsManager, SecurityKeyType issuedKeyType) { this.additionalRequestParameters.Insert(0, standardsManager.TrustDriver.CreateEncryptionAlgorithmElement(algorithmSuite.DefaultEncryptionAlgorithm)); this.additionalRequestParameters.Insert(0, standardsManager.TrustDriver.CreateCanonicalizationAlgorithmElement(algorithmSuite.DefaultCanonicalizationAlgorithm)); if (this.keyType == SecurityKeyType.BearerKey) { // As the client does not have a proof token in the Bearer case // we don't have any specific algorithms to request for. return; } string signWithAlgorithm = (this.keyType == SecurityKeyType.SymmetricKey) ? algorithmSuite.DefaultSymmetricSignatureAlgorithm : algorithmSuite.DefaultAsymmetricSignatureAlgorithm; this.additionalRequestParameters.Insert(0, standardsManager.TrustDriver.CreateSignWithElement(signWithAlgorithm)); string encryptWithAlgorithm; if (issuedKeyType == SecurityKeyType.SymmetricKey) { encryptWithAlgorithm = algorithmSuite.DefaultEncryptionAlgorithm; } else { encryptWithAlgorithm = algorithmSuite.DefaultAsymmetricKeyWrapAlgorithm; } this.additionalRequestParameters.Insert(0, standardsManager.TrustDriver.CreateEncryptWithElement(encryptWithAlgorithm)); if (standardsManager.TrustVersion != TrustVersion.WSTrustFeb2005) { this.additionalRequestParameters.Insert(0, ((WSTrustDec2005.DriverDec2005)standardsManager.TrustDriver).CreateKeyWrapAlgorithmElement(algorithmSuite.DefaultAsymmetricKeyWrapAlgorithm)); } return; } internal bool DoAlgorithmsMatch(SecurityAlgorithmSuite algorithmSuite, SecurityStandardsManager standardsManager, out Collection otherRequestParameters) { bool doesSignWithAlgorithmMatch = false; bool doesEncryptWithAlgorithmMatch = false; bool doesEncryptionAlgorithmMatch = false; bool doesCanonicalizationAlgorithmMatch = false; bool doesKeyWrapAlgorithmMatch = false; otherRequestParameters = new Collection(); bool trustNormalizationPerformed = false; Collection trustVersionNormalizedParameterCollection; // For Trust 1.3 we move all the additional parameters into the secondaryParameters // element. So the list contains just one element called SecondaryParameters that // contains all the other elements as child elements. if ((standardsManager.TrustVersion == TrustVersion.WSTrust13) && (this.AdditionalRequestParameters.Count == 1) && (((WSTrustDec2005.DriverDec2005)standardsManager.TrustDriver).IsSecondaryParametersElement(this.AdditionalRequestParameters[0]))) { trustNormalizationPerformed = true; trustVersionNormalizedParameterCollection = new Collection(); foreach (XmlElement innerElement in this.AdditionalRequestParameters[0]) { trustVersionNormalizedParameterCollection.Add(innerElement); } } else { trustVersionNormalizedParameterCollection = this.AdditionalRequestParameters; } for (int i = 0; i < trustVersionNormalizedParameterCollection.Count; i++) { string algorithm; XmlElement element = trustVersionNormalizedParameterCollection[i]; if (standardsManager.TrustDriver.IsCanonicalizationAlgorithmElement(element, out algorithm)) { if (algorithmSuite.DefaultCanonicalizationAlgorithm != algorithm) { return false; } doesCanonicalizationAlgorithmMatch = true; } else if (standardsManager.TrustDriver.IsSignWithElement(element, out algorithm)) { if ((this.keyType == SecurityKeyType.SymmetricKey && algorithm != algorithmSuite.DefaultSymmetricSignatureAlgorithm) || (this.keyType == SecurityKeyType.AsymmetricKey && algorithm != algorithmSuite.DefaultAsymmetricSignatureAlgorithm)) { return false; } doesSignWithAlgorithmMatch = true; } else if (standardsManager.TrustDriver.IsEncryptWithElement(element, out algorithm)) { if ((this.keyType == SecurityKeyType.SymmetricKey && algorithm != algorithmSuite.DefaultEncryptionAlgorithm) || (this.keyType == SecurityKeyType.AsymmetricKey && algorithm != algorithmSuite.DefaultAsymmetricKeyWrapAlgorithm)) { return false; } doesEncryptWithAlgorithmMatch = true; } else if (standardsManager.TrustDriver.IsEncryptionAlgorithmElement(element, out algorithm)) { if (algorithm != algorithmSuite.DefaultEncryptionAlgorithm) { return false; } doesEncryptionAlgorithmMatch = true; } else if (standardsManager.TrustDriver.IsKeyWrapAlgorithmElement(element, out algorithm)) { if (algorithm != algorithmSuite.DefaultAsymmetricKeyWrapAlgorithm) { return false; } doesKeyWrapAlgorithmMatch = true; } else { otherRequestParameters.Add(element); } } // Undo normalization if performed // move all back into secondaryParameters if (trustNormalizationPerformed) { otherRequestParameters = this.AdditionalRequestParameters; } if (this.keyType == SecurityKeyType.BearerKey) { // As the client does not have a proof token in the Bearer case // we don't have any specific algorithms to request for. return true; } if (standardsManager.TrustVersion == TrustVersion.WSTrustFeb2005) { // For V1 compatibility check all algorithms return (doesSignWithAlgorithmMatch && doesCanonicalizationAlgorithmMatch && doesEncryptionAlgorithmMatch && doesEncryptWithAlgorithmMatch); } else { return (doesSignWithAlgorithmMatch && doesCanonicalizationAlgorithmMatch && doesEncryptionAlgorithmMatch && doesEncryptWithAlgorithmMatch && doesKeyWrapAlgorithmMatch); } } internal static IssuedSecurityTokenParameters CreateInfoCardParameters(SecurityStandardsManager standardsManager, SecurityAlgorithmSuite algorithm) { IssuedSecurityTokenParameters result = new IssuedSecurityTokenParameters(SecurityXXX2005Strings.SamlTokenType); result.KeyType = SecurityKeyType.AsymmetricKey; result.ClaimTypeRequirements.Add(new ClaimTypeRequirement(wsidPPIClaim)); result.IssuerAddress = null; result.AddAlgorithmParameters(algorithm, standardsManager, result.KeyType); return result; } internal static bool IsInfoCardParameters(IssuedSecurityTokenParameters parameters, SecurityStandardsManager standardsManager) { if (parameters == null) return false; if (parameters.TokenType != SecurityXXX2005Strings.SamlTokenType) return false; if (parameters.KeyType != SecurityKeyType.AsymmetricKey) return false; if (parameters.ClaimTypeRequirements.Count == 1) { ClaimTypeRequirement claimTypeRequirement = parameters.ClaimTypeRequirements[0] as ClaimTypeRequirement; if (claimTypeRequirement == null) return false; if (claimTypeRequirement.ClaimType != wsidPPIClaim) return false; } else if ((parameters.AdditionalRequestParameters != null) && (parameters.AdditionalRequestParameters.Count > 0)) { // Check the AdditionalRequest Parameters to see if ClaimTypeRequirements got imported there. bool claimTypeRequirementMatched = false; XmlElement claimTypeRequirement = GetClaimTypeRequirement(parameters.AdditionalRequestParameters, standardsManager); if (claimTypeRequirement != null && claimTypeRequirement.ChildNodes.Count == 1) { XmlElement claimTypeElement = claimTypeRequirement.ChildNodes[0] as XmlElement; if (claimTypeElement != null) { XmlNode claimType = claimTypeElement.Attributes.GetNamedItem("Uri"); if (claimType != null && claimType.Value == wsidPPIClaim) { claimTypeRequirementMatched = true; } } } if (!claimTypeRequirementMatched) { return false; } } else { return false; } if (parameters.IssuerAddress != null) return false; if (parameters.AlternativeIssuerEndpoints != null && parameters.AlternativeIssuerEndpoints.Count > 0) { return false; } return true; } // The method walks through the entire set of AdditionalRequestParameters and return the Claims Type requirement alone. internal static XmlElement GetClaimTypeRequirement(Collection additionalRequestParameters, SecurityStandardsManager standardsManager) { foreach (XmlElement requestParameter in additionalRequestParameters) { if ((requestParameter.LocalName == ((System.ServiceModel.Security.WSTrust.Driver)standardsManager.TrustDriver).DriverDictionary.Claims.Value) && (requestParameter.NamespaceURI == ((System.ServiceModel.Security.WSTrust.Driver)standardsManager.TrustDriver).DriverDictionary.Namespace.Value)) { return requestParameter; } if ((requestParameter.LocalName == DXD.TrustDec2005Dictionary.SecondaryParameters.Value) && (requestParameter.NamespaceURI == DXD.TrustDec2005Dictionary.Namespace.Value)) { Collection secondaryParameters = new Collection(); foreach (XmlNode node in requestParameter.ChildNodes) { XmlElement nodeAsElement = node as XmlElement; if (nodeAsElement != null) { secondaryParameters.Add(nodeAsElement); } } XmlElement claimTypeRequirement = GetClaimTypeRequirement(secondaryParameters, standardsManager); if (claimTypeRequirement != null) { return claimTypeRequirement; } } } return null; } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.AppendLine(base.ToString()); sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "TokenType: {0}", this.tokenType == null ? "null" : this.tokenType)); sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "KeyType: {0}", this.keyType.ToString())); sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "KeySize: {0}", this.keySize.ToString(CultureInfo.InvariantCulture))); sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "IssuerAddress: {0}", this.issuerAddress == null ? "null" : this.issuerAddress.ToString())); sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "IssuerMetadataAddress: {0}", this.issuerMetadataAddress == null ? "null" : this.issuerMetadataAddress.ToString())); sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "DefaultMessgeSecurityVersion: {0}", this.defaultMessageSecurityVersion == null ? "null" : this.defaultMessageSecurityVersion.ToString())); sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "UseStrTransform: {0}", this.useStrTransform.ToString())); if (this.issuerBinding == null) { sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "IssuerBinding: null")); } else { sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "IssuerBinding:")); BindingElementCollection bindingElements = this.issuerBinding.CreateBindingElements(); for (int i = 0; i < bindingElements.Count; i++) { sb.AppendLine(String.Format(CultureInfo.InvariantCulture, " BindingElement[{0}]:", i.ToString(CultureInfo.InvariantCulture))); sb.AppendLine(" " + bindingElements[i].ToString().Trim().Replace("\n", "\n ")); } } if (this.claimTypeRequirements.Count == 0) { sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "ClaimTypeRequirements: none")); } else { sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "ClaimTypeRequirements:")); for (int i = 0; i < this.claimTypeRequirements.Count; i++) { sb.AppendLine(String.Format(CultureInfo.InvariantCulture, " {0}, optional={1}", this.claimTypeRequirements[i].ClaimType, this.claimTypeRequirements[i].IsOptional)); } } return sb.ToString().Trim(); } protected internal override void InitializeSecurityTokenRequirement(SecurityTokenRequirement requirement) { requirement.TokenType = this.TokenType; requirement.RequireCryptographicToken = true; requirement.KeyType = this.KeyType; ServiceModelSecurityTokenRequirement serviceModelSecurityTokenRequirement = requirement as ServiceModelSecurityTokenRequirement; if (serviceModelSecurityTokenRequirement != null) { serviceModelSecurityTokenRequirement.DefaultMessageSecurityVersion = this.DefaultMessageSecurityVersion; } else { requirement.Properties[ServiceModelSecurityTokenRequirement.DefaultMessageSecurityVersionProperty] = this.DefaultMessageSecurityVersion; } if (this.KeySize > 0) { requirement.KeySize = this.KeySize; } requirement.Properties[ServiceModelSecurityTokenRequirement.IssuerAddressProperty] = this.IssuerAddress; if (this.IssuerBinding != null) { requirement.Properties[ServiceModelSecurityTokenRequirement.IssuerBindingProperty] = this.IssuerBinding; } requirement.Properties[ServiceModelSecurityTokenRequirement.IssuedSecurityTokenParametersProperty] = this.Clone(); } } }