Leaked source code of windows server 2003
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.

450 lines
12 KiB

  1. //*************************************************************
  2. //
  3. // SID management functions.
  4. //
  5. // THESE FUNCTIONS ARE WINDOWS NT SPECIFIC!!!!!
  6. //
  7. // Microsoft Confidential
  8. // Copyright (c) Microsoft Corporation 1995
  9. // All rights reserved
  10. //
  11. //*************************************************************
  12. #include "refgp.h"
  13. /***************************************************************************\
  14. * GetSidString
  15. *
  16. * Allocates and returns a string representing the sid of the current user
  17. * The returned pointer should be freed using DeleteSidString().
  18. *
  19. * Returns a pointer to the string or NULL on failure.
  20. *
  21. * History:
  22. * 26-Aug-92 Davidc Created
  23. *
  24. \***************************************************************************/
  25. LPTSTR GetSidString(HANDLE UserToken)
  26. {
  27. NTSTATUS NtStatus;
  28. PSID UserSid;
  29. UNICODE_STRING UnicodeString;
  30. LPTSTR lpEnd;
  31. #ifndef UNICODE
  32. STRING String;
  33. #endif
  34. //
  35. // Get the user sid
  36. //
  37. UserSid = GetUserSid(UserToken);
  38. if (UserSid == NULL) {
  39. return NULL;
  40. }
  41. //
  42. // Convert user SID to a string.
  43. //
  44. NtStatus = RtlConvertSidToUnicodeString(
  45. &UnicodeString,
  46. UserSid,
  47. (BOOLEAN)TRUE // Allocate
  48. );
  49. //
  50. // We're finished with the user sid
  51. //
  52. DeleteUserSid(UserSid);
  53. //
  54. // See if the conversion to a string worked
  55. //
  56. if (!NT_SUCCESS(NtStatus)) {
  57. return NULL;
  58. }
  59. #ifdef UNICODE
  60. return(UnicodeString.Buffer);
  61. #else
  62. //
  63. // Convert the string to ansi
  64. //
  65. NtStatus = RtlUnicodeStringToAnsiString(&String, &UnicodeString, TRUE);
  66. RtlFreeUnicodeString(&UnicodeString);
  67. if (!NT_SUCCESS(NtStatus)) {
  68. return NULL;
  69. }
  70. return(String.Buffer);
  71. #endif
  72. }
  73. /***************************************************************************\
  74. * DeleteSidString
  75. *
  76. * Frees up a sid string previously returned by GetSidString()
  77. *
  78. * Returns nothing.
  79. *
  80. * History:
  81. * 26-Aug-92 Davidc Created
  82. *
  83. \***************************************************************************/
  84. VOID DeleteSidString(LPTSTR SidString)
  85. {
  86. #ifdef UNICODE
  87. UNICODE_STRING String;
  88. RtlInitUnicodeString(&String, SidString);
  89. RtlFreeUnicodeString(&String);
  90. #else
  91. ANSI_STRING String;
  92. RtlInitAnsiString(&String, SidString);
  93. RtlFreeAnsiString(&String);
  94. #endif
  95. }
  96. /***************************************************************************\
  97. * GetUserSid
  98. *
  99. * Allocs space for the user sid, fills it in and returns a pointer. Caller
  100. * The sid should be freed by calling DeleteUserSid.
  101. *
  102. * Note the sid returned is the user's real sid, not the per-logon sid.
  103. *
  104. * Returns pointer to sid or NULL on failure.
  105. *
  106. * History:
  107. * 26-Aug-92 Davidc Created.
  108. \***************************************************************************/
  109. PSID GetUserSid (HANDLE UserToken)
  110. {
  111. PTOKEN_USER pUser, pTemp;
  112. PSID pSid;
  113. DWORD BytesRequired = 200;
  114. NTSTATUS status;
  115. //
  116. // Allocate space for the user info
  117. //
  118. pUser = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, BytesRequired);
  119. if (pUser == NULL) {
  120. return NULL;
  121. }
  122. //
  123. // Read in the UserInfo
  124. //
  125. status = NtQueryInformationToken(
  126. UserToken, // Handle
  127. TokenUser, // TokenInformationClass
  128. pUser, // TokenInformation
  129. BytesRequired, // TokenInformationLength
  130. &BytesRequired // ReturnLength
  131. );
  132. if (status == STATUS_BUFFER_TOO_SMALL) {
  133. //
  134. // Allocate a bigger buffer and try again.
  135. //
  136. pTemp = LocalReAlloc(pUser, BytesRequired, LMEM_MOVEABLE);
  137. if (pTemp == NULL) {
  138. LocalFree (pUser);
  139. return NULL;
  140. }
  141. pUser = pTemp;
  142. status = NtQueryInformationToken(
  143. UserToken, // Handle
  144. TokenUser, // TokenInformationClass
  145. pUser, // TokenInformation
  146. BytesRequired, // TokenInformationLength
  147. &BytesRequired // ReturnLength
  148. );
  149. }
  150. if (!NT_SUCCESS(status)) {
  151. LocalFree(pUser);
  152. return NULL;
  153. }
  154. BytesRequired = RtlLengthSid(pUser->User.Sid);
  155. pSid = LocalAlloc(LMEM_FIXED, BytesRequired);
  156. if (pSid == NULL) {
  157. LocalFree(pUser);
  158. return NULL;
  159. }
  160. status = RtlCopySid(BytesRequired, pSid, pUser->User.Sid);
  161. LocalFree(pUser);
  162. if (!NT_SUCCESS(status)) {
  163. LocalFree(pSid);
  164. pSid = NULL;
  165. }
  166. return pSid;
  167. }
  168. /***************************************************************************\
  169. * DeleteUserSid
  170. *
  171. * Deletes a user sid previously returned by GetUserSid()
  172. *
  173. * Returns nothing.
  174. *
  175. * History:
  176. * 26-Aug-92 Davidc Created
  177. *
  178. \***************************************************************************/
  179. VOID DeleteUserSid(PSID Sid)
  180. {
  181. LocalFree(Sid);
  182. }
  183. //+--------------------------------------------------------------------------
  184. //
  185. // Function: AllocateAndInitSidFromString
  186. //
  187. // Synopsis: given the string representation of a SID, this function
  188. // allocate and initializes a SID which the string represents
  189. // For more information on the string representation of SIDs
  190. // refer to ntseapi.h & ntrtl.h
  191. //
  192. // Arguments: [in] lpszSidStr : the string representation of the SID
  193. // [out] pSID : the actual SID structure created from the string
  194. //
  195. // Returns: STATUS_SUCCESS : if the sid structure was successfully created
  196. // or an error code based on errors that might occur
  197. //
  198. // History: 10/6/1998 RahulTh created
  199. //
  200. //---------------------------------------------------------------------------
  201. NTSTATUS AllocateAndInitSidFromString (const WCHAR* lpszSidStr, PSID* ppSid)
  202. {
  203. WCHAR * pSidStr = 0;
  204. WCHAR* pString = 0;
  205. NTSTATUS Status;
  206. WCHAR* pEnd = 0;
  207. int count;
  208. BYTE SubAuthCount;
  209. DWORD SubAuths[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  210. ULONG n;
  211. HRESULT hr;
  212. SID_IDENTIFIER_AUTHORITY Auth;
  213. ULONG ulNoChars = lstrlen (lpszSidStr) + 1;
  214. pSidStr = LocalAlloc(LPTR, ulNoChars*sizeof(WCHAR));;
  215. if (!pSidStr)
  216. {
  217. Status = STATUS_NO_MEMORY;
  218. goto AllocAndInitSidFromStr_End;
  219. }
  220. hr = StringCchCopy (pSidStr, ulNoChars, lpszSidStr);
  221. ASSERT(SUCCEEDED(hr));
  222. pString = pSidStr;
  223. *ppSid = NULL;
  224. count = 0;
  225. do
  226. {
  227. pString = wcschr (pString, '-');
  228. if (NULL == pString)
  229. break;
  230. count++;
  231. pString++;
  232. } while (1);
  233. SubAuthCount = (BYTE)(count - 2);
  234. if (0 > SubAuthCount || 8 < SubAuthCount)
  235. {
  236. Status = ERROR_INVALID_SID;
  237. goto AllocAndInitSidFromStr_End;
  238. }
  239. pString = wcschr (pSidStr, L'-');
  240. pString++;
  241. pString = wcschr (pString, L'-'); //ignore the revision #
  242. pString++;
  243. pEnd = wcschr (pString, L'-'); //go to the beginning of subauths.
  244. if (NULL != pEnd) *pEnd = L'\0';
  245. Status = LoadSidAuthFromString (pString, &Auth);
  246. if (STATUS_SUCCESS != Status)
  247. goto AllocAndInitSidFromStr_End;
  248. for (count = 0; count < SubAuthCount; count++)
  249. {
  250. pString = pEnd + 1;
  251. pEnd = wcschr (pString, L'-');
  252. if (pEnd)
  253. *pEnd = L'\0';
  254. Status = GetIntFromUnicodeString (pString, 10, &n);
  255. if (STATUS_SUCCESS != Status)
  256. goto AllocAndInitSidFromStr_End;
  257. SubAuths[count] = n;
  258. }
  259. Status = RtlAllocateAndInitializeSid (&Auth, SubAuthCount,
  260. SubAuths[0], SubAuths[1], SubAuths[2],
  261. SubAuths[3], SubAuths[4], SubAuths[5],
  262. SubAuths[6], SubAuths[7], ppSid);
  263. AllocAndInitSidFromStr_End:
  264. if (pSidStr)
  265. LocalFree( pSidStr );
  266. return Status;
  267. }
  268. //+--------------------------------------------------------------------------
  269. //
  270. // Function: LoadSidAuthFromString
  271. //
  272. // Synopsis: given a string representing the SID authority (as it is
  273. // normally represented in string format, fill the SID_AUTH..
  274. // structure. For more details on the format of the string
  275. // representation of the sid authority, refer to ntseapi.h and
  276. // ntrtl.h
  277. //
  278. // Arguments: [in] pString : pointer to the unicode string
  279. // [out] pSidAuth : pointer to the SID_IDENTIFIER_AUTH.. that is
  280. // desired
  281. //
  282. // Returns: STATUS_SUCCESS if it succeeds
  283. // or an error code
  284. //
  285. // History: 9/29/1998 RahulTh created
  286. //
  287. //---------------------------------------------------------------------------
  288. NTSTATUS LoadSidAuthFromString (const WCHAR* pString,
  289. PSID_IDENTIFIER_AUTHORITY pSidAuth)
  290. {
  291. size_t len;
  292. int i;
  293. NTSTATUS Status;
  294. const ULONG LowByteMask = 0xFF;
  295. ULONG n;
  296. len = lstrlenW (pString);
  297. if (len > 2 && 'x' == pString[1])
  298. {
  299. //this is in hex.
  300. //so we must have exactly 14 characters
  301. //(2 each for each of the 6 bytes) + 2 for the leading 0x
  302. if (14 != len)
  303. {
  304. Status = ERROR_INVALID_SID;
  305. goto LoadAuthEnd;
  306. }
  307. for (i=0; i < 6; i++)
  308. {
  309. pString += 2; //we need to skip the leading 0x
  310. pSidAuth->Value[i] = (UCHAR)(((pString[0] - L'0') << 4) +
  311. (pString[1] - L'0'));
  312. }
  313. }
  314. else
  315. {
  316. //this is in decimal
  317. Status = GetIntFromUnicodeString (pString, 10, &n);
  318. if (Status != STATUS_SUCCESS)
  319. goto LoadAuthEnd;
  320. pSidAuth->Value[0] = pSidAuth->Value[1] = 0;
  321. for (i = 5; i >=2; i--, n>>=8)
  322. pSidAuth->Value[i] = (UCHAR)(n & LowByteMask);
  323. }
  324. Status = STATUS_SUCCESS;
  325. LoadAuthEnd:
  326. return Status;
  327. }
  328. //+--------------------------------------------------------------------------
  329. //
  330. // Function: GetIntfromUnicodeString
  331. //
  332. // Synopsis: converts a unicode string into an integer
  333. //
  334. // Arguments: [in] szNum : the number represented as a unicode string
  335. // [in] Base : the base in which the resultant int is desired
  336. // [out] pValue : pointer to the integer representation of the
  337. // number
  338. //
  339. // Returns: STATUS_SUCCESS if successful.
  340. // or some other error code
  341. //
  342. // History: 9/29/1998 RahulTh created
  343. //
  344. //---------------------------------------------------------------------------
  345. NTSTATUS GetIntFromUnicodeString (const WCHAR* szNum, ULONG Base, PULONG pValue)
  346. {
  347. WCHAR * pwszNumStr = 0;
  348. UNICODE_STRING StringW;
  349. size_t len;
  350. NTSTATUS Status;
  351. HRESULT hr;
  352. len = lstrlen (szNum);
  353. pwszNumStr = LocalAlloc( LPTR, (len + 1) * sizeof(WCHAR));
  354. if (!pwszNumStr)
  355. {
  356. Status = STATUS_NO_MEMORY;
  357. goto GetNumEnd;
  358. }
  359. hr = StringCchCopy (pwszNumStr, len+1, szNum);
  360. ASSERT(SUCCEEDED(hr));
  361. StringW.Length = len * sizeof(WCHAR);
  362. StringW.MaximumLength = StringW.Length + sizeof (WCHAR);
  363. StringW.Buffer = pwszNumStr;
  364. Status = RtlUnicodeStringToInteger (&StringW, Base, pValue);
  365. GetNumEnd:
  366. if (pwszNumStr)
  367. LocalFree( pwszNumStr );
  368. return Status;
  369. }