e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
988 lines
46 KiB
C#
988 lines
46 KiB
C#
//-----------------------------------------------------------------------------
|
|
// 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<XmlElement> additionalRequestParameters = new Collection<XmlElement>();
|
|
Collection<AlternativeIssuerEndpoint> alternativeIssuerEndpoints = new Collection<AlternativeIssuerEndpoint>();
|
|
MessageSecurityVersion defaultMessageSecurityVersion;
|
|
EndpointAddress issuerAddress;
|
|
EndpointAddress issuerMetadataAddress;
|
|
Binding issuerBinding;
|
|
int keySize;
|
|
SecurityKeyType keyType = defaultKeyType;
|
|
Collection<ClaimTypeRequirement> claimTypeRequirements = new Collection<ClaimTypeRequirement>();
|
|
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<XmlElement> AdditionalRequestParameters
|
|
{
|
|
get
|
|
{
|
|
return this.additionalRequestParameters;
|
|
}
|
|
}
|
|
|
|
public MessageSecurityVersion DefaultMessageSecurityVersion
|
|
{
|
|
get
|
|
{
|
|
return this.defaultMessageSecurityVersion;
|
|
}
|
|
|
|
set
|
|
{
|
|
defaultMessageSecurityVersion = value;
|
|
}
|
|
}
|
|
|
|
internal Collection<AlternativeIssuerEndpoint> 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<ClaimTypeRequirement> 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<SamlAssertionKeyIdentifierClause, SamlAssertionKeyIdentifierClause>(token, referenceStyle);
|
|
}
|
|
|
|
internal void SetRequestParameters(Collection<XmlElement> requestParameters, TrustDriver trustDriver)
|
|
{
|
|
if (requestParameters == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("requestParameters");
|
|
|
|
if (trustDriver == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("trustDriver");
|
|
|
|
Collection<XmlElement> unknownRequestParameters = new Collection<XmlElement>();
|
|
|
|
foreach (XmlElement element in requestParameters)
|
|
{
|
|
int keySize;
|
|
string tokenType;
|
|
SecurityKeyType keyType;
|
|
Collection<XmlElement> 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<XmlElement> unrecognizedRequiredClaims = new Collection<XmlElement>();
|
|
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<XmlElement> CreateRequestParameters(MessageSecurityVersion messageSecurityVersion, SecurityTokenSerializer securityTokenSerializer)
|
|
{
|
|
return CreateRequestParameters(SecurityUtils.CreateSecurityStandardsManager(messageSecurityVersion, securityTokenSerializer).TrustDriver);
|
|
}
|
|
|
|
internal Collection<XmlElement> CreateRequestParameters(TrustDriver driver)
|
|
{
|
|
if (driver == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("driver");
|
|
|
|
Collection<XmlElement> result = new Collection<XmlElement>();
|
|
|
|
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<XmlElement> claimsElements = new Collection<XmlElement>();
|
|
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<XmlElement> trustNormalizedParameters = NormalizeAdditionalParameters(this.additionalRequestParameters,
|
|
driver,
|
|
(this.claimTypeRequirements.Count > 0));
|
|
|
|
foreach (XmlElement parameter in trustNormalizedParameters)
|
|
{
|
|
result.Add(parameter);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private Collection<XmlElement> NormalizeAdditionalParameters(Collection<XmlElement> 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<XmlElement> tmpCollection = new Collection<XmlElement>();
|
|
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<XmlElement> 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<XmlElement>();
|
|
// 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<XmlElement> requiredClaims = null;
|
|
|
|
Collection<XmlElement> processedElements = new Collection<XmlElement>();
|
|
|
|
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<XmlElement> 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<XmlElement> 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<XmlElement> 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<XmlElement> otherRequestParameters)
|
|
{
|
|
bool doesSignWithAlgorithmMatch = false;
|
|
bool doesEncryptWithAlgorithmMatch = false;
|
|
bool doesEncryptionAlgorithmMatch = false;
|
|
bool doesCanonicalizationAlgorithmMatch = false;
|
|
bool doesKeyWrapAlgorithmMatch = false;
|
|
otherRequestParameters = new Collection<XmlElement>();
|
|
bool trustNormalizationPerformed = false;
|
|
|
|
Collection<XmlElement> 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<XmlElement>();
|
|
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<XmlElement> 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<XmlElement> secondaryParameters = new Collection<XmlElement>();
|
|
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();
|
|
}
|
|
}
|
|
}
|