//-----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------
namespace System.IdentityModel.Tokens
{
using System;
using System.Collections.Generic;
using System.IdentityModel.Selectors;
using System.Security.Cryptography.X509Certificates;
using System.Text;
///
/// Token Resolver that can resolve X509SecurityTokens against a given X.509 Certificate Store.
///
public class X509CertificateStoreTokenResolver : SecurityTokenResolver
{
private string storeName;
private StoreLocation storeLocation;
///
/// Initializes an instance of
///
public X509CertificateStoreTokenResolver()
: this(System.Security.Cryptography.X509Certificates.StoreName.My, StoreLocation.LocalMachine)
{
}
///
/// Initializes an instance of
///
/// StoreName of the X.509 Certificate Store.
/// StoreLocation of the X.509 Certificate store.
public X509CertificateStoreTokenResolver(StoreName storeName, StoreLocation storeLocation)
: this(Enum.GetName(typeof(System.Security.Cryptography.X509Certificates.StoreName), storeName), storeLocation)
{
}
///
/// Initializes an instance of
///
/// StoreName of the X.509 Certificate Store.
/// StoreLocation of the X.509 Certificate store.
public X509CertificateStoreTokenResolver(string storeName, StoreLocation storeLocation)
{
if (string.IsNullOrEmpty(storeName))
{
throw DiagnosticUtility.ThrowHelperArgumentNullOrEmptyString("storeName");
}
this.storeName = storeName;
this.storeLocation = storeLocation;
}
///
/// Gets the StoreName used by this TokenResolver.
///
public string StoreName
{
get { return this.storeName; }
}
///
/// Gets the StoreLocation used by this TokenResolver.
///
public StoreLocation StoreLocation
{
get { return this.storeLocation; }
}
///
/// Resolves the given SecurityKeyIdentifierClause to a SecurityKey.
///
/// SecurityKeyIdentifierClause to resolve
/// The resolved SecurityKey.
/// True if successfully resolved.
/// The input argument 'keyIdentifierClause' is null.
protected override bool TryResolveSecurityKeyCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key)
{
if (keyIdentifierClause == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifierClause");
}
key = null;
EncryptedKeyIdentifierClause encryptedKeyIdentifierClause = keyIdentifierClause as EncryptedKeyIdentifierClause;
if (encryptedKeyIdentifierClause != null)
{
SecurityKeyIdentifier keyIdentifier = encryptedKeyIdentifierClause.EncryptingKeyIdentifier;
if (keyIdentifier != null && keyIdentifier.Count > 0)
{
for (int i = 0; i < keyIdentifier.Count; i++)
{
SecurityKey unwrappingSecurityKey = null;
if (TryResolveSecurityKey(keyIdentifier[i], out unwrappingSecurityKey))
{
byte[] wrappedKey = encryptedKeyIdentifierClause.GetEncryptedKey();
string wrappingAlgorithm = encryptedKeyIdentifierClause.EncryptionMethod;
byte[] unwrappedKey = unwrappingSecurityKey.DecryptKey(wrappingAlgorithm, wrappedKey);
key = new InMemorySymmetricSecurityKey(unwrappedKey, false);
return true;
}
}
}
}
else
{
SecurityToken token = null;
if (TryResolveToken(keyIdentifierClause, out token))
{
if (token.SecurityKeys.Count > 0)
{
key = token.SecurityKeys[0];
return true;
}
}
}
return false;
}
///
/// Resolves the given SecurityKeyIdentifier to a SecurityToken.
///
/// SecurityKeyIdentifier to resolve.
/// The resolved SecurityToken.
/// True if successfully resolved.
/// The input argument 'keyIdentifier' is null.
protected override bool TryResolveTokenCore(SecurityKeyIdentifier keyIdentifier, out SecurityToken token)
{
if (keyIdentifier == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifier");
}
token = null;
foreach (SecurityKeyIdentifierClause clause in keyIdentifier)
{
if (TryResolveToken(clause, out token))
{
return true;
}
}
return false;
}
///
/// Resolves the given SecurityKeyIdentifierClause to a SecurityToken.
///
/// SecurityKeyIdentifierClause to resolve.
/// The resolved SecurityToken.
/// True if successfully resolved.
/// The input argument 'keyIdentifierClause' is null.
protected override bool TryResolveTokenCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token)
{
if (keyIdentifierClause == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keyIdentifierClause");
}
token = null;
X509Store store = null;
X509Certificate2Collection certs = null;
try
{
store = new X509Store(this.storeName, this.storeLocation);
store.Open(OpenFlags.ReadOnly);
certs = store.Certificates;
foreach (X509Certificate2 cert in certs)
{
X509ThumbprintKeyIdentifierClause thumbprintKeyIdentifierClause = keyIdentifierClause as X509ThumbprintKeyIdentifierClause;
if (thumbprintKeyIdentifierClause != null && thumbprintKeyIdentifierClause.Matches(cert))
{
token = new X509SecurityToken(cert);
return true;
}
X509IssuerSerialKeyIdentifierClause issuerSerialKeyIdentifierClause = keyIdentifierClause as X509IssuerSerialKeyIdentifierClause;
if (issuerSerialKeyIdentifierClause != null && issuerSerialKeyIdentifierClause.Matches(cert))
{
token = new X509SecurityToken(cert);
return true;
}
X509SubjectKeyIdentifierClause subjectKeyIdentifierClause = keyIdentifierClause as X509SubjectKeyIdentifierClause;
if (subjectKeyIdentifierClause != null && subjectKeyIdentifierClause.Matches(cert))
{
token = new X509SecurityToken(cert);
return true;
}
X509RawDataKeyIdentifierClause rawDataKeyIdentifierClause = keyIdentifierClause as X509RawDataKeyIdentifierClause;
if (rawDataKeyIdentifierClause != null && rawDataKeyIdentifierClause.Matches(cert))
{
token = new X509SecurityToken(cert);
return true;
}
}
}
finally
{
if (certs != null)
{
for (int i = 0; i < certs.Count; i++)
{
certs[i].Reset();
}
}
if (store != null)
{
store.Close();
}
}
return false;
}
}
}