You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,41 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// <copyright file="AbsoluteUriCollection.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
/// <summary>
|
||||
/// A collection of absolute URIs.
|
||||
/// </summary>
|
||||
internal class AbsoluteUriCollection : Collection<Uri>
|
||||
{
|
||||
public AbsoluteUriCollection()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void InsertItem(int index, Uri item)
|
||||
{
|
||||
if (null == item || !item.IsAbsoluteUri)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("item", SR.GetString(SR.ID0013));
|
||||
}
|
||||
|
||||
base.InsertItem(index, item);
|
||||
}
|
||||
|
||||
protected override void SetItem(int index, Uri item)
|
||||
{
|
||||
if (null == item || !item.IsAbsoluteUri)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("item", SR.GetString(SR.ID0013));
|
||||
}
|
||||
|
||||
base.SetItem(index, item);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,143 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
|
||||
using System.IdentityModel.Selectors;
|
||||
using System.IdentityModel.Tokens;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// This class defines a TokenResolver that can wrap multiple Token Resolvers
|
||||
/// and resolve tokens across all the wrapped token resolvers.
|
||||
/// </summary>
|
||||
public class AggregateTokenResolver : SecurityTokenResolver
|
||||
{
|
||||
List<SecurityTokenResolver> _tokenResolvers = new List<SecurityTokenResolver>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="AggregateTokenResolver"/>
|
||||
/// </summary>
|
||||
/// <param name="tokenResolvers">IEnumerable list of TokenResolvers to be wrapped.</param>
|
||||
/// <exception cref="ArgumentNullException">The input argument 'tokenResolvers' is null.</exception>
|
||||
/// <exception cref="ArgumentException">The input 'tokenResolver' list does not contain a valid
|
||||
/// SecurityTokenResolver. At least one SecurityTokenResolver should be specified.</exception>
|
||||
public AggregateTokenResolver( IEnumerable<SecurityTokenResolver> tokenResolvers )
|
||||
{
|
||||
if ( tokenResolvers == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "tokenResolvers" );
|
||||
}
|
||||
|
||||
AddNonEmptyResolvers( tokenResolvers );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a read-only collection of TokenResolvers.
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<SecurityTokenResolver> TokenResolvers
|
||||
{
|
||||
get
|
||||
{
|
||||
return _tokenResolvers.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override of the base class. Resolves the given SecurityKeyIdentifierClause to a
|
||||
/// SecurityKey.
|
||||
/// </summary>
|
||||
/// <param name="keyIdentifierClause">The Clause to be resolved.</param>
|
||||
/// <param name="key">The resolved SecurityKey</param>
|
||||
/// <returns>True if successfully resolved.</returns>
|
||||
/// <exception cref="ArgumentNullException">Input argument 'keyIdentifierClause' is null.</exception>
|
||||
protected override bool TryResolveSecurityKeyCore( SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key )
|
||||
{
|
||||
if ( keyIdentifierClause == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "keyIdentifierClause" );
|
||||
}
|
||||
|
||||
key = null;
|
||||
foreach ( SecurityTokenResolver tokenResolver in _tokenResolvers )
|
||||
{
|
||||
if ( tokenResolver.TryResolveSecurityKey( keyIdentifierClause, out key ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override of the base class. Resolves the given SecurityKeyIdentifier to a
|
||||
/// SecurityToken.
|
||||
/// </summary>
|
||||
/// <param name="keyIdentifier">The KeyIdentifier to be resolved.</param>
|
||||
/// <param name="token">The resolved SecurityToken</param>
|
||||
/// <returns>True if successfully resolved.</returns>
|
||||
/// <exception cref="ArgumentNullException">Input argument 'keyIdentifier' is null.</exception>
|
||||
protected override bool TryResolveTokenCore( SecurityKeyIdentifier keyIdentifier, out SecurityToken token )
|
||||
{
|
||||
if ( keyIdentifier == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "keyIdentifer" );
|
||||
}
|
||||
|
||||
token = null;
|
||||
foreach ( SecurityTokenResolver tokenResolver in _tokenResolvers )
|
||||
{
|
||||
if ( tokenResolver.TryResolveToken( keyIdentifier, out token ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override of the base class. Resolves the given SecurityKeyIdentifierClause to a
|
||||
/// SecurityToken.
|
||||
/// </summary>
|
||||
/// <param name="keyIdentifierClause">The KeyIdentifier to be resolved.</param>
|
||||
/// <param name="token">The resolved SecurityToken</param>
|
||||
/// <returns>True if successfully resolved.</returns>
|
||||
/// <exception cref="ArgumentNullException">Input argument 'keyIdentifierClause' is null.</exception>
|
||||
protected override bool TryResolveTokenCore( SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token )
|
||||
{
|
||||
if ( keyIdentifierClause == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "keyIdentifierClause" );
|
||||
}
|
||||
|
||||
token = null;
|
||||
foreach ( SecurityTokenResolver tokenResolver in _tokenResolvers )
|
||||
{
|
||||
if ( tokenResolver.TryResolveToken( keyIdentifierClause, out token ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AddNonEmptyResolvers( IEnumerable<SecurityTokenResolver> resolvers )
|
||||
{
|
||||
foreach ( SecurityTokenResolver resolver in resolvers )
|
||||
{
|
||||
if ( resolver != null && resolver != EmptySecurityTokenResolver.Instance )
|
||||
{
|
||||
_tokenResolvers.Add( resolver );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using RSTR = System.IdentityModel.Protocols.WSTrust.RequestSecurityTokenResponse;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// This class can be used for issuing the asymmetric key based token.
|
||||
/// </summary>
|
||||
public class AsymmetricProofDescriptor : ProofDescriptor
|
||||
{
|
||||
SecurityKeyIdentifier _keyIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for extensibility
|
||||
/// </summary>
|
||||
public AsymmetricProofDescriptor()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a proof token based on RSA key.
|
||||
/// </summary>
|
||||
/// <param name="rsaAlgorithm"></param>
|
||||
public AsymmetricProofDescriptor( RSA rsaAlgorithm )
|
||||
{
|
||||
if ( rsaAlgorithm == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "rsaAlgorithm" );
|
||||
}
|
||||
|
||||
_keyIdentifier = new SecurityKeyIdentifier(new RsaKeyIdentifierClause(rsaAlgorithm));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a proof token based on key identifier.
|
||||
/// </summary>
|
||||
/// <param name="keyIdentifier"></param>
|
||||
public AsymmetricProofDescriptor( SecurityKeyIdentifier keyIdentifier )
|
||||
{
|
||||
if ( keyIdentifier == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "keyIdentifier" );
|
||||
}
|
||||
//
|
||||
// This is a key identifier for an asymmetric key
|
||||
//
|
||||
_keyIdentifier = keyIdentifier;
|
||||
}
|
||||
|
||||
#region ProofDescriptor Overrides
|
||||
|
||||
/// <summary>
|
||||
/// Basically nothing to write into the RSTR's requested proof token.
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
public override void ApplyTo( RSTR response )
|
||||
{
|
||||
if ( response == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "response" );
|
||||
}
|
||||
//
|
||||
// Nothing else to do for an asymmetric key
|
||||
//
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the key identifier that the requestor has provided from the use key.
|
||||
/// This can be echo back inside the saml token if needed. This would be either
|
||||
/// </summary>
|
||||
public override SecurityKeyIdentifier KeyIdentifier
|
||||
{
|
||||
get { return _keyIdentifier; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
using System.Security.Cryptography;
|
||||
|
||||
public abstract class AsymmetricSecurityKey : SecurityKey
|
||||
{
|
||||
public abstract AsymmetricAlgorithm GetAsymmetricAlgorithm(string algorithm, bool privateKey);
|
||||
public abstract HashAlgorithm GetHashAlgorithmForSignature(string algorithm);
|
||||
public abstract AsymmetricSignatureDeformatter GetSignatureDeformatter(string algorithm);
|
||||
public abstract AsymmetricSignatureFormatter GetSignatureFormatter(string algorithm);
|
||||
public abstract bool HasPrivateKey();
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IdentityModel.Selectors;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines settings for a AudienceRestriction verification.
|
||||
/// </summary>
|
||||
public class AudienceRestriction
|
||||
{
|
||||
AudienceUriMode _audienceMode = AudienceUriMode.Always;
|
||||
Collection<Uri> _audience = new Collection<Uri>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="AudienceRestriction"/>
|
||||
/// </summary>
|
||||
public AudienceRestriction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="AudienceRestriction"/>
|
||||
/// </summary>
|
||||
/// <param name="audienceMode">Specifies the mode in which AudienceUri restriction is applied.</param>
|
||||
public AudienceRestriction( AudienceUriMode audienceMode )
|
||||
{
|
||||
_audienceMode = audienceMode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets the mode in which Audience URI restriction is applied.
|
||||
/// </summary>
|
||||
public AudienceUriMode AudienceMode
|
||||
{
|
||||
get { return _audienceMode; }
|
||||
set { _audienceMode = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of Allowed Audience URIs.
|
||||
/// </summary>
|
||||
public Collection<Uri> AllowedAudienceUris
|
||||
{
|
||||
get { return _audience; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// Throw this exception a received Security token failed Audience Uri validation.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class AudienceUriValidationFailedException : SecurityTokenValidationException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="AudienceUriValidationFailedException"/>
|
||||
/// </summary>
|
||||
public AudienceUriValidationFailedException()
|
||||
: base( SR.GetString( SR.ID4183 ) )
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="AudienceUriValidationFailedException"/>
|
||||
/// </summary>
|
||||
public AudienceUriValidationFailedException( string message )
|
||||
: base( message )
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="AudienceUriValidationFailedException"/>
|
||||
/// </summary>
|
||||
public AudienceUriValidationFailedException( string message, Exception inner )
|
||||
: base( message, inner )
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="AudienceUriValidationFailedException"/>
|
||||
/// </summary>
|
||||
protected AudienceUriValidationFailedException( SerializationInfo info, StreamingContext context )
|
||||
: base( info, context )
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is used to specify the context of an authentication event.
|
||||
/// </summary>
|
||||
public class AuthenticationContext
|
||||
{
|
||||
Collection<string> _authorities;
|
||||
string _contextClass;
|
||||
string _contextDeclaration;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of AuthenticationContext.
|
||||
/// </summary>
|
||||
public AuthenticationContext()
|
||||
{
|
||||
_authorities = new Collection<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The collection of authorities for resolving an authentication event.
|
||||
/// </summary>
|
||||
public Collection<string> Authorities
|
||||
{
|
||||
get { return _authorities; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The context class for resolving an authentication event.
|
||||
/// </summary>
|
||||
public string ContextClass
|
||||
{
|
||||
get { return _contextClass; }
|
||||
set { _contextClass = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The context declaration for resolving an authentication event.
|
||||
/// </summary>
|
||||
public string ContextDeclaration
|
||||
{
|
||||
get { return _contextDeclaration; }
|
||||
set { _contextDeclaration = value; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines constants for SAML authentication methods.
|
||||
/// </summary>
|
||||
public static class AuthenticationMethods
|
||||
{
|
||||
#pragma warning disable 1591
|
||||
public const string Namespace = "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/";
|
||||
|
||||
public const string HardwareToken = Namespace + "hardwaretoken";
|
||||
public const string Kerberos = Namespace + "kerberos";
|
||||
public const string Password = Namespace + "password";
|
||||
public const string Pgp = Namespace + "pgp";
|
||||
public const string SecureRemotePassword = Namespace + "secureremotepassword";
|
||||
public const string Signature = Namespace + "signature";
|
||||
public const string Smartcard = Namespace + "smartcard";
|
||||
public const string SmartcardPki = Namespace + "smartcardpki";
|
||||
public const string Spki = Namespace + "spki";
|
||||
public const string TlsClient = Namespace + "tlsclient";
|
||||
public const string Unspecified = Namespace + "unspecified";
|
||||
public const string Windows = Namespace + "windows";
|
||||
public const string Xkms = Namespace + "xkms";
|
||||
public const string X509 = Namespace + "x509";
|
||||
#pragma warning restore 1591
|
||||
}
|
||||
}
|
@@ -0,0 +1,332 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IdentityModel.Diagnostics;
|
||||
using System.IdentityModel.Policy;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
|
||||
using SysClaimSet = System.IdentityModel.Claims.ClaimSet;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines an AuthorizationPolicy that carries the IDFx Claims. When IDFx is enabled
|
||||
/// a new set of Security Token Authenticators are added to the system. These Authenticators
|
||||
/// will generate the new Claims defined in System.Security.Claims.
|
||||
/// </summary>
|
||||
internal class AuthorizationPolicy : IAuthorizationPolicy
|
||||
{
|
||||
#pragma warning disable 1591
|
||||
public const string ClaimsPrincipalKey = "ClaimsPrincipal"; // This key must be different from "Principal". "Principal" is reserved for Custom mode.
|
||||
public const string IdentitiesKey = "Identities";
|
||||
#pragma warning restore 1591
|
||||
|
||||
List<ClaimsIdentity> _identityCollection = new List<ClaimsIdentity>();
|
||||
|
||||
//
|
||||
// Add an issuer to specify that this is a IDFx issued AuthorizationPolicy.
|
||||
//
|
||||
SysClaimSet _issuer = SysClaimSet.System;
|
||||
string _id = UniqueId.CreateUniqueId();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="AuthorizationPolicy"/>
|
||||
/// </summary>
|
||||
public AuthorizationPolicy()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="AuthorizationPolicy"/>
|
||||
/// </summary>
|
||||
/// <param name="identity">ClaimsIdentity for the AuthorizationPolicy.</param>
|
||||
/// <exception cref="ArgumentNullException">One of the input argument is null.</exception>
|
||||
public AuthorizationPolicy(ClaimsIdentity identity)
|
||||
{
|
||||
if (identity == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identity");
|
||||
}
|
||||
|
||||
_identityCollection.Add(identity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="AuthorizationPolicy"/>
|
||||
/// </summary>
|
||||
/// <param name="identityCollection">Collection of identities.</param>
|
||||
public AuthorizationPolicy(IEnumerable<ClaimsIdentity> identityCollection)
|
||||
{
|
||||
if (identityCollection == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identityCollection");
|
||||
}
|
||||
|
||||
List<ClaimsIdentity> collection = new List<ClaimsIdentity>();
|
||||
foreach (ClaimsIdentity identity in identityCollection)
|
||||
{
|
||||
collection.Add(identity);
|
||||
}
|
||||
|
||||
_identityCollection = collection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a ClaimsIdentity collection.
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<ClaimsIdentity> IdentityCollection
|
||||
{
|
||||
get
|
||||
{
|
||||
return _identityCollection.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
#region IAuthorizationPolicy Members
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the current Policy. This is provided for backward compatibility
|
||||
/// of WCF Claims model. We always return true without affecting the EvaluationContext.
|
||||
/// </summary>
|
||||
/// <param name="evaluationContext">The current EvaluationContext.</param>
|
||||
/// <param name="state">The reference state object.</param>
|
||||
/// <returns>True if the Policy was successfully applied.</returns>
|
||||
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
|
||||
{
|
||||
if (null == evaluationContext || null == evaluationContext.Properties)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("evaluationContext");
|
||||
}
|
||||
|
||||
if (0 == _identityCollection.Count)
|
||||
{
|
||||
//
|
||||
// Nothing to do here.
|
||||
//
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Locate or create the ClaimsPrincipal
|
||||
//
|
||||
object principalObj = null;
|
||||
if (!evaluationContext.Properties.TryGetValue(ClaimsPrincipalKey, out principalObj))
|
||||
{
|
||||
ClaimsPrincipal principalToAdd = CreateClaimsPrincipalFromIdentities(_identityCollection);
|
||||
|
||||
evaluationContext.Properties.Add(ClaimsPrincipalKey, principalToAdd);
|
||||
|
||||
if (DiagnosticUtility.ShouldTrace(TraceEventType.Information))
|
||||
{
|
||||
TraceUtility.TraceEvent(
|
||||
TraceEventType.Information,
|
||||
TraceCode.Diagnostics,
|
||||
SR.GetString(SR.TraceSetPrincipalOnEvaluationContext),
|
||||
new ClaimsPrincipalTraceRecord(principalToAdd),
|
||||
null,
|
||||
null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ClaimsPrincipal principal = principalObj as ClaimsPrincipal;
|
||||
if (null != principal && null != principal.Identities)
|
||||
{
|
||||
principal.AddIdentities(_identityCollection);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Someone stomped on our ClaimsPrincipal property key in the properties collection
|
||||
// Just trace this for now.
|
||||
//
|
||||
if (DiagnosticUtility.ShouldTrace(TraceEventType.Error))
|
||||
{
|
||||
TraceUtility.TraceString(
|
||||
TraceEventType.Error,
|
||||
SR.GetString(SR.ID8004,
|
||||
ClaimsPrincipalKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Locate or create evaluationContext.Properties[ "Identities" ] with identities
|
||||
//
|
||||
object identitiesObj = null;
|
||||
if (!evaluationContext.Properties.TryGetValue(IdentitiesKey, out identitiesObj))
|
||||
{
|
||||
List<ClaimsIdentity> identities = new List<ClaimsIdentity>();
|
||||
foreach (ClaimsIdentity ici in _identityCollection)
|
||||
{
|
||||
identities.Add(ici);
|
||||
}
|
||||
|
||||
evaluationContext.Properties.Add(IdentitiesKey, identities);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<ClaimsIdentity> identities;
|
||||
identities = identitiesObj as List<ClaimsIdentity>;
|
||||
|
||||
foreach (ClaimsIdentity ici in _identityCollection)
|
||||
{
|
||||
identities.Add(ici);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static ClaimsPrincipal CreateClaimsPrincipalFromIdentities(IEnumerable<ClaimsIdentity> identities)
|
||||
{
|
||||
ClaimsIdentity selectedClaimsIdentity = SelectPrimaryIdentity(identities);
|
||||
|
||||
if (selectedClaimsIdentity == null)
|
||||
{
|
||||
//return an anonymous identity
|
||||
return new ClaimsPrincipal(new ClaimsIdentity());
|
||||
}
|
||||
|
||||
ClaimsPrincipal principal = CreateFromIdentity(selectedClaimsIdentity);
|
||||
|
||||
// Add the remaining identities.
|
||||
foreach (ClaimsIdentity identity in identities)
|
||||
{
|
||||
if (identity != selectedClaimsIdentity)
|
||||
{
|
||||
principal.AddIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
return principal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the appropriate implementation of an IClaimsPrincipal base on the
|
||||
/// type of the specified IIdentity (e.g. WindowsClaimsPrincipal for a WindowsIdentity).
|
||||
/// Note the appropriate IClaimsIdentity is generated based on the specified IIdentity
|
||||
/// as well.
|
||||
/// </summary>
|
||||
/// <param name="identity">An implementation of IIdentity</param>
|
||||
/// <returns>A claims-based principal.</returns>
|
||||
private static ClaimsPrincipal CreateFromIdentity(IIdentity identity)
|
||||
{
|
||||
if (null == identity)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identity");
|
||||
}
|
||||
|
||||
WindowsIdentity wci = identity as WindowsIdentity;
|
||||
if (null != wci)
|
||||
{
|
||||
return new WindowsPrincipal(wci);
|
||||
}
|
||||
|
||||
WindowsIdentity wi = identity as WindowsIdentity;
|
||||
if (null != wi)
|
||||
{
|
||||
return new WindowsPrincipal(wi);
|
||||
}
|
||||
|
||||
ClaimsIdentity ici = identity as ClaimsIdentity;
|
||||
if (null != ici)
|
||||
{
|
||||
return new ClaimsPrincipal(ici);
|
||||
}
|
||||
|
||||
return new ClaimsPrincipal(new ClaimsIdentity(identity));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method iterates through the collection of ClaimsIdentities
|
||||
/// and determines which identity must be used as the primary one.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the identities collection contains a WindowsClaimsIdentity, it is the most preferred.
|
||||
/// If the identities collection contains an RsaClaimsIdentity, it is the least preferred.
|
||||
/// </remarks>
|
||||
private static ClaimsIdentity SelectPrimaryIdentity(IEnumerable<ClaimsIdentity> identities)
|
||||
{
|
||||
if (identities == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identities");
|
||||
}
|
||||
|
||||
//
|
||||
// Loop through the identities to determine the primary identity.
|
||||
//
|
||||
ClaimsIdentity selectedClaimsIdentity = null;
|
||||
|
||||
foreach (ClaimsIdentity identity in identities)
|
||||
{
|
||||
if (identity is WindowsIdentity)
|
||||
{
|
||||
//
|
||||
// If there is a WindowsIdentity, return that.
|
||||
//
|
||||
selectedClaimsIdentity = identity;
|
||||
break;
|
||||
}
|
||||
else if (identity.FindFirst(ClaimTypes.Rsa) != null)
|
||||
{
|
||||
//this is a RSA identity
|
||||
//it is the least preffered identity
|
||||
if (selectedClaimsIdentity == null)
|
||||
{
|
||||
selectedClaimsIdentity = identity;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (selectedClaimsIdentity == null)
|
||||
{
|
||||
//
|
||||
// If no primary identity has been selected yet, choose the current identity.
|
||||
//
|
||||
selectedClaimsIdentity = identity;
|
||||
}
|
||||
}
|
||||
|
||||
return selectedClaimsIdentity;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Issuer Claimset. This will return a DefaultClaimSet with just one claim
|
||||
/// whose ClaimType is http://schemas.microsoft.com/claims/identityclaim.
|
||||
/// </summary>
|
||||
public SysClaimSet Issuer
|
||||
{
|
||||
get
|
||||
{
|
||||
return _issuer;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IAuthorizationComponent Members
|
||||
|
||||
/// <summary>
|
||||
/// Returns an Id for the ClaimsPrincipal.
|
||||
/// </summary>
|
||||
public string Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
using System.Globalization;
|
||||
using HexBinary = System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary;
|
||||
|
||||
public abstract class BinaryKeyIdentifierClause : SecurityKeyIdentifierClause
|
||||
{
|
||||
readonly byte[] identificationData;
|
||||
|
||||
protected BinaryKeyIdentifierClause(string clauseType, byte[] identificationData, bool cloneBuffer)
|
||||
: this(clauseType, identificationData, cloneBuffer, null, 0)
|
||||
{
|
||||
}
|
||||
|
||||
protected BinaryKeyIdentifierClause(string clauseType, byte[] identificationData, bool cloneBuffer, byte[] derivationNonce, int derivationLength)
|
||||
: base(clauseType, derivationNonce, derivationLength)
|
||||
{
|
||||
if (identificationData == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("identificationData"));
|
||||
}
|
||||
if (identificationData.Length == 0)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("identificationData", SR.GetString(SR.LengthMustBeGreaterThanZero)));
|
||||
}
|
||||
|
||||
if (cloneBuffer)
|
||||
{
|
||||
this.identificationData = SecurityUtils.CloneBuffer(identificationData);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.identificationData = identificationData;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GetBuffer()
|
||||
{
|
||||
return SecurityUtils.CloneBuffer(this.identificationData);
|
||||
}
|
||||
|
||||
protected byte[] GetRawBuffer()
|
||||
{
|
||||
return this.identificationData;
|
||||
}
|
||||
|
||||
public override bool Matches(SecurityKeyIdentifierClause keyIdentifierClause)
|
||||
{
|
||||
BinaryKeyIdentifierClause that = keyIdentifierClause as BinaryKeyIdentifierClause;
|
||||
|
||||
// PreSharp Bug: Parameter 'that' to this public method must be validated: A null-dereference can occur here.
|
||||
#pragma warning suppress 56506
|
||||
return ReferenceEquals(this, that) || (that != null && that.Matches(this.identificationData));
|
||||
}
|
||||
|
||||
public bool Matches(byte[] data)
|
||||
{
|
||||
return Matches(data, 0);
|
||||
}
|
||||
|
||||
public bool Matches(byte[] data, int offset)
|
||||
{
|
||||
if (offset < 0)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
|
||||
}
|
||||
return SecurityUtils.MatchesBuffer(this.identificationData, 0, data, offset);
|
||||
}
|
||||
|
||||
internal string ToBase64String()
|
||||
{
|
||||
return Convert.ToBase64String(this.identificationData);
|
||||
}
|
||||
|
||||
internal string ToHexString()
|
||||
{
|
||||
return new HexBinary(this.identificationData).ToString();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,207 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System.Runtime.Serialization;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a serializable version of a token that can be attached to a <see cref="System.Security.Claims.ClaimsIdentity"/> to retain the
|
||||
/// original token that was used to create <see cref="System.Security.Claims.ClaimsIdentity"/>
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class BootstrapContext : ISerializable
|
||||
{
|
||||
SecurityToken _token;
|
||||
string _tokenString;
|
||||
byte[] _tokenBytes;
|
||||
SecurityTokenHandler _tokenHandler;
|
||||
|
||||
const string _tokenTypeKey = "K";
|
||||
const string _tokenKey = "T";
|
||||
const char _securityTokenType = 'T';
|
||||
const char _stringTokenType = 'S';
|
||||
const char _byteTokenType = 'B';
|
||||
|
||||
protected BootstrapContext(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (info == null)
|
||||
return;
|
||||
|
||||
switch (info.GetChar(_tokenTypeKey))
|
||||
{
|
||||
case _securityTokenType:
|
||||
{
|
||||
SecurityTokenHandler sth = context.Context as SecurityTokenHandler;
|
||||
if (sth != null)
|
||||
{
|
||||
using (XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(Convert.FromBase64String(info.GetString(_tokenKey)), XmlDictionaryReaderQuotas.Max))
|
||||
{
|
||||
reader.MoveToContent();
|
||||
if (sth.CanReadToken(reader))
|
||||
{
|
||||
string tokenName = reader.LocalName;
|
||||
string tokenNamespace = reader.NamespaceURI;
|
||||
SecurityToken token = sth.ReadToken(reader);
|
||||
|
||||
if (token == null)
|
||||
{
|
||||
_tokenString = Text.Encoding.UTF8.GetString(Convert.FromBase64String(info.GetString(_tokenKey)));
|
||||
}
|
||||
else
|
||||
{
|
||||
_token = token;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_tokenString = Text.Encoding.UTF8.GetString(Convert.FromBase64String(info.GetString(_tokenKey)));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case _stringTokenType:
|
||||
{
|
||||
_tokenString = info.GetString(_tokenKey);
|
||||
}
|
||||
break;
|
||||
|
||||
case _byteTokenType:
|
||||
{
|
||||
_tokenBytes = (byte[])info.GetValue(_tokenKey, typeof(byte[]));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A SecurityToken and a SecurityTokenHandler that can serialize the token.
|
||||
/// </summary>
|
||||
/// <param name="token"><see cref="SecurityToken"/> that can be serialized. Cannot be null.</param>
|
||||
/// <param name="tokenHandler"><see cref="SecurityTokenHandler"/> that is responsible for serializing the token. Cannon be null.</param>
|
||||
/// <exception cref="ArgumentNullException"> thrown if 'token' or 'tokenHandler' is null.</exception>
|
||||
/// <remarks>The <see cref="SecurityTokenHandler"/> is used not used to deserialize the token as it cannot be assumed to exist</remarks>
|
||||
public BootstrapContext(SecurityToken token, SecurityTokenHandler tokenHandler)
|
||||
{
|
||||
if (token == null)
|
||||
{
|
||||
throw new ArgumentNullException("token");
|
||||
}
|
||||
|
||||
if (tokenHandler == null)
|
||||
{
|
||||
throw new ArgumentNullException("tokenHandler");
|
||||
}
|
||||
|
||||
_token = token;
|
||||
_tokenHandler = tokenHandler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// String that represents a SecurityToken.
|
||||
/// </summary>
|
||||
/// <param name="token">string that represents a token. Can not be null.</param>
|
||||
/// <exception cref="ArgumentNullException"> thrown if 'token' is null.</exception>
|
||||
public BootstrapContext(string token)
|
||||
{
|
||||
if (token == null)
|
||||
{
|
||||
throw new ArgumentNullException("token");
|
||||
}
|
||||
|
||||
_tokenString = token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// String that represents a SecurityToken.
|
||||
/// </summary>
|
||||
/// <param name="token">string that represents a token. Can not be null.</param>
|
||||
/// <exception cref="ArgumentNullException"> thrown if 'token' is null.</exception>
|
||||
public BootstrapContext(byte[] token)
|
||||
{
|
||||
if (token == null)
|
||||
{
|
||||
throw new ArgumentNullException("token");
|
||||
}
|
||||
|
||||
_tokenBytes = token;
|
||||
}
|
||||
|
||||
#region ISerializable Members
|
||||
/// <summary>
|
||||
/// Called to serialize this context.
|
||||
/// </summary>
|
||||
/// <param name="info"><see cref="SerializationInfo"/> container for storing data. Cannot be null.</param>
|
||||
/// <param name="context"><see cref="StreamingContext"/> contains the context for streaming and optionally additional user data.</param>
|
||||
/// <exception cref="ArgumentNullException"> thrown if 'info' is null.</exception>
|
||||
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (_tokenBytes != null)
|
||||
{
|
||||
info.AddValue(_tokenTypeKey, _byteTokenType);
|
||||
info.AddValue(_tokenKey, _tokenBytes);
|
||||
}
|
||||
else if (_tokenString != null)
|
||||
{
|
||||
info.AddValue(_tokenTypeKey, _stringTokenType);
|
||||
info.AddValue(_tokenKey, _tokenString);
|
||||
}
|
||||
else if (_token != null && _tokenHandler != null)
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
info.AddValue(_tokenTypeKey, _securityTokenType);
|
||||
using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(ms, Text.Encoding.UTF8, false))
|
||||
{
|
||||
_tokenHandler.WriteToken(writer, _token);
|
||||
writer.Flush();
|
||||
info.AddValue(_tokenKey, Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets the string that was passed in constructor. If a different constructor was used, will be null.
|
||||
/// </summary>
|
||||
public byte[] TokenBytes
|
||||
{
|
||||
get { return _tokenBytes; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the string that was passed in constructor. If a different constructor was used, will be null.
|
||||
/// </summary>
|
||||
public string Token
|
||||
{
|
||||
get { return _tokenString; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the SecurityToken that was passed in constructor. If a different constructor was used, will be null.
|
||||
/// </summary>
|
||||
public SecurityToken SecurityToken
|
||||
{
|
||||
get { return _token; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the SecurityTokenHandler that was passed in constructor. If a different constructor was used, will be null.
|
||||
/// </summary>
|
||||
public SecurityTokenHandler SecurityTokenHandler
|
||||
{
|
||||
get { return _tokenHandler; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ComputedKeyAlgorithms.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// Used in the RST to indicated the desired algorithm used to compute key based on
|
||||
/// the combined entropies from both token requestor and token issuer.
|
||||
/// </summary>
|
||||
public static class ComputedKeyAlgorithms
|
||||
{
|
||||
#pragma warning disable 1591
|
||||
public const string Psha1 = "http://schemas.microsoft.com/idfx/computedkeyalgorithm/psha1";
|
||||
#pragma warning restore 1591
|
||||
}
|
||||
}
|
@@ -0,0 +1,220 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Xml;
|
||||
using System.IdentityModel.Configuration;
|
||||
using System.IdentityModel.Diagnostics.Application;
|
||||
using System.Runtime.Diagnostics;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a name service that resolves issuer tokens to strings. This class maintains a
|
||||
/// list of trusted issuers dictionary that maps the trust issuer certificate thumbpring to a
|
||||
/// issuer name. The class can only resolve X.509Certificates. The map can be configured in
|
||||
/// App.config/Web.Config using the following configuration settings.
|
||||
/// <system.identityModel>
|
||||
/// <issuerNameRegistry type='ConfigurationBasedIssuerNameRegistry'>
|
||||
/// <trustedIssuers>
|
||||
/// <add thumbprint='ASN.1EncodedFormOfTheThumbprint' name='MappedName' />
|
||||
/// <add thumbprint='ASN.1EncodedFormOfTheThumbprint' />
|
||||
/// <remove thumbprint='ASN.1EncodedFormOfTheThumbprint' />
|
||||
/// < clear/>
|
||||
/// <trustedIssuers/>
|
||||
/// </issuerNameRegistry>
|
||||
/// </system.identityModel>
|
||||
/// </summary>
|
||||
public class ConfigurationBasedIssuerNameRegistry : IssuerNameRegistry
|
||||
{
|
||||
Dictionary<string, string> _configuredTrustedIssuers = new Dictionary<string, string>(new ThumbprintKeyComparer());
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="ConfigurationBasedIssuerNameRegistry"/>
|
||||
/// </summary>
|
||||
public ConfigurationBasedIssuerNameRegistry()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom handling of configuration elements
|
||||
/// </summary>
|
||||
/// <param name="customConfiguration">Custom configuration to be loaded. This is the XmlElement
|
||||
/// that represents the map that is specified in App.config.</param>
|
||||
/// <exception cref="ArgumentNullException">The input parameter 'customConfiguration' is null.</exception>
|
||||
/// <exception cref="InvalidOperationException">The configuration contains element that is not
|
||||
/// recognized.</exception>
|
||||
public override void LoadCustomConfiguration(XmlNodeList customConfiguration)
|
||||
{
|
||||
if (customConfiguration == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("customConfiguration");
|
||||
}
|
||||
//
|
||||
// We only expect a single child here - TrustedIssuers
|
||||
//
|
||||
List<XmlElement> configNodes = XmlUtil.GetXmlElements(customConfiguration);
|
||||
|
||||
if (configNodes.Count != 1)
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7019, typeof(ConfigurationBasedIssuerNameRegistry).Name));
|
||||
}
|
||||
|
||||
XmlElement customConfigElement = configNodes[0];
|
||||
|
||||
if (!StringComparer.Ordinal.Equals(customConfigElement.LocalName, ConfigurationStrings.TrustedIssuers))
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7002, customConfigElement.LocalName, ConfigurationStrings.TrustedIssuers));
|
||||
}
|
||||
|
||||
foreach (XmlNode node in customConfigElement.ChildNodes)
|
||||
{
|
||||
XmlElement childElement = node as XmlElement;
|
||||
if (childElement != null)
|
||||
{
|
||||
if (StringComparer.Ordinal.Equals(childElement.LocalName, ConfigurationStrings.Add))
|
||||
{
|
||||
var thumbprintAttribute = childElement.Attributes.GetNamedItem(ConfigurationStrings.Thumbprint);
|
||||
var nameAttribute = childElement.Attributes.GetNamedItem(ConfigurationStrings.Name);
|
||||
|
||||
if (childElement.Attributes.Count > 2 || thumbprintAttribute == null)
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(
|
||||
SR.GetString(
|
||||
SR.ID7010,
|
||||
String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/{1}", customConfigElement.LocalName, childElement.LocalName),
|
||||
String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0} and {1}", ConfigurationStrings.Thumbprint, ConfigurationStrings.Name)));
|
||||
}
|
||||
|
||||
string thumbprint = thumbprintAttribute.Value;
|
||||
thumbprint = thumbprint.Replace(" ", "");
|
||||
// add issuer name to interned strings since it will show up in many claims
|
||||
string issuerName = ((nameAttribute == null) || string.IsNullOrEmpty(nameAttribute.Value)) ? String.Empty : String.Intern(nameAttribute.Value);
|
||||
_configuredTrustedIssuers.Add(thumbprint, issuerName);
|
||||
}
|
||||
else if (StringComparer.Ordinal.Equals(childElement.LocalName, ConfigurationStrings.Remove))
|
||||
{
|
||||
if (childElement.Attributes.Count != 1 || !StringComparer.Ordinal.Equals(childElement.Attributes[0].LocalName, ConfigurationStrings.Thumbprint))
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(
|
||||
SR.GetString(
|
||||
SR.ID7010,
|
||||
String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/{1}", customConfigElement.LocalName, childElement.LocalName),
|
||||
ConfigurationStrings.Thumbprint));
|
||||
}
|
||||
|
||||
string thumbprint = childElement.Attributes.GetNamedItem(ConfigurationStrings.Thumbprint).Value;
|
||||
thumbprint = thumbprint.Replace(" ", "");
|
||||
_configuredTrustedIssuers.Remove(thumbprint);
|
||||
}
|
||||
else if (StringComparer.Ordinal.Equals(childElement.LocalName, ConfigurationStrings.Clear))
|
||||
{
|
||||
_configuredTrustedIssuers.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7002, customConfigElement.LocalName, childElement.LocalName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the issuer name of the given X509SecurityToken mapping the Certificate Thumbprint to
|
||||
/// a name in the configured map.
|
||||
/// </summary>
|
||||
/// <param name="securityToken">SecurityToken for which the issuer name is requested.</param>
|
||||
/// <returns>Issuer name if the token was registered, null otherwise.</returns>
|
||||
/// <exception cref="ArgumentNullException">The input parameter 'securityToken' is null.</exception>
|
||||
public override string GetIssuerName(SecurityToken securityToken)
|
||||
{
|
||||
if (securityToken == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("securityToken");
|
||||
}
|
||||
|
||||
X509SecurityToken x509SecurityToken = securityToken as X509SecurityToken;
|
||||
if (x509SecurityToken != null)
|
||||
{
|
||||
string thumbprint = x509SecurityToken.Certificate.Thumbprint;
|
||||
if (_configuredTrustedIssuers.ContainsKey(thumbprint))
|
||||
{
|
||||
string issuerName = _configuredTrustedIssuers[thumbprint];
|
||||
issuerName = string.IsNullOrEmpty(issuerName) ? x509SecurityToken.Certificate.Subject : issuerName;
|
||||
|
||||
if (TD.GetIssuerNameSuccessIsEnabled())
|
||||
{
|
||||
TD.GetIssuerNameSuccess(EventTraceActivity.GetFromThreadOrCreate(), issuerName, securityToken.Id);
|
||||
}
|
||||
|
||||
return issuerName;
|
||||
}
|
||||
}
|
||||
|
||||
if (TD.GetIssuerNameFailureIsEnabled())
|
||||
{
|
||||
TD.GetIssuerNameFailure(EventTraceActivity.GetFromThreadOrCreate(), securityToken.Id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Dictionary of Configured Trusted Issuers. The key
|
||||
/// to the dictionary is the ASN.1 encoded form of the Thumbprint
|
||||
/// of the trusted issuer's certificate and the value is the issuer name.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> ConfiguredTrustedIssuers
|
||||
{
|
||||
get { return _configuredTrustedIssuers; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a trusted issuer to the collection.
|
||||
/// </summary>
|
||||
/// <param name="certificateThumbprint">ASN.1 encoded form of the trusted issuer's certificate Thumbprint.</param>
|
||||
/// <param name="name">Name of the trusted issuer.</param>
|
||||
/// <exception cref="ArgumentException">The argument 'certificateThumbprint' or 'name' is either null or Empty.</exception>
|
||||
/// <exception cref="InvalidOperationException">The issuer specified by 'certificateThumbprint' argument has already been configured.</exception>
|
||||
public void AddTrustedIssuer(string certificateThumbprint, string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(certificateThumbprint))
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperArgumentNullOrEmptyString("certificateThumbprint");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperArgumentNullOrEmptyString("name");
|
||||
}
|
||||
|
||||
if (_configuredTrustedIssuers.ContainsKey(certificateThumbprint))
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4265, certificateThumbprint));
|
||||
}
|
||||
|
||||
certificateThumbprint = certificateThumbprint.Replace(" ", "");
|
||||
|
||||
_configuredTrustedIssuers.Add(certificateThumbprint, name);
|
||||
}
|
||||
|
||||
class ThumbprintKeyComparer : IEqualityComparer<string>
|
||||
{
|
||||
#region IEqualityComparer<string> Members
|
||||
|
||||
public bool Equals(string x, string y)
|
||||
{
|
||||
return StringComparer.OrdinalIgnoreCase.Equals(x, y);
|
||||
}
|
||||
|
||||
public int GetHashCode(string obj)
|
||||
{
|
||||
return obj.ToUpper(CultureInfo.InvariantCulture).GetHashCode();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,342 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
|
||||
// ASN.1 DER. DER refers to Distinguished Encoding Rules.
|
||||
internal static class DEREncoding
|
||||
{
|
||||
// OID=1.2.840.113554.1.2.2 (Kerberos V5) { 0x06, 0x09, 0x2a, 0x86,
|
||||
// 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02 }
|
||||
|
||||
// 1. 0x60 -- Tag for [APPLICATION 0] SEQUENCE; indicates that
|
||||
// -- constructed form, definite length encoding follows.
|
||||
// 2. Token length octets, specifying length of subsequent data
|
||||
// (i.e., the summed lengths of elements 3-5 in this list, and of the
|
||||
// mechanism-defined token object following the tag). This element
|
||||
// comprises a variable number of octets:
|
||||
// 2a. If the indicated value is less than 128, it shall be
|
||||
// represented in a single octet with bit 8 (high order) set to
|
||||
// "0" and the remaining bits representing the value.
|
||||
// 2b. If the indicated value is 128 or more, it shall be
|
||||
// represented in two or more octets, with bit 8 of the first
|
||||
// octet set to "1" and the remaining bits of the first octet
|
||||
// specifying the number of additional octets. The subsequent
|
||||
// octets carry the value, 8 bits per octet, most significant
|
||||
// digit first. The minimum number of octets shall be used to
|
||||
// encode the length (i.e., no octets representing leading zeros
|
||||
// shall be included within the length encoding).
|
||||
|
||||
// 3. 0x06 -- Tag for OBJECT IDENTIFIER
|
||||
|
||||
// 4. Object identifier length -- length (number of octets) of
|
||||
// -- the encoded object identifier contained in element 5,
|
||||
// -- encoded per rules as described in 2a. and 2b. above.
|
||||
|
||||
// 5. Object identifier octets -- variable number of octets,
|
||||
// -- encoded per ASN.1 BER rules:
|
||||
|
||||
// 5a. The first octet contains the sum of two values: (1) the
|
||||
// top-level object identifier component, multiplied by 40
|
||||
// (decimal), and (2) the second-level object identifier
|
||||
// component. This special case is the only point within an
|
||||
// object identifier encoding where a single octet represents
|
||||
// contents of more than one component.
|
||||
|
||||
// 5b. Subsequent octets, if required, encode successively-lower
|
||||
// components in the represented object identifier. A component's
|
||||
// encoding may span multiple octets, encoding 7 bits per octet
|
||||
// (most significant bits first) and with bit 8 set to "1" on all
|
||||
// but the final octet in the component's encoding. The minimum
|
||||
// number of octets shall be used to encode each component (i.e.,
|
||||
// no octets representing leading zeros shall be included within a
|
||||
// component's encoding).
|
||||
|
||||
// (Note: In many implementations, elements 3-5 may be stored and
|
||||
// referenced as a contiguous string constant.)
|
||||
|
||||
|
||||
static byte[] mech = new byte[] { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x12, 0x01, 0x02, 0x02 };
|
||||
static byte[] type = new byte[] { 0x01, 0x00 };
|
||||
|
||||
private static bool BufferIsEqual(byte[] arrayOne, int offsetOne, byte[] arrayTwo, int offsetTwo, int length)
|
||||
{
|
||||
if (length > arrayOne.Length - offsetOne)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (length > arrayTwo.Length - offsetTwo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (arrayOne[offsetOne + i] != arrayTwo[offsetTwo + i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// length is assumed to be non negative
|
||||
//
|
||||
|
||||
public static int LengthSize(int length)
|
||||
{
|
||||
|
||||
if (length < (1 << 7))
|
||||
{
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (length < (1 << 8))
|
||||
{
|
||||
|
||||
return 2;
|
||||
}
|
||||
else if (length < (1 << 16))
|
||||
{
|
||||
|
||||
return 3;
|
||||
}
|
||||
else if (length < (1 << 24))
|
||||
{
|
||||
|
||||
return 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// fills in a buffer with the token header. The buffer is assumed
|
||||
// to be the right size. buffer is advanced past the token header
|
||||
//
|
||||
// bodySize includes TokenId
|
||||
//
|
||||
|
||||
public static void MakeTokenHeader(int bodySize, byte[] buffer, ref int offset, ref int len)
|
||||
{
|
||||
|
||||
buffer[offset++] = 0x60;
|
||||
len--;
|
||||
|
||||
WriteLength(buffer, ref offset, ref len, 1 + LengthSize(mech.Length) + mech.Length + type.Length + bodySize);
|
||||
|
||||
buffer[offset++] = 0x06; // OID
|
||||
len--;
|
||||
|
||||
WriteLength(buffer, ref offset, ref len, mech.Length);
|
||||
|
||||
System.Buffer.BlockCopy(mech, 0, buffer, offset, mech.Length);
|
||||
offset += mech.Length;
|
||||
len -= mech.Length;
|
||||
|
||||
System.Buffer.BlockCopy(type, 0, buffer, offset, type.Length);
|
||||
offset += type.Length;
|
||||
len -= type.Length;
|
||||
}
|
||||
|
||||
//
|
||||
// returns decoded length, or < 0 on failure. Advances buffer and
|
||||
// decrements length
|
||||
//
|
||||
|
||||
public static int ReadLength(byte[] buffer, ref int offset, ref int length)
|
||||
{
|
||||
|
||||
int tmp;
|
||||
int ret = 0;
|
||||
|
||||
if (length < 1)
|
||||
{
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
tmp = buffer[offset++];
|
||||
|
||||
length--;
|
||||
|
||||
if ((tmp & 0x80) != 0)
|
||||
{
|
||||
|
||||
if ((tmp &= 0x7f) > (length - 1))
|
||||
{
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
if (tmp > 4)
|
||||
{ // 4 == sizeof(int)
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
for (; tmp != 0; tmp--)
|
||||
{
|
||||
|
||||
ret = (ret << 8) + buffer[offset++];
|
||||
length--;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
ret = tmp;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// returns the length of a token, given the mech oid and the body
|
||||
// size
|
||||
//
|
||||
|
||||
public static int TokenSize(int bodySize)
|
||||
{
|
||||
|
||||
// set body size to sequence contents size, 2 for token id
|
||||
bodySize += 2 + mech.Length + LengthSize(mech.Length) + 1;
|
||||
|
||||
return (1 + LengthSize(bodySize) + bodySize);
|
||||
}
|
||||
|
||||
//
|
||||
// given a buffer containing a token, reads and verifies the token,
|
||||
// leaving buffer advanced past the token header, and setting body_size
|
||||
// to the number of remaining bytes
|
||||
//
|
||||
|
||||
public static void VerifyTokenHeader(byte[] buffer, ref int offset, ref int len)
|
||||
{
|
||||
|
||||
if ((len -= 1) < 0)
|
||||
{
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
if (buffer[offset++] != 0x60)
|
||||
{
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
int seqSize = ReadLength(buffer, ref offset, ref len);
|
||||
|
||||
if (seqSize != len)
|
||||
{
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
if ((len -= 1) < 0)
|
||||
{
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
if (buffer[offset++] != 0x06)
|
||||
{
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
int oidLength = ReadLength(buffer, ref offset, ref len); // (byte) buffer[offset++];
|
||||
|
||||
if ((oidLength & 0x7fffffff) != mech.Length)
|
||||
{ // Overflow???
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
if ((len -= oidLength) < 0)
|
||||
{
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
if (!BufferIsEqual(mech, 0, buffer, offset, mech.Length))
|
||||
{
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
offset += oidLength;
|
||||
|
||||
if ((len -= type.Length) < 0)
|
||||
{
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
if (!BufferIsEqual(type, 0, buffer, offset, type.Length))
|
||||
{
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException());
|
||||
}
|
||||
|
||||
offset += type.Length;
|
||||
}
|
||||
|
||||
public static void WriteLength(byte[] buffer, ref int offset, ref int bufferLength, int length)
|
||||
{
|
||||
|
||||
if (length < (1 << 7))
|
||||
{ // one byte
|
||||
|
||||
// *(*buffer)++ = (unsigned char) length;
|
||||
buffer[offset++] = (byte)length;
|
||||
bufferLength--;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// *(*buffer)++ = (unsigned char) (der_length_size(length) + 127);
|
||||
buffer[offset++] = (byte)(LengthSize(length) + 127);
|
||||
|
||||
if (length >= (1 << 24))
|
||||
{
|
||||
|
||||
// *(*buffer)++ = (unsigned char) (length >> 24);
|
||||
buffer[offset++] = (byte)(length >> 24);
|
||||
bufferLength--;
|
||||
}
|
||||
|
||||
if (length >= (1 << 16))
|
||||
{
|
||||
|
||||
// *(*buffer)++ = (unsigned char) ((length >> 16) & 0xff);
|
||||
buffer[offset++] = (byte)((length >> 16) & 0xFF);
|
||||
bufferLength--;
|
||||
}
|
||||
|
||||
if (length >= (1 << 8))
|
||||
{
|
||||
|
||||
// *(*buffer)++ = (unsigned char) ((length >> 8) & 0xff);
|
||||
buffer[offset++] = (byte)((length >> 8) & 0xFF);
|
||||
bufferLength--;
|
||||
}
|
||||
|
||||
// *(*buffer)++ = (unsigned char) (length & 0xff);
|
||||
buffer[offset++] = (byte)(length & 0xFF);
|
||||
bufferLength--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,149 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// A default implementation of the Token replay cache that is backed by
|
||||
/// a bounded cache.
|
||||
/// </summary>
|
||||
internal class DefaultTokenReplayCache : TokenReplayCache
|
||||
{
|
||||
static readonly int DefaultTokenReplayCacheCapacity = 500000;
|
||||
static readonly TimeSpan DefaultTokenReplayCachePurgeInterval = TimeSpan.FromMinutes(1);
|
||||
|
||||
BoundedCache<SecurityToken> _internalCache;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the default token replay cache.
|
||||
/// </summary>
|
||||
public DefaultTokenReplayCache()
|
||||
: this(DefaultTokenReplayCache.DefaultTokenReplayCacheCapacity, DefaultTokenReplayCache.DefaultTokenReplayCachePurgeInterval)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the default token replay cache with the specified
|
||||
/// capacity and purge interval.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The capacity of the token cache</param>
|
||||
/// <param name="purgeInterval">The time interval after which the cache must be purged</param>
|
||||
public DefaultTokenReplayCache(int capacity, TimeSpan purgeInterval)
|
||||
: base()
|
||||
{
|
||||
_internalCache = new BoundedCache<SecurityToken>(capacity, purgeInterval, StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the current Capacity of the cache in number of SecurityTokens.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentOutOfRangeException">If 'value' is less than or equal to zero.</exception>
|
||||
public int Capacity
|
||||
{
|
||||
get { return _internalCache.Capacity; }
|
||||
set
|
||||
{
|
||||
if (value <= 0)
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperArgumentOutOfRange("value", value, SR.GetString(SR.ID0002));
|
||||
}
|
||||
|
||||
_internalCache.Capacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all SecurityTokens from the Cache.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_internalCache.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increases the maximum number of SecurityTokens that this cache will hold.
|
||||
/// </summary>
|
||||
/// <param name="size">The capacity to increase.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The input parameter 'size' is less than or equal to zero.</exception>
|
||||
/// <returns>Updated capacity</returns>
|
||||
/// <remarks>If size + current capacity >= int.MaxValue then capacity will be set to int.MaxValue and the cache capacity will be unbounded.</remarks>
|
||||
public int IncreaseCapacity(int size)
|
||||
{
|
||||
if (size <= 0)
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperArgumentOutOfRange("size", size, SR.GetString(SR.ID0002));
|
||||
}
|
||||
|
||||
return _internalCache.IncreaseCapacity(size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the time interval that will be used when checking for expired SecurityTokens.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentOutOfRangeException">If 'value' is less than or equal to TimeSpan.Zero.</exception>
|
||||
public TimeSpan PurgeInterval
|
||||
{
|
||||
get { return _internalCache.PurgeInterval; }
|
||||
set
|
||||
{
|
||||
if (value <= TimeSpan.Zero)
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperArgumentOutOfRange("value", value, SR.GetString(SR.ID0016));
|
||||
}
|
||||
|
||||
_internalCache.PurgeInterval = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to add a new entry or update an existing entry.
|
||||
/// </summary>
|
||||
/// <param name="key">Key to use when adding item.</param>
|
||||
/// <param name="securityToken">SecurityToken to add to cache, can be null.</param>
|
||||
/// <param name="expirationTime">The expiration instant of the token being added.</param>
|
||||
/// <exception cref="System.IdentityModel.LimitExceededException">Thrown if an attempt is made to add a SecurityToken if cache is at capacity.</exception>
|
||||
/// <exception cref="InvalidOperationException">Thrown if the expiration time is infinite.</exception>
|
||||
public override void AddOrUpdate(string key, SecurityToken securityToken, DateTime expirationTime)
|
||||
{
|
||||
if (DateTime.Equals(expirationTime, DateTime.MaxValue))
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID1072));
|
||||
}
|
||||
|
||||
_internalCache.TryRemove(key);
|
||||
_internalCache.TryAdd(key, securityToken, expirationTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to find if a matching entry exists in the cache.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to search for.</param>
|
||||
/// <returns>true if a matching entry is ifound in the cache, false otherwise</returns>
|
||||
public override bool Contains(string key)
|
||||
{
|
||||
return _internalCache.TryFind(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to get a SecurityToken
|
||||
/// </summary>
|
||||
/// <param name="key">The key to search for.</param>
|
||||
/// <returns>The <see cref="SecurityToken"/> found, if any, null otherwise.</returns>
|
||||
public override SecurityToken Get(string key)
|
||||
{
|
||||
SecurityToken token;
|
||||
_internalCache.TryGet(key, out token);
|
||||
return token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to remove an entry from the cache
|
||||
/// </summary>
|
||||
/// <param name="key">The key to the entry to remove</param>
|
||||
public override void Remove(string key)
|
||||
{
|
||||
_internalCache.TryRemove(key);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an empty SecurityKeyClause. This class is used when an 'encrypted data element' or ' signature element' does
|
||||
/// not contain a 'key info element' that is used to describe the key required to decrypt the data or check the signature.
|
||||
/// </summary>
|
||||
public class EmptySecurityKeyIdentifierClause : SecurityKeyIdentifierClause
|
||||
{
|
||||
object _context;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="EmptySecurityKeyIdentifierClause"/>
|
||||
/// </summary>
|
||||
/// <remarks>This constructor assumes that the user knows how to resolve the key required without any context.</remarks>
|
||||
public EmptySecurityKeyIdentifierClause()
|
||||
: this( null )
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="EmptySecurityKeyIdentifierClause"/>
|
||||
/// </summary>
|
||||
/// <param name="context">Used to provide a hint when there is a need resolve an empty clause to a particular key.
|
||||
/// In the case of Saml11 and Saml2 tokens that have signatures without KeyInfo,
|
||||
/// this clause will contain the assertion that is currently being processed.</param>
|
||||
public EmptySecurityKeyIdentifierClause( object context )
|
||||
: base( typeof( EmptySecurityKeyIdentifierClause ).ToString() )
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to provide a hint when there is a need to resolve to a particular key.
|
||||
/// In the case of Saml11 and Saml2 tokens that have signatures without KeyInfo,
|
||||
/// this will contain the assertion that is currently being processed.
|
||||
/// </summary>
|
||||
public object Context
|
||||
{
|
||||
get { return _context; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,99 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// This class defines the encrypted key encrypting credentials. They are usually used
|
||||
/// as data encrypting credentials to encrypt things like token.
|
||||
/// </summary>
|
||||
public class EncryptedKeyEncryptingCredentials : EncryptingCredentials
|
||||
{
|
||||
EncryptingCredentials _wrappingCredentials;
|
||||
byte[] _keyBytes;
|
||||
|
||||
/// <summary>
|
||||
/// Use this constructor if user wants to use the default wrapping algorithm and encryption algorithm,
|
||||
/// which are RSA-OAEP and AES256 respectively.
|
||||
/// </summary>
|
||||
/// <param name="certificate">The certificate used to encrypt the key.</param>
|
||||
public EncryptedKeyEncryptingCredentials( X509Certificate2 certificate )
|
||||
: this( new X509EncryptingCredentials( certificate ), SecurityAlgorithms.DefaultSymmetricKeyLength, SecurityAlgorithms.DefaultEncryptionAlgorithm )
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this contructor if users want to supply their own wrapping algorithm and encryption algorithm
|
||||
/// and wrapping credentials is x509 certificate.
|
||||
/// </summary>
|
||||
/// <param name="certificate">The certificate used to encrypt the session key.</param>
|
||||
/// <param name="keyWrappingAlgorithm">The key wrapping algorithm. This should be asymmetric algorithm.</param>
|
||||
/// <param name="keySizeInBits">The key size of the wrapped session key.</param>
|
||||
/// <param name="encryptionAlgorithm">The encryption algorithm when session key is used. This should be symmetric key algorithm.</param>
|
||||
public EncryptedKeyEncryptingCredentials( X509Certificate2 certificate, string keyWrappingAlgorithm, int keySizeInBits, string encryptionAlgorithm )
|
||||
: this( new X509EncryptingCredentials( certificate, keyWrappingAlgorithm ), keySizeInBits, encryptionAlgorithm )
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this constructor if users already have an encryting credentials and want to use that as a wrapping credentials.
|
||||
/// </summary>
|
||||
/// <param name="wrappingCredentials">The key wrapping credentials used to encrypt the session key.</param>
|
||||
/// <param name="keySizeInBits">The key size of the wrapped session key.</param>
|
||||
/// <param name="encryptionAlgorithm">The encryption algorithm when session key is used. This should be symmetric key algorithm.</param>
|
||||
/// <exception cref="ArgumentNullException">When the wrappingCredentials is null.</exception>
|
||||
public EncryptedKeyEncryptingCredentials( EncryptingCredentials wrappingCredentials, int keySizeInBits, string encryptionAlgorithm )
|
||||
{
|
||||
if ( wrappingCredentials == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "wrappingCredentials" );
|
||||
}
|
||||
|
||||
//
|
||||
// Key materials
|
||||
//
|
||||
if ( encryptionAlgorithm == SecurityAlgorithms.DesEncryption ||
|
||||
encryptionAlgorithm == SecurityAlgorithms.TripleDesEncryption ||
|
||||
encryptionAlgorithm == SecurityAlgorithms.TripleDesKeyWrap )
|
||||
{
|
||||
_keyBytes = CryptoHelper.KeyGenerator.GenerateDESKey( keySizeInBits );
|
||||
}
|
||||
else
|
||||
{
|
||||
_keyBytes = CryptoHelper.KeyGenerator.GenerateSymmetricKey( keySizeInBits );
|
||||
}
|
||||
base.SecurityKey = new InMemorySymmetricSecurityKey( _keyBytes );
|
||||
|
||||
//
|
||||
// Wrapping key
|
||||
//
|
||||
_wrappingCredentials = wrappingCredentials;
|
||||
|
||||
//
|
||||
// key identifier
|
||||
//
|
||||
byte[] encryptedKey = _wrappingCredentials.SecurityKey.EncryptKey( _wrappingCredentials.Algorithm, _keyBytes );
|
||||
base.SecurityKeyIdentifier = new SecurityKeyIdentifier( new EncryptedKeyIdentifierClause( encryptedKey, _wrappingCredentials.Algorithm, _wrappingCredentials.SecurityKeyIdentifier ) );
|
||||
|
||||
//
|
||||
// encryption algorithm
|
||||
//
|
||||
base.Algorithm = encryptionAlgorithm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the key wrapping credentials used to encrypt the session key, for example,
|
||||
/// X509EncryptingCredentials.
|
||||
/// </summary>
|
||||
public EncryptingCredentials WrappingCredentials
|
||||
{
|
||||
get
|
||||
{
|
||||
return _wrappingCredentials;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
using System.Globalization;
|
||||
|
||||
sealed public class EncryptedKeyIdentifierClause : BinaryKeyIdentifierClause
|
||||
{
|
||||
readonly string carriedKeyName;
|
||||
readonly string encryptionMethod;
|
||||
readonly SecurityKeyIdentifier encryptingKeyIdentifier;
|
||||
|
||||
public EncryptedKeyIdentifierClause(byte[] encryptedKey, string encryptionMethod)
|
||||
: this(encryptedKey, encryptionMethod, null)
|
||||
{
|
||||
}
|
||||
|
||||
public EncryptedKeyIdentifierClause(byte[] encryptedKey, string encryptionMethod, SecurityKeyIdentifier encryptingKeyIdentifier)
|
||||
: this(encryptedKey, encryptionMethod, encryptingKeyIdentifier, null)
|
||||
{
|
||||
}
|
||||
|
||||
public EncryptedKeyIdentifierClause(byte[] encryptedKey, string encryptionMethod, SecurityKeyIdentifier encryptingKeyIdentifier, string carriedKeyName)
|
||||
: this(encryptedKey, encryptionMethod, encryptingKeyIdentifier, carriedKeyName, true, null, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public EncryptedKeyIdentifierClause(byte[] encryptedKey, string encryptionMethod, SecurityKeyIdentifier encryptingKeyIdentifier, string carriedKeyName, byte[] derivationNonce, int derivationLength)
|
||||
: this(encryptedKey, encryptionMethod, encryptingKeyIdentifier, carriedKeyName, true, derivationNonce, derivationLength)
|
||||
{
|
||||
}
|
||||
|
||||
internal EncryptedKeyIdentifierClause(byte[] encryptedKey, string encryptionMethod, SecurityKeyIdentifier encryptingKeyIdentifier, string carriedKeyName, bool cloneBuffer, byte[] derivationNonce, int derivationLength)
|
||||
: base("http://www.w3.org/2001/04/xmlenc#EncryptedKey", encryptedKey, cloneBuffer, derivationNonce, derivationLength)
|
||||
{
|
||||
if (encryptionMethod == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encryptionMethod");
|
||||
}
|
||||
this.carriedKeyName = carriedKeyName;
|
||||
this.encryptionMethod = encryptionMethod;
|
||||
this.encryptingKeyIdentifier = encryptingKeyIdentifier;
|
||||
}
|
||||
|
||||
public string CarriedKeyName
|
||||
{
|
||||
get { return this.carriedKeyName; }
|
||||
}
|
||||
|
||||
public SecurityKeyIdentifier EncryptingKeyIdentifier
|
||||
{
|
||||
get { return this.encryptingKeyIdentifier; }
|
||||
}
|
||||
|
||||
public string EncryptionMethod
|
||||
{
|
||||
get { return this.encryptionMethod; }
|
||||
}
|
||||
|
||||
public override bool Matches(SecurityKeyIdentifierClause keyIdentifierClause)
|
||||
{
|
||||
EncryptedKeyIdentifierClause that = keyIdentifierClause as EncryptedKeyIdentifierClause;
|
||||
|
||||
// PreSharp Bug: Parameter 'that' to this public method must be validated: A null-dereference can occur here.
|
||||
#pragma warning suppress 56506
|
||||
return ReferenceEquals(this, that) || (that != null && that.Matches(this.GetRawBuffer(), this.encryptionMethod, this.carriedKeyName));
|
||||
}
|
||||
|
||||
public bool Matches(byte[] encryptedKey, string encryptionMethod, string carriedKeyName)
|
||||
{
|
||||
return Matches(encryptedKey) && this.encryptionMethod == encryptionMethod && this.carriedKeyName == carriedKeyName;
|
||||
}
|
||||
|
||||
public byte[] GetEncryptedKey()
|
||||
{
|
||||
return GetBuffer();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "EncryptedKeyIdentifierClause(EncryptedKey = {0}, Method '{1}')",
|
||||
Convert.ToBase64String(GetRawBuffer()), this.EncryptionMethod);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IdentityModel.Tokens;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// A pseudo-token which handles encryption for a token which
|
||||
/// does not natively support it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For example, a SamlSecurityToken has no notion of how to encrypt
|
||||
/// itself, so to issue an encrypted SAML11 assertion, wrap a
|
||||
/// SamlSecurityToken with an EncryptedSecurityToken and provide
|
||||
/// appropriate EncryptingCredentials.
|
||||
/// </remarks>
|
||||
public class EncryptedSecurityToken : SecurityToken
|
||||
{
|
||||
EncryptingCredentials _encryptingCredentials;
|
||||
SecurityToken _realToken;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of EncryptedSecurityToken.
|
||||
/// </summary>
|
||||
/// <param name="token">The <see cref="SecurityToken"/> to encrypt.</param>
|
||||
/// <param name="encryptingCredentials">The <see cref="EncryptingCredentials"/> to use for encryption.</param>
|
||||
public EncryptedSecurityToken(SecurityToken token, EncryptingCredentials encryptingCredentials)
|
||||
{
|
||||
if (null == token)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token");
|
||||
}
|
||||
if (null == encryptingCredentials)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encryptingCredentials");
|
||||
}
|
||||
|
||||
_encryptingCredentials = encryptingCredentials;
|
||||
_realToken = token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inherited from <see cref="SecurityToken"/>.
|
||||
/// </summary>
|
||||
public override bool CanCreateKeyIdentifierClause<T>()
|
||||
{
|
||||
return _realToken.CanCreateKeyIdentifierClause<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inherited from <see cref="SecurityToken"/>.
|
||||
/// </summary>
|
||||
public override T CreateKeyIdentifierClause<T>()
|
||||
{
|
||||
return _realToken.CreateKeyIdentifierClause<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="EncryptingCredentials"/> to use for encryption.
|
||||
/// </summary>
|
||||
public EncryptingCredentials EncryptingCredentials
|
||||
{
|
||||
get { return _encryptingCredentials; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a unique identifier of the security token.
|
||||
/// </summary>
|
||||
public override string Id
|
||||
{
|
||||
get { return _realToken.Id; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inherited from <see cref="SecurityToken"/>.
|
||||
/// </summary>
|
||||
public override bool MatchesKeyIdentifierClause(SecurityKeyIdentifierClause keyIdentifierClause)
|
||||
{
|
||||
return _realToken.MatchesKeyIdentifierClause(keyIdentifierClause);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inherited from <see cref="SecurityToken"/>.
|
||||
/// </summary>
|
||||
public override SecurityKey ResolveKeyIdentifierClause(SecurityKeyIdentifierClause keyIdentifierClause)
|
||||
{
|
||||
return _realToken.ResolveKeyIdentifierClause(keyIdentifierClause);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inherited from <see cref="SecurityToken"/>.
|
||||
/// </summary>
|
||||
public override ReadOnlyCollection<SecurityKey> SecurityKeys
|
||||
{
|
||||
get { return _realToken.SecurityKeys; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the encrypted <see cref="SecurityToken"/>.
|
||||
/// </summary>
|
||||
public SecurityToken Token
|
||||
{
|
||||
get { return _realToken; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the first instant in time at which this security token is valid.
|
||||
/// </summary>
|
||||
public override DateTime ValidFrom
|
||||
{
|
||||
get { return _realToken.ValidFrom; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last instant in time at which this security token is valid.
|
||||
/// </summary>
|
||||
public override DateTime ValidTo
|
||||
{
|
||||
get { return _realToken.ValidTo; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,363 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IdentityModel.Selectors;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.ServiceModel.Security;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace System.IdentityModel.Tokens
|
||||
{
|
||||
/// <summary>
|
||||
/// Token handler for an encrypted <see cref="SecurityToken"/> type.
|
||||
/// </summary>
|
||||
public class EncryptedSecurityTokenHandler : SecurityTokenHandler
|
||||
{
|
||||
static string[] _tokenTypeIdentifiers = new string[] { null };
|
||||
SecurityTokenSerializer _keyInfoSerializer;
|
||||
object _syncObject = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of <see cref="EncryptedSecurityTokenHandler"/>
|
||||
/// </summary>
|
||||
public EncryptedSecurityTokenHandler()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the current XML element is pointing to a KeyIdentifierClause that
|
||||
/// can be de-serialized by this instance.
|
||||
/// </summary>
|
||||
/// <param name="reader">An XML reader positioned at the start element.
|
||||
/// The reader should not be advanced.</param>
|
||||
/// <returns>true if the XML reader is positioned at an EncryptedKey xml element
|
||||
/// as defined in section 3.5.1 of 'http://www.w3.org/TR/2002/REC-xmlenc-core-20021210'.</returns>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="reader"/> is null.</exception>
|
||||
public override bool CanReadKeyIdentifierClause(XmlReader reader)
|
||||
{
|
||||
if (reader == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
|
||||
}
|
||||
|
||||
// <EncryptedKey>
|
||||
return reader.IsStartElement(XmlEncryptionConstants.Elements.EncryptedKey, XmlEncryptionConstants.Namespace);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the reader is pointing to an EncryptedData element.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader positioned at a security token.</param>
|
||||
/// <returns>true if the reader is positioned at EncryptedData else false.</returns>
|
||||
/// <remarks>Does not move the reader when returning false.</remarks>
|
||||
public override bool CanReadToken(XmlReader reader)
|
||||
{
|
||||
return EncryptedDataElement.CanReadFrom(reader);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the base CanWriteToken and returns true always.
|
||||
/// </summary>
|
||||
public override bool CanWriteToken
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets a SecurityTokenSerializers that will be used to serialize and deserializer
|
||||
/// SecurtyKeyIdentifier of the <xenc:EncryptedData> element.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentNullException">Input parameter 'value' is null.</exception>
|
||||
public SecurityTokenSerializer KeyInfoSerializer
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _keyInfoSerializer == null )
|
||||
{
|
||||
lock ( _syncObject )
|
||||
{
|
||||
if ( _keyInfoSerializer == null )
|
||||
{
|
||||
SecurityTokenHandlerCollection sthc = ( ContainingCollection != null ) ?
|
||||
ContainingCollection : SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();
|
||||
_keyInfoSerializer = new SecurityTokenSerializerAdapter(sthc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _keyInfoSerializer;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
|
||||
}
|
||||
|
||||
_keyInfoSerializer = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the encrypted security token.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader from which to read the token.</param>
|
||||
/// <returns>An instance of <see cref="SecurityToken"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException">Input parameter 'reader' is null.</exception>
|
||||
/// <exception cref="InvalidOperationException">One of the properties 'Configuration' or 'Configuration.ServiceTokenResolver' is null. This property is required for obtaining keys for decryption.</exception>
|
||||
/// <exception cref="SecurityTokenException">A <see cref="SecurityKeyIdentifier"/> is not found inside the xml pointed to by the reader.</exception>
|
||||
/// <exception cref="EncryptedTokenDecryptionFailedException">The <see cref="SecurityKeyIdentifier"/> found inside the xml cannot be resolved by Configuration.ServiceTokenResolver to a <see cref="SecurityKey"/>.</exception>
|
||||
/// <exception cref="SecurityTokenException">The <see cref="SecurityKeyIdentifier"/> is not a <see cref="SymmetricSecurityKey"/>.</exception>
|
||||
/// <exception cref="InvalidOperationException">The ContainingCollection (<see cref="SecurityTokenHandlerCollection"/>) is unable to find a <see cref="SecurityTokenHandler"/> that is able to read the decrypted xml and return a <see cref="SecurityToken"/>.</exception>
|
||||
public override SecurityToken ReadToken(XmlReader reader)
|
||||
{
|
||||
if (null == reader)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
|
||||
}
|
||||
|
||||
if (this.Configuration == null)
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4274));
|
||||
}
|
||||
|
||||
if (this.Configuration.ServiceTokenResolver == null)
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4276));
|
||||
}
|
||||
|
||||
//
|
||||
// Read the encrypted data element
|
||||
//
|
||||
EncryptedDataElement encryptedData = new EncryptedDataElement(KeyInfoSerializer);
|
||||
encryptedData.ReadXml(XmlDictionaryReader.CreateDictionaryReader(reader));
|
||||
|
||||
//
|
||||
// All the clauses in a keyinfo must identify the same key, so we
|
||||
// can try each clause in turn and stop when one resolves.
|
||||
//
|
||||
SecurityKey decryptionKey = null;
|
||||
foreach (SecurityKeyIdentifierClause clause in encryptedData.KeyIdentifier)
|
||||
{
|
||||
this.Configuration.ServiceTokenResolver.TryResolveSecurityKey(clause, out decryptionKey);
|
||||
|
||||
if (null != decryptionKey)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Try to use the SKI to create the key instead.
|
||||
//
|
||||
if (decryptionKey == null && encryptedData.KeyIdentifier.CanCreateKey)
|
||||
{
|
||||
decryptionKey = encryptedData.KeyIdentifier.CreateKey();
|
||||
}
|
||||
|
||||
//
|
||||
// Fail if none of the clauses resolved or ski itself cannot create key.
|
||||
//
|
||||
if (null == decryptionKey)
|
||||
{
|
||||
EncryptedKeyIdentifierClause encryptedKeyClause;
|
||||
if (encryptedData.KeyIdentifier.TryFind<EncryptedKeyIdentifierClause>(out encryptedKeyClause))
|
||||
{
|
||||
//
|
||||
// System.IdentityModel.Tokens.EncryptedKeyIdentifierClause.ToString() does not print out
|
||||
// very good information except the cipher data in this case. We have worked around that
|
||||
// by using the token serializer to serialize the key identifier clause again.
|
||||
//
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
||||
new EncryptedTokenDecryptionFailedException(
|
||||
SR.GetString(SR.ID4036, XmlUtil.SerializeSecurityKeyIdentifier(encryptedData.KeyIdentifier, base.ContainingCollection.KeyInfoSerializer))));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
||||
new EncryptedTokenDecryptionFailedException(SR.GetString(SR.ID4036, encryptedData.KeyIdentifier.ToString())));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Need a symmetric key
|
||||
//
|
||||
SymmetricSecurityKey symmetricKey = decryptionKey as SymmetricSecurityKey;
|
||||
if (null == symmetricKey)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
||||
new SecurityTokenException(SR.GetString(SR.ID4023)));
|
||||
}
|
||||
|
||||
//
|
||||
// Do the actual decryption
|
||||
//
|
||||
byte[] plainText;
|
||||
|
||||
using (SymmetricAlgorithm decrypter = symmetricKey.GetSymmetricAlgorithm(encryptedData.Algorithm))
|
||||
{
|
||||
plainText = encryptedData.Decrypt(decrypter);
|
||||
}
|
||||
|
||||
DebugEncryptedTokenClearText(plainText, Encoding.UTF8);
|
||||
|
||||
//
|
||||
// Read and return the plaintext token
|
||||
//
|
||||
using (XmlReader innerTokenReader = XmlDictionaryReader.CreateTextReader(plainText, XmlDictionaryReaderQuotas.Max))
|
||||
{
|
||||
if (this.ContainingCollection != null && this.ContainingCollection.CanReadToken(innerTokenReader))
|
||||
{
|
||||
return this.ContainingCollection.ReadToken(innerTokenReader);
|
||||
}
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4014, innerTokenReader.LocalName, innerTokenReader.NamespaceURI));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an EncryptedKeyIdentifierClause from a XML stream.
|
||||
/// </summary>
|
||||
/// <param name="reader">An XML reader positioned at an EncryptedKey element as defined in 'http://www.w3.org/TR/2002/REC-xmlenc-core-20021210' .</param>
|
||||
/// <returns>SecurityKeyIdentifierClause instance of type EncryptedKeyIdentifierClause.</returns>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="reader"/> is null.</exception>
|
||||
/// <exception cref="InvalidOperationException">If the <paramref name="reader"/> is not positioned at an EncryptedKey element.</exception>
|
||||
public override SecurityKeyIdentifierClause ReadKeyIdentifierClause(XmlReader reader)
|
||||
{
|
||||
if (reader == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
|
||||
}
|
||||
|
||||
// <EncryptedKey>
|
||||
if (reader.IsStartElement(XmlEncryptionConstants.Elements.EncryptedKey, XmlEncryptionConstants.Namespace))
|
||||
{
|
||||
EncryptedKeyElement encryptedKey = new EncryptedKeyElement(KeyInfoSerializer);
|
||||
encryptedKey.ReadXml(XmlDictionaryReader.CreateDictionaryReader(reader));
|
||||
return new EncryptedKeyIdentifierClause(encryptedKey.CipherData.CipherValue, encryptedKey.Algorithm, encryptedKey.KeyIdentifier);
|
||||
}
|
||||
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID3275, reader.Name, reader.NamespaceURI)));
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
static void DebugEncryptedTokenClearText(byte[] bytes, Encoding encoding)
|
||||
{
|
||||
string text = encoding.GetString(bytes);
|
||||
Debug.WriteLine(text.Substring(0, 40));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the System.Type of the token that this SecurityTokenHandler handles.
|
||||
/// Returns typeof <see cref="EncryptedSecurityToken"/> by default.
|
||||
/// </summary>
|
||||
public override Type TokenType
|
||||
{
|
||||
get { return typeof(EncryptedSecurityToken); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// By default returns an array with a single null string as there isn't any specific TokenType identifier that is
|
||||
/// associated with a <see cref="EncryptedSecurityToken"/>.
|
||||
/// </summary>
|
||||
public override string[] GetTokenTypeIdentifiers()
|
||||
{
|
||||
return _tokenTypeIdentifiers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a <see cref="EncryptedSecurityToken"/> using the xmlWriter.
|
||||
/// </summary>
|
||||
/// <param name="writer">The XmlWriter to which the encrypted token is written.</param>
|
||||
/// <param name="token">The <see cref="SecurityToken"/> which must be an instance of <see cref="EncryptedSecurityToken"/>.</param>
|
||||
/// <exception cref="ArgumentNullException">The input prameter 'writer' is null.</exception>
|
||||
/// <exception cref="ArgumentNullException">The input prameter 'token' is null.</exception>
|
||||
/// <exception cref="ArgumentException">The <see cref="SecurityToken"/> is not an instance of <see cref="EncryptedSecurityToken"/>.</exception>
|
||||
/// <exception cref="InvalidOperationException">The property 'Configuration' is null. This property is required for obtaining keys for encryption.</exception>
|
||||
/// <exception cref="InvalidOperationException">The ContaingCollection was unable to find a <see cref="SecurityTokenHandler"/> that is able to write
|
||||
/// the <see cref="SecurityToken"/> returned by 'EncryptedSecurityToken.Token'.</exception>
|
||||
/// <exception cref="SecurityTokenException">The property 'EncryptinCredentials.SecurityKey is not a <see cref="SymmetricSecurityKey"/></exception>
|
||||
public override void WriteToken(XmlWriter writer, SecurityToken token)
|
||||
{
|
||||
if (null == writer)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
|
||||
}
|
||||
|
||||
if (null == token)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token");
|
||||
}
|
||||
|
||||
EncryptedSecurityToken encryptedToken = token as EncryptedSecurityToken;
|
||||
if (null == encryptedToken)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("token", SR.GetString(SR.ID4024));
|
||||
}
|
||||
|
||||
if (this.ContainingCollection == null)
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4279));
|
||||
}
|
||||
|
||||
//
|
||||
// This implementation simply wraps the token in xenc:EncryptedData
|
||||
//
|
||||
EncryptedDataElement encryptedData = new EncryptedDataElement(KeyInfoSerializer);
|
||||
using (MemoryStream plaintextStream = new MemoryStream())
|
||||
{
|
||||
//
|
||||
// Buffer the plaintext
|
||||
//
|
||||
using (XmlDictionaryWriter plaintextWriter = XmlDictionaryWriter.CreateTextWriter(plaintextStream, Encoding.UTF8, false))
|
||||
{
|
||||
SecurityTokenHandler securityTokenHandler = this.ContainingCollection[encryptedToken.Token.GetType()];
|
||||
if (securityTokenHandler != null)
|
||||
{
|
||||
securityTokenHandler.WriteToken(plaintextWriter, encryptedToken.Token);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4224, encryptedToken.Token.GetType()));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Set up the EncryptedData element
|
||||
//
|
||||
EncryptingCredentials encryptingCredentials = encryptedToken.EncryptingCredentials;
|
||||
encryptedData.Type = XmlEncryptionConstants.EncryptedDataTypes.Element;
|
||||
encryptedData.KeyIdentifier = encryptingCredentials.SecurityKeyIdentifier;
|
||||
encryptedData.Algorithm = encryptingCredentials.Algorithm;
|
||||
|
||||
//
|
||||
// Get the encryption key, which must be symmetric
|
||||
//
|
||||
SymmetricSecurityKey encryptingKey = encryptingCredentials.SecurityKey as SymmetricSecurityKey;
|
||||
if (encryptingKey == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID3064)));
|
||||
}
|
||||
|
||||
//
|
||||
// Do the actual encryption
|
||||
//
|
||||
using (SymmetricAlgorithm symmetricAlgorithm = encryptingKey.GetSymmetricAlgorithm(encryptingCredentials.Algorithm))
|
||||
{
|
||||
byte[] plainTextBytes = plaintextStream.GetBuffer();
|
||||
DebugEncryptedTokenClearText(plainTextBytes, Encoding.UTF8);
|
||||
encryptedData.Encrypt(symmetricAlgorithm, plainTextBytes, 0, (int)plaintextStream.Length);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Write the EncryptedData element
|
||||
//
|
||||
encryptedData.WriteXml(writer, KeyInfoSerializer);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user