You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

264 lines
7.1 KiB

  1. using System;
  2. using System.Security.Principal;
  3. using System.Text.RegularExpressions;
  4. namespace Security2
  5. {
  6. public class IdentityReference2
  7. {
  8. protected static Regex sidValidation = new Regex("(S-1-)[0-9-]+", RegexOptions.IgnoreCase);
  9. protected SecurityIdentifier sid;
  10. protected NTAccount ntAccount;
  11. protected string lastError;
  12. #region Properties
  13. public string Sid
  14. {
  15. get { return sid.Value; }
  16. }
  17. public string AccountName
  18. {
  19. get
  20. {
  21. return ntAccount != null ? ntAccount.Value : string.Empty;
  22. }
  23. }
  24. public string LastError
  25. {
  26. get { return lastError; }
  27. }
  28. #endregion Properties
  29. #region Constructors
  30. public IdentityReference2(IdentityReference ir)
  31. {
  32. ntAccount = ir as NTAccount;
  33. if (ntAccount != null)
  34. {
  35. //throws an IdentityNotMapped Exception if the account cannot be translated
  36. sid = (SecurityIdentifier)ntAccount.Translate(typeof(SecurityIdentifier));
  37. }
  38. else
  39. {
  40. sid = ir as SecurityIdentifier;
  41. if (sid != null)
  42. {
  43. try
  44. {
  45. ntAccount = (NTAccount)sid.Translate(typeof(NTAccount));
  46. }
  47. catch (Exception ex)
  48. {
  49. lastError = ex.Message;
  50. }
  51. }
  52. }
  53. }
  54. public IdentityReference2(string value)
  55. {
  56. if (string.IsNullOrEmpty(value))
  57. throw new ArgumentException("The value cannot be empty");
  58. var sidMatch = sidValidation.Match(value);
  59. if (!string.IsNullOrEmpty(sidMatch.Value))
  60. {
  61. //creating a SecurityIdentifier should always work if the string is in the right format
  62. try
  63. {
  64. sid = new SecurityIdentifier(sidMatch.Value);
  65. }
  66. catch (Exception ex)
  67. {
  68. throw new InvalidCastException("Could not create an IdentityReference2 with the given SID", ex);
  69. }
  70. //this is only going to work if the SID can be resolved
  71. try
  72. {
  73. ntAccount = (NTAccount)sid.Translate(typeof(NTAccount));
  74. }
  75. catch (Exception ex)
  76. {
  77. lastError = ex.Message;
  78. }
  79. }
  80. else
  81. {
  82. try
  83. {
  84. //creating an NTAccount always works, the OS does not verify the name
  85. ntAccount = new NTAccount(value);
  86. //verification si done by translating the name into a SecurityIdentifier (SID)
  87. sid = (SecurityIdentifier)ntAccount.Translate(typeof(SecurityIdentifier));
  88. }
  89. catch (IdentityNotMappedException ex)
  90. {
  91. throw ex;
  92. }
  93. }
  94. }
  95. #endregion Constructors
  96. #region Conversion
  97. //NTAccount
  98. public static explicit operator NTAccount(IdentityReference2 ir2)
  99. {
  100. return ir2.ntAccount;
  101. }
  102. public static explicit operator IdentityReference2(NTAccount ntAccount)
  103. {
  104. return new IdentityReference2(ntAccount);
  105. }
  106. //SecurityIdentifier
  107. public static explicit operator SecurityIdentifier(IdentityReference2 ir2)
  108. {
  109. return ir2.sid;
  110. }
  111. public static explicit operator IdentityReference2(SecurityIdentifier sid)
  112. {
  113. return new IdentityReference2(sid);
  114. }
  115. //IdentityReference
  116. public static implicit operator IdentityReference(IdentityReference2 ir2)
  117. {
  118. return ir2.sid;
  119. }
  120. public static implicit operator IdentityReference2(IdentityReference ir)
  121. {
  122. return new IdentityReference2(ir);
  123. }
  124. //string
  125. public static implicit operator IdentityReference2(string value)
  126. {
  127. return new IdentityReference2(value);
  128. }
  129. public static implicit operator string(IdentityReference2 ir2)
  130. {
  131. return ir2.ToString();
  132. }
  133. #endregion Conversion
  134. #region comparison
  135. public override bool Equals(object obj)
  136. {
  137. //Instance cannot be null
  138. if (ReferenceEquals(obj, null))
  139. return false;
  140. //Instances are equal
  141. if (ReferenceEquals(this, obj))
  142. return true;
  143. SecurityIdentifier sid = obj as SecurityIdentifier;
  144. if (sid != null)
  145. {
  146. return this.sid == sid;
  147. }
  148. var ntAccount = obj as NTAccount;
  149. if (ntAccount != null)
  150. {
  151. return this.ntAccount == ntAccount;
  152. }
  153. IdentityReference2 ir2 = obj as IdentityReference2;
  154. if (ir2 != null)
  155. {
  156. return this.sid == ir2.sid;
  157. }
  158. string value = obj as string;
  159. if (value != null)
  160. {
  161. if (this.sid.Value == value)
  162. {
  163. return true;
  164. }
  165. if (this.ntAccount != null)
  166. {
  167. if (this.ntAccount.Value.ToLower() == value.ToLower())
  168. {
  169. return true;
  170. }
  171. }
  172. }
  173. return false;
  174. }
  175. public override int GetHashCode()
  176. {
  177. return sid.GetHashCode();
  178. }
  179. public static bool operator ==(IdentityReference2 ir1, IdentityReference2 ir2)
  180. {
  181. //Instances are equal
  182. if (ReferenceEquals(ir1, ir2))
  183. return true;
  184. //Instance cannot be null
  185. if (ReferenceEquals(ir1, null) | ReferenceEquals(ir2, null))
  186. return false;
  187. return ir1.Equals(ir2);
  188. }
  189. public static bool operator !=(IdentityReference2 ir1, IdentityReference2 ir2)
  190. {
  191. //Instances are equal
  192. if (ReferenceEquals(ir1, ir2))
  193. return false;
  194. //Instance cannot be null
  195. if (ReferenceEquals(ir1, null) | ReferenceEquals(ir2, null))
  196. return true;
  197. return !ir1.Equals(ir2);
  198. }
  199. #endregion comparison
  200. #region Methods
  201. public byte[] GetBinaryForm()
  202. {
  203. byte[] rawSid = new byte[sid.BinaryLength];
  204. sid.GetBinaryForm(rawSid, 0);
  205. return rawSid;
  206. }
  207. public override string ToString()
  208. {
  209. if (ntAccount == null)
  210. {
  211. return sid.ToString();
  212. }
  213. else
  214. {
  215. return ntAccount.ToString();
  216. }
  217. }
  218. #endregion Methods
  219. }
  220. }