1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 // <OWNER>Microsoft</OWNER>
7 //
8 
9 //
10 // WindowsIdentity.cs
11 //
12 // Representation of a process/thread token.
13 //
14 
15 namespace System.Security.Principal
16 {
17     using System.Diagnostics.Contracts;
18     using System.Reflection;
19     using System.Runtime.CompilerServices;
20     #if FEATURE_CORRUPTING_EXCEPTIONS
21     using System.Runtime.ExceptionServices;
22     #endif // FEATURE_CORRUPTING_EXCEPTIONS
23     using System.Runtime.InteropServices;
24     using System.Runtime.Serialization;
25     using System.Runtime.Versioning;
26     using System.Security.AccessControl;
27     using System.Security.Permissions;
28     using System.Text;
29     using System.Threading;
30     using Microsoft.Win32;
31     using Microsoft.Win32.SafeHandles;
32 
33 #if !FEATURE_CORECLR
34     using System.Security.Claims;
35     using System.Collections.ObjectModel;
36     using System.Collections.Generic;
37     using System.Globalization;
38 #endif
39 
40     [Serializable]
41     [System.Runtime.InteropServices.ComVisible(true)]
42     public enum WindowsAccountType {
43         Normal      = 0,
44         Guest       = 1,
45         System      = 2,
46         Anonymous   = 3
47     }
48 
49     // Keep in sync with vm\comprincipal.h
50     internal enum WinSecurityContext {
51         Thread = 1, // OpenAsSelf = false
52         Process = 2, // OpenAsSelf = true
53         Both = 3 // OpenAsSelf = true, then OpenAsSelf = false
54     }
55 
56     internal enum ImpersonationQueryResult {
57         Impersonated    = 0,    // current thread is impersonated
58         NotImpersonated = 1,    // current thread is not impersonated
59         Failed          = 2     // failed to query
60     }
61 
62     [Serializable]
63     [System.Runtime.InteropServices.ComVisible(true)]
64 #if !FEATURE_CORECLR
65     public class WindowsIdentity : ClaimsIdentity, ISerializable, IDeserializationCallback, IDisposable {
66 #else
67     public class WindowsIdentity : IIdentity, ISerializable, IDeserializationCallback, IDisposable {
68 #endif
69         [System.Security.SecurityCritical] // auto-generated
70         static SafeAccessTokenHandle s_invalidTokenHandle = SafeAccessTokenHandle.InvalidHandle;
71         private string m_name = null;
72         private SecurityIdentifier m_owner = null;
73         private SecurityIdentifier m_user = null;
74         private object m_groups = null;
75         [System.Security.SecurityCritical] // auto-generated
76         private SafeAccessTokenHandle m_safeTokenHandle = SafeAccessTokenHandle.InvalidHandle;
77         private string m_authType = null;
78         private int m_isAuthenticated = -1;
79         private volatile TokenImpersonationLevel m_impersonationLevel;
80         private volatile bool m_impersonationLevelInitialized;
81         private static RuntimeConstructorInfo s_specialSerializationCtor;
82 
83 #if !FEATURE_CORECLR
84 
85         [NonSerialized]
86         public new const string DefaultIssuer = @"AD AUTHORITY";
87 
88         [NonSerialized]
89         string m_issuerName = DefaultIssuer;
90 
91         [NonSerialized]
92         private object m_claimsIntiailizedLock = new object();
93 
94         [NonSerialized]
95         volatile bool m_claimsInitialized;
96 
97         [NonSerialized]
98         List<Claim> m_deviceClaims;
99 
100         [NonSerialized]
101         List<Claim> m_userClaims;
102 
103 #endif
104 
105         //
106         // Constructors.
107         //
108 
109         [System.Security.SecuritySafeCritical]  // auto-generated
WindowsIdentity()110         static WindowsIdentity()
111         {
112             s_specialSerializationCtor = typeof(WindowsIdentity).GetConstructor(
113                 BindingFlags.Instance | BindingFlags.NonPublic,
114                 null,
115                 new Type[] { typeof(SerializationInfo) },
116                 null) as RuntimeConstructorInfo;
117         }
118 
119         [System.Security.SecurityCritical]  // auto-generated
120 #if !FEATURE_CORECLR
WindowsIdentity()121         private WindowsIdentity ()
122             : base( null, null, null, ClaimTypes.Name, ClaimTypes.GroupSid ) {}
123 #else
WindowsIdentity()124         private WindowsIdentity () {}
125 #endif
126 
127         [System.Security.SecurityCritical]  // auto-generated
WindowsIdentity(SafeAccessTokenHandle safeTokenHandle)128         internal WindowsIdentity (SafeAccessTokenHandle safeTokenHandle) : this (safeTokenHandle.DangerousGetHandle(), null, -1) {
129             GC.KeepAlive(safeTokenHandle);
130         }
131 
132         [System.Security.SecuritySafeCritical]  // auto-generated
133         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
134         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
WindowsIdentity(IntPtr userToken)135         public WindowsIdentity (IntPtr userToken) : this (userToken, null, -1) {}
136 
137         [System.Security.SecuritySafeCritical]  // auto-generated
138         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
139         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
WindowsIdentity(IntPtr userToken, string type)140         public WindowsIdentity (IntPtr userToken, string type) : this (userToken, type, -1) {}
141 
142         [System.Security.SecuritySafeCritical]  // auto-generated
143         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
144         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
WindowsIdentity(IntPtr userToken, string type, WindowsAccountType acctType)145         public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType) : this (userToken, type, -1) {}
146 
147         [System.Security.SecuritySafeCritical]  // auto-generated
148         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
149         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
WindowsIdentity(IntPtr userToken, string type, WindowsAccountType acctType, bool isAuthenticated)150         public WindowsIdentity (IntPtr userToken, string type, WindowsAccountType acctType, bool isAuthenticated)
151             : this (userToken, type, isAuthenticated ? 1 : 0) {}
152 
153         [System.Security.SecurityCritical]  // auto-generated
154 
155 
WindowsIdentity(IntPtr userToken, string authType, int isAuthenticated )156         private WindowsIdentity (IntPtr userToken, string authType, int isAuthenticated )
157 #if !FEATURE_CORECLR
158             : base(null, null, null, ClaimTypes.Name, ClaimTypes.GroupSid)
159 #endif
160         {
161             CreateFromToken(userToken);
162             m_authType = authType;
163             m_isAuthenticated = isAuthenticated;
164         }
165 
166         [System.Security.SecurityCritical]  // auto-generated
167         [ResourceExposure(ResourceScope.None)]
168         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
CreateFromToken(IntPtr userToken)169         private void CreateFromToken (IntPtr userToken) {
170             if (userToken == IntPtr.Zero)
171                 throw new ArgumentException(Environment.GetResourceString("Argument_TokenZero"));
172             Contract.EndContractBlock();
173 
174             // Find out if the specified token is a valid.
175             uint dwLength = (uint) Marshal.SizeOf(typeof(uint));
176             bool result = Win32Native.GetTokenInformation(userToken, (uint) TokenInformationClass.TokenType,
177                                                           SafeLocalAllocHandle.InvalidHandle, 0, out dwLength);
178             if (Marshal.GetLastWin32Error() == Win32Native.ERROR_INVALID_HANDLE)
179                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidImpersonationToken"));
180 
181             if (!Win32Native.DuplicateHandle(Win32Native.GetCurrentProcess(),
182                                              userToken,
183                                              Win32Native.GetCurrentProcess(),
184                                              ref m_safeTokenHandle,
185                                              0,
186                                              true,
187                                              Win32Native.DUPLICATE_SAME_ACCESS))
188                 throw new SecurityException(Win32Native.GetMessage(Marshal.GetLastWin32Error()));
189         }
190 
191         [System.Security.SecuritySafeCritical]  // auto-generated
192         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
WindowsIdentity(string sUserPrincipalName)193         public WindowsIdentity (string sUserPrincipalName) : this (sUserPrincipalName, null) {}
194 
195         [System.Security.SecuritySafeCritical]  // auto-generated
196         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
197 
198 
WindowsIdentity(string sUserPrincipalName, string type )199         public WindowsIdentity (string sUserPrincipalName, string type )
200 #if !FEATURE_CORECLR
201             : base( null, null, null, ClaimTypes.Name, ClaimTypes.GroupSid )
202 #endif
203         {
204             KerbS4ULogon(sUserPrincipalName, ref m_safeTokenHandle);
205         }
206 
207         //
208         // We cannot make sure the token will stay alive
209         // until it is being deserialized in another AppDomain. We do not have a way to capture
210         // the state of a token (just a pointer to kernel memory) and re-construct it later
211         // and even if we did (via calling NtQueryInformationToken and relying on the token undocumented
212         // format), constructing a token requires TCB privilege. We need to address the "serializable"
213         // nature of WindowsIdentity since it is not obvious that can be achieved at all.
214         //
215 
216         [System.Security.SecuritySafeCritical]  // auto-generated
217         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
218         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.SerializationFormatter )]
WindowsIdentity(SerializationInfo info, StreamingContext context)219         public WindowsIdentity (SerializationInfo info, StreamingContext context) : this(info)
220         {
221         }
222 
223         // This is a copy of the serialization constructor above but without the
224         // security demand that's slow and breaks partial trust scenarios
225         // without an expensive assert in place in the remoting code. Instead we
226         // special case this class and call the private constructor directly
227         // (changing the demand above is considered a breaking change, even
228         // though nobody else should have been using a serialization constructor
229         // directly).
230         [System.Security.SecurityCritical]  // auto-generated
WindowsIdentity(SerializationInfo info)231         private WindowsIdentity(SerializationInfo info)
232 #if !FEATURE_CORECLR
233             : base(info)
234 #endif
235         {
236 
237             #if !FEATURE_CORECLR
238             m_claimsInitialized = false;
239             #endif
240 
241             IntPtr userToken = (IntPtr) info.GetValue("m_userToken", typeof(IntPtr));
242             if (userToken != IntPtr.Zero)
243                 CreateFromToken(userToken);
244         }
245 
246         /// <internalonly/>
247         [System.Security.SecurityCritical]  // auto-generated_required
ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)248         void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context) {
249 #if !FEATURE_CORECLR
250                 base.GetObjectData(info, context);
251 #endif
252             info.AddValue("m_userToken", m_safeTokenHandle.DangerousGetHandle());
253         }
254 
255         /// <internalonly/>
IDeserializationCallback.OnDeserialization(Object sender)256         void IDeserializationCallback.OnDeserialization (Object sender) {}
257 
258         //
259         // Factory methods.
260         //
261 
262 
263         [System.Security.SecuritySafeCritical]  // auto-generated
264         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
GetCurrent()265         public static WindowsIdentity GetCurrent () {
266            return GetCurrentInternal(TokenAccessLevels.MaximumAllowed, false);
267         }
268 
269         [System.Security.SecuritySafeCritical]  // auto-generated
270         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
GetCurrent(bool ifImpersonating)271         public static WindowsIdentity GetCurrent (bool ifImpersonating) {
272            return GetCurrentInternal(TokenAccessLevels.MaximumAllowed, ifImpersonating);
273         }
274 
275         [System.Security.SecuritySafeCritical]  // auto-generated
276         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
GetCurrent(TokenAccessLevels desiredAccess)277         public static WindowsIdentity GetCurrent (TokenAccessLevels desiredAccess) {
278            return GetCurrentInternal(desiredAccess, false);
279         }
280 
281         // GetAnonymous() is used heavily in ASP.NET requests as a dummy identity to indicate
282         // the request is anonymous. It does not represent a real process or thread token so
283         // it cannot impersonate or do anything useful. Note this identity does not represent the
284         // usual concept of an anonymous token, and the name is simply misleading but we cannot change it now.
285 
286         [System.Security.SecuritySafeCritical]  // auto-generated
GetAnonymous()287         public static WindowsIdentity GetAnonymous () {
288             return new WindowsIdentity();
289         }
290 
291         //
292         // Properties.
293         //
294         // this is defined 'override sealed' for back compat. Il generated is 'virtual final' and this needs to be the same.
295 #if !FEATURE_CORECLR
296         public override sealed string AuthenticationType {
297 #else
298         public string AuthenticationType {
299 #endif
300             [System.Security.SecuritySafeCritical]  // auto-generated
301             get {
302                 // If this is an anonymous identity, return an empty string
303                 if (m_safeTokenHandle.IsInvalid)
304                     return String.Empty;
305 
306                 if (m_authType == null) {
307                     Win32Native.LUID authId = GetLogonAuthId(m_safeTokenHandle);
308                     if (authId.LowPart == Win32Native.ANONYMOUS_LOGON_LUID)
309                         return String.Empty; // no authentication, just return an empty string
310 
311                     SafeLsaReturnBufferHandle pLogonSessionData = SafeLsaReturnBufferHandle.InvalidHandle;
312                     try {
313                         int status = Win32Native.LsaGetLogonSessionData(ref authId, ref pLogonSessionData);
314                     if (status < 0) // non-negative numbers indicate success
315                         throw GetExceptionFromNtStatus(status);
316 
317                         pLogonSessionData.Initialize((uint)Marshal.SizeOf(typeof(Win32Native.SECURITY_LOGON_SESSION_DATA)));
318 
319                         Win32Native.SECURITY_LOGON_SESSION_DATA logonSessionData = pLogonSessionData.Read<Win32Native.SECURITY_LOGON_SESSION_DATA>(0);
320                         return Marshal.PtrToStringUni(logonSessionData.AuthenticationPackage.Buffer);
321                     }
322                     finally {
323                         if (!pLogonSessionData.IsInvalid)
324                             pLogonSessionData.Dispose();
325                     }
326                 }
327 
328                 return m_authType;
329             }
330         }
331 
332 
333         [ComVisible(false)]
334         public TokenImpersonationLevel ImpersonationLevel {
335             [System.Security.SecuritySafeCritical]  // auto-generated
336             get {
337                 // If two threads ---- here, they'll both set m_impersonationLevel to the same value,
338                 // which is ok.
339                 if (!m_impersonationLevelInitialized) {
340                     TokenImpersonationLevel impersonationLevel = TokenImpersonationLevel.None;
341                     // If this is an anonymous identity
342                     if (m_safeTokenHandle.IsInvalid) {
343                         impersonationLevel = TokenImpersonationLevel.Anonymous;
344                     }
345                     else {
346                         TokenType tokenType = (TokenType)GetTokenInformation<int>(TokenInformationClass.TokenType);
347                         if (tokenType == TokenType.TokenPrimary) {
348                             impersonationLevel = TokenImpersonationLevel.None; // primary token;
349                         }
350                         else {
351                             /// This is an impersonation token, get the impersonation level
352                             int level = GetTokenInformation<int>(TokenInformationClass.TokenImpersonationLevel);
353                             impersonationLevel = (TokenImpersonationLevel)level + 1;
354                         }
355                     }
356 
357                     m_impersonationLevel = impersonationLevel;
358                     m_impersonationLevelInitialized = true;
359                 }
360 
361                 return m_impersonationLevel;
362             }
363         }
364 
365 #if !FEATURE_CORECLR
366         public override bool IsAuthenticated {
367 #else
368         public virtual bool IsAuthenticated {
369 #endif
370 
371             get {
372                 if (m_isAuthenticated == -1) {
373                     // There is a known bug where this approach will not work correctly for domain guests (will return false
374                     // instead of true). But this is a corner-case that is not very interesting.
375 #if !FEATURE_CORECLR
376                     m_isAuthenticated = CheckNtTokenForSid(new SecurityIdentifier(IdentifierAuthority.NTAuthority,
377                                                                     new int[] { Win32Native.SECURITY_AUTHENTICATED_USER_RID })) ? 1 : 0;
378 #else
379                     WindowsPrincipal wp = new WindowsPrincipal(this);
380                     SecurityIdentifier sid = new SecurityIdentifier(IdentifierAuthority.NTAuthority,
381                                                                     new int[] {Win32Native.SECURITY_AUTHENTICATED_USER_RID});
382                     m_isAuthenticated = wp.IsInRole(sid) ? 1 : 0;
383 #endif
384 
385                 }
386 
387                 return m_isAuthenticated == 1;
388             }
389         }
390 
391 #if !FEATURE_CORECLR
392         [System.Security.SecuritySafeCritical]
393         [ComVisible(false)]
CheckNtTokenForSid(SecurityIdentifier sid)394         bool CheckNtTokenForSid (SecurityIdentifier sid) {
395 
396             Contract.EndContractBlock();
397 
398             // special case the anonymous identity.
399             if (m_safeTokenHandle.IsInvalid)
400                 return false;
401 
402             // CheckTokenMembership expects an impersonation token
403             SafeAccessTokenHandle token = SafeAccessTokenHandle.InvalidHandle;
404             TokenImpersonationLevel til = ImpersonationLevel;
405             bool isMember = false;
406 
407             try {
408                 if (til == TokenImpersonationLevel.None) {
409                     if (!Win32Native.DuplicateTokenEx(m_safeTokenHandle,
410                                                       (uint) TokenAccessLevels.Query,
411                                                       IntPtr.Zero,
412                                                       (uint) TokenImpersonationLevel.Identification,
413                                                       (uint) TokenType.TokenImpersonation,
414                                                       ref token))
415                         throw new SecurityException(Win32Native.GetMessage(Marshal.GetLastWin32Error()));
416                 }
417 
418 
419                 // CheckTokenMembership will check if the SID is both present and enabled in the access token.
420                 if (!Win32Native.CheckTokenMembership((til != TokenImpersonationLevel.None ? m_safeTokenHandle : token),
421                                                       sid.BinaryForm,
422                                                       ref isMember))
423                     throw new SecurityException(Win32Native.GetMessage(Marshal.GetLastWin32Error()));
424             }
425             finally {
426                 if (token != SafeAccessTokenHandle.InvalidHandle) {
427                     token.Dispose();
428                 }
429             }
430 
431             return isMember;
432         }
433 #endif
434 
435         //
436         // IsGuest, IsSystem and IsAnonymous are maintained for compatibility reasons. It is always
437         // possible to extract this same information from the User SID property and the new
438         // (and more general) methods defined in the SID class (IsWellKnown, etc...).
439         //
440 
441         public virtual bool IsGuest {
442             [System.Security.SecuritySafeCritical]  // auto-generated
443             get {
444                 // special case the anonymous identity.
445                 if (m_safeTokenHandle.IsInvalid)
446                     return false;
447 
448 #if !FEATURE_CORECLR
449                 return CheckNtTokenForSid(new SecurityIdentifier(IdentifierAuthority.NTAuthority,
450                                                 new int[] { Win32Native.SECURITY_BUILTIN_DOMAIN_RID, (int)WindowsBuiltInRole.Guest }));
451 #else
452                 WindowsPrincipal principal = new WindowsPrincipal(this);
453                 return principal.IsInRole(WindowsBuiltInRole.Guest);
454 #endif
455 
456             }
457         }
458 
459         public virtual bool IsSystem {
460             [System.Security.SecuritySafeCritical]  // auto-generated
461             get {
462                 // special case the anonymous identity.
463                 if (m_safeTokenHandle.IsInvalid)
464                     return false;
465                 SecurityIdentifier sid = new SecurityIdentifier(IdentifierAuthority.NTAuthority,
466                                                                 new int[] {Win32Native.SECURITY_LOCAL_SYSTEM_RID});
467                 return (this.User == sid);
468             }
469         }
470 
471         public virtual bool IsAnonymous {
472             [System.Security.SecuritySafeCritical]  // auto-generated
473             get {
474                 // special case the anonymous identity.
475                 if (m_safeTokenHandle.IsInvalid)
476                     return true;
477                 SecurityIdentifier sid = new SecurityIdentifier(IdentifierAuthority.NTAuthority,
478                                                                 new int[] {Win32Native.SECURITY_ANONYMOUS_LOGON_RID});
479                 return (this.User == sid);
480             }
481         }
482 
483 #if !FEATURE_CORECLR
484         public override string Name {
485 #else
486         public virtual string Name {
487 #endif
488             [System.Security.SecuritySafeCritical]  // auto-generated
489             get {
490                 return GetName();
491             }
492         }
493 
494         [System.Security.SecurityCritical]  // auto-generated
495         [DynamicSecurityMethodAttribute()]
496         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
GetName()497         internal String GetName()
498         {
499             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
500             // special case the anonymous identity.
501             if (m_safeTokenHandle.IsInvalid)
502                 return String.Empty;
503 
504             if (m_name == null)
505             {
506                 // revert thread impersonation for the duration of the call to get the name.
507                 using (SafeRevertToSelf(ref stackMark))
508                 {
509                     NTAccount ntAccount = this.User.Translate(typeof(NTAccount)) as NTAccount;
510                     m_name = ntAccount.ToString();
511                 }
512             }
513 
514             return m_name;
515         }
516 
517         [ComVisible(false)]
518         public SecurityIdentifier Owner {
519             [System.Security.SecuritySafeCritical]  // auto-generated
520             get {
521                 // special case the anonymous identity.
522                 if (m_safeTokenHandle.IsInvalid)
523                     return null;
524 
525                 if (m_owner == null) {
526                     using (SafeLocalAllocHandle tokenOwner = GetTokenInformation(m_safeTokenHandle, TokenInformationClass.TokenOwner)) {
527                         m_owner = new SecurityIdentifier(tokenOwner.Read<IntPtr>(0), true);
528                     }
529                 }
530 
531                 return m_owner;
532             }
533         }
534 
535         [ComVisible(false)]
536         public SecurityIdentifier User {
537             [System.Security.SecuritySafeCritical]  // auto-generated
538             get {
539                 // special case the anonymous identity.
540                 if (m_safeTokenHandle.IsInvalid)
541                     return null;
542 
543                 if (m_user == null) {
544                     using (SafeLocalAllocHandle tokenUser = GetTokenInformation(m_safeTokenHandle, TokenInformationClass.TokenUser)) {
545                         m_user = new SecurityIdentifier(tokenUser.Read<IntPtr>(0), true);
546                     }
547                 }
548 
549                 return m_user;
550             }
551         }
552 
553         public IdentityReferenceCollection Groups {
554             [System.Security.SecuritySafeCritical]  // auto-generated
555             get {
556                 // special case the anonymous identity.
557                 if (m_safeTokenHandle.IsInvalid)
558                     return null;
559 
560                 if (m_groups == null) {
561                     IdentityReferenceCollection groups = new IdentityReferenceCollection();
562                     using (SafeLocalAllocHandle pGroups = GetTokenInformation(m_safeTokenHandle, TokenInformationClass.TokenGroups)) {
563 
564                         uint groupCount = pGroups.Read<uint>(0);
565                         // Work-around bug on WS03 that only populates the GroupCount field of TOKEN_GROUPS if the count is 0
566                         // In that situation, attempting to read the entire TOKEN_GROUPS structure will lead to InsufficientBuffer exception
567                         // since the field is only 4 bytes long (uint only, for GroupCount), but we try to read more (including the pointer to GroupDetails).
568                         if (groupCount != 0)
569                         {
570 
571                             Win32Native.TOKEN_GROUPS tokenGroups = pGroups.Read<Win32Native.TOKEN_GROUPS>(0);
572                             Win32Native.SID_AND_ATTRIBUTES[] groupDetails = new Win32Native.SID_AND_ATTRIBUTES[tokenGroups.GroupCount];
573 
574                             pGroups.ReadArray((uint)Marshal.OffsetOf(typeof(Win32Native.TOKEN_GROUPS), "Groups").ToInt32(),
575                                               groupDetails,
576                                               0,
577                                               groupDetails.Length);
578 
579                             foreach (Win32Native.SID_AND_ATTRIBUTES group in groupDetails)
580                             {
581                                 // Ignore disabled, logon ID, and deny-only groups.
582                                 uint mask = Win32Native.SE_GROUP_ENABLED | Win32Native.SE_GROUP_LOGON_ID | Win32Native.SE_GROUP_USE_FOR_DENY_ONLY;
583                                 if ((group.Attributes & mask) == Win32Native.SE_GROUP_ENABLED) {
584                                     groups.Add(new SecurityIdentifier(group.Sid, true ));
585                                 }
586                             }
587                         }
588                     }
589                     Interlocked.CompareExchange(ref m_groups, groups, null);
590                 }
591 
592                 return m_groups as IdentityReferenceCollection;
593             }
594         }
595 
596         //
597         // Note this property does not duplicate the token. This is also the same as V1/Everett behaviour.
598         //
599 
600         public virtual IntPtr Token {
601             [System.Security.SecuritySafeCritical]  // auto-generated
602             [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
603             get {
604                 return m_safeTokenHandle.DangerousGetHandle();
605             }
606         }
607 
608         //
609         // Public methods.
610         //
611         [SecuritySafeCritical]
612         [DynamicSecurityMethodAttribute()]
613         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
RunImpersonated(SafeAccessTokenHandle safeAccessTokenHandle, Action action)614         public static void RunImpersonated(SafeAccessTokenHandle safeAccessTokenHandle, Action action)
615         {
616             if (action == null)
617                 throw new ArgumentNullException("action");
618 
619             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
620 
621             WindowsIdentity wi = null;
622             if (!safeAccessTokenHandle.IsInvalid)
623                 wi = new WindowsIdentity(safeAccessTokenHandle);
624 
625             using (WindowsImpersonationContext wiContext = SafeImpersonate(safeAccessTokenHandle, wi, ref stackMark))
626             {
627                 action();
628             }
629         }
630 
631         [SecuritySafeCritical]
632         [DynamicSecurityMethodAttribute()]
633         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
RunImpersonated(SafeAccessTokenHandle safeAccessTokenHandle, Func<T> func)634         public static T RunImpersonated<T>(SafeAccessTokenHandle safeAccessTokenHandle, Func<T> func)
635         {
636             if (func == null)
637                 throw new ArgumentNullException("func");
638 
639             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
640 
641             WindowsIdentity wi = null;
642             if (!safeAccessTokenHandle.IsInvalid)
643                 wi = new WindowsIdentity(safeAccessTokenHandle);
644 
645             T result = default(T);
646             using (WindowsImpersonationContext wiContext = SafeImpersonate(safeAccessTokenHandle, wi, ref stackMark))
647             {
648                 result = func();
649             }
650 
651             return result;
652         }
653 
654         [System.Security.SecuritySafeCritical]  // auto-generated
655         [DynamicSecurityMethodAttribute()]
656         [ResourceExposure(ResourceScope.Process)]  // Call from within a CER, or use a RunAsUser helper.
657         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
Impersonate()658         public virtual WindowsImpersonationContext Impersonate ()
659         {
660             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
661             return Impersonate(ref stackMark);
662         }
663 
664         [System.Security.SecuritySafeCritical]  // auto-generated
665         [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPrincipal | SecurityPermissionFlag.UnmanagedCode)]
666         [DynamicSecurityMethodAttribute()]
667         [ResourceExposure(ResourceScope.Process)]  // Call from within a CER, or use a RunAsUser helper.
668         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
Impersonate(IntPtr userToken)669         public static WindowsImpersonationContext Impersonate (IntPtr userToken)
670         {
671             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
672             if (userToken == IntPtr.Zero)
673                 return SafeRevertToSelf(ref stackMark);
674 
675             WindowsIdentity wi = new WindowsIdentity(userToken, null, -1);
676             return wi.Impersonate(ref stackMark);
677         }
678 
679         [System.Security.SecurityCritical]  // auto-generated
Impersonate(ref StackCrawlMark stackMark)680         internal WindowsImpersonationContext Impersonate (ref StackCrawlMark stackMark) {
681             if (m_safeTokenHandle.IsInvalid)
682                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AnonymousCannotImpersonate"));
683 
684             return SafeImpersonate(m_safeTokenHandle, this, ref stackMark);
685         }
686 
687         [System.Security.SecuritySafeCritical]  // auto-generated
688         [ComVisible(false)]
Dispose(bool disposing)689         protected virtual void Dispose(bool disposing) {
690             if (disposing) {
691                 if (m_safeTokenHandle != null && !m_safeTokenHandle.IsClosed)
692                     m_safeTokenHandle.Dispose();
693             }
694             m_name = null;
695             m_owner = null;
696             m_user = null;
697         }
698 
699         [ComVisible(false)]
Dispose()700         public void Dispose() {
701             Dispose(true);
702         }
703 
704         public SafeAccessTokenHandle AccessToken {
705             [System.Security.SecurityCritical]  // auto-generated
706             get {
707                 return m_safeTokenHandle;
708             }
709         }
710 
711         //
712         // internal.
713         //
714 
715         [System.Security.SecurityCritical]  // auto-generated
716         [ResourceExposure(ResourceScope.None)]
717         [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
SafeRevertToSelf(ref StackCrawlMark stackMark)718         internal static WindowsImpersonationContext SafeRevertToSelf(ref StackCrawlMark stackMark)
719         {
720             return SafeImpersonate(s_invalidTokenHandle, null, ref stackMark);
721         }
722 
723         [System.Security.SecurityCritical]  // auto-generated
724         [ResourceExposure(ResourceScope.Process)]
725         [ResourceConsumption(ResourceScope.Process)]
SafeImpersonate(SafeAccessTokenHandle userToken, WindowsIdentity wi, ref StackCrawlMark stackMark)726         internal static WindowsImpersonationContext SafeImpersonate (SafeAccessTokenHandle userToken, WindowsIdentity wi, ref StackCrawlMark stackMark)
727         {
728             bool isImpersonating;
729             int hr = 0;
730             SafeAccessTokenHandle safeTokenHandle = GetCurrentToken(TokenAccessLevels.MaximumAllowed, false, out isImpersonating, out hr);
731             if (safeTokenHandle == null || safeTokenHandle.IsInvalid)
732                 throw new SecurityException(Win32Native.GetMessage(hr));
733 
734             // Set the SafeAccessTokenHandle on the FSD:
735             FrameSecurityDescriptor secObj = SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true);
736             if (secObj == null)
737             {
738                 // Security: REQ_SQ flag is missing. Bad compiler ?
739                 // This can happen when you create delegates over functions that need the REQ_SQ
740                 throw new SecurityException(Environment.GetResourceString( "ExecutionEngine_MissingSecurityDescriptor" ) );
741             }
742 
743             WindowsImpersonationContext context = new WindowsImpersonationContext(safeTokenHandle, GetCurrentThreadWI(), isImpersonating, secObj);
744 
745             if (userToken.IsInvalid) { // impersonating a zero token means clear the token on the thread
746                 hr = Win32.RevertToSelf();
747                 if (hr < 0)
748                     Environment.FailFast(Win32Native.GetMessage(hr));
749                 // update identity on the thread
750                 UpdateThreadWI(wi);
751                 secObj.SetTokenHandles(safeTokenHandle, (wi == null?null:wi.AccessToken));
752             } else {
753                 hr = Win32.RevertToSelf();
754                 if (hr < 0)
755                         Environment.FailFast(Win32Native.GetMessage(hr));
756                 hr = Win32.ImpersonateLoggedOnUser(userToken);
757                 if (hr < 0) {
758                     context.Undo();
759                     throw new SecurityException(Environment.GetResourceString("Argument_ImpersonateUser"));
760                 }
761                 UpdateThreadWI(wi);
762                 secObj.SetTokenHandles(safeTokenHandle, (wi == null?null:wi.AccessToken));
763             }
764 
765             return context;
766         }
767 
768         [System.Security.SecurityCritical]  // auto-generated
GetCurrentThreadWI()769         internal static WindowsIdentity GetCurrentThreadWI()
770         {
771             return SecurityContext.GetCurrentWI(Thread.CurrentThread.GetExecutionContextReader());
772         }
773 
774         [SecurityCritical]
UpdateThreadWI(WindowsIdentity wi)775         internal static void UpdateThreadWI(WindowsIdentity wi)
776         {
777             // Set WI on Thread.CurrentThread.ExecutionContext.SecurityContext
778             Thread currentThread = Thread.CurrentThread;
779             if (currentThread.GetExecutionContextReader().SecurityContext.WindowsIdentity != wi)
780             {
781                 ExecutionContext ec = currentThread.GetMutableExecutionContext();
782                 SecurityContext sc = ec.SecurityContext;
783                 if (wi != null && sc == null)
784                 {
785                     // create a new security context on the thread
786                     sc = new SecurityContext();
787                     ec.SecurityContext = sc;
788                 }
789 
790                 if (sc != null) // null-check needed here since we will not create an sc if wi is null
791                 {
792                     sc.WindowsIdentity = wi;
793                 }
794             }
795         }
796 
797 
798         [System.Security.SecurityCritical]  // auto-generated
799         [ResourceExposure(ResourceScope.None)]
800         [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
GetCurrentInternal(TokenAccessLevels desiredAccess, bool threadOnly)801         internal static WindowsIdentity GetCurrentInternal (TokenAccessLevels desiredAccess, bool threadOnly) {
802             int hr = 0;
803             bool isImpersonating;
804             SafeAccessTokenHandle safeTokenHandle = GetCurrentToken(desiredAccess, threadOnly, out isImpersonating, out hr);
805             if (safeTokenHandle == null || safeTokenHandle.IsInvalid) {
806                 // either we wanted only ThreadToken - return null
807                 if (threadOnly && !isImpersonating)
808                     return null;
809                 // or there was an error
810                 throw new SecurityException(Win32Native.GetMessage(hr));
811             }
812             WindowsIdentity wi = new WindowsIdentity();
813             wi.m_safeTokenHandle.Dispose();
814             wi.m_safeTokenHandle = safeTokenHandle;
815             return wi;
816         }
817 
GetSpecialSerializationCtor()818         internal static RuntimeConstructorInfo GetSpecialSerializationCtor()
819         {
820             return s_specialSerializationCtor;
821         }
822 
823         //
824         // private.
825         //
826 
GetHRForWin32Error(int dwLastError)827         private static int GetHRForWin32Error (int dwLastError) {
828             if ((dwLastError & 0x80000000) == 0x80000000)
829                 return dwLastError;
830             else
831                 return (dwLastError & 0x0000FFFF) | unchecked((int)0x80070000);
832         }
833 
834         [System.Security.SecurityCritical]  // auto-generated
GetExceptionFromNtStatus(int status)835         private static Exception GetExceptionFromNtStatus (int status) {
836             if ((uint) status == Win32Native.STATUS_ACCESS_DENIED)
837                 return new UnauthorizedAccessException();
838 
839             if ((uint) status == Win32Native.STATUS_INSUFFICIENT_RESOURCES || (uint) status == Win32Native.STATUS_NO_MEMORY)
840                 return new OutOfMemoryException();
841 
842             int win32ErrorCode = Win32Native.LsaNtStatusToWinError(status);
843             return new SecurityException(Win32Native.GetMessage(win32ErrorCode));
844         }
845 
846         [System.Security.SecurityCritical]  // auto-generated
847         [ResourceExposure(ResourceScope.Process)]
848         [ResourceConsumption(ResourceScope.Process)]
GetCurrentToken(TokenAccessLevels desiredAccess, bool threadOnly, out bool isImpersonating, out int hr)849         private static SafeAccessTokenHandle GetCurrentToken(TokenAccessLevels desiredAccess, bool threadOnly, out bool isImpersonating, out int hr) {
850             isImpersonating = true;
851             SafeAccessTokenHandle safeTokenHandle = GetCurrentThreadToken(desiredAccess, out hr);
852             if (safeTokenHandle == null && hr == GetHRForWin32Error(Win32Native.ERROR_NO_TOKEN)) {
853                 // No impersonation
854                 isImpersonating = false;
855                 if (!threadOnly)
856                     safeTokenHandle = GetCurrentProcessToken(desiredAccess, out hr);
857             }
858             return safeTokenHandle;
859         }
860 
861         [System.Security.SecurityCritical]  // auto-generated
862         [ResourceExposure(ResourceScope.Process)]
863         [ResourceConsumption(ResourceScope.Process)]
GetCurrentProcessToken(TokenAccessLevels desiredAccess, out int hr)864         private static SafeAccessTokenHandle GetCurrentProcessToken (TokenAccessLevels desiredAccess, out int hr) {
865             hr = 0;
866             SafeAccessTokenHandle safeTokenHandle;
867             if (!Win32Native.OpenProcessToken(Win32Native.GetCurrentProcess(), desiredAccess, out safeTokenHandle))
868                 hr = GetHRForWin32Error(Marshal.GetLastWin32Error());
869             return safeTokenHandle;
870         }
871 
872         [System.Security.SecurityCritical]  // auto-generated
873         [ResourceExposure(ResourceScope.Process)]
874         [ResourceConsumption(ResourceScope.Process)]
GetCurrentThreadToken(TokenAccessLevels desiredAccess, out int hr)875         internal static SafeAccessTokenHandle GetCurrentThreadToken(TokenAccessLevels desiredAccess, out int hr) {
876             SafeAccessTokenHandle safeTokenHandle;
877             hr = Win32.OpenThreadToken(desiredAccess, WinSecurityContext.Both, out safeTokenHandle);
878             return safeTokenHandle;
879         }
880 
881         /// <summary>
882         ///     Get a property from the current token
883         /// </summary>
884         [System.Security.SecurityCritical]  // auto-generated
885         private T GetTokenInformation<T>(TokenInformationClass tokenInformationClass) where T : struct{
886             Contract.Assert(!m_safeTokenHandle.IsInvalid && !m_safeTokenHandle.IsClosed, "!m_safeTokenHandle.IsInvalid && !m_safeTokenHandle.IsClosed");
887 
888             using (SafeLocalAllocHandle information = GetTokenInformation(m_safeTokenHandle, tokenInformationClass)) {
889                 Contract.Assert(information.ByteLength >= (ulong)Marshal.SizeOf(typeof(T)),
890                                 "information.ByteLength >= (ulong)Marshal.SizeOf(typeof(T))");
891 
892                 return information.Read<T>(0);
893             }
894         }
895 
896         //
897         // QueryImpersonation used to test if the current thread is impersonated.
898         // This method doesn't return the thread token (WindowsIdentity).
899         // Although GetCurrentInternal can be used to perform the same test but
900         // QueryImpersonation is optimized for the perf.
901         //
902         [System.Security.SecurityCritical]  // auto-generated
903         [ResourceExposure(ResourceScope.Process)]
904         [ResourceConsumption(ResourceScope.Process)]
QueryImpersonation()905         internal static ImpersonationQueryResult QueryImpersonation() {
906             SafeAccessTokenHandle safeTokenHandle = null;
907             int hr = Win32.OpenThreadToken(TokenAccessLevels.Query,  WinSecurityContext.Thread, out safeTokenHandle);
908 
909             if (safeTokenHandle != null) {
910                 Contract.Assert(hr == 0, "[WindowsIdentity..QueryImpersonation] - hr == 0");
911                 safeTokenHandle.Close();
912                 return ImpersonationQueryResult.Impersonated;
913             }
914 
915             if (hr == GetHRForWin32Error(Win32Native.ERROR_ACCESS_DENIED)) {
916                 // thread is impersonated because the thread was there (and we failed to open it).
917                 return ImpersonationQueryResult.Impersonated;
918             }
919 
920             if (hr == GetHRForWin32Error(Win32Native.ERROR_NO_TOKEN)) {
921                 // definitely not impersonating
922                 return ImpersonationQueryResult.NotImpersonated;
923             }
924 
925             // Unexpected failure.
926             return ImpersonationQueryResult.Failed;
927         }
928 
929         [System.Security.SecurityCritical]  // auto-generated
GetLogonAuthId(SafeAccessTokenHandle safeTokenHandle)930         private static Win32Native.LUID GetLogonAuthId (SafeAccessTokenHandle safeTokenHandle) {
931             using (SafeLocalAllocHandle pStatistics = GetTokenInformation(safeTokenHandle, TokenInformationClass.TokenStatistics)) {
932                 Win32Native.TOKEN_STATISTICS statistics = pStatistics.Read<Win32Native.TOKEN_STATISTICS>(0);
933             return statistics.AuthenticationId;
934         }
935         }
936 
937         [System.Security.SecurityCritical]
GetTokenInformation(SafeAccessTokenHandle tokenHandle, TokenInformationClass tokenInformationClass)938         private static SafeLocalAllocHandle GetTokenInformation (SafeAccessTokenHandle tokenHandle, TokenInformationClass tokenInformationClass) {
939             SafeLocalAllocHandle safeLocalAllocHandle = SafeLocalAllocHandle.InvalidHandle;
940             uint dwLength = (uint) Marshal.SizeOf(typeof(uint));
941             bool result = Win32Native.GetTokenInformation(tokenHandle,
942                                                           (uint) tokenInformationClass,
943                                                           safeLocalAllocHandle,
944                                                           0,
945                                                           out dwLength);
946             int dwErrorCode = Marshal.GetLastWin32Error();
947             switch (dwErrorCode) {
948             case Win32Native.ERROR_BAD_LENGTH:
949                 // special case for TokenSessionId. Falling through
950             case Win32Native.ERROR_INSUFFICIENT_BUFFER:
951                 // ptrLength is an [In] param to LocalAlloc
952                 UIntPtr ptrLength = new UIntPtr(dwLength);
953                 safeLocalAllocHandle.Dispose();
954                 safeLocalAllocHandle = Win32Native.LocalAlloc(Win32Native.LMEM_FIXED, ptrLength);
955                 if (safeLocalAllocHandle == null || safeLocalAllocHandle.IsInvalid)
956                     throw new OutOfMemoryException();
957                 safeLocalAllocHandle.Initialize(dwLength);
958 
959                 result = Win32Native.GetTokenInformation(tokenHandle,
960                                                          (uint) tokenInformationClass,
961                                                          safeLocalAllocHandle,
962                                                          dwLength,
963                                                          out dwLength);
964                 if (!result)
965                     throw new SecurityException(Win32Native.GetMessage(Marshal.GetLastWin32Error()));
966                 break;
967             case Win32Native.ERROR_INVALID_HANDLE:
968                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidImpersonationToken"));
969             default:
970                 throw new SecurityException(Win32Native.GetMessage(dwErrorCode));
971             }
972             return safeLocalAllocHandle;
973         }
974 
975         [System.Security.SecurityCritical]  // auto-generated
976 #if FEATURE_CORRUPTING_EXCEPTIONS
977         [HandleProcessCorruptedStateExceptions] //
978 #endif // FEATURE_CORRUPTING_EXCEPTIONS
KerbS4ULogon(string upn, ref SafeAccessTokenHandle safeTokenHandle)979         private unsafe static SafeAccessTokenHandle KerbS4ULogon (string upn, ref SafeAccessTokenHandle safeTokenHandle)
980         {
981             // source name
982             byte[] sourceName = new byte[] { (byte)'C', (byte)'L', (byte)'R' }; // we set the source name to "CLR".
983 
984             // ptrLength is an [In] param to LocalAlloc
985             UIntPtr ptrLength = new UIntPtr((uint)(sourceName.Length + 1));
986 
987             using (SafeLocalAllocHandle pSourceName = Win32Native.LocalAlloc(Win32Native.LPTR, ptrLength)) {
988                 if (pSourceName == null || pSourceName.IsInvalid)
989                     throw new OutOfMemoryException();
990 
991                 pSourceName.Initialize((ulong)sourceName.Length + 1);
992                 pSourceName.WriteArray(0, sourceName, 0, sourceName.Length);
993                 Win32Native.UNICODE_INTPTR_STRING Name = new Win32Native.UNICODE_INTPTR_STRING(sourceName.Length,
994                                                                                                pSourceName);
995 
996                 int status;
997                 SafeLsaLogonProcessHandle logonHandle = SafeLsaLogonProcessHandle.InvalidHandle;
998                 SafeLsaReturnBufferHandle profile = SafeLsaReturnBufferHandle.InvalidHandle;
999                 try {
1000                     Privilege privilege = null;
1001 
1002                     RuntimeHelpers.PrepareConstrainedRegions();
1003                     // Try to get an impersonation token.
1004                     try {
1005                         // Try to enable the TCB privilege if possible
1006                         try {
1007                             privilege = new Privilege("SeTcbPrivilege");
1008                             privilege.Enable();
1009                         }
1010                         catch (PrivilegeNotHeldException) { }
1011 
1012                         IntPtr dummy = IntPtr.Zero;
1013                         status = Win32Native.LsaRegisterLogonProcess(ref Name, ref logonHandle, ref dummy);
1014                         if (Win32Native.ERROR_ACCESS_DENIED == Win32Native.LsaNtStatusToWinError(status)) {
1015                             // We don't have the Tcb privilege. The best we can hope for is to get an Identification token.
1016                             status = Win32Native.LsaConnectUntrusted(ref logonHandle);
1017                         }
1018                     }
1019                     catch {
1020                         // protect against exception filter-based luring attacks
1021                         if (privilege != null)
1022                             privilege.Revert();
1023                         throw;
1024                     }
1025                     finally {
1026                         if (privilege != null)
1027                             privilege.Revert();
1028                     }
1029                     if (status < 0) // non-negative numbers indicate success
1030                         throw GetExceptionFromNtStatus(status);
1031 
1032                     // package name ("Kerberos")
1033                     byte[] arrayPackageName = new byte[Win32Native.MICROSOFT_KERBEROS_NAME.Length + 1];
1034                     Encoding.ASCII.GetBytes(Win32Native.MICROSOFT_KERBEROS_NAME, 0, Win32Native.MICROSOFT_KERBEROS_NAME.Length, arrayPackageName, 0);
1035 
1036                     // ptrLength is an [In] param to LocalAlloc
1037                     ptrLength = new UIntPtr((uint)arrayPackageName.Length);
1038                     using (SafeLocalAllocHandle pPackageName = Win32Native.LocalAlloc(Win32Native.LMEM_FIXED, ptrLength)) {
1039                         if (pPackageName == null || pPackageName.IsInvalid)
1040                             throw new OutOfMemoryException();
1041                         pPackageName.Initialize((ulong)(uint)arrayPackageName.Length);
1042 
1043                         pPackageName.WriteArray(0, arrayPackageName, 0, arrayPackageName.Length);
1044                         Win32Native.UNICODE_INTPTR_STRING PackageName = new Win32Native.UNICODE_INTPTR_STRING(Win32Native.MICROSOFT_KERBEROS_NAME.Length,
1045                                                                                                               pPackageName);
1046                         uint packageId = 0;
1047                         status = Win32Native.LsaLookupAuthenticationPackage(logonHandle, ref PackageName, ref packageId);
1048                         if (status < 0) // non-negative numbers indicate success
1049                             throw GetExceptionFromNtStatus(status);
1050 
1051                         // source context
1052                         Win32Native.TOKEN_SOURCE sourceContext = new Win32Native.TOKEN_SOURCE();
1053                         if (!Win32Native.AllocateLocallyUniqueId(ref sourceContext.SourceIdentifier))
1054                             throw new SecurityException(Win32Native.GetMessage(Marshal.GetLastWin32Error()));
1055                         sourceContext.Name = new char[8];
1056                         sourceContext.Name[0] = 'C'; sourceContext.Name[1] = 'L'; sourceContext.Name[2] = 'R';
1057 
1058                         uint profileSize = 0;
1059                         Win32Native.LUID logonId = new Win32Native.LUID();
1060                         Win32Native.QUOTA_LIMITS quotas = new Win32Native.QUOTA_LIMITS();
1061                         int subStatus = 0;
1062 
1063                         //
1064                         // Build the KERB_S4U_LOGON structure.  Note that the LSA expects this entire
1065                         // structure to be contained within the same block of memory, so we need to allocate
1066                         // enough room for both the structure itself and the UPN string in a single buffer
1067                         // and do the marshalling into this buffer by hand.
1068                         //
1069 
1070                         byte[] upnBytes = Encoding.Unicode.GetBytes(upn);
1071 
1072                         Contract.Assert(Marshal.SizeOf(typeof(Win32Native.KERB_S4U_LOGON)) % IntPtr.Size == 0, "Potential allignment issue setting up S4U logon buffer");
1073                         uint logonInfoSize = (uint) (Marshal.SizeOf(typeof(Win32Native.KERB_S4U_LOGON)) + upnBytes.Length);
1074                         using (SafeLocalAllocHandle logonInfoBuffer = Win32Native.LocalAlloc(Win32Native.LPTR, new UIntPtr(logonInfoSize))) {
1075                             if (logonInfoBuffer == null || logonInfoBuffer.IsInvalid) {
1076                                 throw new OutOfMemoryException();
1077                             }
1078 
1079                             logonInfoBuffer.Initialize((ulong)logonInfoSize);
1080 
1081                             // Write the UPN to the end of the serialized buffer
1082                             ulong upnOffset = (ulong)Marshal.SizeOf(typeof(Win32Native.KERB_S4U_LOGON));
1083                             logonInfoBuffer.WriteArray(upnOffset,
1084                                                        upnBytes,
1085                                                        0,
1086                                                        upnBytes.Length);
1087 
1088                             unsafe {
1089                                 byte* pLogonInfoBuffer = null;
1090 
1091                                 RuntimeHelpers.PrepareConstrainedRegions();
1092                                 try {
1093                                     logonInfoBuffer.AcquirePointer(ref pLogonInfoBuffer);
1094 
1095                                     // Setup the KERB_S4U_LOGON structure
1096                                     Win32Native.KERB_S4U_LOGON logonInfo = new Win32Native.KERB_S4U_LOGON();
1097                                     logonInfo.MessageType = (uint)KerbLogonSubmitType.KerbS4ULogon;
1098                                     logonInfo.Flags = 0;
1099 
1100                                     // Point the ClientUpn at the UPN written at the end of this buffer
1101                                     logonInfo.ClientUpn = new Win32Native.UNICODE_INTPTR_STRING(upnBytes.Length,
1102                                                                                                 new IntPtr(pLogonInfoBuffer + upnOffset));
1103 
1104                                     logonInfoBuffer.Write(0, logonInfo);
1105 
1106                                     // logon user
1107                                     status = Win32Native.LsaLogonUser(logonHandle,
1108                                                                       ref Name,
1109                                                                       (uint)SecurityLogonType.Network,
1110                                                                       packageId,
1111                                                                                           new IntPtr(pLogonInfoBuffer),
1112                                                                                           (uint)logonInfoBuffer.ByteLength,
1113                                                                       IntPtr.Zero,
1114                                                                       ref sourceContext,
1115                                                                       ref profile,
1116                                                                       ref profileSize,
1117                                                                       ref logonId,
1118                                                                       ref safeTokenHandle,
1119                                                                       ref quotas,
1120                                                                       ref subStatus);
1121 
1122                                     // If both status and substatus are < 0, substatus is preferred.
1123                                     if (status == Win32Native.STATUS_ACCOUNT_RESTRICTION && subStatus < 0)
1124                                         status = subStatus;
1125                                     if (status < 0) // non-negative numbers indicate success
1126                                         throw GetExceptionFromNtStatus(status);
1127                                     if (subStatus < 0) // non-negative numbers indicate success
1128                                         throw GetExceptionFromNtStatus(subStatus);
1129                                 }
1130                                 finally {
1131                                     if (pLogonInfoBuffer != null) {
1132                                         logonInfoBuffer.ReleasePointer();
1133                                     }
1134                                 }
1135                             }
1136                         }
1137 
1138                         return safeTokenHandle;
1139                     }
1140                 }
1141                 finally {
1142                     if (!logonHandle.IsInvalid)
1143                         logonHandle.Dispose();
1144                     if (!profile.IsInvalid)
1145                         profile.Dispose();
1146                 }
1147             }
1148         }
1149 
1150 #if !FEATURE_CORECLR
1151 
1152         [SecuritySafeCritical]
WindowsIdentity(WindowsIdentity identity)1153         protected WindowsIdentity (WindowsIdentity identity)
1154             : base( identity, null, identity.m_authType, null, null, false )
1155         {
1156             if (identity == null)
1157                 throw new ArgumentNullException("identity");
1158 
1159             Contract.EndContractBlock();
1160 
1161             bool mustDecrement = false;
1162             RuntimeHelpers.PrepareConstrainedRegions();
1163             try
1164             {
1165                 if (!identity.m_safeTokenHandle.IsInvalid && identity.m_safeTokenHandle != SafeAccessTokenHandle.InvalidHandle && identity.m_safeTokenHandle.DangerousGetHandle() != IntPtr.Zero)
1166                 {
1167                     identity.m_safeTokenHandle.DangerousAddRef(ref mustDecrement);
1168 
1169                     if (!identity.m_safeTokenHandle.IsInvalid && identity.m_safeTokenHandle.DangerousGetHandle() != IntPtr.Zero)
1170                         CreateFromToken(identity.m_safeTokenHandle.DangerousGetHandle());
1171 
1172                     m_authType = identity.m_authType;
1173                     m_isAuthenticated = identity.m_isAuthenticated;
1174                 }
1175             }
1176             finally
1177             {
1178                 if (mustDecrement)
1179                     identity.m_safeTokenHandle.DangerousRelease();
1180             }
1181         }
1182 
1183         [SecurityCritical]
GetTokenInternal()1184         internal IntPtr GetTokenInternal()
1185         {
1186             return m_safeTokenHandle.DangerousGetHandle();
1187         }
1188 
1189         [SecurityCritical]
WindowsIdentity(ClaimsIdentity claimsIdentity, IntPtr userToken)1190         internal WindowsIdentity(ClaimsIdentity claimsIdentity, IntPtr userToken)
1191             : base(claimsIdentity)
1192         {
1193             if (userToken != IntPtr.Zero && userToken.ToInt64() > 0)
1194             {
1195                 CreateFromToken(userToken);
1196             }
1197         }
1198 
1199         /// <summary>
1200         /// Returns a new instance of the base, used when serializing the WindowsIdentity.
1201         /// </summary>
CloneAsBase()1202         internal ClaimsIdentity CloneAsBase()
1203         {
1204             return base.Clone();
1205         }
1206 
1207         /// <summary>
1208         /// Returns a new instance of <see cref="WindowsIdentity"/> with values copied from this object.
1209         /// </summary>
Clone()1210         public override ClaimsIdentity Clone()
1211         {
1212             return new WindowsIdentity(this);
1213         }
1214 
1215         /// <summary>
1216         /// Gets the 'User Claims' from the NTToken that represents this identity
1217         /// </summary>
1218         public virtual IEnumerable<Claim> UserClaims
1219         {
1220             get
1221             {
1222                 InitializeClaims();
1223 
1224                 return m_userClaims.AsReadOnly();
1225             }
1226         }
1227 
1228         /// <summary>
1229         /// Gets the 'Device Claims' from the NTToken that represents the device the identity is using
1230         /// </summary>
1231         public virtual IEnumerable<Claim> DeviceClaims
1232         {
1233             get
1234             {
1235                 InitializeClaims();
1236 
1237                 return m_deviceClaims.AsReadOnly();
1238             }
1239         }
1240 
1241         /// <summary>
1242         /// Gets the claims as <see cref="IEnumerable{Claim}"/>, associated with this <see cref="WindowsIdentity"/>.
1243         /// Includes UserClaims and DeviceClaims.
1244         /// </summary>
1245         public override IEnumerable<Claim> Claims
1246         {
1247             get
1248             {
1249                 if (!m_claimsInitialized)
1250                 {
1251                     InitializeClaims();
1252                 }
1253 
1254                 foreach (Claim claim in base.Claims)
1255                     yield return claim;
1256 
1257                 foreach (Claim claim in m_userClaims)
1258                     yield return claim;
1259 
1260                 foreach (Claim claim in m_deviceClaims)
1261                     yield return claim;
1262             }
1263         }
1264 
1265         /// <summary>
1266         /// Intenal method to initialize the claim collection.
1267         /// Lazy init is used so claims are not initialzed until needed
1268         /// </summary>
1269         [SecuritySafeCritical]
InitializeClaims()1270         void InitializeClaims()
1271         {
1272             if (!m_claimsInitialized)
1273             {
1274                 lock (m_claimsIntiailizedLock)
1275                 {
1276                     if (!m_claimsInitialized)
1277                     {
1278                         m_userClaims = new List<Claim>();
1279                         m_deviceClaims = new List<Claim>();
1280 
1281                         if (!String.IsNullOrEmpty(Name))
1282                         {
1283                             //
1284                             // Add the name claim only if the WindowsIdentity.Name is populated
1285                             // WindowsIdentity.Name will be null when it is the fake anonymous user
1286                             // with a token value of IntPtr.Zero
1287                             //
1288                             m_userClaims.Add(new Claim(NameClaimType, Name, ClaimValueTypes.String, m_issuerName, m_issuerName, this));
1289                         }
1290 
1291                         // primary sid
1292                         AddPrimarySidClaim(m_userClaims);
1293 
1294                         // group sids
1295                         AddGroupSidClaims(m_userClaims);
1296 
1297                         // The following TokenInformationClass's were part of the Win8 release
1298                         if (Environment.IsWindows8OrAbove)
1299                         {
1300                             // Device group sids
1301                             AddDeviceGroupSidClaims(m_deviceClaims, TokenInformationClass.TokenDeviceGroups);
1302 
1303                             // User token claims
1304                             AddTokenClaims(m_userClaims, TokenInformationClass.TokenUserClaimAttributes, ClaimTypes.WindowsUserClaim);
1305 
1306                             // Device token claims
1307                             AddTokenClaims(m_deviceClaims, TokenInformationClass.TokenDeviceClaimAttributes, ClaimTypes.WindowsDeviceClaim);
1308                         }
1309 
1310                         m_claimsInitialized = true;
1311                     }
1312                 }
1313             }
1314         }
1315 
1316         /// <summary>
1317         /// Creates a collection of SID claims that represent the DeviceSidGroups.
1318         /// </summary>
1319         /// this is SafeCritical as it accesss the NT token.
1320         [SecurityCritical]
AddDeviceGroupSidClaims(List<Claim> instanceClaims, TokenInformationClass tokenInformationClass)1321         void AddDeviceGroupSidClaims(List<Claim> instanceClaims,  TokenInformationClass tokenInformationClass)
1322         {
1323             // special case the anonymous identity.
1324             if (m_safeTokenHandle.IsInvalid)
1325                 return;
1326 
1327             SafeLocalAllocHandle safeAllocHandle =  SafeLocalAllocHandle.InvalidHandle;
1328             try
1329             {
1330                 // Retrieve all group sids
1331 
1332                 safeAllocHandle = GetTokenInformation(m_safeTokenHandle, tokenInformationClass);
1333                 int count = Marshal.ReadInt32(safeAllocHandle.DangerousGetHandle());
1334                 IntPtr pSidAndAttributes = new IntPtr((long)safeAllocHandle.DangerousGetHandle() + (long)Marshal.OffsetOf(typeof(Win32Native.TOKEN_GROUPS), "Groups"));
1335                 string claimType = null;
1336 
1337                 for (int i = 0; i < count; ++i)
1338                 {
1339                     Win32Native.SID_AND_ATTRIBUTES group = (Win32Native.SID_AND_ATTRIBUTES)Marshal.PtrToStructure(pSidAndAttributes, typeof(Win32Native.SID_AND_ATTRIBUTES));
1340                     uint mask = Win32Native.SE_GROUP_ENABLED | Win32Native.SE_GROUP_LOGON_ID | Win32Native.SE_GROUP_USE_FOR_DENY_ONLY;
1341                     SecurityIdentifier groupSid = new SecurityIdentifier(group.Sid, true);
1342                     if ((group.Attributes & mask) == Win32Native.SE_GROUP_ENABLED)
1343                     {
1344                         claimType = ClaimTypes.WindowsDeviceGroup;
1345                         Claim claim = new Claim(claimType, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture));
1346                         claim.Properties.Add(claimType, "");
1347                         instanceClaims.Add(claim);
1348                     }
1349                     else if ((group.Attributes & mask) == Win32Native.SE_GROUP_USE_FOR_DENY_ONLY)
1350                     {
1351                         claimType = ClaimTypes.DenyOnlyWindowsDeviceGroup;
1352                         Claim claim = new Claim(claimType, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture));
1353                         claim.Properties.Add(claimType, "");
1354                         instanceClaims.Add(claim);
1355                     }
1356 
1357                     pSidAndAttributes = new IntPtr((long)pSidAndAttributes + Win32Native.SID_AND_ATTRIBUTES.SizeOf);
1358                 }
1359             }
1360             finally
1361             {
1362                 safeAllocHandle.Close();
1363             }
1364         }
1365 
1366         /// <summary>
1367         /// Creates a collection of SID claims that represent the users groups.
1368         /// </summary>
1369         /// this is SafeCritical as it accesss the NT token.
1370         [SecurityCritical]
AddGroupSidClaims(List<Claim> instanceClaims)1371         void AddGroupSidClaims(List<Claim> instanceClaims)
1372         {
1373             // special case the anonymous identity.
1374             if (m_safeTokenHandle.IsInvalid)
1375                 return;
1376 
1377             SafeLocalAllocHandle safeAllocHandle =  SafeLocalAllocHandle.InvalidHandle;
1378             SafeLocalAllocHandle safeAllocHandlePrimaryGroup =  SafeLocalAllocHandle.InvalidHandle;
1379             try
1380             {
1381                 // Retrieve the primary group sid
1382                 safeAllocHandlePrimaryGroup = GetTokenInformation(m_safeTokenHandle, TokenInformationClass.TokenPrimaryGroup);
1383                 Win32Native.TOKEN_PRIMARY_GROUP primaryGroup = (Win32Native.TOKEN_PRIMARY_GROUP)Marshal.PtrToStructure(safeAllocHandlePrimaryGroup.DangerousGetHandle(), typeof(Win32Native.TOKEN_PRIMARY_GROUP));
1384                 SecurityIdentifier primaryGroupSid = new SecurityIdentifier(primaryGroup.PrimaryGroup, true);
1385 
1386                 // only add one primary group sid
1387                 bool foundPrimaryGroupSid = false;
1388 
1389                 // Retrieve all group sids, primary group sid is one of them
1390                 safeAllocHandle = GetTokenInformation(m_safeTokenHandle, TokenInformationClass.TokenGroups);
1391                 int count = Marshal.ReadInt32(safeAllocHandle.DangerousGetHandle());
1392                 IntPtr pSidAndAttributes = new IntPtr((long)safeAllocHandle.DangerousGetHandle() + (long)Marshal.OffsetOf(typeof(Win32Native.TOKEN_GROUPS), "Groups"));
1393                 for (int i = 0; i < count; ++i)
1394                 {
1395                     Win32Native.SID_AND_ATTRIBUTES group = (Win32Native.SID_AND_ATTRIBUTES)Marshal.PtrToStructure(pSidAndAttributes, typeof(Win32Native.SID_AND_ATTRIBUTES));
1396                     uint mask = Win32Native.SE_GROUP_ENABLED | Win32Native.SE_GROUP_LOGON_ID | Win32Native.SE_GROUP_USE_FOR_DENY_ONLY;
1397                     SecurityIdentifier groupSid = new SecurityIdentifier(group.Sid, true);
1398 
1399                     if ((group.Attributes & mask) == Win32Native.SE_GROUP_ENABLED)
1400                     {
1401                         if (!foundPrimaryGroupSid && StringComparer.Ordinal.Equals( groupSid.Value, primaryGroupSid.Value))
1402                         {
1403                             instanceClaims.Add(new Claim(ClaimTypes.PrimaryGroupSid, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1404                             foundPrimaryGroupSid = true;
1405                         }
1406                         //Primary group sid generates both regular groupsid claim and primary groupsid claim
1407                         instanceClaims.Add(new Claim(ClaimTypes.GroupSid, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1408 
1409                     }
1410                     else if ((group.Attributes & mask) == Win32Native.SE_GROUP_USE_FOR_DENY_ONLY)
1411                     {
1412                         if (!foundPrimaryGroupSid && StringComparer.Ordinal.Equals( groupSid.Value, primaryGroupSid.Value))
1413                         {
1414                             instanceClaims.Add(new Claim(ClaimTypes.DenyOnlyPrimaryGroupSid, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1415                             foundPrimaryGroupSid = true;
1416                         }
1417                         //Primary group sid generates both regular groupsid claim and primary groupsid claim
1418                         instanceClaims.Add(new Claim(ClaimTypes.DenyOnlySid, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1419                     }
1420                     pSidAndAttributes = new IntPtr((long)pSidAndAttributes + Win32Native.SID_AND_ATTRIBUTES.SizeOf);
1421                 }
1422             }
1423             finally
1424             {
1425                 safeAllocHandle.Close();
1426                 safeAllocHandlePrimaryGroup.Close();
1427             }
1428         }
1429 
1430         /// <summary>
1431         /// Creates a Windows SID Claim and adds to collection of claims.
1432         /// </summary>
1433         /// this is SafeCritical as it accesss the NT token.
1434         [SecurityCritical]
AddPrimarySidClaim(List<Claim> instanceClaims)1435         void AddPrimarySidClaim(List<Claim> instanceClaims)
1436         {
1437             // special case the anonymous identity.
1438             if (m_safeTokenHandle.IsInvalid)
1439                 return;
1440 
1441             SafeLocalAllocHandle safeAllocHandle = SafeLocalAllocHandle.InvalidHandle;
1442             try
1443             {
1444                 safeAllocHandle = GetTokenInformation(m_safeTokenHandle, TokenInformationClass.TokenUser);
1445                 Win32Native.SID_AND_ATTRIBUTES user = (Win32Native.SID_AND_ATTRIBUTES)Marshal.PtrToStructure(safeAllocHandle.DangerousGetHandle(), typeof(Win32Native.SID_AND_ATTRIBUTES));
1446                 uint mask = Win32Native.SE_GROUP_USE_FOR_DENY_ONLY;
1447 
1448                 SecurityIdentifier sid = new SecurityIdentifier(user.Sid, true);
1449 
1450                 if (user.Attributes == 0)
1451                 {
1452                     instanceClaims.Add(new Claim(ClaimTypes.PrimarySid, sid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(sid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1453                 }
1454                 else if ((user.Attributes & mask) == Win32Native.SE_GROUP_USE_FOR_DENY_ONLY)
1455                 {
1456                     instanceClaims.Add(new Claim(ClaimTypes.DenyOnlyPrimarySid, sid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(sid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1457                 }
1458             }
1459             finally
1460             {
1461                 safeAllocHandle.Close();
1462             }
1463         }
1464 
1465         [SecurityCritical]
AddTokenClaims(List<Claim> instanceClaims, TokenInformationClass tokenInformationClass, string propertyValue)1466         void AddTokenClaims(List<Claim> instanceClaims, TokenInformationClass tokenInformationClass, string propertyValue)
1467         {
1468             // special case the anonymous identity.
1469             if (m_safeTokenHandle.IsInvalid)
1470                 return;
1471 
1472             SafeLocalAllocHandle safeAllocHandle = SafeLocalAllocHandle.InvalidHandle;
1473 
1474             try
1475             {
1476                 SafeLocalAllocHandle safeLocalAllocHandle = SafeLocalAllocHandle.InvalidHandle;
1477                 safeAllocHandle = GetTokenInformation(m_safeTokenHandle, tokenInformationClass);
1478 
1479                 Win32Native.CLAIM_SECURITY_ATTRIBUTES_INFORMATION claimAttributes = (Win32Native.CLAIM_SECURITY_ATTRIBUTES_INFORMATION)Marshal.PtrToStructure(safeAllocHandle.DangerousGetHandle(), typeof(Win32Native.CLAIM_SECURITY_ATTRIBUTES_INFORMATION));
1480                 // An attribute represents a collection of claims.  Inside each attribute a claim can be multivalued, we create a claim for each value.
1481                 // It is a ragged multi-dimentional array, where each cell can be of different lenghts.
1482 
1483                 // index into array of claims.
1484                 long offset = 0;
1485 
1486                 for (int attribute = 0; attribute < claimAttributes.AttributeCount; attribute++)
1487                 {
1488                     IntPtr pAttribute = new IntPtr(claimAttributes.Attribute.pAttributeV1.ToInt64() + offset);
1489                     Win32Native.CLAIM_SECURITY_ATTRIBUTE_V1 windowsClaim = (Win32Native.CLAIM_SECURITY_ATTRIBUTE_V1)Marshal.PtrToStructure(pAttribute, typeof(Win32Native.CLAIM_SECURITY_ATTRIBUTE_V1));
1490 
1491                     // the switch was written this way, which appears to have multiple for loops, because each item in the ValueCount is of the same ValueType.  This saves the type check each item.
1492                     switch (windowsClaim.ValueType)
1493                     {
1494                         case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING:
1495                             IntPtr[] stringPointers = new IntPtr[windowsClaim.ValueCount];
1496                             Marshal.Copy(windowsClaim.Values.ppString, stringPointers, 0, (int)windowsClaim.ValueCount);
1497 
1498                             for (int item = 0; item < windowsClaim.ValueCount; item++)
1499                             {
1500                                 instanceClaims.Add( new Claim(windowsClaim.Name, Marshal.PtrToStringAuto(stringPointers[item]), ClaimValueTypes.String, m_issuerName, m_issuerName, this, propertyValue, string.Empty));
1501                             }
1502                             break;
1503 
1504                         case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64:
1505                             Int64[] intValues = new Int64[windowsClaim.ValueCount];
1506                             Marshal.Copy(windowsClaim.Values.pInt64, intValues, 0, (int)windowsClaim.ValueCount);
1507 
1508                             for (int item = 0; item < windowsClaim.ValueCount; item++)
1509                             {
1510                                 instanceClaims.Add(new Claim(windowsClaim.Name, Convert.ToString(intValues[item], CultureInfo.InvariantCulture), ClaimValueTypes.Integer64, m_issuerName, m_issuerName, this, propertyValue, string.Empty));
1511                             }
1512                             break;
1513 
1514 
1515                         case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64:
1516                             Int64[] uintValues = new Int64[windowsClaim.ValueCount];
1517                             Marshal.Copy(windowsClaim.Values.pUint64, uintValues, 0, (int)windowsClaim.ValueCount);
1518 
1519                             for (int item = 0; item < windowsClaim.ValueCount; item++)
1520                             {
1521                                 instanceClaims.Add( new Claim(windowsClaim.Name, Convert.ToString((UInt64)uintValues[item], CultureInfo.InvariantCulture), ClaimValueTypes.UInteger64, m_issuerName, m_issuerName, this, propertyValue, string.Empty));
1522                             }
1523                             break;
1524 
1525                         case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN:
1526                             Int64[] boolValues = new Int64[windowsClaim.ValueCount];
1527                             Marshal.Copy(windowsClaim.Values.pUint64, boolValues, 0, (int)windowsClaim.ValueCount);
1528 
1529                             for (int item = 0; item < windowsClaim.ValueCount; item++)
1530                             {
1531                                 instanceClaims.Add(new Claim(windowsClaim.Name,
1532                                                   ((UInt64)boolValues[item] == 0 ? Convert.ToString(false, CultureInfo.InvariantCulture) : Convert.ToString(true, CultureInfo.InvariantCulture)),
1533                                                   ClaimValueTypes.Boolean,
1534                                                   m_issuerName,
1535                                                   m_issuerName,
1536                                                   this,
1537                                                   propertyValue,
1538                                                   string.Empty));
1539                             }
1540                             break;
1541 
1542 
1543                         // These claim types are defined in the structure found in winnt.h, but I haven't received confirmation (may  2011) that they are supported and are not enabled.
1544 
1545                         //case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN:
1546                         //    break;
1547 
1548                         //case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_SID:
1549                         //    break;
1550 
1551                         //case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING:
1552                         //    break;
1553 
1554                     }
1555 
1556                     offset += Marshal.SizeOf(windowsClaim);
1557                 }
1558             }
1559             finally
1560             {
1561                 safeAllocHandle.Close();
1562             }
1563         }
1564 
1565     }
1566 #endif
1567 
1568     [Serializable]
1569     internal enum KerbLogonSubmitType : int {
1570         KerbInteractiveLogon = 2,
1571         KerbSmartCardLogon = 6,
1572         KerbWorkstationUnlockLogon = 7,
1573         KerbSmartCardUnlockLogon = 8,
1574         KerbProxyLogon = 9,
1575         KerbTicketLogon = 10,
1576         KerbTicketUnlockLogon = 11,
1577         KerbS4ULogon = 12
1578     }
1579 
1580     [Serializable]
1581     internal enum SecurityLogonType : int {
1582         Interactive = 2,
1583         Network,
1584         Batch,
1585         Service,
1586         Proxy,
1587         Unlock
1588     }
1589 
1590     [Serializable]
1591     internal enum TokenType : int {
1592         TokenPrimary = 1,
1593         TokenImpersonation
1594     }
1595 
1596     [Serializable]
1597     internal enum TokenInformationClass : int {
1598         TokenUser = 1,
1599         TokenGroups,
1600         TokenPrivileges,
1601         TokenOwner,
1602         TokenPrimaryGroup,
1603         TokenDefaultDacl,
1604         TokenSource,
1605         TokenType,
1606         TokenImpersonationLevel,
1607         TokenStatistics,
1608         TokenRestrictedSids,
1609         TokenSessionId,
1610         TokenGroupsAndPrivileges,
1611         TokenSessionReference,
1612         TokenSandBoxInert,
1613         TokenAuditPolicy,
1614         TokenOrigin,
1615         TokenElevationType,
1616         TokenLinkedToken,
1617         TokenElevation,
1618         TokenHasRestrictions,
1619         TokenAccessInformation,
1620         TokenVirtualizationAllowed,
1621         TokenVirtualizationEnabled,
1622         TokenIntegrityLevel,
1623         TokenUIAccess,
1624         TokenMandatoryPolicy,
1625         TokenLogonSid,
1626         TokenIsAppContainer,
1627         TokenCapabilities,
1628         TokenAppContainerSid,
1629         TokenAppContainerNumber,
1630         TokenUserClaimAttributes,
1631         TokenDeviceClaimAttributes,
1632         TokenRestrictedUserClaimAttributes,
1633         TokenRestrictedDeviceClaimAttributes,
1634         TokenDeviceGroups,
1635         TokenRestrictedDeviceGroups,
1636         MaxTokenInfoClass  // MaxTokenInfoClass should always be the last enum
1637     }
1638 }
1639