1 using System;
2 using System.Runtime.InteropServices;
3 using System.Security.Principal;
4 using System.Text;
5
6 ///<summary>
7 /// Provides the ability to translate a <see cref="NTAccount"/> to a <see cref="SecurityIdentifier"/>
8 /// and vice versa, optionally using a remote computer for the translation process.
9 ///</summary>
10 publicclassIdentityResolver: IEquatable<IdentityReference>
11 {
12 privatestring _ComputerName;
13 privateAccountType _AccountType;
14 privateNTAccount _Account;
15 privateSecurityIdentifier _Sid;
16
17 ///<summary>
18 /// Returns the <see cref="SecurityIdentifier"/> of this instance.
19 ///</summary>
20 publicSecurityIdentifier Sid
21 {
22 get
23 {
24 if (_Sid == null) TranslateFromNTAccount();
25 return _Sid;
26 }
27 }
28 ///<summary>
29 /// Returns the <see cref="NTAccount"/> of this instance.
30 ///</summary>
31 publicNTAccount Account
32 {
33 get
34 {
35 if (_Account == null) TranslateFromSecurityDescriptor();
36 return _Account;
37 }
38 }
39
40 ///<summary>
41 /// Returns the <see cref="AccountType"/> of this instance
42 ///</summary>
43 publicAccountType AccountType
44 {
45 get {
46 if (_Sid == null) TranslateFromNTAccount();
47 elseif (_Account == null) TranslateFromSecurityDescriptor();
48
49 return _AccountType;
50 }
51 }
52
53 ///<summary>
54 /// Creates a new instance of this class. A remote computer is not used for the
55 /// translation process
56 ///</summary>
57 ///<param name="identity">The identity to translate</param>
58 public IdentityResolver(IdentityReference identity): this(identity, null) { }
59
60 ///<summary>
61 /// Creates a new instance of this class.
62 ///</summary>
63 ///<param name="identity">The identity to translate</param>
64 ///<param name="computerName">The computer to use for the translation</param>
65 ///<remarks>The remote computer is not used for translation, if
66 /// the provided identity is a <see cref="SecurityIdentifier"/> and the domain
67 /// sid of that identity equals the domain sid of the current user</remarks>
68 public IdentityResolver(IdentityReference identity, string computerName)
69 {
70 _Sid = identity asSecurityIdentifier;
71 _Account = identity asNTAccount;
72
73 if (_Sid == null || !_Sid.IsEqualDomainSid(WindowsIdentity.GetCurrent().User))
74 {
75 _ComputerName = computerName;
76 }
77
78 }
79
80 privatevoid TranslateFromNTAccount()
81 {
82 byte[] binarySid;
83 uint binarySidLength;
84 StringBuilder referencedDomain;
85 uint referencedDomainLength;
86 bool result;
87
88 binarySid = newbyte[SecurityIdentifier.MaxBinaryLength];
89 binarySidLength = (uint) binarySid.Length;
90 referencedDomain = newStringBuilder(0xff);
91 referencedDomainLength = (uint) referencedDomain.Capacity;
92
93 result = NativeMethods.LookupAccountName(_ComputerName, _Account.Value,
94 binarySid, ref binarySidLength, referencedDomain,
95 ref referencedDomainLength, out _AccountType);
96
97 if (!result) throwMarshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
98
99 _Sid = newSecurityIdentifier(binarySid, 0);
100
101 }
102
103 privatevoid TranslateFromSecurityDescriptor()
104 {
105 byte[] binarySid;
106 StringBuilder name;
107 StringBuilder domain;
108 uint nameLength;
109 uint domainLength;
110 bool result;
111
112 name = newStringBuilder(0x100);
113 domain = newStringBuilder(0xff);
114
115 nameLength = (uint) name.Capacity - 2;
116 domainLength = (uint) domain.Capacity - 2;
117
118 binarySid = newbyte[_Sid.BinaryLength];
119 _Sid.GetBinaryForm(binarySid, 0);
120
121 result = NativeMethods.LookupAccountSid(
122 _ComputerName, binarySid, name, ref nameLength, domain, ref domainLength, out _AccountType);
123
124 if (!result) throwMarshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
125
126 _Account = newNTAccount(domain.ToString(), name.ToString());
127 }
128
129 #region IEquatable<NTAccount> Members
130
131 ///<summary>
132 /// Compares this identity with the specified othe identity.
133 ///</summary>
134 ///<param name="other">The identity to compare this identity with.</param>
135 ///<returns>True, if both identities represent the same identity</returns>
136 publicbool Equals(IdentityReference other)
137 {
138 if (other == null) returnfalse;
139
140 if (other isNTAccount) return Account.Equals(other);
141 elseif (other isSecurityIdentifier) Sid.Equals((SecurityIdentifier) other);
142
143 returnfalse;
144 }
145
146 #endregion
147 }
The interesting stuff happens in the TranslateFromSecurityDescriptor and the TranslateFromNTAccount method. They prepare some buffers and call the LookupAccountSid and LookupAccountName function. On return of either these functions, the account type is stored in the _AccountType field.