Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / mscorlib / system / security / principal / windowsidentity.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // <OWNER>[....]</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 [....] 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
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
121         private WindowsIdentity ()
122             : base( null, null, null, ClaimTypes.Name, ClaimTypes.GroupSid ) {}
123 #else
124         private WindowsIdentity () {}
125 #endif
126
127         [System.Security.SecurityCritical]  // auto-generated
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)]
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)]
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)]
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)]
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
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)]
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)]
193         public WindowsIdentity (string sUserPrincipalName) : this (sUserPrincipalName, null) {}
194
195         [System.Security.SecuritySafeCritical]  // auto-generated
196         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
197
198
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 )]
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
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
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/>
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)]
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)]
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)]
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
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)]
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
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         public static void RunImpersonated(SafeAccessTokenHandle safeAccessTokenHandle, Action action)
613         {
614             if (action == null)
615                 throw new ArgumentNullException("action");
616
617             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
618
619             WindowsIdentity wi = null;
620             if (!safeAccessTokenHandle.IsInvalid)
621                 wi = new WindowsIdentity(safeAccessTokenHandle);
622
623             using (WindowsImpersonationContext wiContext = SafeImpersonate(safeAccessTokenHandle, wi, ref stackMark))
624             {
625                 action();
626             }
627         }
628
629         [SecuritySafeCritical]
630         public static T RunImpersonated<T>(SafeAccessTokenHandle safeAccessTokenHandle, Func<T> func)
631         {
632             if (func == null)
633                 throw new ArgumentNullException("func");
634
635             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
636
637             WindowsIdentity wi = null;
638             if (!safeAccessTokenHandle.IsInvalid)
639                 wi = new WindowsIdentity(safeAccessTokenHandle);
640
641             T result = default(T);
642             using (WindowsImpersonationContext wiContext = SafeImpersonate(safeAccessTokenHandle, wi, ref stackMark))
643             {
644                 result = func();
645             }
646
647             return result;
648         }
649
650         [System.Security.SecuritySafeCritical]  // auto-generated
651         [DynamicSecurityMethodAttribute()]
652         [ResourceExposure(ResourceScope.Process)]  // Call from within a CER, or use a RunAsUser helper.
653         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
654         public virtual WindowsImpersonationContext Impersonate () 
655         {
656             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
657             return Impersonate(ref stackMark);
658         }
659
660         [System.Security.SecuritySafeCritical]  // auto-generated
661         [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPrincipal | SecurityPermissionFlag.UnmanagedCode)]
662         [DynamicSecurityMethodAttribute()]
663         [ResourceExposure(ResourceScope.Process)]  // Call from within a CER, or use a RunAsUser helper.
664         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
665         public static WindowsImpersonationContext Impersonate (IntPtr userToken) 
666         {
667             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
668             if (userToken == IntPtr.Zero)
669                 return SafeRevertToSelf(ref stackMark);
670
671             WindowsIdentity wi = new WindowsIdentity(userToken, null, -1);
672             return wi.Impersonate(ref stackMark);
673         }
674
675         [System.Security.SecurityCritical]  // auto-generated
676         internal WindowsImpersonationContext Impersonate (ref StackCrawlMark stackMark) {
677             if (m_safeTokenHandle.IsInvalid)
678                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AnonymousCannotImpersonate"));
679
680             return SafeImpersonate(m_safeTokenHandle, this, ref stackMark);
681         }
682
683         [System.Security.SecuritySafeCritical]  // auto-generated
684         [ComVisible(false)]
685         protected virtual void Dispose(bool disposing) {
686             if (disposing) {
687                 if (m_safeTokenHandle != null && !m_safeTokenHandle.IsClosed)
688                     m_safeTokenHandle.Dispose();
689             }
690             m_name = null;
691             m_owner = null;
692             m_user = null;
693         }
694
695         [ComVisible(false)]
696         public void Dispose() {
697             Dispose(true);
698         }
699
700         public SafeAccessTokenHandle AccessToken {
701             [System.Security.SecurityCritical]  // auto-generated
702             get {
703                 return m_safeTokenHandle;
704             }
705         }
706
707         //
708         // internal.
709         //
710
711         [System.Security.SecurityCritical]  // auto-generated
712         [ResourceExposure(ResourceScope.None)]
713         [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
714         internal static WindowsImpersonationContext SafeRevertToSelf(ref StackCrawlMark stackMark) 
715         {
716             return SafeImpersonate(s_invalidTokenHandle, null, ref stackMark);
717         }
718
719         [System.Security.SecurityCritical]  // auto-generated
720         [ResourceExposure(ResourceScope.Process)]
721         [ResourceConsumption(ResourceScope.Process)]
722         internal static WindowsImpersonationContext SafeImpersonate (SafeAccessTokenHandle userToken, WindowsIdentity wi, ref StackCrawlMark stackMark) 
723         {
724             bool isImpersonating;
725             int hr = 0;
726             SafeAccessTokenHandle safeTokenHandle = GetCurrentToken(TokenAccessLevels.MaximumAllowed, false, out isImpersonating, out hr);
727             if (safeTokenHandle == null || safeTokenHandle.IsInvalid)
728                 throw new SecurityException(Win32Native.GetMessage(hr));
729
730             // Set the SafeAccessTokenHandle on the FSD:
731             FrameSecurityDescriptor secObj = SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true);
732             if (secObj == null)
733             {
734                 // Security: REQ_SQ flag is missing. Bad compiler ?
735                 // This can happen when you create delegates over functions that need the REQ_SQ 
736                 throw new SecurityException(Environment.GetResourceString( "ExecutionEngine_MissingSecurityDescriptor" ) );
737             }
738                 
739             WindowsImpersonationContext context = new WindowsImpersonationContext(safeTokenHandle, GetCurrentThreadWI(), isImpersonating, secObj);
740
741             if (userToken.IsInvalid) { // impersonating a zero token means clear the token on the thread
742                 hr = Win32.RevertToSelf();
743                 if (hr < 0)
744                     Environment.FailFast(Win32Native.GetMessage(hr));
745                 // update identity on the thread
746                 UpdateThreadWI(wi);
747                 secObj.SetTokenHandles(safeTokenHandle, (wi == null?null:wi.AccessToken));
748             } else {
749                 hr = Win32.RevertToSelf();
750                 if (hr < 0)
751                         Environment.FailFast(Win32Native.GetMessage(hr));
752                 hr = Win32.ImpersonateLoggedOnUser(userToken);
753                 if (hr < 0) {
754                     context.Undo();
755                     throw new SecurityException(Environment.GetResourceString("Argument_ImpersonateUser"));
756                 }
757                 UpdateThreadWI(wi);
758                 secObj.SetTokenHandles(safeTokenHandle, (wi == null?null:wi.AccessToken));
759             }
760
761             return context;
762         }
763
764         [System.Security.SecurityCritical]  // auto-generated
765         internal static WindowsIdentity GetCurrentThreadWI()
766         {
767             return SecurityContext.GetCurrentWI(Thread.CurrentThread.GetExecutionContextReader());
768         }
769
770         [SecurityCritical]
771         internal static void UpdateThreadWI(WindowsIdentity wi)
772         {
773             // Set WI on Thread.CurrentThread.ExecutionContext.SecurityContext
774             Thread currentThread = Thread.CurrentThread;
775             if (currentThread.GetExecutionContextReader().SecurityContext.WindowsIdentity != wi)
776             {
777                 ExecutionContext ec = currentThread.GetMutableExecutionContext(); 
778                 SecurityContext sc = ec.SecurityContext;
779                 if (wi != null && sc == null)
780                 {
781                     // create a new security context on the thread
782                     sc = new SecurityContext();
783                     ec.SecurityContext = sc;
784                 }
785
786                 if (sc != null) // null-check needed here since we will not create an sc if wi is null
787                 {
788                     sc.WindowsIdentity = wi;
789                 }
790             }
791         }
792
793
794         [System.Security.SecurityCritical]  // auto-generated
795         [ResourceExposure(ResourceScope.None)]
796         [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
797         internal static WindowsIdentity GetCurrentInternal (TokenAccessLevels desiredAccess, bool threadOnly) {
798             int hr = 0;
799             bool isImpersonating;
800             SafeAccessTokenHandle safeTokenHandle = GetCurrentToken(desiredAccess, threadOnly, out isImpersonating, out hr);
801             if (safeTokenHandle == null || safeTokenHandle.IsInvalid) {
802                 // either we wanted only ThreadToken - return null
803                 if (threadOnly && !isImpersonating)
804                     return null;
805                 // or there was an error
806                 throw new SecurityException(Win32Native.GetMessage(hr));
807             }
808             WindowsIdentity wi = new WindowsIdentity();
809             wi.m_safeTokenHandle.Dispose();
810             wi.m_safeTokenHandle = safeTokenHandle;
811             return wi;
812         }
813
814         internal static RuntimeConstructorInfo GetSpecialSerializationCtor()
815         {
816             return s_specialSerializationCtor;
817         }
818
819         //
820         // private.
821         //
822
823         private static int GetHRForWin32Error (int dwLastError) {
824             if ((dwLastError & 0x80000000) == 0x80000000)
825                 return dwLastError;
826             else
827                 return (dwLastError & 0x0000FFFF) | unchecked((int)0x80070000);
828         }
829
830         [System.Security.SecurityCritical]  // auto-generated
831         private static Exception GetExceptionFromNtStatus (int status) {
832             if ((uint) status == Win32Native.STATUS_ACCESS_DENIED)
833                 return new UnauthorizedAccessException();
834
835             if ((uint) status == Win32Native.STATUS_INSUFFICIENT_RESOURCES || (uint) status == Win32Native.STATUS_NO_MEMORY)
836                 return new OutOfMemoryException();
837
838             int win32ErrorCode = Win32Native.LsaNtStatusToWinError(status);
839             return new SecurityException(Win32Native.GetMessage(win32ErrorCode));
840         }
841
842         [System.Security.SecurityCritical]  // auto-generated
843         [ResourceExposure(ResourceScope.Process)]
844         [ResourceConsumption(ResourceScope.Process)]
845         private static SafeAccessTokenHandle GetCurrentToken(TokenAccessLevels desiredAccess, bool threadOnly, out bool isImpersonating, out int hr) {
846             isImpersonating = true;
847             SafeAccessTokenHandle safeTokenHandle = GetCurrentThreadToken(desiredAccess, out hr);
848             if (safeTokenHandle == null && hr == GetHRForWin32Error(Win32Native.ERROR_NO_TOKEN)) {
849                 // No impersonation
850                 isImpersonating = false;
851                 if (!threadOnly)
852                     safeTokenHandle = GetCurrentProcessToken(desiredAccess, out hr);
853             }
854             return safeTokenHandle;
855         }
856
857         [System.Security.SecurityCritical]  // auto-generated
858         [ResourceExposure(ResourceScope.Process)]
859         [ResourceConsumption(ResourceScope.Process)]
860         private static SafeAccessTokenHandle GetCurrentProcessToken (TokenAccessLevels desiredAccess, out int hr) {
861             hr = 0;
862             SafeAccessTokenHandle safeTokenHandle;
863             if (!Win32Native.OpenProcessToken(Win32Native.GetCurrentProcess(), desiredAccess, out safeTokenHandle))
864                 hr = GetHRForWin32Error(Marshal.GetLastWin32Error());
865             return safeTokenHandle;
866         }
867
868         [System.Security.SecurityCritical]  // auto-generated
869         [ResourceExposure(ResourceScope.Process)]
870         [ResourceConsumption(ResourceScope.Process)]
871         internal static SafeAccessTokenHandle GetCurrentThreadToken(TokenAccessLevels desiredAccess, out int hr) {
872             SafeAccessTokenHandle safeTokenHandle;
873             hr = Win32.OpenThreadToken(desiredAccess, WinSecurityContext.Both, out safeTokenHandle);
874             return safeTokenHandle;
875         }
876
877         /// <summary>
878         ///     Get a property from the current token
879         /// </summary>
880         [System.Security.SecurityCritical]  // auto-generated
881         private T GetTokenInformation<T>(TokenInformationClass tokenInformationClass) where T : struct{
882             Contract.Assert(!m_safeTokenHandle.IsInvalid && !m_safeTokenHandle.IsClosed, "!m_safeTokenHandle.IsInvalid && !m_safeTokenHandle.IsClosed");
883
884             using (SafeLocalAllocHandle information = GetTokenInformation(m_safeTokenHandle, tokenInformationClass)) {
885                 Contract.Assert(information.ByteLength >= (ulong)Marshal.SizeOf(typeof(T)),
886                                 "information.ByteLength >= (ulong)Marshal.SizeOf(typeof(T))");
887
888                 return information.Read<T>(0);
889             }
890         }
891
892         //
893         // QueryImpersonation used to test if the current thread is impersonated.
894         // This method doesn't return the thread token (WindowsIdentity).
895         // Although GetCurrentInternal can be used to perform the same test but 
896         // QueryImpersonation is optimized for the perf.
897         // 
898         [System.Security.SecurityCritical]  // auto-generated
899         [ResourceExposure(ResourceScope.Process)]
900         [ResourceConsumption(ResourceScope.Process)]
901         internal static ImpersonationQueryResult QueryImpersonation() {
902             SafeAccessTokenHandle safeTokenHandle = null;
903             int hr = Win32.OpenThreadToken(TokenAccessLevels.Query,  WinSecurityContext.Thread, out safeTokenHandle);
904                         
905             if (safeTokenHandle != null) {
906                 Contract.Assert(hr == 0, "[WindowsIdentity..QueryImpersonation] - hr == 0");
907                 safeTokenHandle.Close();
908                 return ImpersonationQueryResult.Impersonated;
909             } 
910
911             if (hr == GetHRForWin32Error(Win32Native.ERROR_ACCESS_DENIED)) {
912                 // thread is impersonated because the thread was there (and we failed to open it).
913                 return ImpersonationQueryResult.Impersonated;
914             } 
915             
916             if (hr == GetHRForWin32Error(Win32Native.ERROR_NO_TOKEN)) {
917                 // definitely not impersonating
918                 return ImpersonationQueryResult.NotImpersonated;
919             }
920             
921             // Unexpected failure.
922             return ImpersonationQueryResult.Failed;
923         }
924
925         [System.Security.SecurityCritical]  // auto-generated
926         private static Win32Native.LUID GetLogonAuthId (SafeAccessTokenHandle safeTokenHandle) {
927             using (SafeLocalAllocHandle pStatistics = GetTokenInformation(safeTokenHandle, TokenInformationClass.TokenStatistics)) {
928                 Win32Native.TOKEN_STATISTICS statistics = pStatistics.Read<Win32Native.TOKEN_STATISTICS>(0);
929             return statistics.AuthenticationId;
930         }
931         }
932
933         [System.Security.SecurityCritical]
934         private static SafeLocalAllocHandle GetTokenInformation (SafeAccessTokenHandle tokenHandle, TokenInformationClass tokenInformationClass) {
935             SafeLocalAllocHandle safeLocalAllocHandle = SafeLocalAllocHandle.InvalidHandle;
936             uint dwLength = (uint) Marshal.SizeOf(typeof(uint));
937             bool result = Win32Native.GetTokenInformation(tokenHandle, 
938                                                           (uint) tokenInformationClass, 
939                                                           safeLocalAllocHandle, 
940                                                           0, 
941                                                           out dwLength);
942             int dwErrorCode = Marshal.GetLastWin32Error();
943             switch (dwErrorCode) {
944             case Win32Native.ERROR_BAD_LENGTH:
945                 // special case for TokenSessionId. Falling through
946             case Win32Native.ERROR_INSUFFICIENT_BUFFER:
947                 // ptrLength is an [In] param to LocalAlloc 
948                 UIntPtr ptrLength = new UIntPtr(dwLength);
949                 safeLocalAllocHandle.Dispose();
950                 safeLocalAllocHandle = Win32Native.LocalAlloc(Win32Native.LMEM_FIXED, ptrLength);
951                 if (safeLocalAllocHandle == null || safeLocalAllocHandle.IsInvalid) 
952                     throw new OutOfMemoryException();
953                 safeLocalAllocHandle.Initialize(dwLength);
954
955                 result = Win32Native.GetTokenInformation(tokenHandle, 
956                                                          (uint) tokenInformationClass, 
957                                                          safeLocalAllocHandle, 
958                                                          dwLength, 
959                                                          out dwLength);
960                 if (!result)
961                     throw new SecurityException(Win32Native.GetMessage(Marshal.GetLastWin32Error()));
962                 break;
963             case Win32Native.ERROR_INVALID_HANDLE:
964                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidImpersonationToken"));
965             default:
966                 throw new SecurityException(Win32Native.GetMessage(dwErrorCode));
967             }
968             return safeLocalAllocHandle;
969         }
970
971         [System.Security.SecurityCritical]  // auto-generated
972 #if FEATURE_CORRUPTING_EXCEPTIONS
973         [HandleProcessCorruptedStateExceptions] // 
974 #endif // FEATURE_CORRUPTING_EXCEPTIONS
975         private unsafe static SafeAccessTokenHandle KerbS4ULogon (string upn, ref SafeAccessTokenHandle safeTokenHandle)
976         {
977             // source name
978             byte[] sourceName = new byte[] { (byte)'C', (byte)'L', (byte)'R' }; // we set the source name to "CLR".
979
980             // ptrLength is an [In] param to LocalAlloc 
981             UIntPtr ptrLength = new UIntPtr((uint)(sourceName.Length + 1));
982
983             using (SafeLocalAllocHandle pSourceName = Win32Native.LocalAlloc(Win32Native.LPTR, ptrLength)) {
984                 if (pSourceName == null || pSourceName.IsInvalid)
985                     throw new OutOfMemoryException();
986
987                 pSourceName.Initialize((ulong)sourceName.Length + 1);
988                 pSourceName.WriteArray(0, sourceName, 0, sourceName.Length);
989                 Win32Native.UNICODE_INTPTR_STRING Name = new Win32Native.UNICODE_INTPTR_STRING(sourceName.Length,
990                                                                                                pSourceName);
991
992                 int status;
993                 SafeLsaLogonProcessHandle logonHandle = SafeLsaLogonProcessHandle.InvalidHandle;
994                 SafeLsaReturnBufferHandle profile = SafeLsaReturnBufferHandle.InvalidHandle;
995                 try {
996                     Privilege privilege = null;
997
998                     RuntimeHelpers.PrepareConstrainedRegions();
999                     // Try to get an impersonation token.
1000                     try {
1001                         // Try to enable the TCB privilege if possible
1002                         try {
1003                             privilege = new Privilege("SeTcbPrivilege");
1004                             privilege.Enable();
1005                         }
1006                         catch (PrivilegeNotHeldException) { }
1007
1008                         IntPtr dummy = IntPtr.Zero;
1009                         status = Win32Native.LsaRegisterLogonProcess(ref Name, ref logonHandle, ref dummy);
1010                         if (Win32Native.ERROR_ACCESS_DENIED == Win32Native.LsaNtStatusToWinError(status)) {
1011                             // We don't have the Tcb privilege. The best we can hope for is to get an Identification token.
1012                             status = Win32Native.LsaConnectUntrusted(ref logonHandle);
1013                         }
1014                     }
1015                     catch {
1016                         // protect against exception filter-based luring attacks
1017                         if (privilege != null)
1018                             privilege.Revert();
1019                         throw;
1020                     }
1021                     finally {
1022                         if (privilege != null)
1023                             privilege.Revert();
1024                     }
1025                     if (status < 0) // non-negative numbers indicate success
1026                         throw GetExceptionFromNtStatus(status);
1027
1028                     // package name ("Kerberos")
1029                     byte[] arrayPackageName = new byte[Win32Native.MICROSOFT_KERBEROS_NAME.Length + 1];
1030                     Encoding.ASCII.GetBytes(Win32Native.MICROSOFT_KERBEROS_NAME, 0, Win32Native.MICROSOFT_KERBEROS_NAME.Length, arrayPackageName, 0);
1031
1032                     // ptrLength is an [In] param to LocalAlloc 
1033                     ptrLength = new UIntPtr((uint)arrayPackageName.Length);
1034                     using (SafeLocalAllocHandle pPackageName = Win32Native.LocalAlloc(Win32Native.LMEM_FIXED, ptrLength)) {
1035                         if (pPackageName == null || pPackageName.IsInvalid)
1036                             throw new OutOfMemoryException();
1037                         pPackageName.Initialize((ulong)(uint)arrayPackageName.Length);
1038
1039                         pPackageName.WriteArray(0, arrayPackageName, 0, arrayPackageName.Length);
1040                         Win32Native.UNICODE_INTPTR_STRING PackageName = new Win32Native.UNICODE_INTPTR_STRING(Win32Native.MICROSOFT_KERBEROS_NAME.Length,
1041                                                                                                               pPackageName);
1042                         uint packageId = 0;
1043                         status = Win32Native.LsaLookupAuthenticationPackage(logonHandle, ref PackageName, ref packageId);
1044                         if (status < 0) // non-negative numbers indicate success
1045                             throw GetExceptionFromNtStatus(status);
1046
1047                         // source context
1048                         Win32Native.TOKEN_SOURCE sourceContext = new Win32Native.TOKEN_SOURCE();
1049                         if (!Win32Native.AllocateLocallyUniqueId(ref sourceContext.SourceIdentifier))
1050                             throw new SecurityException(Win32Native.GetMessage(Marshal.GetLastWin32Error()));
1051                         sourceContext.Name = new char[8];
1052                         sourceContext.Name[0] = 'C'; sourceContext.Name[1] = 'L'; sourceContext.Name[2] = 'R';
1053
1054                         uint profileSize = 0;
1055                         Win32Native.LUID logonId = new Win32Native.LUID();
1056                         Win32Native.QUOTA_LIMITS quotas = new Win32Native.QUOTA_LIMITS();
1057                         int subStatus = 0;
1058
1059                         //
1060                         // Build the KERB_S4U_LOGON structure.  Note that the LSA expects this entire
1061                         // structure to be contained within the same block of memory, so we need to allocate
1062                         // enough room for both the structure itself and the UPN string in a single buffer
1063                         // and do the marshalling into this buffer by hand.
1064                         //
1065
1066                         byte[] upnBytes = Encoding.Unicode.GetBytes(upn);
1067
1068                         Contract.Assert(Marshal.SizeOf(typeof(Win32Native.KERB_S4U_LOGON)) % IntPtr.Size == 0, "Potential allignment issue setting up S4U logon buffer");
1069                         uint logonInfoSize = (uint) (Marshal.SizeOf(typeof(Win32Native.KERB_S4U_LOGON)) + upnBytes.Length);
1070                         using (SafeLocalAllocHandle logonInfoBuffer = Win32Native.LocalAlloc(Win32Native.LPTR, new UIntPtr(logonInfoSize))) {
1071                             if (logonInfoBuffer == null || logonInfoBuffer.IsInvalid) {
1072                                 throw new OutOfMemoryException();
1073                             }
1074
1075                             logonInfoBuffer.Initialize((ulong)logonInfoSize);
1076
1077                             // Write the UPN to the end of the serialized buffer
1078                             ulong upnOffset = (ulong)Marshal.SizeOf(typeof(Win32Native.KERB_S4U_LOGON));
1079                             logonInfoBuffer.WriteArray(upnOffset,
1080                                                        upnBytes,
1081                                                        0,
1082                                                        upnBytes.Length);
1083
1084                             unsafe {
1085                                 byte* pLogonInfoBuffer = null;
1086
1087                                 RuntimeHelpers.PrepareConstrainedRegions();
1088                                 try {
1089                                     logonInfoBuffer.AcquirePointer(ref pLogonInfoBuffer);
1090
1091                                     // Setup the KERB_S4U_LOGON structure
1092                                     Win32Native.KERB_S4U_LOGON logonInfo = new Win32Native.KERB_S4U_LOGON();
1093                                     logonInfo.MessageType = (uint)KerbLogonSubmitType.KerbS4ULogon;
1094                                     logonInfo.Flags = 0;
1095
1096                                     // Point the ClientUpn at the UPN written at the end of this buffer
1097                                     logonInfo.ClientUpn = new Win32Native.UNICODE_INTPTR_STRING(upnBytes.Length,
1098                                                                                                 new IntPtr(pLogonInfoBuffer + upnOffset));
1099
1100                                     logonInfoBuffer.Write(0, logonInfo);
1101
1102                                     // logon user
1103                                     status = Win32Native.LsaLogonUser(logonHandle,
1104                                                                       ref Name,
1105                                                                       (uint)SecurityLogonType.Network,
1106                                                                       packageId,
1107                                                                                           new IntPtr(pLogonInfoBuffer),
1108                                                                                           (uint)logonInfoBuffer.ByteLength,
1109                                                                       IntPtr.Zero,
1110                                                                       ref sourceContext,
1111                                                                       ref profile,
1112                                                                       ref profileSize,
1113                                                                       ref logonId,
1114                                                                       ref safeTokenHandle,
1115                                                                       ref quotas,
1116                                                                       ref subStatus);
1117
1118                                     // If both status and substatus are < 0, substatus is preferred.
1119                                     if (status == Win32Native.STATUS_ACCOUNT_RESTRICTION && subStatus < 0)
1120                                         status = subStatus;
1121                                     if (status < 0) // non-negative numbers indicate success
1122                                         throw GetExceptionFromNtStatus(status);
1123                                     if (subStatus < 0) // non-negative numbers indicate success
1124                                         throw GetExceptionFromNtStatus(subStatus);
1125                                 }
1126                                 finally {
1127                                     if (pLogonInfoBuffer != null) {
1128                                         logonInfoBuffer.ReleasePointer();
1129                                     }
1130                                 }
1131                             }
1132                         }
1133
1134                         return safeTokenHandle;
1135                     }
1136                 }
1137                 finally {
1138                     if (!logonHandle.IsInvalid)
1139                         logonHandle.Dispose();
1140                     if (!profile.IsInvalid)
1141                         profile.Dispose();
1142                 }
1143             }
1144         }
1145     
1146 #if !FEATURE_CORECLR
1147
1148         [SecuritySafeCritical]
1149         protected WindowsIdentity (WindowsIdentity identity)
1150             : base( identity, null, identity.m_authType, null, null, false )
1151         {
1152             if (identity == null)
1153                 throw new ArgumentNullException("identity");
1154
1155             Contract.EndContractBlock();
1156
1157             bool mustDecrement = false;
1158             RuntimeHelpers.PrepareConstrainedRegions();
1159             try
1160             {
1161                 if (!identity.m_safeTokenHandle.IsInvalid && identity.m_safeTokenHandle != SafeAccessTokenHandle.InvalidHandle && identity.m_safeTokenHandle.DangerousGetHandle() != IntPtr.Zero)
1162                 {
1163                     identity.m_safeTokenHandle.DangerousAddRef(ref mustDecrement);
1164
1165                     if (!identity.m_safeTokenHandle.IsInvalid && identity.m_safeTokenHandle.DangerousGetHandle() != IntPtr.Zero)
1166                         CreateFromToken(identity.m_safeTokenHandle.DangerousGetHandle());
1167
1168                     m_authType = identity.m_authType;
1169                     m_isAuthenticated = identity.m_isAuthenticated;
1170                 }
1171             }
1172             finally
1173             {
1174                 if (mustDecrement)
1175                     identity.m_safeTokenHandle.DangerousRelease();
1176             }
1177         }
1178         
1179         [SecurityCritical]
1180         internal IntPtr GetTokenInternal()
1181         {
1182             return m_safeTokenHandle.DangerousGetHandle();
1183         }
1184
1185         [SecurityCritical]
1186         internal WindowsIdentity(ClaimsIdentity claimsIdentity, IntPtr userToken)
1187             : base(claimsIdentity)
1188         {
1189             if (userToken != IntPtr.Zero && userToken.ToInt64() > 0)
1190             {
1191                 CreateFromToken(userToken);
1192             }
1193         }
1194
1195         /// <summary>
1196         /// Returns a new instance of the base, used when serializing the WindowsIdentity.
1197         /// </summary>
1198         internal ClaimsIdentity CloneAsBase()
1199         {
1200             return base.Clone();
1201         }
1202
1203         /// <summary>
1204         /// Returns a new instance of <see cref="WindowsIdentity"/> with values copied from this object.
1205         /// </summary>
1206         public override ClaimsIdentity Clone()
1207         {
1208             return new WindowsIdentity(this);
1209         }
1210
1211         /// <summary>
1212         /// Gets the 'User Claims' from the NTToken that represents this identity
1213         /// </summary>
1214         public virtual IEnumerable<Claim> UserClaims
1215         {
1216             get
1217             {
1218                 InitializeClaims();
1219
1220                 return m_userClaims.AsReadOnly();
1221             }
1222         }
1223
1224         /// <summary>
1225         /// Gets the 'Device Claims' from the NTToken that represents the device the identity is using
1226         /// </summary>
1227         public virtual IEnumerable<Claim> DeviceClaims
1228         {
1229             get
1230             {
1231                 InitializeClaims();
1232
1233                 return m_deviceClaims.AsReadOnly();
1234             }
1235         }
1236
1237         /// <summary>
1238         /// Gets the claims as <see cref="IEnumerable{Claim}"/>, associated with this <see cref="WindowsIdentity"/>.
1239         /// Includes UserClaims and DeviceClaims.
1240         /// </summary>
1241         public override IEnumerable<Claim> Claims
1242         {
1243             get 
1244             {
1245                 if (!m_claimsInitialized)
1246                 {
1247                     InitializeClaims();
1248                 }
1249
1250                 foreach (Claim claim in base.Claims)
1251                     yield return claim;
1252
1253                 foreach (Claim claim in m_userClaims)
1254                     yield return claim;
1255
1256                 foreach (Claim claim in m_deviceClaims)
1257                     yield return claim;
1258             }
1259         }
1260
1261         /// <summary>
1262         /// Intenal method to initialize the claim collection.
1263         /// Lazy init is used so claims are not initialzed until needed
1264         /// </summary>
1265         [SecuritySafeCritical]
1266         void InitializeClaims()
1267         {
1268             if (!m_claimsInitialized)
1269             {
1270                 lock (m_claimsIntiailizedLock)
1271                 {
1272                     if (!m_claimsInitialized)
1273                     {
1274                         m_userClaims = new List<Claim>();
1275                         m_deviceClaims = new List<Claim>();
1276
1277                         if (!String.IsNullOrEmpty(Name))
1278                         {
1279                             //
1280                             // Add the name claim only if the WindowsIdentity.Name is populated
1281                             // WindowsIdentity.Name will be null when it is the fake anonymous user
1282                             // with a token value of IntPtr.Zero
1283                             //
1284                             m_userClaims.Add(new Claim(NameClaimType, Name, ClaimValueTypes.String, m_issuerName, m_issuerName, this));
1285                         }
1286
1287                         // primary sid
1288                         AddPrimarySidClaim(m_userClaims);
1289
1290                         // group sids
1291                         AddGroupSidClaims(m_userClaims);
1292
1293                         // The following TokenInformationClass's were part of the Win8 release
1294                         if (Environment.IsWindows8OrAbove)
1295                         {
1296                             // Device group sids
1297                             AddDeviceGroupSidClaims(m_deviceClaims, TokenInformationClass.TokenDeviceGroups);
1298
1299                             // User token claims
1300                             AddTokenClaims(m_userClaims, TokenInformationClass.TokenUserClaimAttributes, ClaimTypes.WindowsUserClaim);
1301
1302                             // Device token claims
1303                             AddTokenClaims(m_deviceClaims, TokenInformationClass.TokenDeviceClaimAttributes, ClaimTypes.WindowsDeviceClaim);
1304                         }
1305
1306                         m_claimsInitialized = true;
1307                     }
1308                 }
1309             }
1310         }
1311
1312         /// <summary>
1313         /// Creates a collection of SID claims that represent the DeviceSidGroups.
1314         /// </summary>
1315         /// this is SafeCritical as it accesss the NT token.
1316         [SecurityCritical]
1317         void AddDeviceGroupSidClaims(List<Claim> instanceClaims,  TokenInformationClass tokenInformationClass)
1318         {
1319             // special case the anonymous identity.
1320             if (m_safeTokenHandle.IsInvalid)
1321                 return;
1322
1323             SafeLocalAllocHandle safeAllocHandle =  SafeLocalAllocHandle.InvalidHandle;
1324             try
1325             {
1326                 // Retrieve all group sids
1327
1328                 safeAllocHandle = GetTokenInformation(m_safeTokenHandle, tokenInformationClass);
1329                 int count = Marshal.ReadInt32(safeAllocHandle.DangerousGetHandle());
1330                 IntPtr pSidAndAttributes = new IntPtr((long)safeAllocHandle.DangerousGetHandle() + (long)Marshal.OffsetOf(typeof(Win32Native.TOKEN_GROUPS), "Groups"));
1331                 string claimType = null;
1332
1333                 for (int i = 0; i < count; ++i)
1334                 {
1335                     Win32Native.SID_AND_ATTRIBUTES group = (Win32Native.SID_AND_ATTRIBUTES)Marshal.PtrToStructure(pSidAndAttributes, typeof(Win32Native.SID_AND_ATTRIBUTES));
1336                     uint mask = Win32Native.SE_GROUP_ENABLED | Win32Native.SE_GROUP_LOGON_ID | Win32Native.SE_GROUP_USE_FOR_DENY_ONLY;
1337                     SecurityIdentifier groupSid = new SecurityIdentifier(group.Sid, true);
1338                     if ((group.Attributes & mask) == Win32Native.SE_GROUP_ENABLED)
1339                     {
1340                         claimType = ClaimTypes.WindowsDeviceGroup;
1341                         Claim claim = new Claim(claimType, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture));
1342                         claim.Properties.Add(claimType, "");
1343                         instanceClaims.Add(claim);
1344                     }
1345                     else if ((group.Attributes & mask) == Win32Native.SE_GROUP_USE_FOR_DENY_ONLY)
1346                     {
1347                         claimType = ClaimTypes.DenyOnlyWindowsDeviceGroup;
1348                         Claim claim = new Claim(claimType, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture));
1349                         claim.Properties.Add(claimType, "");
1350                         instanceClaims.Add(claim);
1351                     }
1352
1353                     pSidAndAttributes = new IntPtr((long)pSidAndAttributes + Win32Native.SID_AND_ATTRIBUTES.SizeOf);
1354                 }
1355             }
1356             finally
1357             {
1358                 safeAllocHandle.Close();
1359             }
1360         }
1361
1362         /// <summary>
1363         /// Creates a collection of SID claims that represent the users groups.
1364         /// </summary>
1365         /// this is SafeCritical as it accesss the NT token.
1366         [SecurityCritical]
1367         void AddGroupSidClaims(List<Claim> instanceClaims)
1368         {
1369             // special case the anonymous identity.
1370             if (m_safeTokenHandle.IsInvalid)
1371                 return;
1372
1373             SafeLocalAllocHandle safeAllocHandle =  SafeLocalAllocHandle.InvalidHandle;
1374             SafeLocalAllocHandle safeAllocHandlePrimaryGroup =  SafeLocalAllocHandle.InvalidHandle;
1375             try
1376             {
1377                 // Retrieve the primary group sid
1378                 safeAllocHandlePrimaryGroup = GetTokenInformation(m_safeTokenHandle, TokenInformationClass.TokenPrimaryGroup);
1379                 Win32Native.TOKEN_PRIMARY_GROUP primaryGroup = (Win32Native.TOKEN_PRIMARY_GROUP)Marshal.PtrToStructure(safeAllocHandlePrimaryGroup.DangerousGetHandle(), typeof(Win32Native.TOKEN_PRIMARY_GROUP));
1380                 SecurityIdentifier primaryGroupSid = new SecurityIdentifier(primaryGroup.PrimaryGroup, true);
1381                     
1382                 // only add one primary group sid
1383                 bool foundPrimaryGroupSid = false;
1384
1385                 // Retrieve all group sids, primary group sid is one of them
1386                 safeAllocHandle = GetTokenInformation(m_safeTokenHandle, TokenInformationClass.TokenGroups);
1387                 int count = Marshal.ReadInt32(safeAllocHandle.DangerousGetHandle());
1388                 IntPtr pSidAndAttributes = new IntPtr((long)safeAllocHandle.DangerousGetHandle() + (long)Marshal.OffsetOf(typeof(Win32Native.TOKEN_GROUPS), "Groups"));
1389                 for (int i = 0; i < count; ++i)
1390                 {
1391                     Win32Native.SID_AND_ATTRIBUTES group = (Win32Native.SID_AND_ATTRIBUTES)Marshal.PtrToStructure(pSidAndAttributes, typeof(Win32Native.SID_AND_ATTRIBUTES));
1392                     uint mask = Win32Native.SE_GROUP_ENABLED | Win32Native.SE_GROUP_LOGON_ID | Win32Native.SE_GROUP_USE_FOR_DENY_ONLY;
1393                     SecurityIdentifier groupSid = new SecurityIdentifier(group.Sid, true);
1394
1395                     if ((group.Attributes & mask) == Win32Native.SE_GROUP_ENABLED)
1396                     {
1397                         if (!foundPrimaryGroupSid && StringComparer.Ordinal.Equals( groupSid.Value, primaryGroupSid.Value))
1398                         {
1399                             instanceClaims.Add(new Claim(ClaimTypes.PrimaryGroupSid, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1400                             foundPrimaryGroupSid = true;
1401                         }
1402                         //Primary group sid generates both regular groupsid claim and primary groupsid claim
1403                         instanceClaims.Add(new Claim(ClaimTypes.GroupSid, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1404
1405                     }
1406                     else if ((group.Attributes & mask) == Win32Native.SE_GROUP_USE_FOR_DENY_ONLY)
1407                     {
1408                         if (!foundPrimaryGroupSid && StringComparer.Ordinal.Equals( groupSid.Value, primaryGroupSid.Value))
1409                         {
1410                             instanceClaims.Add(new Claim(ClaimTypes.DenyOnlyPrimaryGroupSid, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1411                             foundPrimaryGroupSid = true;
1412                         }
1413                         //Primary group sid generates both regular groupsid claim and primary groupsid claim
1414                         instanceClaims.Add(new Claim(ClaimTypes.DenyOnlySid, groupSid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(groupSid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1415                     }
1416                     pSidAndAttributes = new IntPtr((long)pSidAndAttributes + Win32Native.SID_AND_ATTRIBUTES.SizeOf);
1417                 }
1418             }
1419             finally
1420             {
1421                 safeAllocHandle.Close();
1422                 safeAllocHandlePrimaryGroup.Close();
1423             }
1424         }
1425         
1426         /// <summary>
1427         /// Creates a Windows SID Claim and adds to collection of claims.
1428         /// </summary>
1429         /// this is SafeCritical as it accesss the NT token.        
1430         [SecurityCritical]        
1431         void AddPrimarySidClaim(List<Claim> instanceClaims)
1432         {
1433             // special case the anonymous identity.
1434             if (m_safeTokenHandle.IsInvalid)
1435                 return;
1436
1437             SafeLocalAllocHandle safeAllocHandle = SafeLocalAllocHandle.InvalidHandle;
1438             try
1439             {
1440                 safeAllocHandle = GetTokenInformation(m_safeTokenHandle, TokenInformationClass.TokenUser);
1441                 Win32Native.SID_AND_ATTRIBUTES user = (Win32Native.SID_AND_ATTRIBUTES)Marshal.PtrToStructure(safeAllocHandle.DangerousGetHandle(), typeof(Win32Native.SID_AND_ATTRIBUTES));
1442                 uint mask = Win32Native.SE_GROUP_USE_FOR_DENY_ONLY;
1443                
1444                 SecurityIdentifier sid = new SecurityIdentifier(user.Sid, true);
1445
1446                 if (user.Attributes == 0)
1447                 {
1448                     instanceClaims.Add(new Claim(ClaimTypes.PrimarySid, sid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(sid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1449                 }
1450                 else if ((user.Attributes & mask) == Win32Native.SE_GROUP_USE_FOR_DENY_ONLY)
1451                 {
1452                     instanceClaims.Add(new Claim(ClaimTypes.DenyOnlyPrimarySid, sid.Value, ClaimValueTypes.String, m_issuerName, m_issuerName, this, ClaimTypes.WindowsSubAuthority, Convert.ToString(sid.IdentifierAuthority, CultureInfo.InvariantCulture)));
1453                 }
1454             }
1455             finally
1456             {
1457                 safeAllocHandle.Close();
1458             }
1459         }
1460
1461         [SecurityCritical]
1462         void AddTokenClaims(List<Claim> instanceClaims, TokenInformationClass tokenInformationClass, string propertyValue)
1463         {
1464             // special case the anonymous identity.
1465             if (m_safeTokenHandle.IsInvalid)
1466                 return;
1467
1468             SafeLocalAllocHandle safeAllocHandle = SafeLocalAllocHandle.InvalidHandle;
1469
1470             try
1471             {
1472                 SafeLocalAllocHandle safeLocalAllocHandle = SafeLocalAllocHandle.InvalidHandle;
1473                 safeAllocHandle = GetTokenInformation(m_safeTokenHandle, tokenInformationClass);
1474
1475                 Win32Native.CLAIM_SECURITY_ATTRIBUTES_INFORMATION claimAttributes = (Win32Native.CLAIM_SECURITY_ATTRIBUTES_INFORMATION)Marshal.PtrToStructure(safeAllocHandle.DangerousGetHandle(), typeof(Win32Native.CLAIM_SECURITY_ATTRIBUTES_INFORMATION));
1476                 // An attribute represents a collection of claims.  Inside each attribute a claim can be multivalued, we create a claim for each value.
1477                 // It is a ragged multi-dimentional array, where each cell can be of different lenghts.
1478                 
1479                 // index into array of claims.
1480                 long offset = 0;
1481                
1482                 for (int attribute = 0; attribute < claimAttributes.AttributeCount; attribute++)
1483                 {
1484                     IntPtr pAttribute = new IntPtr(claimAttributes.Attribute.pAttributeV1.ToInt64() + offset);
1485                     Win32Native.CLAIM_SECURITY_ATTRIBUTE_V1 windowsClaim = (Win32Native.CLAIM_SECURITY_ATTRIBUTE_V1)Marshal.PtrToStructure(pAttribute, typeof(Win32Native.CLAIM_SECURITY_ATTRIBUTE_V1));                    
1486                     
1487                     // 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.
1488                     switch (windowsClaim.ValueType)
1489                     {
1490                         case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING:
1491                             IntPtr[] stringPointers = new IntPtr[windowsClaim.ValueCount];
1492                             Marshal.Copy(windowsClaim.Values.ppString, stringPointers, 0, (int)windowsClaim.ValueCount);
1493
1494                             for (int item = 0; item < windowsClaim.ValueCount; item++)
1495                             {
1496                                 instanceClaims.Add( new Claim(windowsClaim.Name, Marshal.PtrToStringAuto(stringPointers[item]), ClaimValueTypes.String, m_issuerName, m_issuerName, this, propertyValue, string.Empty));
1497                             }
1498                             break;
1499
1500                         case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64:
1501                             Int64[] intValues = new Int64[windowsClaim.ValueCount];
1502                             Marshal.Copy(windowsClaim.Values.pInt64, intValues, 0, (int)windowsClaim.ValueCount);
1503
1504                             for (int item = 0; item < windowsClaim.ValueCount; item++)
1505                             {
1506                                 instanceClaims.Add(new Claim(windowsClaim.Name, Convert.ToString(intValues[item], CultureInfo.InvariantCulture), ClaimValueTypes.Integer64, m_issuerName, m_issuerName, this, propertyValue, string.Empty));
1507                             }
1508                             break;
1509
1510
1511                         case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64:
1512                             Int64[] uintValues = new Int64[windowsClaim.ValueCount];
1513                             Marshal.Copy(windowsClaim.Values.pUint64, uintValues, 0, (int)windowsClaim.ValueCount);
1514
1515                             for (int item = 0; item < windowsClaim.ValueCount; item++)
1516                             {
1517                                 instanceClaims.Add( new Claim(windowsClaim.Name, Convert.ToString((UInt64)uintValues[item], CultureInfo.InvariantCulture), ClaimValueTypes.UInteger64, m_issuerName, m_issuerName, this, propertyValue, string.Empty));
1518                             }
1519                             break;
1520
1521                         case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN:
1522                             Int64[] boolValues = new Int64[windowsClaim.ValueCount];
1523                             Marshal.Copy(windowsClaim.Values.pUint64, boolValues, 0, (int)windowsClaim.ValueCount);
1524
1525                             for (int item = 0; item < windowsClaim.ValueCount; item++)
1526                             {
1527                                 instanceClaims.Add(new Claim(windowsClaim.Name,
1528                                                   ((UInt64)boolValues[item] == 0 ? Convert.ToString(false, CultureInfo.InvariantCulture) : Convert.ToString(true, CultureInfo.InvariantCulture)),
1529                                                   ClaimValueTypes.Boolean, 
1530                                                   m_issuerName, 
1531                                                   m_issuerName, 
1532                                                   this, 
1533                                                   propertyValue, 
1534                                                   string.Empty));
1535                             }
1536                             break;
1537
1538
1539                         // 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.
1540
1541                         //case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN:
1542                         //    break;
1543
1544                         //case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_SID:
1545                         //    break;
1546
1547                         //case Win32Native.CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING:
1548                         //    break;
1549
1550                     }
1551
1552                     offset += Marshal.SizeOf(windowsClaim);
1553                 }
1554             }
1555             finally
1556             {
1557                 safeAllocHandle.Close();
1558             }
1559         }
1560
1561     }
1562 #endif
1563
1564     [Serializable]
1565     internal enum KerbLogonSubmitType : int {
1566         KerbInteractiveLogon = 2,
1567         KerbSmartCardLogon = 6,
1568         KerbWorkstationUnlockLogon = 7,
1569         KerbSmartCardUnlockLogon = 8,
1570         KerbProxyLogon = 9,
1571         KerbTicketLogon = 10,
1572         KerbTicketUnlockLogon = 11,
1573         KerbS4ULogon = 12
1574     }
1575
1576     [Serializable]
1577     internal enum SecurityLogonType : int {
1578         Interactive = 2,
1579         Network,
1580         Batch,
1581         Service,
1582         Proxy,
1583         Unlock
1584     }
1585
1586     [Serializable]
1587     internal enum TokenType : int {
1588         TokenPrimary = 1,
1589         TokenImpersonation
1590     }
1591
1592     [Serializable]
1593     internal enum TokenInformationClass : int {
1594         TokenUser = 1,
1595         TokenGroups,
1596         TokenPrivileges,
1597         TokenOwner,
1598         TokenPrimaryGroup,
1599         TokenDefaultDacl,
1600         TokenSource,
1601         TokenType,
1602         TokenImpersonationLevel,
1603         TokenStatistics,
1604         TokenRestrictedSids,
1605         TokenSessionId,
1606         TokenGroupsAndPrivileges,
1607         TokenSessionReference,
1608         TokenSandBoxInert,
1609         TokenAuditPolicy,
1610         TokenOrigin,
1611         TokenElevationType,
1612         TokenLinkedToken,
1613         TokenElevation,
1614         TokenHasRestrictions,
1615         TokenAccessInformation,
1616         TokenVirtualizationAllowed,
1617         TokenVirtualizationEnabled,
1618         TokenIntegrityLevel,
1619         TokenUIAccess,
1620         TokenMandatoryPolicy,
1621         TokenLogonSid,
1622         TokenIsAppContainer,
1623         TokenCapabilities,
1624         TokenAppContainerSid,
1625         TokenAppContainerNumber,
1626         TokenUserClaimAttributes,
1627         TokenDeviceClaimAttributes,
1628         TokenRestrictedUserClaimAttributes,
1629         TokenRestrictedDeviceClaimAttributes,
1630         TokenDeviceGroups,
1631         TokenRestrictedDeviceGroups,
1632         MaxTokenInfoClass  // MaxTokenInfoClass should always be the last enum
1633     }
1634 }