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.

557 lines
14 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 "uenv.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. DebugMsg((DM_WARNING, TEXT("GetSidString: GetUserSid returned NULL")));
  40. return NULL;
  41. }
  42. //
  43. // Convert user SID to a string.
  44. //
  45. NtStatus = RtlConvertSidToUnicodeString(
  46. &UnicodeString,
  47. UserSid,
  48. (BOOLEAN)TRUE // Allocate
  49. );
  50. //
  51. // We're finished with the user sid
  52. //
  53. DeleteUserSid(UserSid);
  54. //
  55. // See if the conversion to a string worked
  56. //
  57. if (!NT_SUCCESS(NtStatus)) {
  58. DebugMsg((DM_WARNING, TEXT("GetSidString: RtlConvertSidToUnicodeString failed, status = 0x%x"),
  59. NtStatus));
  60. return NULL;
  61. }
  62. #ifdef UNICODE
  63. return(UnicodeString.Buffer);
  64. #else
  65. //
  66. // Convert the string to ansi
  67. //
  68. NtStatus = RtlUnicodeStringToAnsiString(&String, &UnicodeString, TRUE);
  69. RtlFreeUnicodeString(&UnicodeString);
  70. if (!NT_SUCCESS(NtStatus)) {
  71. DebugMsg((DM_WARNING, TEXT("GetSidString: RtlUnicodeStringToAnsiString failed, status = 0x%x"),
  72. status));
  73. return NULL;
  74. }
  75. return(String.Buffer);
  76. #endif
  77. }
  78. /***************************************************************************\
  79. * DeleteSidString
  80. *
  81. * Frees up a sid string previously returned by GetSidString()
  82. *
  83. * Returns nothing.
  84. *
  85. * History:
  86. * 26-Aug-92 Davidc Created
  87. *
  88. \***************************************************************************/
  89. VOID DeleteSidString(LPTSTR SidString)
  90. {
  91. #ifdef UNICODE
  92. UNICODE_STRING String;
  93. RtlInitUnicodeString(&String, SidString);
  94. RtlFreeUnicodeString(&String);
  95. #else
  96. ANSI_STRING String;
  97. RtlInitAnsiString(&String, SidString);
  98. RtlFreeAnsiString(&String);
  99. #endif
  100. }
  101. /***************************************************************************\
  102. * GetUserSid
  103. *
  104. * Allocs space for the user sid, fills it in and returns a pointer. Caller
  105. * The sid should be freed by calling DeleteUserSid.
  106. *
  107. * Note the sid returned is the user's real sid, not the per-logon sid.
  108. *
  109. * Returns pointer to sid or NULL on failure.
  110. *
  111. * History:
  112. * 26-Aug-92 Davidc Created.
  113. \***************************************************************************/
  114. PSID GetUserSid (HANDLE UserToken)
  115. {
  116. PTOKEN_USER pUser, pTemp;
  117. PSID pSid;
  118. DWORD BytesRequired = 200;
  119. NTSTATUS status;
  120. //
  121. // Allocate space for the user info
  122. //
  123. pUser = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, BytesRequired);
  124. if (pUser == NULL) {
  125. DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"),
  126. BytesRequired));
  127. return NULL;
  128. }
  129. //
  130. // Read in the UserInfo
  131. //
  132. status = NtQueryInformationToken(
  133. UserToken, // Handle
  134. TokenUser, // TokenInformationClass
  135. pUser, // TokenInformation
  136. BytesRequired, // TokenInformationLength
  137. &BytesRequired // ReturnLength
  138. );
  139. if (status == STATUS_BUFFER_TOO_SMALL) {
  140. //
  141. // Allocate a bigger buffer and try again.
  142. //
  143. pTemp = LocalReAlloc(pUser, BytesRequired, LMEM_MOVEABLE);
  144. if (pTemp == NULL) {
  145. DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"),
  146. BytesRequired));
  147. LocalFree (pUser);
  148. return NULL;
  149. }
  150. pUser = pTemp;
  151. status = NtQueryInformationToken(
  152. UserToken, // Handle
  153. TokenUser, // TokenInformationClass
  154. pUser, // TokenInformation
  155. BytesRequired, // TokenInformationLength
  156. &BytesRequired // ReturnLength
  157. );
  158. }
  159. if (!NT_SUCCESS(status)) {
  160. DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to query user info from user token, status = 0x%x"),
  161. status));
  162. LocalFree(pUser);
  163. return NULL;
  164. }
  165. BytesRequired = RtlLengthSid(pUser->User.Sid);
  166. pSid = LocalAlloc(LMEM_FIXED, BytesRequired);
  167. if (pSid == NULL) {
  168. DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"),
  169. BytesRequired));
  170. LocalFree(pUser);
  171. return NULL;
  172. }
  173. status = RtlCopySid(BytesRequired, pSid, pUser->User.Sid);
  174. LocalFree(pUser);
  175. if (!NT_SUCCESS(status)) {
  176. DebugMsg((DM_WARNING, TEXT("GetUserSid: RtlCopySid Failed. status = %d"),
  177. status));
  178. LocalFree(pSid);
  179. pSid = NULL;
  180. }
  181. return pSid;
  182. }
  183. /***************************************************************************\
  184. * DeleteUserSid
  185. *
  186. * Deletes a user sid previously returned by GetUserSid()
  187. *
  188. * Returns nothing.
  189. *
  190. * History:
  191. * 26-Aug-92 Davidc Created
  192. *
  193. \***************************************************************************/
  194. VOID DeleteUserSid(PSID Sid)
  195. {
  196. LocalFree(Sid);
  197. }
  198. //+--------------------------------------------------------------------------
  199. //
  200. // Function: AllocateAndInitSidFromString
  201. //
  202. // Synopsis: given the string representation of a SID, this function
  203. // allocate and initializes a SID which the string represents
  204. // For more information on the string representation of SIDs
  205. // refer to ntseapi.h & ntrtl.h
  206. //
  207. // Arguments: [in] lpszSidStr : the string representation of the SID
  208. // [out] pSID : the actual SID structure created from the string
  209. //
  210. // Returns: STATUS_SUCCESS : if the sid structure was successfully created
  211. // or an error code based on errors that might occur
  212. //
  213. // History: 10/6/1998 RahulTh created
  214. //
  215. //---------------------------------------------------------------------------
  216. NTSTATUS AllocateAndInitSidFromString (const WCHAR* lpszSidStr, PSID* ppSid)
  217. {
  218. WCHAR * pSidStr = 0;
  219. WCHAR* pString = 0;
  220. NTSTATUS Status;
  221. WCHAR* pEnd = 0;
  222. int count;
  223. BYTE SubAuthCount;
  224. DWORD SubAuths[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  225. ULONG n;
  226. SID_IDENTIFIER_AUTHORITY Auth;
  227. pSidStr = LocalAlloc(LPTR, (lstrlen (lpszSidStr) + 1)*sizeof(WCHAR));;
  228. if (!pSidStr)
  229. {
  230. Status = STATUS_NO_MEMORY;
  231. goto AllocAndInitSidFromStr_End;
  232. }
  233. lstrcpy (pSidStr, lpszSidStr);
  234. pString = pSidStr;
  235. *ppSid = NULL;
  236. count = 0;
  237. do
  238. {
  239. pString = wcschr (pString, '-');
  240. if (NULL == pString)
  241. break;
  242. count++;
  243. pString++;
  244. } while (1);
  245. SubAuthCount = (BYTE)(count - 2);
  246. if (0 > SubAuthCount || 8 < SubAuthCount)
  247. {
  248. Status = ERROR_INVALID_SID;
  249. goto AllocAndInitSidFromStr_End;
  250. }
  251. pString = wcschr (pSidStr, L'-');
  252. pString++;
  253. pString = wcschr (pString, L'-'); //ignore the revision #
  254. pString++;
  255. pEnd = wcschr (pString, L'-'); //go to the beginning of subauths.
  256. if (NULL != pEnd) *pEnd = L'\0';
  257. Status = LoadSidAuthFromString (pString, &Auth);
  258. if (STATUS_SUCCESS != Status)
  259. goto AllocAndInitSidFromStr_End;
  260. for (count = 0; count < SubAuthCount; count++)
  261. {
  262. pString = pEnd + 1;
  263. pEnd = wcschr (pString, L'-');
  264. if (pEnd)
  265. *pEnd = L'\0';
  266. Status = GetIntFromUnicodeString (pString, 10, &n);
  267. if (STATUS_SUCCESS != Status)
  268. goto AllocAndInitSidFromStr_End;
  269. SubAuths[count] = n;
  270. }
  271. Status = RtlAllocateAndInitializeSid (&Auth, SubAuthCount,
  272. SubAuths[0], SubAuths[1], SubAuths[2],
  273. SubAuths[3], SubAuths[4], SubAuths[5],
  274. SubAuths[6], SubAuths[7], ppSid);
  275. AllocAndInitSidFromStr_End:
  276. if (pSidStr)
  277. LocalFree( pSidStr );
  278. return Status;
  279. }
  280. //+--------------------------------------------------------------------------
  281. //
  282. // Function: LoadSidAuthFromString
  283. //
  284. // Synopsis: given a string representing the SID authority (as it is
  285. // normally represented in string format, fill the SID_AUTH..
  286. // structure. For more details on the format of the string
  287. // representation of the sid authority, refer to ntseapi.h and
  288. // ntrtl.h
  289. //
  290. // Arguments: [in] pString : pointer to the unicode string
  291. // [out] pSidAuth : pointer to the SID_IDENTIFIER_AUTH.. that is
  292. // desired
  293. //
  294. // Returns: STATUS_SUCCESS if it succeeds
  295. // or an error code
  296. //
  297. // History: 9/29/1998 RahulTh created
  298. //
  299. //---------------------------------------------------------------------------
  300. NTSTATUS LoadSidAuthFromString (const WCHAR* pString,
  301. PSID_IDENTIFIER_AUTHORITY pSidAuth)
  302. {
  303. size_t len;
  304. int i;
  305. NTSTATUS Status;
  306. const ULONG LowByteMask = 0xFF;
  307. ULONG n;
  308. len = lstrlenW (pString);
  309. if (len > 2 && 'x' == pString[1])
  310. {
  311. //this is in hex.
  312. //so we must have exactly 14 characters
  313. //(2 each for each of the 6 bytes) + 2 for the leading 0x
  314. if (14 != len)
  315. {
  316. Status = ERROR_INVALID_SID;
  317. goto LoadAuthEnd;
  318. }
  319. for (i=0; i < 6; i++)
  320. {
  321. pString += 2; //we need to skip the leading 0x
  322. pSidAuth->Value[i] = (UCHAR)(((pString[0] - L'0') << 4) +
  323. (pString[1] - L'0'));
  324. }
  325. }
  326. else
  327. {
  328. //this is in decimal
  329. Status = GetIntFromUnicodeString (pString, 10, &n);
  330. if (Status != STATUS_SUCCESS)
  331. goto LoadAuthEnd;
  332. pSidAuth->Value[0] = pSidAuth->Value[1] = 0;
  333. for (i = 5; i >=2; i--, n>>=8)
  334. pSidAuth->Value[i] = (UCHAR)(n & LowByteMask);
  335. }
  336. Status = STATUS_SUCCESS;
  337. LoadAuthEnd:
  338. return Status;
  339. }
  340. //+--------------------------------------------------------------------------
  341. //
  342. // Function: GetIntfromUnicodeString
  343. //
  344. // Synopsis: converts a unicode string into an integer
  345. //
  346. // Arguments: [in] szNum : the number represented as a unicode string
  347. // [in] Base : the base in which the resultant int is desired
  348. // [out] pValue : pointer to the integer representation of the
  349. // number
  350. //
  351. // Returns: STATUS_SUCCESS if successful.
  352. // or some other error code
  353. //
  354. // History: 9/29/1998 RahulTh created
  355. //
  356. //---------------------------------------------------------------------------
  357. NTSTATUS GetIntFromUnicodeString (const WCHAR* szNum, ULONG Base, PULONG pValue)
  358. {
  359. WCHAR * pwszNumStr = 0;
  360. UNICODE_STRING StringW;
  361. size_t len;
  362. NTSTATUS Status;
  363. len = lstrlen (szNum);
  364. pwszNumStr = LocalAlloc( LPTR, (len + 1) * sizeof(WCHAR));
  365. if (!pwszNumStr)
  366. {
  367. Status = STATUS_NO_MEMORY;
  368. goto GetNumEnd;
  369. }
  370. lstrcpy (pwszNumStr, szNum);
  371. StringW.Length = len * sizeof(WCHAR);
  372. StringW.MaximumLength = StringW.Length + sizeof (WCHAR);
  373. StringW.Buffer = pwszNumStr;
  374. Status = RtlUnicodeStringToInteger (&StringW, Base, pValue);
  375. GetNumEnd:
  376. if (pwszNumStr)
  377. LocalFree( pwszNumStr );
  378. return Status;
  379. }
  380. //*************************************************************
  381. //
  382. // GetDomainSidFromRid()
  383. //
  384. // Purpose: Given one domain sid, constructs another domain sid
  385. // by replacing the tail by the passed in Rid
  386. //
  387. // Parameters: pSid - Given Domain Sid
  388. // dwRid - Domain Rid
  389. // ppNewSid - Pointer to the New Sid
  390. //
  391. // Return: ERROR_SUCCESS on Success
  392. // FALSE if an error occurs
  393. //
  394. // Comments:
  395. // Sid returned must be freed using FreeSid.
  396. //
  397. // History: Date Author Comment
  398. // 6/6/95 ericflo Created
  399. //
  400. //*************************************************************
  401. NTSTATUS GetDomainSidFromDomainRid(PSID pSid, DWORD dwRid, PSID *ppNewSid)
  402. {
  403. PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority;
  404. // pointer to identifier authority
  405. BYTE nSubAuthorityCount, i; // count of subauthorities
  406. DWORD dwSubAuthority[8]={0,0,0,0,0,0,0,0}; // subauthority
  407. PUCHAR pSubAuthCount;
  408. DWORD *pdwSubAuth;
  409. NTSTATUS Status=ERROR_SUCCESS;
  410. DmAssert(IsValidSid(pSid));
  411. //
  412. // Will fail only if passed in sid is invalid and in the case
  413. // the returned value is undefined.
  414. //
  415. pIdentifierAuthority = RtlIdentifierAuthoritySid(pSid);
  416. //
  417. // get the count of subauthorities
  418. //
  419. pSubAuthCount = RtlSubAuthorityCountSid (pSid);
  420. if (!pSubAuthCount) {
  421. Status = ERROR_INVALID_SID;
  422. goto Exit;
  423. }
  424. nSubAuthorityCount = *pSubAuthCount;
  425. //
  426. // get each of the subauthorities
  427. //
  428. for (i = 0; i < (nSubAuthorityCount-1); i++) {
  429. pdwSubAuth = RtlSubAuthoritySid(pSid, i);
  430. if (!pdwSubAuth) {
  431. Status = ERROR_INVALID_SID;
  432. goto Exit;
  433. }
  434. dwSubAuthority[i] = *pdwSubAuth;
  435. }
  436. dwSubAuthority[i] = dwRid;
  437. //
  438. // Allocate a sid with these..
  439. //
  440. Status = RtlAllocateAndInitializeSid(
  441. pIdentifierAuthority,
  442. nSubAuthorityCount,
  443. dwSubAuthority[0],
  444. dwSubAuthority[1],
  445. dwSubAuthority[2],
  446. dwSubAuthority[3],
  447. dwSubAuthority[4],
  448. dwSubAuthority[5],
  449. dwSubAuthority[6],
  450. dwSubAuthority[7],
  451. ppNewSid
  452. );
  453. Exit:
  454. // Sid, All Done
  455. return Status;
  456. }