223 lines
9.2 KiB
C#
223 lines
9.2 KiB
C#
|
//-----------------------------------------------------------------------
|
||
|
// <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;
|
||
|
}
|
||
|
}
|
||
|
}
|