Source code of Windows XP (NT5)
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.

443 lines
11 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 "gpresult.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. SID_IDENTIFIER_AUTHORITY Auth;
  212. pSidStr = LocalAlloc(LPTR, (lstrlen (lpszSidStr) + 1)*sizeof(WCHAR));;
  213. if (!pSidStr)
  214. {
  215. Status = STATUS_NO_MEMORY;
  216. goto AllocAndInitSidFromStr_End;
  217. }
  218. lstrcpy (pSidStr, lpszSidStr);
  219. pString = pSidStr;
  220. *ppSid = NULL;
  221. count = 0;
  222. do
  223. {
  224. pString = wcschr (pString, '-');
  225. if (NULL == pString)
  226. break;
  227. count++;
  228. pString++;
  229. } while (1);
  230. SubAuthCount = (BYTE)(count - 2);
  231. if (0 > SubAuthCount || 8 < SubAuthCount)
  232. {
  233. Status = ERROR_INVALID_SID;
  234. goto AllocAndInitSidFromStr_End;
  235. }
  236. pString = wcschr (pSidStr, L'-');
  237. pString++;
  238. pString = wcschr (pString, L'-'); //ignore the revision #
  239. pString++;
  240. pEnd = wcschr (pString, L'-'); //go to the beginning of subauths.
  241. if (NULL != pEnd) *pEnd = L'\0';
  242. Status = LoadSidAuthFromString (pString, &Auth);
  243. if (STATUS_SUCCESS != Status)
  244. goto AllocAndInitSidFromStr_End;
  245. for (count = 0; count < SubAuthCount; count++)
  246. {
  247. pString = pEnd + 1;
  248. pEnd = wcschr (pString, L'-');
  249. if (pEnd)
  250. *pEnd = L'\0';
  251. Status = GetIntFromUnicodeString (pString, 10, &n);
  252. if (STATUS_SUCCESS != Status)
  253. goto AllocAndInitSidFromStr_End;
  254. SubAuths[count] = n;
  255. }
  256. Status = RtlAllocateAndInitializeSid (&Auth, SubAuthCount,
  257. SubAuths[0], SubAuths[1], SubAuths[2],
  258. SubAuths[3], SubAuths[4], SubAuths[5],
  259. SubAuths[6], SubAuths[7], ppSid);
  260. AllocAndInitSidFromStr_End:
  261. if (pSidStr)
  262. LocalFree( pSidStr );
  263. return Status;
  264. }
  265. //+--------------------------------------------------------------------------
  266. //
  267. // Function: LoadSidAuthFromString
  268. //
  269. // Synopsis: given a string representing the SID authority (as it is
  270. // normally represented in string format, fill the SID_AUTH..
  271. // structure. For more details on the format of the string
  272. // representation of the sid authority, refer to ntseapi.h and
  273. // ntrtl.h
  274. //
  275. // Arguments: [in] pString : pointer to the unicode string
  276. // [out] pSidAuth : pointer to the SID_IDENTIFIER_AUTH.. that is
  277. // desired
  278. //
  279. // Returns: STATUS_SUCCESS if it succeeds
  280. // or an error code
  281. //
  282. // History: 9/29/1998 RahulTh created
  283. //
  284. //---------------------------------------------------------------------------
  285. NTSTATUS LoadSidAuthFromString (const WCHAR* pString,
  286. PSID_IDENTIFIER_AUTHORITY pSidAuth)
  287. {
  288. size_t len;
  289. int i;
  290. NTSTATUS Status;
  291. const ULONG LowByteMask = 0xFF;
  292. ULONG n;
  293. len = lstrlenW (pString);
  294. if (len > 2 && 'x' == pString[1])
  295. {
  296. //this is in hex.
  297. //so we must have exactly 14 characters
  298. //(2 each for each of the 6 bytes) + 2 for the leading 0x
  299. if (14 != len)
  300. {
  301. Status = ERROR_INVALID_SID;
  302. goto LoadAuthEnd;
  303. }
  304. for (i=0; i < 6; i++)
  305. {
  306. pString += 2; //we need to skip the leading 0x
  307. pSidAuth->Value[i] = (UCHAR)(((pString[0] - L'0') << 4) +
  308. (pString[1] - L'0'));
  309. }
  310. }
  311. else
  312. {
  313. //this is in decimal
  314. Status = GetIntFromUnicodeString (pString, 10, &n);
  315. if (Status != STATUS_SUCCESS)
  316. goto LoadAuthEnd;
  317. pSidAuth->Value[0] = pSidAuth->Value[1] = 0;
  318. for (i = 5; i >=2; i--, n>>=8)
  319. pSidAuth->Value[i] = (UCHAR)(n & LowByteMask);
  320. }
  321. Status = STATUS_SUCCESS;
  322. LoadAuthEnd:
  323. return Status;
  324. }
  325. //+--------------------------------------------------------------------------
  326. //
  327. // Function: GetIntfromUnicodeString
  328. //
  329. // Synopsis: converts a unicode string into an integer
  330. //
  331. // Arguments: [in] szNum : the number represented as a unicode string
  332. // [in] Base : the base in which the resultant int is desired
  333. // [out] pValue : pointer to the integer representation of the
  334. // number
  335. //
  336. // Returns: STATUS_SUCCESS if successful.
  337. // or some other error code
  338. //
  339. // History: 9/29/1998 RahulTh created
  340. //
  341. //---------------------------------------------------------------------------
  342. NTSTATUS GetIntFromUnicodeString (const WCHAR* szNum, ULONG Base, PULONG pValue)
  343. {
  344. WCHAR * pwszNumStr = 0;
  345. UNICODE_STRING StringW;
  346. size_t len;
  347. NTSTATUS Status;
  348. len = lstrlen (szNum);
  349. pwszNumStr = LocalAlloc( LPTR, (len + 1) * sizeof(WCHAR));
  350. if (!pwszNumStr)
  351. {
  352. Status = STATUS_NO_MEMORY;
  353. goto GetNumEnd;
  354. }
  355. lstrcpy (pwszNumStr, szNum);
  356. StringW.Length = len * sizeof(WCHAR);
  357. StringW.MaximumLength = StringW.Length + sizeof (WCHAR);
  358. StringW.Buffer = pwszNumStr;
  359. Status = RtlUnicodeStringToInteger (&StringW, Base, pValue);
  360. GetNumEnd:
  361. if (pwszNumStr)
  362. LocalFree( pwszNumStr );
  363. return Status;
  364. }