|
//-----------------------------------------------------------------------
// <copyright file="X509CertificateStoreTokenResolver.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace System.IdentityModel.Tokens
{
using System;
using System.Collections.Generic;
using System.IdentityModel.Selectors;
using System.Security.Cryptography.X509Certificates;
using System.Text;
/// <summary>
/// Token Resolver that can resolve X509SecurityTokens against a given X.509 Certificate Store.
/// </summary>
public class X509CertificateStoreTokenResolver : SecurityTokenResolver
{
private string storeName;
private StoreLocation storeLocation;
/// <summary>
/// Initializes an instance of <see cref="X509CertificateStoreTokenResolver"/>
/// </summary>
public X509CertificateStoreTokenResolver()
: this(System.Security.Cryptography.X509Certificates.StoreName.My, StoreLocation.LocalMachine)
{
}
/// <summary>
/// Initializes an instance of <see cref="X509CertificateStoreTokenResolver"/>
/// </summary>
/// <param name="storeName">StoreName of the X.509 Certificate Store.</param>
/// <param name="storeLocation">StoreLocation of the X.509 Certificate store.</param>
public X509CertificateStoreTokenResolver(StoreName storeName, StoreLocation storeLocation)
: this(Enum.GetName(typeof(System.Security.Cryptography.X509Certificates.StoreName), storeName), storeLocation)
{
}
/// <summary>
/// Initializes an instance of <see cref="X509CertificateStoreTokenResolver"/>
/// </summary>
/// <param name="storeName">StoreName of the X.509 Certificate Store.</param>
/// <param name="storeLocation">StoreLocation of the X.509 Certificate store.</param>
public X509CertificateStoreTokenResolver(string storeName, StoreLocation storeLocation)
{
if (string.IsNullOrEmpty(storeName))
{
throw DiagnosticUtility.ThrowHelperArgumentNullOrEmptyString("storeName");
}
this.storeName = storeName;
this.storeLocation = storeLocation;
}
/// <summary>
/// Gets the StoreName used by this TokenResolver.
/// </summary>
public string StoreName
{
get { return this.storeName; }
}
/// <summary>
/// Gets the StoreLocation used by this TokenResolver.
/// </summary>
public StoreLocation StoreLocation
{
get { return this.storeLocation; }
}
/// <summary>
/// Resolves the given SecurityKeyIdentifierClause to a SecurityKey.
/// </summary>
/// <param name="keyIdentifierClause">SecurityKeyIdentifierClause to resolve</param>
/// <param name="key">The resolved SecurityKey.</param>
/// <returns>True if successfully resolved.</returns>
/// <exception cref="ArgumentNullException">The 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;
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;
}
/// <summary>
/// Resolves the given SecurityKeyIdentifier to a SecurityToken.
/// </summary>
/// <param name="keyIdentifier">SecurityKeyIdentifier to resolve.</param>
/// <param name="token">The resolved SecurityToken.</param>
/// <returns>True if successfully resolved.</returns>
/// <exception cref="ArgumentNullException">The input argument 'keyIdentifier' is null.</exception>
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;
}
/// <summary>
/// Resolves the given SecurityKeyIdentifierClause to a SecurityToken.
/// </summary>
/// <param name="keyIdentifierClause">SecurityKeyIdentifierClause to resolve.</param>
/// <param name="token">The resolved SecurityToken.</param>
/// <returns>True if successfully resolved.</returns>
/// <exception cref="ArgumentNullException">The 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;
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;
}
}
}
|