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