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.

566 lines
15 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 "main.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 = (PTOKEN_USER)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. ULONG ulNoChars;
  227. SID_IDENTIFIER_AUTHORITY Auth;
  228. ulNoChars = lstrlen (lpszSidStr) + 1;
  229. pSidStr = (WCHAR *)LocalAlloc(LPTR, ulNoChars*sizeof(WCHAR));;
  230. if (!pSidStr)
  231. {
  232. Status = STATUS_NO_MEMORY;
  233. goto AllocAndInitSidFromStr_End;
  234. }
  235. HRESULT hr;
  236. hr = StringCchCopy (pSidStr, ulNoChars, lpszSidStr);
  237. ASSERT(SUCCEEDED(hr));
  238. pString = pSidStr;
  239. *ppSid = NULL;
  240. count = 0;
  241. do
  242. {
  243. pString = wcschr (pString, '-');
  244. if (NULL == pString)
  245. break;
  246. count++;
  247. pString++;
  248. } while (1);
  249. SubAuthCount = (BYTE)(count - 2);
  250. if (0 > SubAuthCount || 8 < SubAuthCount)
  251. {
  252. Status = ERROR_INVALID_SID;
  253. goto AllocAndInitSidFromStr_End;
  254. }
  255. pString = wcschr (pSidStr, L'-');
  256. pString++;
  257. pString = wcschr (pString, L'-'); //ignore the revision #
  258. pString++;
  259. pEnd = wcschr (pString, L'-'); //go to the beginning of subauths.
  260. if (NULL != pEnd) *pEnd = L'\0';
  261. Status = LoadSidAuthFromString (pString, &Auth);
  262. if (STATUS_SUCCESS != Status)
  263. goto AllocAndInitSidFromStr_End;
  264. for (count = 0; count < SubAuthCount; count++)
  265. {
  266. pString = pEnd + 1;
  267. pEnd = wcschr (pString, L'-');
  268. if (pEnd)
  269. *pEnd = L'\0';
  270. Status = GetIntFromUnicodeString (pString, 10, &n);
  271. if (STATUS_SUCCESS != Status)
  272. goto AllocAndInitSidFromStr_End;
  273. SubAuths[count] = n;
  274. }
  275. Status = RtlAllocateAndInitializeSid (&Auth, SubAuthCount,
  276. SubAuths[0], SubAuths[1], SubAuths[2],
  277. SubAuths[3], SubAuths[4], SubAuths[5],
  278. SubAuths[6], SubAuths[7], ppSid);
  279. AllocAndInitSidFromStr_End:
  280. if (pSidStr)
  281. LocalFree( pSidStr );
  282. return Status;
  283. }
  284. //+--------------------------------------------------------------------------
  285. //
  286. // Function: LoadSidAuthFromString
  287. //
  288. // Synopsis: given a string representing the SID authority (as it is
  289. // normally represented in string format, fill the SID_AUTH..
  290. // structure. For more details on the format of the string
  291. // representation of the sid authority, refer to ntseapi.h and
  292. // ntrtl.h
  293. //
  294. // Arguments: [in] pString : pointer to the unicode string
  295. // [out] pSidAuth : pointer to the SID_IDENTIFIER_AUTH.. that is
  296. // desired
  297. //
  298. // Returns: STATUS_SUCCESS if it succeeds
  299. // or an error code
  300. //
  301. // History: 9/29/1998 RahulTh created
  302. //
  303. //---------------------------------------------------------------------------
  304. NTSTATUS LoadSidAuthFromString (const WCHAR* pString,
  305. PSID_IDENTIFIER_AUTHORITY pSidAuth)
  306. {
  307. size_t len;
  308. int i;
  309. NTSTATUS Status;
  310. const ULONG LowByteMask = 0xFF;
  311. ULONG n;
  312. len = lstrlenW (pString);
  313. if (len > 2 && 'x' == pString[1])
  314. {
  315. //this is in hex.
  316. //so we must have exactly 14 characters
  317. //(2 each for each of the 6 bytes) + 2 for the leading 0x
  318. if (14 != len)
  319. {
  320. Status = ERROR_INVALID_SID;
  321. goto LoadAuthEnd;
  322. }
  323. for (i=0; i < 6; i++)
  324. {
  325. pString += 2; //we need to skip the leading 0x
  326. pSidAuth->Value[i] = (UCHAR)(((pString[0] - L'0') << 4) +
  327. (pString[1] - L'0'));
  328. }
  329. }
  330. else
  331. {
  332. //this is in decimal
  333. Status = GetIntFromUnicodeString (pString, 10, &n);
  334. if (Status != STATUS_SUCCESS)
  335. goto LoadAuthEnd;
  336. pSidAuth->Value[0] = pSidAuth->Value[1] = 0;
  337. for (i = 5; i >=2; i--, n>>=8)
  338. pSidAuth->Value[i] = (UCHAR)(n & LowByteMask);
  339. }
  340. Status = STATUS_SUCCESS;
  341. LoadAuthEnd:
  342. return Status;
  343. }
  344. //+--------------------------------------------------------------------------
  345. //
  346. // Function: GetIntfromUnicodeString
  347. //
  348. // Synopsis: converts a unicode string into an integer
  349. //
  350. // Arguments: [in] szNum : the number represented as a unicode string
  351. // [in] Base : the base in which the resultant int is desired
  352. // [out] pValue : pointer to the integer representation of the
  353. // number
  354. //
  355. // Returns: STATUS_SUCCESS if successful.
  356. // or some other error code
  357. //
  358. // History: 9/29/1998 RahulTh created
  359. //
  360. //---------------------------------------------------------------------------
  361. NTSTATUS GetIntFromUnicodeString (const WCHAR* szNum, ULONG Base, PULONG pValue)
  362. {
  363. WCHAR * pwszNumStr = 0;
  364. UNICODE_STRING StringW;
  365. size_t len;
  366. NTSTATUS Status;
  367. len = lstrlen (szNum);
  368. pwszNumStr = (WCHAR *)LocalAlloc( LPTR, (len + 1) * sizeof(WCHAR));
  369. if (!pwszNumStr)
  370. {
  371. Status = STATUS_NO_MEMORY;
  372. goto GetNumEnd;
  373. }
  374. HRESULT hr;
  375. hr = StringCchCopy (pwszNumStr, len+1, szNum);
  376. ASSERT(SUCCEEDED(hr));
  377. StringW.Length = len * sizeof(WCHAR);
  378. StringW.MaximumLength = StringW.Length + sizeof (WCHAR);
  379. StringW.Buffer = pwszNumStr;
  380. Status = RtlUnicodeStringToInteger (&StringW, Base, pValue);
  381. GetNumEnd:
  382. if (pwszNumStr)
  383. LocalFree( pwszNumStr );
  384. return Status;
  385. }
  386. //*************************************************************
  387. //
  388. // GetDomainSidFromRid()
  389. //
  390. // Purpose: Given one domain sid, constructs another domain sid
  391. // by replacing the tail by the passed in Rid
  392. //
  393. // Parameters: pSid - Given Domain Sid
  394. // dwRid - Domain Rid
  395. // ppNewSid - Pointer to the New Sid
  396. //
  397. // Return: ERROR_SUCCESS on Success
  398. // FALSE if an error occurs
  399. //
  400. // Comments:
  401. // Sid returned must be freed using FreeSid.
  402. //
  403. // History: Date Author Comment
  404. // 6/6/95 ericflo Created
  405. //
  406. //*************************************************************
  407. NTSTATUS GetDomainSidFromDomainRid(PSID pSid, DWORD dwRid, PSID *ppNewSid)
  408. {
  409. PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority;
  410. // pointer to identifier authority
  411. BYTE nSubAuthorityCount, i; // count of subauthorities
  412. DWORD dwSubAuthority[8]={0,0,0,0,0,0,0,0}; // subauthority
  413. PUCHAR pSubAuthCount;
  414. DWORD *pdwSubAuth;
  415. NTSTATUS Status=ERROR_SUCCESS;
  416. DmAssert(IsValidSid(pSid));
  417. //
  418. // Will fail only if passed in sid is invalid and in the case
  419. // the returned value is undefined.
  420. //
  421. pIdentifierAuthority = RtlIdentifierAuthoritySid(pSid);
  422. //
  423. // get the count of subauthorities
  424. //
  425. pSubAuthCount = RtlSubAuthorityCountSid (pSid);
  426. if (!pSubAuthCount) {
  427. Status = ERROR_INVALID_SID;
  428. goto Exit;
  429. }
  430. nSubAuthorityCount = *pSubAuthCount;
  431. //
  432. // get each of the subauthorities
  433. //
  434. for (i = 0; i < (nSubAuthorityCount-1); i++) {
  435. pdwSubAuth = RtlSubAuthoritySid(pSid, i);
  436. if (!pdwSubAuth) {
  437. Status = ERROR_INVALID_SID;
  438. goto Exit;
  439. }
  440. dwSubAuthority[i] = *pdwSubAuth;
  441. }
  442. dwSubAuthority[i] = dwRid;
  443. //
  444. // Allocate a sid with these..
  445. //
  446. Status = RtlAllocateAndInitializeSid(
  447. pIdentifierAuthority,
  448. nSubAuthorityCount,
  449. dwSubAuthority[0],
  450. dwSubAuthority[1],
  451. dwSubAuthority[2],
  452. dwSubAuthority[3],
  453. dwSubAuthority[4],
  454. dwSubAuthority[5],
  455. dwSubAuthority[6],
  456. dwSubAuthority[7],
  457. ppNewSid
  458. );
  459. Exit:
  460. // Sid, All Done
  461. return Status;
  462. }