1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 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.
/// <system.identityModel>
/// <issuerNameRegistry type='ConfigurationBasedIssuerNameRegistry'>
/// <trustedIssuers>
/// <add thumbprint='ASN.1EncodedFormOfTheThumbprint' name='MappedName' />
/// <add thumbprint='ASN.1EncodedFormOfTheThumbprint' />
/// <remove thumbprint='ASN.1EncodedFormOfTheThumbprint' />
/// < clear/>
/// <trustedIssuers/>
/// </issuerNameRegistry>
/// </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
}
}
}
|