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