You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IdentityModel.Tokens;
|
||||
|
||||
namespace System.Security.Claims
|
||||
{
|
||||
/// <summary>
|
||||
/// The authentication information that an authority asserted when creating a token for a subject.
|
||||
/// </summary>
|
||||
public class AuthenticationInformation
|
||||
{
|
||||
string _address;
|
||||
Collection<AuthenticationContext> _authContexts;
|
||||
string _dnsName;
|
||||
DateTime? _notOnOrAfter;
|
||||
string _session;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthenticationInformation"/> class.
|
||||
/// </summary>
|
||||
public AuthenticationInformation()
|
||||
{
|
||||
_authContexts = new Collection<AuthenticationContext>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the address of the authority that created the token.
|
||||
/// </summary>
|
||||
public string Address
|
||||
{
|
||||
get { return _address; }
|
||||
set { _address = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="AuthorizationContext"/> used by the authenticating authority when issuing tokens.
|
||||
/// </summary>
|
||||
public Collection<AuthenticationContext> AuthorizationContexts
|
||||
{
|
||||
get { return _authContexts; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DNS name of the authority that created the token.
|
||||
/// </summary>
|
||||
public string DnsName
|
||||
{
|
||||
get { return _dnsName; }
|
||||
set { _dnsName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time that the session referred to in the session index MUST be considered ended.
|
||||
/// </summary>
|
||||
public DateTime? NotOnOrAfter
|
||||
{
|
||||
get { return _notOnOrAfter; }
|
||||
set { _notOnOrAfter = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the session index that describes the session between the authority and the client.
|
||||
/// </summary>
|
||||
public string Session
|
||||
{
|
||||
get { return _session; }
|
||||
set { _session = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Security.Claims;
|
||||
using System.IdentityModel.Tokens;
|
||||
|
||||
namespace System.Security.Claims
|
||||
{
|
||||
internal static class AuthenticationTypeMaps
|
||||
{
|
||||
public struct Mapping
|
||||
{
|
||||
public Mapping( string normalized, string unnormalized )
|
||||
{
|
||||
Normalized = normalized;
|
||||
Unnormalized = unnormalized;
|
||||
}
|
||||
|
||||
public string Normalized;
|
||||
public string Unnormalized;
|
||||
}
|
||||
|
||||
public static Mapping[] Saml = new Mapping[]
|
||||
{
|
||||
new Mapping( AuthenticationMethods.HardwareToken, SamlConstants.AuthenticationMethods.HardwareTokenString ),
|
||||
new Mapping( AuthenticationMethods.Kerberos, SamlConstants.AuthenticationMethods.KerberosString ),
|
||||
new Mapping( AuthenticationMethods.Password, SamlConstants.AuthenticationMethods.PasswordString ),
|
||||
new Mapping( AuthenticationMethods.Pgp, SamlConstants.AuthenticationMethods.PgpString ),
|
||||
new Mapping( AuthenticationMethods.SecureRemotePassword, SamlConstants.AuthenticationMethods.SecureRemotePasswordString ),
|
||||
new Mapping( AuthenticationMethods.Signature, SamlConstants.AuthenticationMethods.SignatureString ),
|
||||
new Mapping( AuthenticationMethods.Spki, SamlConstants.AuthenticationMethods.SpkiString ),
|
||||
new Mapping( AuthenticationMethods.TlsClient, SamlConstants.AuthenticationMethods.TlsClientString ),
|
||||
new Mapping( AuthenticationMethods.Unspecified, SamlConstants.AuthenticationMethods.UnspecifiedString ),
|
||||
new Mapping( AuthenticationMethods.Windows, SamlConstants.AuthenticationMethods.WindowsString ),
|
||||
new Mapping( AuthenticationMethods.X509, SamlConstants.AuthenticationMethods.X509String ),
|
||||
new Mapping( AuthenticationMethods.Xkms, SamlConstants.AuthenticationMethods.XkmsString ),
|
||||
};
|
||||
|
||||
public static Mapping[] Saml2 = new Mapping[]
|
||||
{
|
||||
new Mapping( AuthenticationMethods.Kerberos, Saml2Constants.AuthenticationContextClasses.KerberosString ),
|
||||
new Mapping( AuthenticationMethods.Password, Saml2Constants.AuthenticationContextClasses.PasswordString ),
|
||||
new Mapping( AuthenticationMethods.Pgp, Saml2Constants.AuthenticationContextClasses.PgpString ),
|
||||
new Mapping( AuthenticationMethods.SecureRemotePassword, Saml2Constants.AuthenticationContextClasses.SecureRemotePasswordString ),
|
||||
new Mapping( AuthenticationMethods.Signature, Saml2Constants.AuthenticationContextClasses.XmlDsigString ),
|
||||
new Mapping( AuthenticationMethods.Spki, Saml2Constants.AuthenticationContextClasses.SpkiString ),
|
||||
new Mapping( AuthenticationMethods.Smartcard, Saml2Constants.AuthenticationContextClasses.SmartcardString ),
|
||||
new Mapping( AuthenticationMethods.SmartcardPki, Saml2Constants.AuthenticationContextClasses.SmartcardPkiString ),
|
||||
new Mapping( AuthenticationMethods.TlsClient, Saml2Constants.AuthenticationContextClasses.TlsClientString ),
|
||||
new Mapping( AuthenticationMethods.Unspecified, Saml2Constants.AuthenticationContextClasses.UnspecifiedString ),
|
||||
new Mapping( AuthenticationMethods.X509, Saml2Constants.AuthenticationContextClasses.X509String ),
|
||||
new Mapping( AuthenticationMethods.Windows, Saml2Constants.AuthenticationContextClasses.WindowsString ),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Returns the protocol specific value matching a normalized value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If no match is found, the original value is returned.
|
||||
/// </remarks>
|
||||
public static string Denormalize( string normalizedAuthenticationMethod, Mapping[] mappingTable )
|
||||
{
|
||||
foreach ( Mapping mapping in mappingTable )
|
||||
{
|
||||
if (StringComparer.Ordinal.Equals( normalizedAuthenticationMethod, mapping.Normalized ) )
|
||||
return mapping.Unnormalized;
|
||||
}
|
||||
|
||||
return normalizedAuthenticationMethod;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the normalized value matching a protocol specific value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If no match is found, the original value is returned.
|
||||
/// </remarks>
|
||||
public static string Normalize( string unnormalizedAuthenticationMethod, Mapping[] mappingTable )
|
||||
{
|
||||
foreach ( Mapping mapping in mappingTable )
|
||||
{
|
||||
if ( StringComparer.Ordinal.Equals( unnormalizedAuthenticationMethod, mapping.Unnormalized ) )
|
||||
return mapping.Normalized;
|
||||
}
|
||||
|
||||
return unnormalizedAuthenticationMethod;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Security.Claims
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines types for WindowsIdentity AuthenticationType
|
||||
/// </summary>
|
||||
public static class AuthenticationTypes
|
||||
{
|
||||
#pragma warning disable 1591
|
||||
public const string Basic = "Basic";
|
||||
public const string Federation = "Federation";
|
||||
public const string Kerberos = "Kerberos";
|
||||
public const string Negotiate = "Negotiate";
|
||||
public const string Password = "Password";
|
||||
public const string Signature = "Signature";
|
||||
public const string Windows = "Windows";
|
||||
public const string X509 = "X509";
|
||||
#pragma warning restore 1591
|
||||
|
||||
// Types generated by CLR WindowsIdentity:
|
||||
// :generated by NTAuthenticationInfoClass: NTLM, Kerberos, WDigest, Negotiate
|
||||
// :generated by GetServerVariable("AUTH_TYPE"): Basic, Digest, Kerberos, NTLM, and RADIUS
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IdentityModel;
|
||||
|
||||
|
||||
namespace System.Security.Claims
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is used to specify the context of the authorization event.
|
||||
/// </summary>
|
||||
public class AuthorizationContext
|
||||
{
|
||||
Collection<System.Security.Claims.Claim> _action = new Collection<System.Security.Claims.Claim>();
|
||||
Collection<System.Security.Claims.Claim> _resource = new Collection<System.Security.Claims.Claim>();
|
||||
ClaimsPrincipal _principal;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an AuthorizationContext with the specified principal, resource, and action.
|
||||
/// </summary>
|
||||
/// <param name="principal">The principal to be authorized.</param>
|
||||
/// <param name="resource">The resource to be authorized for.</param>
|
||||
/// <param name="action">The action to be performed on the resource.</param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="principal"/> or <paramref name="resource"/> is set to null.
|
||||
/// </exception>
|
||||
public AuthorizationContext( ClaimsPrincipal principal, string resource, string action )
|
||||
{
|
||||
if ( principal == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "principal" );
|
||||
}
|
||||
|
||||
if ( string.IsNullOrEmpty( resource ) )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "resource" );
|
||||
}
|
||||
|
||||
_principal = principal;
|
||||
_resource.Add( new System.Security.Claims.Claim( ClaimTypes.Name, resource ) );
|
||||
if ( action != null )
|
||||
{
|
||||
_action.Add( new System.Security.Claims.Claim( ClaimTypes.Name, action ) );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an AuthorizationContext with the specified principal, resource, and action.
|
||||
/// </summary>
|
||||
/// <param name="principal">The principal to check authorization for</param>
|
||||
/// <param name="resource">The resource for checking authorization to</param>
|
||||
/// <param name="action">The action to be performed on the resource</param>
|
||||
/// <exception cref="ArgumentNullException">When <paramref name="principal"/> or <paramref name="resource"/> or <paramref name="action"/> is null</exception>
|
||||
public AuthorizationContext( ClaimsPrincipal principal, Collection<System.Security.Claims.Claim> resource, Collection<System.Security.Claims.Claim> action )
|
||||
{
|
||||
if ( principal == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "principal" );
|
||||
}
|
||||
|
||||
if ( resource == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "resource" );
|
||||
}
|
||||
|
||||
if ( action == null )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "action" );
|
||||
}
|
||||
|
||||
_principal = principal;
|
||||
_resource = resource;
|
||||
_action = action;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authorization action
|
||||
/// </summary>
|
||||
public Collection<System.Security.Claims.Claim> Action
|
||||
{
|
||||
get { return _action; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authorization resource
|
||||
/// </summary>
|
||||
public Collection<System.Security.Claims.Claim> Resource
|
||||
{
|
||||
get { return _resource; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authorization principal
|
||||
/// </summary>
|
||||
public ClaimsPrincipal Principal
|
||||
{
|
||||
get { return _principal; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Claims
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net.Mail;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Principal;
|
||||
|
||||
// Examples:
|
||||
// ClaimType ResourceValue ResourceRight
|
||||
// --------------- ---------------- ------------------
|
||||
// "File" "boot.ini" "Read"
|
||||
// "HairColor" "Brown" "PossessProperty"
|
||||
// "UserName" "[....]" "PossessProperty"
|
||||
// "Service" "MailService" "Access"
|
||||
// "Operation" "ReadMail" "Invoke"
|
||||
// ClaimType:
|
||||
// DESC: The type of resource for which rights are granted
|
||||
// XrML: ClaimSet/Resource
|
||||
// SAML: SamlAttributeStatement/Attribute/@Name/..., SamlAuthorizationDecisionStatement/Action/@Namespace/...
|
||||
// ResourceValue:
|
||||
// DESC: Value identifying the resource for which rights are granted
|
||||
// XrML: ClaimSet/Resource/...
|
||||
// SAML: SamlAttributeStatement/Attribute/..., SamlAuthorizationDecisionStatement/@Resource/...
|
||||
// Right:
|
||||
// DESC: Rights expressed about a resource
|
||||
// XRML: ClaimSet/Right
|
||||
// SAML: SamlAttributeStatement (aka. "PossessProperty") or, SamlAuthorizationDecisionStatement/Action/...
|
||||
|
||||
[DataContract(Namespace = XsiConstants.Namespace)]
|
||||
public class Claim
|
||||
{
|
||||
static Claim system;
|
||||
|
||||
[DataMember(Name = "ClaimType")]
|
||||
string claimType;
|
||||
[DataMember(Name = "Resource")]
|
||||
object resource;
|
||||
[DataMember(Name = "Right")]
|
||||
string right;
|
||||
|
||||
IEqualityComparer<Claim> comparer;
|
||||
|
||||
Claim(string claimType, object resource, string right, IEqualityComparer<Claim> comparer)
|
||||
{
|
||||
if (claimType == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("claimType");
|
||||
if (claimType.Length <= 0)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("claimType", SR.GetString(SR.ArgumentCannotBeEmptyString));
|
||||
if (right == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("right");
|
||||
if (right.Length <= 0)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("right", SR.GetString(SR.ArgumentCannotBeEmptyString));
|
||||
|
||||
this.claimType = StringUtil.OptimizeString(claimType);
|
||||
this.resource = resource;
|
||||
this.right = StringUtil.OptimizeString(right);
|
||||
this.comparer = comparer;
|
||||
}
|
||||
|
||||
public Claim(string claimType, object resource, string right) : this(claimType, resource, right, null)
|
||||
{
|
||||
}
|
||||
|
||||
public static IEqualityComparer<Claim> DefaultComparer
|
||||
{
|
||||
get
|
||||
{
|
||||
return EqualityComparer<Claim>.Default;
|
||||
}
|
||||
}
|
||||
|
||||
public static Claim System
|
||||
{
|
||||
get
|
||||
{
|
||||
if (system == null)
|
||||
system = new Claim(ClaimTypes.System, XsiConstants.System, Rights.Identity);
|
||||
|
||||
return system;
|
||||
}
|
||||
}
|
||||
|
||||
public object Resource
|
||||
{
|
||||
get { return this.resource; }
|
||||
}
|
||||
|
||||
public string ClaimType
|
||||
{
|
||||
get { return this.claimType; }
|
||||
}
|
||||
|
||||
public string Right
|
||||
{
|
||||
get { return this.right; }
|
||||
}
|
||||
|
||||
// Turn key claims
|
||||
public static Claim CreateDnsClaim(string dns)
|
||||
{
|
||||
if (dns == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dns");
|
||||
|
||||
return new Claim(ClaimTypes.Dns, dns, Rights.PossessProperty, ClaimComparer.Dns);
|
||||
}
|
||||
|
||||
public static Claim CreateDenyOnlyWindowsSidClaim(SecurityIdentifier sid)
|
||||
{
|
||||
if (sid == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sid");
|
||||
|
||||
return new Claim(ClaimTypes.DenyOnlySid, sid, Rights.PossessProperty);
|
||||
}
|
||||
|
||||
public static Claim CreateHashClaim(byte[] hash)
|
||||
{
|
||||
if (hash == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("hash");
|
||||
|
||||
return new Claim(ClaimTypes.Hash, SecurityUtils.CloneBuffer(hash), Rights.PossessProperty, ClaimComparer.Hash);
|
||||
}
|
||||
|
||||
public static Claim CreateMailAddressClaim(MailAddress mailAddress)
|
||||
{
|
||||
if (mailAddress == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("mailAddress");
|
||||
|
||||
return new Claim(ClaimTypes.Email, mailAddress, Rights.PossessProperty);
|
||||
}
|
||||
|
||||
public static Claim CreateNameClaim(string name)
|
||||
{
|
||||
if (name == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("name");
|
||||
|
||||
return new Claim(ClaimTypes.Name, name, Rights.PossessProperty);
|
||||
}
|
||||
|
||||
public static Claim CreateRsaClaim(RSA rsa)
|
||||
{
|
||||
if (rsa == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rsa");
|
||||
|
||||
return new Claim(ClaimTypes.Rsa, rsa, Rights.PossessProperty, ClaimComparer.Rsa);
|
||||
}
|
||||
|
||||
public static Claim CreateSpnClaim(string spn)
|
||||
{
|
||||
if (spn == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("spn");
|
||||
|
||||
return new Claim(ClaimTypes.Spn, spn, Rights.PossessProperty);
|
||||
}
|
||||
|
||||
public static Claim CreateThumbprintClaim(byte[] thumbprint)
|
||||
{
|
||||
if (thumbprint == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("thumbprint");
|
||||
|
||||
return new Claim(ClaimTypes.Thumbprint, SecurityUtils.CloneBuffer(thumbprint), Rights.PossessProperty, ClaimComparer.Thumbprint);
|
||||
}
|
||||
|
||||
public static Claim CreateUpnClaim(string upn)
|
||||
{
|
||||
if (upn == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("upn");
|
||||
|
||||
return new Claim(ClaimTypes.Upn, upn, Rights.PossessProperty, ClaimComparer.Upn);
|
||||
}
|
||||
|
||||
public static Claim CreateUriClaim(Uri uri)
|
||||
{
|
||||
if (uri == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("uri");
|
||||
|
||||
return new Claim(ClaimTypes.Uri, uri, Rights.PossessProperty);
|
||||
}
|
||||
|
||||
public static Claim CreateWindowsSidClaim(SecurityIdentifier sid)
|
||||
{
|
||||
if (sid == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sid");
|
||||
|
||||
return new Claim(ClaimTypes.Sid, sid, Rights.PossessProperty);
|
||||
}
|
||||
|
||||
public static Claim CreateX500DistinguishedNameClaim(X500DistinguishedName x500DistinguishedName)
|
||||
{
|
||||
if (x500DistinguishedName == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("x500DistinguishedName");
|
||||
|
||||
return new Claim(ClaimTypes.X500DistinguishedName, x500DistinguishedName, Rights.PossessProperty, ClaimComparer.X500DistinguishedName);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (comparer == null)
|
||||
comparer = ClaimComparer.GetComparer(this.claimType);
|
||||
return comparer.Equals(this, obj as Claim);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (comparer == null)
|
||||
comparer = ClaimComparer.GetComparer(this.claimType);
|
||||
return comparer.GetHashCode(this);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, "{0}: {1}", this.right, this.claimType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Claims
|
||||
{
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Principal;
|
||||
|
||||
class ClaimComparer : IEqualityComparer<Claim>
|
||||
{
|
||||
static IEqualityComparer<Claim> defaultComparer;
|
||||
static IEqualityComparer<Claim> hashComparer;
|
||||
static IEqualityComparer<Claim> dnsComparer;
|
||||
static IEqualityComparer<Claim> rsaComparer;
|
||||
static IEqualityComparer<Claim> thumbprintComparer;
|
||||
static IEqualityComparer<Claim> upnComparer;
|
||||
static IEqualityComparer<Claim> x500DistinguishedNameComparer;
|
||||
IEqualityComparer resourceComparer;
|
||||
|
||||
ClaimComparer(IEqualityComparer resourceComparer)
|
||||
{
|
||||
this.resourceComparer = resourceComparer;
|
||||
}
|
||||
|
||||
public static IEqualityComparer<Claim> GetComparer(string claimType)
|
||||
{
|
||||
if (claimType == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("claimType");
|
||||
if (claimType == ClaimTypes.Dns)
|
||||
return Dns;
|
||||
if (claimType == ClaimTypes.Hash)
|
||||
return Hash;
|
||||
if (claimType == ClaimTypes.Rsa)
|
||||
return Rsa;
|
||||
if (claimType == ClaimTypes.Thumbprint)
|
||||
return Thumbprint;
|
||||
if (claimType == ClaimTypes.Upn)
|
||||
return Upn;
|
||||
if (claimType == ClaimTypes.X500DistinguishedName)
|
||||
return X500DistinguishedName;
|
||||
return Default;
|
||||
}
|
||||
|
||||
public static IEqualityComparer<Claim> Default
|
||||
{
|
||||
get
|
||||
{
|
||||
if (defaultComparer == null)
|
||||
{
|
||||
defaultComparer = new ClaimComparer(new ObjectComparer());
|
||||
}
|
||||
return defaultComparer;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEqualityComparer<Claim> Dns
|
||||
{
|
||||
get
|
||||
{
|
||||
if (dnsComparer == null)
|
||||
{
|
||||
dnsComparer = new ClaimComparer(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
return dnsComparer;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEqualityComparer<Claim> Hash
|
||||
{
|
||||
get
|
||||
{
|
||||
if (hashComparer == null)
|
||||
{
|
||||
hashComparer = new ClaimComparer(new BinaryObjectComparer());
|
||||
}
|
||||
return hashComparer;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEqualityComparer<Claim> Rsa
|
||||
{
|
||||
get
|
||||
{
|
||||
if (rsaComparer == null)
|
||||
{
|
||||
rsaComparer = new ClaimComparer(new RsaObjectComparer());
|
||||
}
|
||||
return rsaComparer;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEqualityComparer<Claim> Thumbprint
|
||||
{
|
||||
get
|
||||
{
|
||||
if (thumbprintComparer == null)
|
||||
{
|
||||
thumbprintComparer = new ClaimComparer(new BinaryObjectComparer());
|
||||
}
|
||||
return thumbprintComparer;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEqualityComparer<Claim> Upn
|
||||
{
|
||||
get
|
||||
{
|
||||
if (upnComparer == null)
|
||||
{
|
||||
upnComparer = new ClaimComparer(new UpnObjectComparer());
|
||||
}
|
||||
return upnComparer;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEqualityComparer<Claim> X500DistinguishedName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (x500DistinguishedNameComparer == null)
|
||||
{
|
||||
x500DistinguishedNameComparer = new ClaimComparer(new X500DistinguishedNameObjectComparer());
|
||||
}
|
||||
return x500DistinguishedNameComparer;
|
||||
}
|
||||
}
|
||||
|
||||
// we still need to review how the default equals works, this is not how Doug envisioned it.
|
||||
public bool Equals(Claim claim1, Claim claim2)
|
||||
{
|
||||
if (ReferenceEquals(claim1, claim2))
|
||||
return true;
|
||||
|
||||
if (claim1 == null || claim2 == null)
|
||||
return false;
|
||||
|
||||
if (claim1.ClaimType != claim2.ClaimType || claim1.Right != claim2.Right)
|
||||
return false;
|
||||
|
||||
return resourceComparer.Equals(claim1.Resource, claim2.Resource);
|
||||
}
|
||||
|
||||
public int GetHashCode(Claim claim)
|
||||
{
|
||||
if (claim == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("claim");
|
||||
|
||||
return claim.ClaimType.GetHashCode() ^ claim.Right.GetHashCode()
|
||||
^ ( (claim.Resource == null) ? 0 : resourceComparer.GetHashCode(claim.Resource));
|
||||
}
|
||||
|
||||
class ObjectComparer : IEqualityComparer
|
||||
{
|
||||
bool IEqualityComparer.Equals(object obj1, object obj2)
|
||||
{
|
||||
if (obj1 == null && obj2 == null)
|
||||
return true;
|
||||
if (obj1 == null || obj2 == null)
|
||||
return false;
|
||||
return obj1.Equals(obj2);
|
||||
}
|
||||
|
||||
int IEqualityComparer.GetHashCode(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return 0;
|
||||
return obj.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
class BinaryObjectComparer : IEqualityComparer
|
||||
{
|
||||
bool IEqualityComparer.Equals(object obj1, object obj2)
|
||||
{
|
||||
if (ReferenceEquals(obj1, obj2))
|
||||
return true;
|
||||
|
||||
byte[] bytes1 = obj1 as byte[];
|
||||
byte[] bytes2 = obj2 as byte[];
|
||||
if (bytes1 == null || bytes2 == null)
|
||||
return false;
|
||||
|
||||
if (bytes1.Length != bytes2.Length)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < bytes1.Length; ++i)
|
||||
{
|
||||
if (bytes1[i] != bytes2[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int IEqualityComparer.GetHashCode(object obj)
|
||||
{
|
||||
byte[] bytes = obj as byte[];
|
||||
if (bytes == null)
|
||||
return 0;
|
||||
|
||||
int hashCode = 0;
|
||||
for (int i = 0; i < bytes.Length && i < 4; ++i)
|
||||
{
|
||||
hashCode = (hashCode << 8) | bytes[i];
|
||||
}
|
||||
|
||||
return hashCode ^ bytes.Length;
|
||||
}
|
||||
}
|
||||
|
||||
class RsaObjectComparer : IEqualityComparer
|
||||
{
|
||||
bool IEqualityComparer.Equals(object obj1, object obj2)
|
||||
{
|
||||
if (ReferenceEquals(obj1, obj2))
|
||||
return true;
|
||||
|
||||
RSA rsa1 = obj1 as RSA;
|
||||
RSA rsa2 = obj2 as RSA;
|
||||
if (rsa1 == null || rsa2 == null)
|
||||
return false;
|
||||
|
||||
RSAParameters parm1 = rsa1.ExportParameters(false);
|
||||
RSAParameters parm2 = rsa2.ExportParameters(false);
|
||||
|
||||
if (parm1.Modulus.Length != parm2.Modulus.Length ||
|
||||
parm1.Exponent.Length != parm2.Exponent.Length)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < parm1.Modulus.Length; ++i)
|
||||
{
|
||||
if (parm1.Modulus[i] != parm2.Modulus[i])
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < parm1.Exponent.Length; ++i)
|
||||
{
|
||||
if (parm1.Exponent[i] != parm2.Exponent[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int IEqualityComparer.GetHashCode(object obj)
|
||||
{
|
||||
RSA rsa = obj as RSA;
|
||||
if (rsa == null)
|
||||
return 0;
|
||||
|
||||
RSAParameters parm = rsa.ExportParameters(false);
|
||||
return parm.Modulus.Length ^ parm.Exponent.Length;
|
||||
}
|
||||
}
|
||||
|
||||
class X500DistinguishedNameObjectComparer : IEqualityComparer
|
||||
{
|
||||
IEqualityComparer binaryComparer;
|
||||
public X500DistinguishedNameObjectComparer()
|
||||
{
|
||||
binaryComparer = new BinaryObjectComparer();
|
||||
}
|
||||
|
||||
bool IEqualityComparer.Equals(object obj1, object obj2)
|
||||
{
|
||||
if (ReferenceEquals(obj1, obj2))
|
||||
return true;
|
||||
|
||||
X500DistinguishedName dn1 = obj1 as X500DistinguishedName;
|
||||
X500DistinguishedName dn2 = obj2 as X500DistinguishedName;
|
||||
if (dn1 == null || dn2 == null)
|
||||
return false;
|
||||
|
||||
// 1) Hopefully cover most cases (perf reason).
|
||||
if (StringComparer.Ordinal.Equals(dn1.Name, dn2.Name))
|
||||
return true;
|
||||
|
||||
// 2) Raw byte compare. Note: we assume the rawbyte is in the same order
|
||||
// (default = X500DistinguishedNameFlags.Reversed).
|
||||
return binaryComparer.Equals(dn1.RawData, dn2.RawData);
|
||||
}
|
||||
|
||||
int IEqualityComparer.GetHashCode(object obj)
|
||||
{
|
||||
X500DistinguishedName dn = obj as X500DistinguishedName;
|
||||
if (dn == null)
|
||||
return 0;
|
||||
|
||||
return binaryComparer.GetHashCode(dn.RawData);
|
||||
}
|
||||
}
|
||||
|
||||
class UpnObjectComparer : IEqualityComparer
|
||||
{
|
||||
bool IEqualityComparer.Equals(object obj1, object obj2)
|
||||
{
|
||||
if (StringComparer.OrdinalIgnoreCase.Equals(obj1, obj2))
|
||||
return true;
|
||||
|
||||
string upn1 = obj1 as string;
|
||||
string upn2 = obj2 as string;
|
||||
if (upn1 == null || upn2 == null)
|
||||
return false;
|
||||
|
||||
SecurityIdentifier sid1;
|
||||
if (!TryLookupSidFromName(upn1, out sid1))
|
||||
return false;
|
||||
|
||||
// Normalize to sid
|
||||
SecurityIdentifier sid2;
|
||||
if (!TryLookupSidFromName(upn2, out sid2))
|
||||
return false;
|
||||
|
||||
return sid1 == sid2;
|
||||
}
|
||||
|
||||
int IEqualityComparer.GetHashCode(object obj)
|
||||
{
|
||||
string upn = obj as string;
|
||||
if (upn == null)
|
||||
return 0;
|
||||
|
||||
// Normalize to sid
|
||||
SecurityIdentifier sid;
|
||||
if (TryLookupSidFromName(upn, out sid))
|
||||
return sid.GetHashCode();
|
||||
|
||||
return StringComparer.OrdinalIgnoreCase.GetHashCode(upn);
|
||||
}
|
||||
|
||||
bool TryLookupSidFromName(string upn, out SecurityIdentifier sid)
|
||||
{
|
||||
sid = null;
|
||||
try
|
||||
{
|
||||
NTAccount acct = new NTAccount(upn);
|
||||
sid = acct.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier;
|
||||
}
|
||||
catch (IdentityNotMappedException e)
|
||||
{
|
||||
DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
|
||||
}
|
||||
return sid != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Security.Claims
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the keys for properties contained in <see cref="Claim.Properties"/>.
|
||||
/// </summary>
|
||||
public static class ClaimProperties
|
||||
{
|
||||
#pragma warning disable 1591
|
||||
public const string Namespace = "http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties";
|
||||
|
||||
public const string SamlAttributeDisplayName = Namespace + "/displayname";
|
||||
public const string SamlAttributeNameFormat = Namespace + "/attributename";
|
||||
public const string SamlNameIdentifierFormat = Namespace + "/format";
|
||||
public const string SamlNameIdentifierNameQualifier = Namespace + "/namequalifier";
|
||||
public const string SamlNameIdentifierSPNameQualifier = Namespace + "/spnamequalifier";
|
||||
public const string SamlNameIdentifierSPProvidedId = Namespace + "/spprovidedid";
|
||||
#pragma warning restore 1591
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Claims
|
||||
{
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
|
||||
[DataContract(Namespace = XsiConstants.Namespace)]
|
||||
public abstract class ClaimSet : IEnumerable<Claim>
|
||||
{
|
||||
static ClaimSet system;
|
||||
static ClaimSet windows;
|
||||
static ClaimSet anonymous;
|
||||
|
||||
public static ClaimSet System
|
||||
{
|
||||
get
|
||||
{
|
||||
if (system == null)
|
||||
{
|
||||
List<Claim> claims = new List<Claim>(2);
|
||||
claims.Add(Claim.System);
|
||||
claims.Add(new Claim(ClaimTypes.System, XsiConstants.System, Rights.PossessProperty));
|
||||
system = new DefaultClaimSet(claims);
|
||||
}
|
||||
return system;
|
||||
}
|
||||
}
|
||||
|
||||
public static ClaimSet Windows
|
||||
{
|
||||
get
|
||||
{
|
||||
if (windows == null)
|
||||
{
|
||||
List<Claim> claims = new List<Claim>(2);
|
||||
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.NTAuthoritySid, null);
|
||||
claims.Add(new Claim(ClaimTypes.Sid, sid, Rights.Identity));
|
||||
claims.Add(Claim.CreateWindowsSidClaim(sid));
|
||||
windows = new DefaultClaimSet(claims);
|
||||
}
|
||||
return windows;
|
||||
}
|
||||
}
|
||||
|
||||
internal static ClaimSet Anonymous
|
||||
{
|
||||
get
|
||||
{
|
||||
if (anonymous == null)
|
||||
anonymous = new DefaultClaimSet();
|
||||
|
||||
return anonymous;
|
||||
}
|
||||
}
|
||||
|
||||
static internal bool SupportedRight(string right)
|
||||
{
|
||||
return right == null ||
|
||||
Rights.Identity.Equals(right) ||
|
||||
Rights.PossessProperty.Equals(right);
|
||||
}
|
||||
|
||||
|
||||
public virtual bool ContainsClaim(Claim claim, IEqualityComparer<Claim> comparer)
|
||||
{
|
||||
if (claim == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("claim");
|
||||
if (comparer == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("comparer");
|
||||
|
||||
IEnumerable<Claim> claims = FindClaims(null, null);
|
||||
if (claims != null)
|
||||
{
|
||||
foreach (Claim matchingClaim in claims)
|
||||
{
|
||||
if (comparer.Equals(claim, matchingClaim))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool ContainsClaim(Claim claim)
|
||||
{
|
||||
if (claim == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("claim");
|
||||
|
||||
IEnumerable<Claim> claims = FindClaims(claim.ClaimType, claim.Right);
|
||||
if (claims != null)
|
||||
{
|
||||
foreach (Claim matchingClaim in claims)
|
||||
{
|
||||
if (claim.Equals(matchingClaim))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract Claim this[int index] { get; }
|
||||
public abstract int Count { get; }
|
||||
public abstract ClaimSet Issuer { get; }
|
||||
// Note: null string represents any.
|
||||
public abstract IEnumerable<Claim> FindClaims(string claimType, string right);
|
||||
public abstract IEnumerator<Claim> GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Claims
|
||||
{
|
||||
public static class ClaimTypes
|
||||
{
|
||||
const string claimTypeNamespace = XsiConstants.Namespace + "/claims";
|
||||
|
||||
const string anonymous = claimTypeNamespace + "/anonymous";
|
||||
const string dns = claimTypeNamespace + "/dns";
|
||||
const string email = claimTypeNamespace + "/emailaddress";
|
||||
const string hash = claimTypeNamespace + "/hash";
|
||||
const string name = claimTypeNamespace + "/name";
|
||||
const string rsa = claimTypeNamespace + "/rsa";
|
||||
const string sid = claimTypeNamespace + "/sid";
|
||||
const string denyOnlySid = claimTypeNamespace + "/denyonlysid";
|
||||
const string spn = claimTypeNamespace + "/spn";
|
||||
const string system = claimTypeNamespace + "/system";
|
||||
const string thumbprint = claimTypeNamespace + "/thumbprint";
|
||||
const string upn = claimTypeNamespace + "/upn";
|
||||
const string uri = claimTypeNamespace + "/uri";
|
||||
const string x500DistinguishedName = claimTypeNamespace + "/x500distinguishedname";
|
||||
|
||||
const string givenname = claimTypeNamespace + "/givenname";
|
||||
const string surname = claimTypeNamespace + "/surname";
|
||||
const string streetaddress = claimTypeNamespace + "/streetaddress";
|
||||
const string locality = claimTypeNamespace + "/locality";
|
||||
const string stateorprovince = claimTypeNamespace + "/stateorprovince";
|
||||
const string postalcode = claimTypeNamespace + "/postalcode";
|
||||
const string country = claimTypeNamespace + "/country";
|
||||
const string homephone = claimTypeNamespace + "/homephone";
|
||||
const string otherphone = claimTypeNamespace + "/otherphone";
|
||||
const string mobilephone = claimTypeNamespace + "/mobilephone";
|
||||
const string dateofbirth = claimTypeNamespace + "/dateofbirth";
|
||||
const string gender = claimTypeNamespace + "/gender";
|
||||
const string ppid = claimTypeNamespace + "/privatepersonalidentifier";
|
||||
const string webpage = claimTypeNamespace + "/webpage";
|
||||
const string nameidentifier = claimTypeNamespace + "/nameidentifier";
|
||||
const string authentication = claimTypeNamespace + "/authentication";
|
||||
const string authorizationdecision = claimTypeNamespace + "/authorizationdecision";
|
||||
|
||||
static public string Anonymous { get { return anonymous; } }
|
||||
static public string DenyOnlySid { get { return denyOnlySid; } }
|
||||
static public string Dns { get { return dns; } }
|
||||
static public string Email { get { return email; } }
|
||||
static public string Hash { get { return hash; } }
|
||||
static public string Name { get { return name; } }
|
||||
static public string Rsa { get { return rsa; } }
|
||||
static public string Sid { get { return sid; } }
|
||||
static public string Spn { get { return spn; } }
|
||||
static public string System { get { return system; } }
|
||||
static public string Thumbprint { get { return thumbprint; } }
|
||||
static public string Upn { get { return upn; } }
|
||||
static public string Uri { get { return uri; } }
|
||||
static public string X500DistinguishedName { get { return x500DistinguishedName; } }
|
||||
static public string NameIdentifier { get { return nameidentifier; } }
|
||||
static public string Authentication { get { return authentication; } }
|
||||
static public string AuthorizationDecision { get { return authorizationdecision; } }
|
||||
|
||||
// used in info card
|
||||
static public string GivenName { get { return givenname; } }
|
||||
static public string Surname { get { return surname; } }
|
||||
static public string StreetAddress { get { return streetaddress; } }
|
||||
static public string Locality { get { return locality; } }
|
||||
static public string StateOrProvince { get { return stateorprovince; } }
|
||||
static public string PostalCode { get { return postalcode; } }
|
||||
static public string Country { get { return country; } }
|
||||
static public string HomePhone { get { return homephone; } }
|
||||
static public string OtherPhone { get { return otherphone; } }
|
||||
static public string MobilePhone { get { return mobilephone; } }
|
||||
static public string DateOfBirth { get { return dateofbirth; } }
|
||||
static public string Gender { get { return gender; } }
|
||||
static public string PPID { get { return ppid; } }
|
||||
static public string Webpage { get { return webpage; } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System.IdentityModel;
|
||||
using System.IdentityModel.Configuration;
|
||||
using System.Xml;
|
||||
|
||||
namespace System.Security.Claims
|
||||
{
|
||||
/// <summary>
|
||||
/// A Simple ClaimsAuthenticationManager that echoes back the incoming ClaimsIdentities.
|
||||
/// </summary>
|
||||
public class ClaimsAuthenticationManager : ICustomIdentityConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// The method echoes back the incoming ClaimsIdentities.
|
||||
/// </summary>
|
||||
/// <param name="resourceName">The address to which the request was sent.</param>
|
||||
/// <param name="incomingPrincipal"><see cref="ClaimsPrincipal"/> presented by the client (in the form of a
|
||||
/// SecurityToken) to access the resource.</param>
|
||||
/// <returns>The ClaimsPrincipal given to the method.</returns>
|
||||
public virtual ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
|
||||
{
|
||||
return incomingPrincipal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load custom configuration from Xml
|
||||
/// </summary>
|
||||
/// <param name="nodelist">Custom configuration elements</param>
|
||||
public virtual void LoadCustomConfiguration(XmlNodeList nodelist)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID0023, this.GetType().AssemblyQualifiedName)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ClaimsAuthorizationManager.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace System.Security.Claims
|
||||
{
|
||||
using System.IdentityModel;
|
||||
using System.IdentityModel.Configuration;
|
||||
using System.Security.Claims;
|
||||
using System.Xml;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the base implementation for a claims authorization manager.
|
||||
/// </summary>
|
||||
public class ClaimsAuthorizationManager : ICustomIdentityConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// When implemented in a derived class, this method will authorize the subject specified in the
|
||||
/// context to perform the specified action on the specified resource.
|
||||
/// </summary>
|
||||
/// <param name="context"><see cref="AuthorizationContext"/> that encapsulates the subject, resource, and action.</param>
|
||||
/// <returns>true if authorized, false otherwise.</returns>
|
||||
public virtual bool CheckAccess(AuthorizationContext context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load custom configuration from Xml
|
||||
/// </summary>
|
||||
/// <param name="nodelist">Custom configuration elements</param>
|
||||
public virtual void LoadCustomConfiguration(XmlNodeList nodelist)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID0023, this.GetType().AssemblyQualifiedName)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
|
||||
namespace System.Security.Claims
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens;
|
||||
using System.Net.Mail;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Principal;
|
||||
|
||||
internal static class ClaimsConversionHelper
|
||||
{
|
||||
public static ClaimsIdentity CreateClaimsIdentityFromClaimSet(System.IdentityModel.Claims.ClaimSet claimset, string authenticationType)
|
||||
{
|
||||
if (claimset == null)
|
||||
{
|
||||
throw new ArgumentNullException("claimSet");
|
||||
}
|
||||
|
||||
string issuer = null;
|
||||
if (claimset.Issuer == null)
|
||||
{
|
||||
issuer = ClaimsIdentity.DefaultIssuer;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (System.IdentityModel.Claims.Claim claim in claimset.Issuer.FindClaims(System.IdentityModel.Claims.ClaimTypes.Name, System.IdentityModel.Claims.Rights.Identity))
|
||||
{
|
||||
if ((claim != null) && (claim.Resource is string))
|
||||
{
|
||||
issuer = claim.Resource as string;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ClaimsIdentity claimsIdentity = new ClaimsIdentity(authenticationType);
|
||||
|
||||
for (int i = 0; i < claimset.Count; ++i)
|
||||
{
|
||||
//
|
||||
// Only capture possesses property claims
|
||||
//
|
||||
if (String.Equals(claimset[i].Right, System.IdentityModel.Claims.Rights.PossessProperty, StringComparison.Ordinal))
|
||||
{
|
||||
claimsIdentity.AddClaim(CreateClaimFromWcfClaim(claimset[i], issuer));
|
||||
}
|
||||
}
|
||||
|
||||
return claimsIdentity;
|
||||
}
|
||||
|
||||
public static ClaimsIdentity CreateClaimsIdentityFromClaimSet(System.IdentityModel.Claims.ClaimSet claimset)
|
||||
{
|
||||
return CreateClaimsIdentityFromClaimSet(claimset, null);
|
||||
}
|
||||
|
||||
public static System.Security.Claims.Claim CreateClaimFromWcfClaim(System.IdentityModel.Claims.Claim wcfClaim)
|
||||
{
|
||||
return CreateClaimFromWcfClaim(wcfClaim, null);
|
||||
}
|
||||
|
||||
public static System.Security.Claims.Claim CreateClaimFromWcfClaim(System.IdentityModel.Claims.Claim wcfClaim, string issuer)
|
||||
{
|
||||
string claimType = null;
|
||||
string value = null;
|
||||
string valueType = ClaimValueTypes.String;
|
||||
string originalIssuer = issuer;
|
||||
string samlNameIdentifierFormat = null;
|
||||
string samlNameIdentifierNameQualifier = null;
|
||||
|
||||
if (wcfClaim == null)
|
||||
{
|
||||
throw new ArgumentNullException("claim");
|
||||
}
|
||||
|
||||
if (wcfClaim.Resource == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(issuer))
|
||||
{
|
||||
issuer = ClaimsIdentity.DefaultIssuer;
|
||||
}
|
||||
|
||||
if (wcfClaim.Resource is string)
|
||||
{
|
||||
AssignClaimFromStringResourceSysClaim(wcfClaim, out claimType, out value);
|
||||
}
|
||||
else
|
||||
{
|
||||
AssignClaimFromSysClaim(wcfClaim, out claimType, out value, out valueType, out samlNameIdentifierFormat, out samlNameIdentifierNameQualifier);
|
||||
}
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
System.Security.Claims.Claim newClaim = new System.Security.Claims.Claim(claimType, value, valueType, issuer, originalIssuer);
|
||||
newClaim.Properties[ClaimProperties.SamlNameIdentifierFormat] = samlNameIdentifierFormat;
|
||||
newClaim.Properties[ClaimProperties.SamlNameIdentifierNameQualifier] = samlNameIdentifierNameQualifier;
|
||||
return newClaim;
|
||||
}
|
||||
|
||||
static void AssignClaimFromStringResourceSysClaim(System.IdentityModel.Claims.Claim claim, out string claimType, out string claimValue)
|
||||
{
|
||||
claimType = claim.ClaimType;
|
||||
claimValue = (string)claim.Resource;
|
||||
|
||||
if (StringComparer.Ordinal.Equals(claim.ClaimType, ClaimTypes.Sid))
|
||||
{
|
||||
if (claim.Right == System.IdentityModel.Claims.Rights.Identity)
|
||||
{
|
||||
claimType = ClaimTypes.PrimarySid;
|
||||
}
|
||||
else
|
||||
{
|
||||
claimType = ClaimTypes.GroupSid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void AssignClaimFromSysClaim(System.IdentityModel.Claims.Claim claim, out string _type, out string _value, out string _valueType, out string samlNameIdentifierFormat, out string samlNameIdentifierNameQualifier)
|
||||
{
|
||||
samlNameIdentifierFormat = null;
|
||||
samlNameIdentifierNameQualifier = null;
|
||||
_type = null;
|
||||
_value = null;
|
||||
_valueType = null;
|
||||
|
||||
if (StringComparer.Ordinal.Equals(claim.ClaimType, ClaimTypes.Sid) && claim.Resource is SecurityIdentifier)
|
||||
{
|
||||
if (claim.Right == System.IdentityModel.Claims.Rights.Identity)
|
||||
{
|
||||
_type = ClaimTypes.PrimarySid;
|
||||
}
|
||||
else
|
||||
{
|
||||
_type = ClaimTypes.GroupSid;
|
||||
}
|
||||
_value = ((SecurityIdentifier)claim.Resource).Value;
|
||||
}
|
||||
else if (StringComparer.Ordinal.Equals(claim.ClaimType, ClaimTypes.Email) && claim.Resource is MailAddress)
|
||||
{
|
||||
_type = claim.ClaimType;
|
||||
_value = ((MailAddress)claim.Resource).Address;
|
||||
}
|
||||
else if (StringComparer.Ordinal.Equals(claim.ClaimType, ClaimTypes.Thumbprint) && claim.Resource is byte[])
|
||||
{
|
||||
_type = claim.ClaimType;
|
||||
_value = Convert.ToBase64String(((byte[])claim.Resource));
|
||||
_valueType = ClaimValueTypes.Base64Binary;
|
||||
}
|
||||
else if (StringComparer.Ordinal.Equals(claim.ClaimType, ClaimTypes.Hash) && claim.Resource is byte[])
|
||||
{
|
||||
_type = claim.ClaimType;
|
||||
_value = Convert.ToBase64String(((byte[])claim.Resource));
|
||||
_valueType = ClaimValueTypes.Base64Binary;
|
||||
}
|
||||
else if (StringComparer.Ordinal.Equals(claim.ClaimType, ClaimTypes.NameIdentifier) && claim.Resource is SamlNameIdentifierClaimResource)
|
||||
{
|
||||
_type = claim.ClaimType;
|
||||
_value = ((SamlNameIdentifierClaimResource)claim.Resource).Name;
|
||||
|
||||
if (((SamlNameIdentifierClaimResource)claim.Resource).Format != null)
|
||||
{
|
||||
|
||||
samlNameIdentifierFormat = ((SamlNameIdentifierClaimResource)claim.Resource).Format;
|
||||
}
|
||||
if (((SamlNameIdentifierClaimResource)claim.Resource).NameQualifier != null)
|
||||
{
|
||||
samlNameIdentifierNameQualifier = ((SamlNameIdentifierClaimResource)claim.Resource).NameQualifier;
|
||||
}
|
||||
}
|
||||
else if (StringComparer.Ordinal.Equals(claim.ClaimType, ClaimTypes.X500DistinguishedName) && claim.Resource is X500DistinguishedName)
|
||||
{
|
||||
_type = claim.ClaimType;
|
||||
_value = ((X500DistinguishedName)claim.Resource).Name;
|
||||
_valueType = ClaimValueTypes.X500Name;
|
||||
}
|
||||
else if (StringComparer.Ordinal.Equals(claim.ClaimType, ClaimTypes.Uri) && claim.Resource is Uri)
|
||||
{
|
||||
_type = claim.ClaimType;
|
||||
_value = ((Uri)claim.Resource).ToString();
|
||||
}
|
||||
else if (StringComparer.Ordinal.Equals(claim.ClaimType, ClaimTypes.Rsa) && claim.Resource is RSA)
|
||||
{
|
||||
_type = claim.ClaimType;
|
||||
_value = ((RSA)claim.Resource).ToXmlString(false);
|
||||
_valueType = ClaimValueTypes.RsaKeyValue;
|
||||
}
|
||||
else if (StringComparer.Ordinal.Equals(claim.ClaimType, ClaimTypes.DenyOnlySid) && claim.Resource is SecurityIdentifier)
|
||||
{
|
||||
_type = claim.ClaimType;
|
||||
_value = ((SecurityIdentifier)claim.Resource).Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System.IdentityModel;
|
||||
using System.IdentityModel.Tokens;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Principal;
|
||||
using System.Security.Claims;
|
||||
|
||||
using Claim = System.Security.Claims.Claim;
|
||||
|
||||
namespace System.Security.Claims
|
||||
{
|
||||
internal static class ClaimsHelper
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="WindowsIdentity"/> associated with a given X509 certificate.
|
||||
/// </summary>
|
||||
/// <param name="x509Certificate">The certificate to use to map to the associated <see cref="WindowsIdentity"/></param>
|
||||
/// <returns></returns>
|
||||
public static WindowsIdentity CertificateLogon(X509Certificate2 x509Certificate)
|
||||
{
|
||||
// for Vista, LsaLogon supporting mapping cert to NTToken
|
||||
if (Environment.OSVersion.Version.Major >= CryptoHelper.WindowsVistaMajorNumber)
|
||||
{
|
||||
return X509SecurityTokenHandler.KerberosCertificateLogon(x509Certificate);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Downlevel, S4U over PrincipalName SubjectAltNames
|
||||
string upn = x509Certificate.GetNameInfo(X509NameType.UpnName, false);
|
||||
if (string.IsNullOrEmpty(upn))
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenValidationException(SR.GetString(SR.ID4067,
|
||||
X509Util.GetCertificateId(x509Certificate))));
|
||||
}
|
||||
|
||||
return new WindowsIdentity(upn);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the UPN claim value in the provided <see cref="ClaimsIdentity" /> object for the purpose
|
||||
/// of mapping the identity to a <see cref="WindowsIdentity" /> object.
|
||||
/// </summary>
|
||||
/// <param name="claimsIdentity">The claims identity object containing the desired UPN claim.</param>
|
||||
/// <returns>The UPN claim value found.</returns>
|
||||
/// <exception cref="SecurityTokenException">
|
||||
/// If <paramref name="claimsIdentity"/> contains zero UPN claims or more than one UPN claim.
|
||||
/// </exception>
|
||||
public static string FindUpn(ClaimsIdentity claimsIdentity)
|
||||
{
|
||||
string upn = null;
|
||||
foreach (Claim claim in claimsIdentity.Claims)
|
||||
{
|
||||
if (StringComparer.Ordinal.Equals(ClaimTypes.Upn, claim.Type))
|
||||
{
|
||||
// Complain if we already found a UPN claim
|
||||
if (upn != null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID1053)));
|
||||
}
|
||||
upn = claim.Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(upn))
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID1054)));
|
||||
}
|
||||
return upn;
|
||||
}
|
||||
|
||||
#region FIP 12979 GetAnonymous resolved as Postponed
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Generates a <see cref="WindowsClaimsIdentity"/> based on an anonymous user Windows token.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="WindowsClaimsIdentity"/> whose base <see cref="WindowsIdentity"/> has a Windows token for the NT AUTHORITY\ANONYMOUS LOGON user.</returns>
|
||||
/// <exception cref="Win32Exception">Thrown if this method fails to open the current thread token.</exception>
|
||||
/// <exception cref="Win32Exception">Thrown if this method fails to impersonate NT AUTHORITY\ANONYMOUS LOGON.</exception>
|
||||
/// <exception cref="Win32Exception">Thrown if this method fails in attempt to reset thread token.</exception>
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPrincipal )]
|
||||
new public static WindowsClaimsIdentity GetAnonymous()
|
||||
{
|
||||
SafeCloseHandle originalThreadToken;
|
||||
WindowsClaimsIdentity result = null;
|
||||
|
||||
//
|
||||
// If the thread is impersonating
|
||||
// preserve the token so we can put it back
|
||||
// after capturing the anonymous token.
|
||||
//
|
||||
if( !NativeMethods.OpenThreadToken(
|
||||
NativeMethods.GetCurrentThread(),
|
||||
TokenAccessLevels.Impersonate,
|
||||
true, // Use the process identity permissions
|
||||
out originalThreadToken ) )
|
||||
{
|
||||
int win32Result = Marshal.GetLastWin32Error();
|
||||
if( ( (int) Win32Error.ERROR_NO_TOKEN ) != win32Result )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new Win32Exception( win32Result ) );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Use CER to prevent the app-domain from unloading before
|
||||
// we can set the thread token back to the original value.
|
||||
//
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
if( !NativeMethods.ImpersonateAnonymousToken( NativeMethods.GetCurrentThread() ) )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new Win32Exception() );
|
||||
}
|
||||
|
||||
result = WindowsClaimsIdentity.GetCurrent();
|
||||
}
|
||||
finally
|
||||
{
|
||||
//
|
||||
// Replace the thread token with the original.
|
||||
// Setting the thread token to zero will stop impersonating.
|
||||
//
|
||||
if( !NativeMethods.SetThreadToken(
|
||||
IntPtr.Zero, // current thread
|
||||
originalThreadToken ) )
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new Win32Exception() );
|
||||
}
|
||||
|
||||
originalThreadToken.Close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Claims
|
||||
{
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
[DataContract(Namespace = XsiConstants.Namespace)]
|
||||
public class DefaultClaimSet : ClaimSet
|
||||
{
|
||||
[DataMember(Name = "Issuer")]
|
||||
ClaimSet issuer;
|
||||
[DataMember(Name = "Claims")]
|
||||
IList<Claim> claims;
|
||||
|
||||
public DefaultClaimSet(params Claim[] claims)
|
||||
{
|
||||
Initialize(this, claims);
|
||||
}
|
||||
|
||||
public DefaultClaimSet(IList<Claim> claims)
|
||||
{
|
||||
Initialize(this, claims);
|
||||
}
|
||||
|
||||
public DefaultClaimSet(ClaimSet issuer, params Claim[] claims)
|
||||
{
|
||||
Initialize(issuer, claims);
|
||||
}
|
||||
|
||||
public DefaultClaimSet(ClaimSet issuer, IList<Claim> claims)
|
||||
{
|
||||
Initialize(issuer, claims);
|
||||
}
|
||||
|
||||
public override Claim this[int index]
|
||||
{
|
||||
get { return this.claims[index]; }
|
||||
}
|
||||
|
||||
public override int Count
|
||||
{
|
||||
get { return this.claims.Count; }
|
||||
}
|
||||
|
||||
public override ClaimSet Issuer
|
||||
{
|
||||
get { return this.issuer; }
|
||||
}
|
||||
|
||||
public override bool ContainsClaim(Claim claim)
|
||||
{
|
||||
if (claim == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("claim");
|
||||
|
||||
for (int i = 0; i < this.claims.Count; ++i)
|
||||
{
|
||||
if (claim.Equals(this.claims[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override IEnumerable<Claim> FindClaims(string claimType, string right)
|
||||
{
|
||||
bool anyClaimType = (claimType == null);
|
||||
bool anyRight = (right == null);
|
||||
|
||||
for (int i = 0; i < this.claims.Count; ++i)
|
||||
{
|
||||
Claim claim = this.claims[i];
|
||||
if ((claim != null) &&
|
||||
(anyClaimType || claimType == claim.ClaimType) &&
|
||||
(anyRight || right == claim.Right))
|
||||
{
|
||||
yield return claim;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerator<Claim> GetEnumerator()
|
||||
{
|
||||
return this.claims.GetEnumerator();
|
||||
}
|
||||
|
||||
protected void Initialize(ClaimSet issuer, IList<Claim> claims)
|
||||
{
|
||||
if (issuer == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("issuer");
|
||||
if (claims == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("claims");
|
||||
|
||||
this.issuer = issuer;
|
||||
this.claims = claims;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return SecurityUtils.ClaimSetToString(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Claims
|
||||
{
|
||||
public static class Rights
|
||||
{
|
||||
const string rightNamespace = XsiConstants.Namespace + "/right";
|
||||
|
||||
const string identity = rightNamespace + "/identity";
|
||||
const string possessProperty = rightNamespace + "/possessproperty";
|
||||
|
||||
static public string Identity { get { return identity; } }
|
||||
static public string PossessProperty { get { return possessProperty; } }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Claims
|
||||
{
|
||||
using System.IdentityModel.Policy;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Security.Principal;
|
||||
|
||||
public class WindowsClaimSet : ClaimSet, IIdentityInfo, IDisposable
|
||||
{
|
||||
internal const bool DefaultIncludeWindowsGroups = true;
|
||||
WindowsIdentity windowsIdentity;
|
||||
DateTime expirationTime;
|
||||
bool includeWindowsGroups;
|
||||
IList<Claim> claims;
|
||||
GroupSidClaimCollection groups;
|
||||
bool disposed = false;
|
||||
string authenticationType;
|
||||
|
||||
public WindowsClaimSet(WindowsIdentity windowsIdentity)
|
||||
: this(windowsIdentity, DefaultIncludeWindowsGroups)
|
||||
{
|
||||
}
|
||||
|
||||
public WindowsClaimSet(WindowsIdentity windowsIdentity, bool includeWindowsGroups)
|
||||
: this(windowsIdentity, includeWindowsGroups, DateTime.UtcNow.AddHours(10))
|
||||
{
|
||||
}
|
||||
|
||||
public WindowsClaimSet(WindowsIdentity windowsIdentity, DateTime expirationTime)
|
||||
: this(windowsIdentity, DefaultIncludeWindowsGroups, expirationTime)
|
||||
{
|
||||
}
|
||||
|
||||
public WindowsClaimSet(WindowsIdentity windowsIdentity, bool includeWindowsGroups, DateTime expirationTime)
|
||||
: this(windowsIdentity, null, includeWindowsGroups, expirationTime, true)
|
||||
{
|
||||
}
|
||||
|
||||
public WindowsClaimSet(WindowsIdentity windowsIdentity, string authenticationType, bool includeWindowsGroups, DateTime expirationTime)
|
||||
: this( windowsIdentity, authenticationType, includeWindowsGroups, expirationTime, true )
|
||||
{
|
||||
}
|
||||
|
||||
internal WindowsClaimSet(WindowsIdentity windowsIdentity, string authenticationType, bool includeWindowsGroups, bool clone)
|
||||
: this( windowsIdentity, authenticationType, includeWindowsGroups, DateTime.UtcNow.AddHours( 10 ), clone )
|
||||
{
|
||||
}
|
||||
|
||||
internal WindowsClaimSet(WindowsIdentity windowsIdentity, string authenticationType, bool includeWindowsGroups, DateTime expirationTime, bool clone)
|
||||
{
|
||||
if (windowsIdentity == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("windowsIdentity");
|
||||
|
||||
this.windowsIdentity = clone ? SecurityUtils.CloneWindowsIdentityIfNecessary(windowsIdentity, authenticationType) : windowsIdentity;
|
||||
this.includeWindowsGroups = includeWindowsGroups;
|
||||
this.expirationTime = expirationTime;
|
||||
this.authenticationType = authenticationType;
|
||||
}
|
||||
|
||||
WindowsClaimSet(WindowsClaimSet from)
|
||||
: this(from.WindowsIdentity, from.authenticationType, from.includeWindowsGroups, from.expirationTime, true)
|
||||
{
|
||||
}
|
||||
|
||||
public override Claim this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
EnsureClaims();
|
||||
return this.claims[index];
|
||||
}
|
||||
}
|
||||
|
||||
public override int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
EnsureClaims();
|
||||
return this.claims.Count;
|
||||
}
|
||||
}
|
||||
|
||||
IIdentity IIdentityInfo.Identity
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return this.windowsIdentity;
|
||||
}
|
||||
}
|
||||
|
||||
public WindowsIdentity WindowsIdentity
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return this.windowsIdentity;
|
||||
}
|
||||
}
|
||||
|
||||
public override ClaimSet Issuer
|
||||
{
|
||||
get { return ClaimSet.Windows; }
|
||||
}
|
||||
|
||||
public DateTime ExpirationTime
|
||||
{
|
||||
get { return this.expirationTime; }
|
||||
}
|
||||
|
||||
GroupSidClaimCollection Groups
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.groups == null)
|
||||
{
|
||||
this.groups = new GroupSidClaimCollection(this.windowsIdentity);
|
||||
}
|
||||
return this.groups;
|
||||
}
|
||||
}
|
||||
|
||||
internal WindowsClaimSet Clone()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return new WindowsClaimSet(this);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!this.disposed)
|
||||
{
|
||||
this.disposed = true;
|
||||
this.windowsIdentity.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
IList<Claim> InitializeClaimsCore()
|
||||
{
|
||||
if (this.windowsIdentity.Token == IntPtr.Zero)
|
||||
return new List<Claim>();
|
||||
|
||||
List<Claim> claims = new List<Claim>(3);
|
||||
claims.Add(new Claim(ClaimTypes.Sid, this.windowsIdentity.User, Rights.Identity));
|
||||
Claim claim;
|
||||
if (TryCreateWindowsSidClaim(this.windowsIdentity, out claim))
|
||||
{
|
||||
claims.Add(claim);
|
||||
}
|
||||
claims.Add(Claim.CreateNameClaim(this.windowsIdentity.Name));
|
||||
if (this.includeWindowsGroups)
|
||||
{
|
||||
claims.AddRange(this.Groups);
|
||||
}
|
||||
return claims;
|
||||
}
|
||||
|
||||
void EnsureClaims()
|
||||
{
|
||||
if (this.claims != null)
|
||||
return;
|
||||
|
||||
this.claims = InitializeClaimsCore();
|
||||
}
|
||||
|
||||
void ThrowIfDisposed()
|
||||
{
|
||||
if (this.disposed)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName));
|
||||
}
|
||||
}
|
||||
|
||||
static bool SupportedClaimType(string claimType)
|
||||
{
|
||||
return claimType == null ||
|
||||
ClaimTypes.Sid == claimType ||
|
||||
ClaimTypes.DenyOnlySid == claimType ||
|
||||
ClaimTypes.Name == claimType;
|
||||
}
|
||||
|
||||
// Note: null string represents any.
|
||||
public override IEnumerable<Claim> FindClaims(string claimType, string right)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (!SupportedClaimType(claimType) || !ClaimSet.SupportedRight(right))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
else if (this.claims == null && (ClaimTypes.Sid == claimType || ClaimTypes.DenyOnlySid == claimType))
|
||||
{
|
||||
if (ClaimTypes.Sid == claimType)
|
||||
{
|
||||
if (right == null || Rights.Identity == right)
|
||||
{
|
||||
yield return new Claim(ClaimTypes.Sid, this.windowsIdentity.User, Rights.Identity);
|
||||
}
|
||||
}
|
||||
|
||||
if (right == null || Rights.PossessProperty == right)
|
||||
{
|
||||
Claim sid;
|
||||
if (TryCreateWindowsSidClaim(this.windowsIdentity, out sid))
|
||||
{
|
||||
if (claimType == sid.ClaimType)
|
||||
{
|
||||
yield return sid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.includeWindowsGroups && (right == null || Rights.PossessProperty == right))
|
||||
{
|
||||
for (int i = 0; i < this.Groups.Count; ++i)
|
||||
{
|
||||
Claim sid = this.Groups[i];
|
||||
if (claimType == sid.ClaimType)
|
||||
{
|
||||
yield return sid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnsureClaims();
|
||||
|
||||
bool anyClaimType = (claimType == null);
|
||||
bool anyRight = (right == null);
|
||||
|
||||
for (int i = 0; i < this.claims.Count; ++i)
|
||||
{
|
||||
Claim claim = this.claims[i];
|
||||
if ((claim != null) &&
|
||||
(anyClaimType || claimType == claim.ClaimType) &&
|
||||
(anyRight || right == claim.Right))
|
||||
{
|
||||
yield return claim;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerator<Claim> GetEnumerator()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
EnsureClaims();
|
||||
return this.claims.GetEnumerator();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return this.disposed ? base.ToString() : SecurityUtils.ClaimSetToString(this);
|
||||
}
|
||||
|
||||
class GroupSidClaimCollection : Collection<Claim>
|
||||
{
|
||||
// Copy from System\Security\Principal\WindowsIdentity.cs
|
||||
[Fx.Tag.SecurityNote(Critical = "Uses critical type SafeHGlobalHandle.",
|
||||
Safe = "Performs a Demand for full trust.")]
|
||||
[SecuritySafeCritical]
|
||||
[SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
|
||||
public GroupSidClaimCollection(WindowsIdentity windowsIdentity)
|
||||
{
|
||||
if (windowsIdentity.Token != IntPtr.Zero)
|
||||
{
|
||||
SafeHGlobalHandle safeAllocHandle = SafeHGlobalHandle.InvalidHandle;
|
||||
try
|
||||
{
|
||||
uint dwLength;
|
||||
safeAllocHandle = GetTokenInformation(windowsIdentity.Token, TokenInformationClass.TokenGroups, out dwLength);
|
||||
int count = Marshal.ReadInt32(safeAllocHandle.DangerousGetHandle());
|
||||
IntPtr pSidAndAttributes = new IntPtr((long)safeAllocHandle.DangerousGetHandle() + (long)Marshal.OffsetOf(typeof(TOKEN_GROUPS), "Groups"));
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
SID_AND_ATTRIBUTES group = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(pSidAndAttributes, typeof(SID_AND_ATTRIBUTES));
|
||||
uint mask = NativeMethods.SE_GROUP_ENABLED | NativeMethods.SE_GROUP_LOGON_ID | NativeMethods.SE_GROUP_USE_FOR_DENY_ONLY;
|
||||
if ((group.Attributes & mask) == NativeMethods.SE_GROUP_ENABLED)
|
||||
{
|
||||
base.Add(Claim.CreateWindowsSidClaim(new SecurityIdentifier(group.Sid)));
|
||||
}
|
||||
else if ((group.Attributes & mask) == NativeMethods.SE_GROUP_USE_FOR_DENY_ONLY)
|
||||
{
|
||||
base.Add(Claim.CreateDenyOnlyWindowsSidClaim(new SecurityIdentifier(group.Sid)));
|
||||
}
|
||||
pSidAndAttributes = new IntPtr((long)pSidAndAttributes + SID_AND_ATTRIBUTES.SizeOf);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
safeAllocHandle.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy from System\Security\Principal\WindowsIdentity.cs
|
||||
[Fx.Tag.SecurityNote(Critical = "Uses critical type SafeHGlobalHandle.",
|
||||
Safe = "Performs a Demand for full trust.")]
|
||||
[SecuritySafeCritical]
|
||||
[SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
|
||||
static SafeHGlobalHandle GetTokenInformation(IntPtr tokenHandle, TokenInformationClass tokenInformationClass, out uint dwLength)
|
||||
{
|
||||
SafeHGlobalHandle safeAllocHandle = SafeHGlobalHandle.InvalidHandle;
|
||||
dwLength = (uint)Marshal.SizeOf(typeof(uint));
|
||||
bool result = NativeMethods.GetTokenInformation(tokenHandle,
|
||||
(uint)tokenInformationClass,
|
||||
safeAllocHandle,
|
||||
0,
|
||||
out dwLength);
|
||||
int dwErrorCode = Marshal.GetLastWin32Error();
|
||||
switch (dwErrorCode)
|
||||
{
|
||||
case NativeMethods.ERROR_BAD_LENGTH:
|
||||
// special case for TokenSessionId. Falling through
|
||||
case NativeMethods.ERROR_INSUFFICIENT_BUFFER:
|
||||
safeAllocHandle = SafeHGlobalHandle.AllocHGlobal(dwLength);
|
||||
result = NativeMethods.GetTokenInformation(tokenHandle,
|
||||
(uint)tokenInformationClass,
|
||||
safeAllocHandle,
|
||||
dwLength,
|
||||
out dwLength);
|
||||
dwErrorCode = Marshal.GetLastWin32Error();
|
||||
if (!result)
|
||||
{
|
||||
safeAllocHandle.Close();
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(dwErrorCode));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(dwErrorCode));
|
||||
}
|
||||
return safeAllocHandle;
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Uses critical type SafeHGlobalHandle.",
|
||||
Safe = "Performs a Demand for full trust.")]
|
||||
[SecuritySafeCritical]
|
||||
[SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
|
||||
static bool TryCreateWindowsSidClaim(WindowsIdentity windowsIdentity, out Claim claim)
|
||||
{
|
||||
SafeHGlobalHandle safeAllocHandle = SafeHGlobalHandle.InvalidHandle;
|
||||
try
|
||||
{
|
||||
uint dwLength;
|
||||
safeAllocHandle = GetTokenInformation(windowsIdentity.Token, TokenInformationClass.TokenUser, out dwLength);
|
||||
SID_AND_ATTRIBUTES user = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(safeAllocHandle.DangerousGetHandle(), typeof(SID_AND_ATTRIBUTES));
|
||||
uint mask = NativeMethods.SE_GROUP_USE_FOR_DENY_ONLY;
|
||||
if (user.Attributes == 0)
|
||||
{
|
||||
claim = Claim.CreateWindowsSidClaim(new SecurityIdentifier(user.Sid));
|
||||
return true;
|
||||
}
|
||||
else if ((user.Attributes & mask) == NativeMethods.SE_GROUP_USE_FOR_DENY_ONLY)
|
||||
{
|
||||
claim = Claim.CreateDenyOnlyWindowsSidClaim(new SecurityIdentifier(user.Sid));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
safeAllocHandle.Close();
|
||||
}
|
||||
claim = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,471 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Claims
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Policy;
|
||||
using System.Net.Mail;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Principal;
|
||||
|
||||
public class X509CertificateClaimSet : ClaimSet, IIdentityInfo, IDisposable
|
||||
{
|
||||
X509Certificate2 certificate;
|
||||
DateTime expirationTime = SecurityUtils.MinUtcDateTime;
|
||||
ClaimSet issuer;
|
||||
X509Identity identity;
|
||||
X509ChainElementCollection elements;
|
||||
IList<Claim> claims;
|
||||
int index;
|
||||
bool disposed = false;
|
||||
|
||||
public X509CertificateClaimSet(X509Certificate2 certificate)
|
||||
: this(certificate, true)
|
||||
{
|
||||
}
|
||||
|
||||
internal X509CertificateClaimSet(X509Certificate2 certificate, bool clone)
|
||||
{
|
||||
if (certificate == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("certificate");
|
||||
this.certificate = clone ? new X509Certificate2(certificate) : certificate;
|
||||
}
|
||||
|
||||
X509CertificateClaimSet(X509CertificateClaimSet from)
|
||||
: this(from.X509Certificate, true)
|
||||
{
|
||||
}
|
||||
|
||||
X509CertificateClaimSet(X509ChainElementCollection elements, int index)
|
||||
{
|
||||
this.elements = elements;
|
||||
this.index = index;
|
||||
this.certificate = elements[index].Certificate;
|
||||
}
|
||||
|
||||
public override Claim this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
EnsureClaims();
|
||||
return this.claims[index];
|
||||
}
|
||||
}
|
||||
|
||||
public override int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
EnsureClaims();
|
||||
return this.claims.Count;
|
||||
}
|
||||
}
|
||||
|
||||
IIdentity IIdentityInfo.Identity
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (this.identity == null)
|
||||
this.identity = new X509Identity(this.certificate, false, false);
|
||||
return this.identity;
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime ExpirationTime
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (this.expirationTime == SecurityUtils.MinUtcDateTime)
|
||||
this.expirationTime = this.certificate.NotAfter.ToUniversalTime();
|
||||
return this.expirationTime;
|
||||
}
|
||||
}
|
||||
|
||||
public override ClaimSet Issuer
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (this.issuer == null)
|
||||
{
|
||||
if (this.elements == null)
|
||||
{
|
||||
X509Chain chain = new X509Chain();
|
||||
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
|
||||
chain.Build(certificate);
|
||||
this.index = 0;
|
||||
this.elements = chain.ChainElements;
|
||||
}
|
||||
|
||||
if (this.index + 1 < this.elements.Count)
|
||||
{
|
||||
this.issuer = new X509CertificateClaimSet(this.elements, this.index + 1);
|
||||
this.elements = null;
|
||||
}
|
||||
// SelfSigned?
|
||||
else if (StringComparer.OrdinalIgnoreCase.Equals(this.certificate.SubjectName.Name, this.certificate.IssuerName.Name))
|
||||
this.issuer = this;
|
||||
else
|
||||
this.issuer = new X500DistinguishedNameClaimSet(this.certificate.IssuerName);
|
||||
|
||||
}
|
||||
return this.issuer;
|
||||
}
|
||||
}
|
||||
|
||||
public X509Certificate2 X509Certificate
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return this.certificate;
|
||||
}
|
||||
}
|
||||
|
||||
internal X509CertificateClaimSet Clone()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return new X509CertificateClaimSet(this);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!this.disposed)
|
||||
{
|
||||
this.disposed = true;
|
||||
SecurityUtils.DisposeIfNecessary(this.identity);
|
||||
if (this.issuer != null)
|
||||
{
|
||||
if (this.issuer != this)
|
||||
{
|
||||
SecurityUtils.DisposeIfNecessary(this.issuer as IDisposable);
|
||||
}
|
||||
}
|
||||
if (this.elements != null)
|
||||
{
|
||||
for (int i = this.index + 1; i < this.elements.Count; ++i)
|
||||
{
|
||||
SecurityUtils.ResetCertificate(this.elements[i].Certificate);
|
||||
}
|
||||
}
|
||||
SecurityUtils.ResetCertificate(this.certificate);
|
||||
}
|
||||
}
|
||||
|
||||
IList<Claim> InitializeClaimsCore()
|
||||
{
|
||||
List<Claim> claims = new List<Claim>();
|
||||
byte[] thumbprint = this.certificate.GetCertHash();
|
||||
claims.Add(new Claim(ClaimTypes.Thumbprint, thumbprint, Rights.Identity));
|
||||
claims.Add(new Claim(ClaimTypes.Thumbprint, thumbprint, Rights.PossessProperty));
|
||||
|
||||
// Ordering SubjectName, Dns, SimpleName, Email, Upn
|
||||
string value = this.certificate.SubjectName.Name;
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
claims.Add(Claim.CreateX500DistinguishedNameClaim(this.certificate.SubjectName));
|
||||
|
||||
// App context switch for disabling support for multiple dns entries in a SAN certificate
|
||||
if (LocalAppContextSwitches.DisableMultipleDNSEntriesInSANCertificate)
|
||||
{
|
||||
// old behavior, default for <= 4.6
|
||||
value = this.certificate.GetNameInfo(X509NameType.DnsName, false);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
claims.Add(Claim.CreateDnsClaim(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
// new behavior as this is the default long term behavior
|
||||
// Since a SAN can have multiple DNS entries
|
||||
string[] entries = GetDnsFromExtensions(this.certificate);
|
||||
for (int i = 0; i < entries.Length; ++i)
|
||||
{
|
||||
claims.Add(Claim.CreateDnsClaim(entries[i]));
|
||||
}
|
||||
}
|
||||
|
||||
value = this.certificate.GetNameInfo(X509NameType.SimpleName, false);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
claims.Add(Claim.CreateNameClaim(value));
|
||||
|
||||
value = this.certificate.GetNameInfo(X509NameType.EmailName, false);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
claims.Add(Claim.CreateMailAddressClaim(new MailAddress(value)));
|
||||
|
||||
value = this.certificate.GetNameInfo(X509NameType.UpnName, false);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
claims.Add(Claim.CreateUpnClaim(value));
|
||||
|
||||
value = this.certificate.GetNameInfo(X509NameType.UrlName, false);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
claims.Add(Claim.CreateUriClaim(new Uri(value)));
|
||||
|
||||
RSA rsa = this.certificate.PublicKey.Key as RSA;
|
||||
if (rsa != null)
|
||||
claims.Add(Claim.CreateRsaClaim(rsa));
|
||||
|
||||
return claims;
|
||||
}
|
||||
|
||||
void EnsureClaims()
|
||||
{
|
||||
if (this.claims != null)
|
||||
return;
|
||||
|
||||
this.claims = InitializeClaimsCore();
|
||||
}
|
||||
|
||||
static bool SupportedClaimType(string claimType)
|
||||
{
|
||||
return claimType == null ||
|
||||
ClaimTypes.Thumbprint.Equals(claimType) ||
|
||||
ClaimTypes.X500DistinguishedName.Equals(claimType) ||
|
||||
ClaimTypes.Dns.Equals(claimType) ||
|
||||
ClaimTypes.Name.Equals(claimType) ||
|
||||
ClaimTypes.Email.Equals(claimType) ||
|
||||
ClaimTypes.Upn.Equals(claimType) ||
|
||||
ClaimTypes.Uri.Equals(claimType) ||
|
||||
ClaimTypes.Rsa.Equals(claimType);
|
||||
}
|
||||
|
||||
// Note: null string represents any.
|
||||
public override IEnumerable<Claim> FindClaims(string claimType, string right)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (!SupportedClaimType(claimType) || !ClaimSet.SupportedRight(right))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
else if (this.claims == null && ClaimTypes.Thumbprint.Equals(claimType))
|
||||
{
|
||||
if (right == null || Rights.Identity.Equals(right))
|
||||
{
|
||||
yield return new Claim(ClaimTypes.Thumbprint, this.certificate.GetCertHash(), Rights.Identity);
|
||||
}
|
||||
if (right == null || Rights.PossessProperty.Equals(right))
|
||||
{
|
||||
yield return new Claim(ClaimTypes.Thumbprint, this.certificate.GetCertHash(), Rights.PossessProperty);
|
||||
}
|
||||
}
|
||||
else if (this.claims == null && ClaimTypes.Dns.Equals(claimType))
|
||||
{
|
||||
if (right == null || Rights.PossessProperty.Equals(right))
|
||||
{
|
||||
// App context switch for disabling support for multiple dns entries in a SAN certificate
|
||||
if (LocalAppContextSwitches.DisableMultipleDNSEntriesInSANCertificate)
|
||||
{
|
||||
// old behavior, default for <= 4.6
|
||||
string value = this.certificate.GetNameInfo(X509NameType.DnsName, false);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
yield return Claim.CreateDnsClaim(value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// new behavior since this is the default long term behavior
|
||||
string[] entries = GetDnsFromExtensions(certificate);
|
||||
for (int i = 0; i < entries.Length; ++i)
|
||||
{
|
||||
yield return Claim.CreateDnsClaim(entries[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnsureClaims();
|
||||
|
||||
bool anyClaimType = (claimType == null);
|
||||
bool anyRight = (right == null);
|
||||
|
||||
for (int i = 0; i < this.claims.Count; ++i)
|
||||
{
|
||||
Claim claim = this.claims[i];
|
||||
if ((claim != null) &&
|
||||
(anyClaimType || claimType.Equals(claim.ClaimType)) &&
|
||||
(anyRight || right.Equals(claim.Right)))
|
||||
{
|
||||
yield return claim;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fixing Bug 795660: SAN having multiple DNS entries
|
||||
private static string[] GetDnsFromExtensions(X509Certificate2 cert)
|
||||
{
|
||||
foreach (X509Extension ext in cert.Extensions)
|
||||
{
|
||||
// Extension is SAN or SAN2
|
||||
if (ext.Oid.Value == "2.5.29.7" || ext.Oid.Value == "2.5.29.17")
|
||||
{
|
||||
string asnString = ext.Format(true);
|
||||
if (string.IsNullOrEmpty(asnString))
|
||||
{
|
||||
return new string[0];
|
||||
}
|
||||
|
||||
string[] rawDnsEntries = asnString.Split(new string[1] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
string[] dnsEntries = new string[rawDnsEntries.Length];
|
||||
for (int i = 0; i < rawDnsEntries.Length; ++i)
|
||||
{
|
||||
int equalSignIndex = rawDnsEntries[i].IndexOf('=');
|
||||
dnsEntries[i] = rawDnsEntries[i].Substring(equalSignIndex + 1).Trim();
|
||||
}
|
||||
return dnsEntries;
|
||||
}
|
||||
}
|
||||
return new string[0];
|
||||
}
|
||||
|
||||
public override IEnumerator<Claim> GetEnumerator()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
EnsureClaims();
|
||||
return this.claims.GetEnumerator();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return this.disposed ? base.ToString() : SecurityUtils.ClaimSetToString(this);
|
||||
}
|
||||
|
||||
void ThrowIfDisposed()
|
||||
{
|
||||
if (this.disposed)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName));
|
||||
}
|
||||
}
|
||||
|
||||
class X500DistinguishedNameClaimSet : DefaultClaimSet, IIdentityInfo
|
||||
{
|
||||
IIdentity identity;
|
||||
|
||||
public X500DistinguishedNameClaimSet(X500DistinguishedName x500DistinguishedName)
|
||||
{
|
||||
if (x500DistinguishedName == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("x500DistinguishedName");
|
||||
|
||||
this.identity = new X509Identity(x500DistinguishedName);
|
||||
List<Claim> claims = new List<Claim>(2);
|
||||
claims.Add(new Claim(ClaimTypes.X500DistinguishedName, x500DistinguishedName, Rights.Identity));
|
||||
claims.Add(Claim.CreateX500DistinguishedNameClaim(x500DistinguishedName));
|
||||
Initialize(ClaimSet.Anonymous, claims);
|
||||
}
|
||||
|
||||
public IIdentity Identity
|
||||
{
|
||||
get { return this.identity; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class X509Identity : GenericIdentity, IDisposable
|
||||
{
|
||||
const string X509 = "X509";
|
||||
const string Thumbprint = "; ";
|
||||
X500DistinguishedName x500DistinguishedName;
|
||||
X509Certificate2 certificate;
|
||||
string name;
|
||||
bool disposed = false;
|
||||
bool disposable = true;
|
||||
|
||||
public X509Identity(X509Certificate2 certificate)
|
||||
: this(certificate, true, true)
|
||||
{
|
||||
}
|
||||
|
||||
public X509Identity(X500DistinguishedName x500DistinguishedName)
|
||||
: base(X509, X509)
|
||||
{
|
||||
this.x500DistinguishedName = x500DistinguishedName;
|
||||
}
|
||||
|
||||
internal X509Identity(X509Certificate2 certificate, bool clone, bool disposable)
|
||||
: base(X509, X509)
|
||||
{
|
||||
this.certificate = clone ? new X509Certificate2(certificate) : certificate;
|
||||
this.disposable = clone || disposable;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (this.name == null)
|
||||
{
|
||||
//
|
||||
// DCR 48092: PrincipalPermission authorization using certificates could cause Elevation of Privilege.
|
||||
// because there could be duplicate subject name. In order to be more unique, we use SubjectName + Thumbprint
|
||||
// instead
|
||||
//
|
||||
this.name = GetName() + Thumbprint + this.certificate.Thumbprint;
|
||||
}
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
string GetName()
|
||||
{
|
||||
if (this.x500DistinguishedName != null)
|
||||
return this.x500DistinguishedName.Name;
|
||||
|
||||
string value = this.certificate.SubjectName.Name;
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
return value;
|
||||
|
||||
value = this.certificate.GetNameInfo(X509NameType.DnsName, false);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
return value;
|
||||
|
||||
value = this.certificate.GetNameInfo(X509NameType.SimpleName, false);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
return value;
|
||||
|
||||
value = this.certificate.GetNameInfo(X509NameType.EmailName, false);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
return value;
|
||||
|
||||
value = this.certificate.GetNameInfo(X509NameType.UpnName, false);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
return value;
|
||||
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
public override ClaimsIdentity Clone()
|
||||
{
|
||||
return this.certificate != null ? new X509Identity(this.certificate) : new X509Identity(this.x500DistinguishedName);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.disposable && !this.disposed)
|
||||
{
|
||||
this.disposed = true;
|
||||
if (this.certificate != null)
|
||||
{
|
||||
this.certificate.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThrowIfDisposed()
|
||||
{
|
||||
if (this.disposed)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.IdentityModel.Claims
|
||||
{
|
||||
static class XsiConstants
|
||||
{
|
||||
public const string Namespace = "http://schemas.xmlsoap.org/ws/2005/05/identity";
|
||||
public const string System = "System";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user