/mcs/class/corlib/System.Security.Principal/corefx/WindowsPrincipal.cs

https://github.com/madewokherd/mono · C# · 193 lines · 137 code · 28 blank · 28 comment · 25 complexity · 4df24d32c7458c7f0080cd75981911b1 MD5 · raw file

  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using Microsoft.Win32.SafeHandles;
  5. using System.Collections.Generic;
  6. using System.Globalization;
  7. using System.Runtime.InteropServices;
  8. using System.Security.Claims;
  9. namespace System.Security.Principal
  10. {
  11. public enum WindowsBuiltInRole
  12. {
  13. Administrator = 0x220,
  14. User = 0x221,
  15. Guest = 0x222,
  16. PowerUser = 0x223,
  17. AccountOperator = 0x224,
  18. SystemOperator = 0x225,
  19. PrintOperator = 0x226,
  20. BackupOperator = 0x227,
  21. Replicator = 0x228
  22. }
  23. [Serializable]
  24. public class WindowsPrincipal : ClaimsPrincipal
  25. {
  26. private WindowsIdentity _identity = null;
  27. //
  28. // Constructors.
  29. //
  30. private WindowsPrincipal() { }
  31. public WindowsPrincipal(WindowsIdentity ntIdentity)
  32. : base(ntIdentity)
  33. {
  34. if (ntIdentity == null)
  35. throw new ArgumentNullException(nameof(ntIdentity));
  36. _identity = ntIdentity;
  37. }
  38. //
  39. // Properties.
  40. //
  41. public override IIdentity Identity
  42. {
  43. get
  44. {
  45. return _identity;
  46. }
  47. }
  48. //
  49. // Public methods.
  50. //
  51. public override bool IsInRole(string role)
  52. {
  53. if (role == null || role.Length == 0)
  54. return false;
  55. NTAccount ntAccount = new NTAccount(role);
  56. IdentityReferenceCollection source = new IdentityReferenceCollection(1);
  57. source.Add(ntAccount);
  58. IdentityReferenceCollection target = NTAccount.Translate(source, typeof(SecurityIdentifier), false);
  59. SecurityIdentifier sid = target[0] as SecurityIdentifier;
  60. if (sid != null)
  61. {
  62. if (IsInRole(sid))
  63. {
  64. return true;
  65. }
  66. }
  67. // possible that identity has other role claims that match
  68. return base.IsInRole(role);
  69. }
  70. // <summary
  71. // Returns all of the claims from all of the identities that are windows user claims
  72. // found in the NT token.
  73. // </summary>
  74. public virtual IEnumerable<Claim> UserClaims
  75. {
  76. get
  77. {
  78. foreach (ClaimsIdentity identity in Identities)
  79. {
  80. WindowsIdentity wi = identity as WindowsIdentity;
  81. if (wi != null)
  82. {
  83. foreach (Claim claim in wi.UserClaims)
  84. {
  85. yield return claim;
  86. }
  87. }
  88. }
  89. }
  90. }
  91. // <summary
  92. // Returns all of the claims from all of the identities that are windows device claims
  93. // found in the NT token.
  94. // </summary>
  95. public virtual IEnumerable<Claim> DeviceClaims
  96. {
  97. get
  98. {
  99. foreach (ClaimsIdentity identity in Identities)
  100. {
  101. WindowsIdentity wi = identity as WindowsIdentity;
  102. if (wi != null)
  103. {
  104. foreach (Claim claim in wi.DeviceClaims)
  105. {
  106. yield return claim;
  107. }
  108. }
  109. }
  110. }
  111. }
  112. public virtual bool IsInRole(WindowsBuiltInRole role)
  113. {
  114. if (role < WindowsBuiltInRole.Administrator || role > WindowsBuiltInRole.Replicator)
  115. throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)role), nameof(role));
  116. return IsInRole((int)role);
  117. }
  118. public virtual bool IsInRole(int rid)
  119. {
  120. SecurityIdentifier sid = new SecurityIdentifier(IdentifierAuthority.NTAuthority,
  121. new int[] { Interop.SecurityIdentifier.SECURITY_BUILTIN_DOMAIN_RID, rid });
  122. return IsInRole(sid);
  123. }
  124. // This method (with a SID parameter) is more general than the 2 overloads that accept a WindowsBuiltInRole or
  125. // a rid (as an int). It is also better from a performance standpoint than the overload that accepts a string.
  126. // The aformentioned overloads remain in this class since we do not want to introduce a
  127. // breaking change. However, this method should be used in all new applications.
  128. public virtual bool IsInRole(SecurityIdentifier sid)
  129. {
  130. if (sid == null)
  131. throw new ArgumentNullException(nameof(sid));
  132. // special case the anonymous identity.
  133. if (_identity.AccessToken.IsInvalid)
  134. return false;
  135. // CheckTokenMembership expects an impersonation token
  136. SafeAccessTokenHandle token = SafeAccessTokenHandle.InvalidHandle;
  137. if (_identity.ImpersonationLevel == TokenImpersonationLevel.None)
  138. {
  139. if (!Interop.Advapi32.DuplicateTokenEx(_identity.AccessToken,
  140. (uint)TokenAccessLevels.Query,
  141. IntPtr.Zero,
  142. (uint)TokenImpersonationLevel.Identification,
  143. (uint)TokenType.TokenImpersonation,
  144. ref token))
  145. throw new SecurityException(string.Format(CultureInfo.InvariantCulture, "DuplicateTokenEx returned error {0}", Marshal.GetLastWin32Error()));
  146. }
  147. bool isMember = false;
  148. // CheckTokenMembership will check if the SID is both present and enabled in the access token.
  149. #if uap
  150. if (!Interop.Kernel32.CheckTokenMembershipEx((_identity.ImpersonationLevel != TokenImpersonationLevel.None ? _identity.AccessToken : token),
  151. sid.BinaryForm,
  152. Interop.Kernel32.CTMF_INCLUDE_APPCONTAINER,
  153. ref isMember))
  154. throw new SecurityException(new Win32Exception().Message);
  155. #else
  156. if (!Interop.Advapi32.CheckTokenMembership((_identity.ImpersonationLevel != TokenImpersonationLevel.None ? _identity.AccessToken : token),
  157. sid.BinaryForm,
  158. ref isMember))
  159. throw new SecurityException(string.Format(CultureInfo.InvariantCulture, "CheckTokenMembership returned error {0}", Marshal.GetLastWin32Error()));
  160. #endif
  161. token.Dispose();
  162. return isMember;
  163. }
  164. }
  165. }