Imported Upstream version 4.6.0.125

Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-08-03 10:59:49 +00:00
parent a569aebcfd
commit e79aa3c0ed
17047 changed files with 3137615 additions and 392334 deletions

View File

@@ -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);
}
}
}

View File

@@ -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 );
}
}
}
}
}

View File

@@ -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
}
}

View File

@@ -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();
}
}

View File

@@ -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; }
}
}
}

View File

@@ -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 )
{
}
}
}

View File

@@ -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; }
}
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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();
}
}
}

View File

@@ -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; }
}
}
}

View File

@@ -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
}
}

View File

@@ -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.
/// &lt;system.identityModel>
/// &lt;issuerNameRegistry type='ConfigurationBasedIssuerNameRegistry'>
/// &lt;trustedIssuers>
/// &lt;add thumbprint='ASN.1EncodedFormOfTheThumbprint' name='MappedName' />
/// &lt;add thumbprint='ASN.1EncodedFormOfTheThumbprint' />
/// &lt;remove thumbprint='ASN.1EncodedFormOfTheThumbprint' />
/// &lt; clear/>
/// &lt;trustedIssuers/>
/// &lt;/issuerNameRegistry>
/// &lt;/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
}
}
}

View File

@@ -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--;
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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; }
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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; }
}
}
}

View File

@@ -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 &lt;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