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.

502 lines
15 KiB

  1. /*---------------------------------------------------------------------------
  2. File: TextualSid.cpp
  3. Comments: Converts a SID to and from its canonical textual representation.
  4. (c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
  5. Proprietary and confidential to Mission Critical Software, Inc.
  6. REVISION LOG ENTRY
  7. Revision By: Christy Boles
  8. Revised on 02/15/99 11:33:52
  9. ---------------------------------------------------------------------------
  10. */
  11. #ifdef USE_STDAFX
  12. #include "stdafx.h"
  13. #else
  14. #include <windows.h>
  15. #include <malloc.h>
  16. #include <stdio.h>
  17. #endif
  18. #include "Mcs.h"
  19. #include "TxtSid.h"
  20. #ifndef SECURITY_MAX_SID_SIZE
  21. #define SECURITY_MAX_SID_SIZE (sizeof(SID) - sizeof(DWORD) + (SID_MAX_SUB_AUTHORITIES * sizeof(DWORD)))
  22. #endif
  23. BOOL
  24. GetTextualSid(
  25. PSID pSid, // in - binary Sid
  26. LPTSTR TextualSid, // i/o- buffer for Textual representation of Sid
  27. LPDWORD lpdwBufferLen // in - required/provided TextualSid buffersize
  28. )
  29. {
  30. PSID_IDENTIFIER_AUTHORITY psia;
  31. DWORD dwSubAuthorities;
  32. DWORD dwSidRev=SID_REVISION;
  33. DWORD dwCounter;
  34. DWORD dwSidSize;
  35. // Validate the binary SID.
  36. if(!IsValidSid(pSid))
  37. {
  38. SetLastError(ERROR_INVALID_SID);
  39. return FALSE;
  40. }
  41. // Get the identifier authority value from the SID.
  42. psia = GetSidIdentifierAuthority(pSid);
  43. // Get the number of subauthorities in the SID.
  44. dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
  45. // Compute the buffer length.
  46. // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
  47. dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
  48. // Check input buffer length.
  49. // If too small, indicate the proper size and set last error.
  50. if (*lpdwBufferLen < dwSidSize)
  51. {
  52. *lpdwBufferLen = dwSidSize;
  53. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  54. return FALSE;
  55. }
  56. // Add 'S' prefix and revision number to the string.
  57. dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
  58. // Add SID identifier authority to the string.
  59. if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
  60. {
  61. dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
  62. TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
  63. (USHORT)psia->Value[0],
  64. (USHORT)psia->Value[1],
  65. (USHORT)psia->Value[2],
  66. (USHORT)psia->Value[3],
  67. (USHORT)psia->Value[4],
  68. (USHORT)psia->Value[5]);
  69. }
  70. else
  71. {
  72. dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
  73. TEXT("%lu"),
  74. (ULONG)(psia->Value[5] ) +
  75. (ULONG)(psia->Value[4] << 8) +
  76. (ULONG)(psia->Value[3] << 16) +
  77. (ULONG)(psia->Value[2] << 24) );
  78. }
  79. // Add SID subauthorities to the string. //
  80. for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
  81. {
  82. dwSidSize+=wsprintf(TextualSid + dwSidSize, TEXT("-%lu"),
  83. *GetSidSubAuthority(pSid, dwCounter) );
  84. }
  85. return TRUE;
  86. }
  87. PSID // ret- binary representation of SID, or NULL caller must free using FreeSid()
  88. SidFromString(
  89. WCHAR const * strSid // in - string representation of SID
  90. )
  91. {
  92. BOOL bSuccess = TRUE;
  93. PSID pSid = NULL;
  94. DWORD dwSidRev;
  95. // WCHAR * strPtr = NULL;
  96. WCHAR sidIA[100];
  97. WCHAR sidSubs[100];
  98. int ia0,ia1,ia2,ia3,ia4,ia5;
  99. SID_IDENTIFIER_AUTHORITY sia;
  100. do
  101. {
  102. if ( strSid[0] != L'S' || strSid[1] != L'-' )
  103. {
  104. bSuccess = FALSE;
  105. break;
  106. }
  107. // Read SID revision level
  108. sidSubs[0] = 0;
  109. int result = swscanf(strSid,L"S-%d-%[^-]-%ls",&dwSidRev,sidIA,sidSubs);
  110. if ( result == 3 )
  111. {
  112. // evaluate the IA
  113. if ( sidIA[1] == L'x' )
  114. {
  115. // full format
  116. result = swscanf(sidIA,L"0x%02hx%02hx%02hx%02hx%02hx%02hx",&ia0,&ia1,&ia2,&ia3,&ia4,&ia5);
  117. if ( result == 6 )
  118. {
  119. sia.Value[0] = (BYTE) ia0;
  120. sia.Value[1] = (BYTE) ia1;
  121. sia.Value[2] = (BYTE) ia2;
  122. sia.Value[3] = (BYTE) ia3;
  123. sia.Value[4] = (BYTE) ia4;
  124. sia.Value[5] = (BYTE) ia5;
  125. }
  126. else
  127. {
  128. bSuccess = FALSE;
  129. break;
  130. }
  131. }
  132. else
  133. {
  134. DWORD bignumber;
  135. result = swscanf(sidIA,L"%lu",&bignumber);
  136. sia.Value[0] = 0;
  137. sia.Value[1] = 0;
  138. sia.Value[2] = BYTE( (bignumber & 0xff000000) >> 24);
  139. sia.Value[3] = BYTE( (bignumber & 0x00ff0000) >> 16);
  140. sia.Value[4] = BYTE( (bignumber & 0x0000ff00) >> 8);
  141. sia.Value[5] = BYTE(bignumber & 0x000000ff);
  142. }
  143. // read the subauthorities
  144. DWORD subs[10];
  145. memset(subs,0,(sizeof subs));
  146. result = swscanf(sidSubs,L"%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu",&subs[0],&subs[1],&subs[2],&subs[3],&subs[4],
  147. &subs[5],&subs[6],&subs[7]);
  148. if ( result )
  149. {
  150. if ( !AllocateAndInitializeSid(&sia,(BYTE)result,subs[0],subs[1],subs[2],subs[3],subs[4],subs[5],subs[6],subs[7],&pSid) )
  151. {
  152. pSid = NULL;
  153. bSuccess = FALSE;
  154. }
  155. }
  156. }
  157. } while ( false);
  158. //see if IsValidSid also thinks this is valid
  159. if (pSid)
  160. {
  161. //if not valid, free it and return NULL
  162. if (!IsValidSid(pSid))
  163. {
  164. FreeSid(pSid);
  165. pSid = NULL;
  166. }
  167. }
  168. return pSid;
  169. }
  170. /*****************************************************************************************************/
  171. /* DomainizeSid:
  172. Takes a domain sid, and verifies that its last subauthority value is -1. If the RID is not
  173. -1, DomainizeSid adds a -1 to the end.
  174. /*****************************************************************************************************/
  175. PSID // ret -the sid with RID = -1
  176. DomainizeSid(
  177. PSID psid, // in -sid to check and possibly fix
  178. BOOL freeOldSid // in -whether to free the old sid
  179. )
  180. {
  181. MCSASSERT(psid);
  182. UCHAR len = (* GetSidSubAuthorityCount(psid));
  183. PDWORD sub = GetSidSubAuthority(psid,len-1);
  184. if ( *sub != -1 )
  185. {
  186. DWORD sdsize = GetSidLengthRequired(len+1); // sid doesn't already have -1 as rid
  187. PSID newsid = (SID *)malloc(sdsize); // copy the sid, and add -1 to the end
  188. if (newsid)
  189. {
  190. if ( ! InitializeSid(newsid,GetSidIdentifierAuthority(psid),len+1) ) // make a bigger sid w/same IA
  191. {
  192. MCSASSERT(false);
  193. }
  194. for ( DWORD i = 0 ; i < len ; i++ )
  195. {
  196. sub = GetSidSubAuthority(newsid,i); // copy subauthorities
  197. (*sub) = (*GetSidSubAuthority(psid,i));
  198. }
  199. sub = GetSidSubAuthority(newsid,len);
  200. *sub = -1; // set rid =-1
  201. if ( freeOldSid )
  202. {
  203. FreeSid(psid);
  204. }
  205. psid = newsid;
  206. len++;
  207. }
  208. else
  209. {
  210. return NULL;
  211. }
  212. }
  213. return psid;
  214. }
  215. /*********************************************************************
  216. * *
  217. * Written by: Paul Thompson *
  218. * Date: 4 OCT 2000 *
  219. * *
  220. * This function is responsible for taking the given source and *
  221. * target account SIDs and breaking them up and returning the src *
  222. * domain sid, src account rid, tgt domain sid, and tgt account rid. *
  223. * The caller must call "FreeSid" on the src and tgt domain sid *
  224. * pointers. *
  225. * *
  226. *********************************************************************/
  227. //BEGIN SplitAccountSids
  228. BOOL // ret - Success ? TRUE | FALSE
  229. SplitAccountSids(
  230. PSID srcSid, // in - src account sid
  231. WCHAR *srcDomainSid, // out - src domain sid textual
  232. DWORD *srcRid, // out - src account rid
  233. PSID tgtSid, // in - tgt account sid
  234. WCHAR *tgtDomainSid, // out - tgt domain sid textual
  235. DWORD *tgtRid // out - tgt account rid
  236. )
  237. {
  238. /* local variables */
  239. DWORD sidLen;
  240. UCHAR Count;
  241. PDWORD psubAuth;
  242. BOOL bSuccess = TRUE;
  243. DWORD lenTxt = MAX_PATH;
  244. /* function body */
  245. if ((!IsValidSid(srcSid)) && (!IsValidSid(tgtSid)))
  246. return FALSE;
  247. //split up the src account sid
  248. sidLen = GetLengthSid(srcSid);
  249. PSID srcDomSid = new BYTE[sidLen+1];
  250. if (!srcDomSid)
  251. return FALSE;
  252. if (!CopySid(sidLen+1, srcDomSid, srcSid))
  253. {
  254. delete [] srcDomSid;
  255. return FALSE;
  256. }
  257. //get the RID out of the SID and get the domain SID
  258. Count = (* GetSidSubAuthorityCount(srcDomSid));
  259. psubAuth = GetSidSubAuthority(srcDomSid, Count-1);
  260. if (psubAuth)
  261. {
  262. *srcRid = *psubAuth;
  263. *psubAuth = -1;
  264. }
  265. //convert domain sid to text format
  266. if (srcDomSid)
  267. {
  268. if (!GetTextualSid(srcDomSid,srcDomainSid,&lenTxt)) {
  269. delete [] srcDomSid;
  270. return FALSE;
  271. }
  272. delete [] srcDomSid;
  273. }
  274. //split up the tgt account sid
  275. sidLen = GetLengthSid(tgtSid);
  276. PSID tgtDomSid = new BYTE[sidLen+1];
  277. if (!tgtDomSid)
  278. return FALSE;
  279. if (!CopySid(sidLen+1, tgtDomSid, tgtSid))
  280. {
  281. delete [] tgtDomSid;
  282. return FALSE;
  283. }
  284. //get the RID out of the SID and get the domain SID
  285. Count = (* GetSidSubAuthorityCount(tgtDomSid));
  286. psubAuth = GetSidSubAuthority(tgtDomSid, Count-1);
  287. if (psubAuth)
  288. {
  289. *tgtRid = *psubAuth;
  290. *psubAuth = -1;
  291. }
  292. //convert domain sid to text format
  293. lenTxt = MAX_PATH;
  294. if (tgtDomSid)
  295. {
  296. if (!GetTextualSid(tgtDomSid,tgtDomainSid,&lenTxt)) {
  297. delete [] tgtDomSid;
  298. return FALSE;
  299. }
  300. delete [] tgtDomSid;
  301. }
  302. return bSuccess;
  303. }
  304. //END SplitAccountSids
  305. PSID // ret- binary representation of SID, or NULL caller must free using free()
  306. MallocedSidFromString(
  307. WCHAR const * strSid // in - string representation of SID
  308. )
  309. {
  310. /* local constants */
  311. const BYTE NUM_OF_SUBAUTHS = 8;
  312. /* local variables */
  313. BOOL bSuccess = TRUE;
  314. PSID pSid = (SID *)malloc(SECURITY_MAX_SID_SIZE); // create a new sid
  315. DWORD dwSidRev;
  316. WCHAR sidIA[100];
  317. WCHAR sidSubs[100];
  318. int ia0,ia1,ia2,ia3,ia4,ia5;
  319. SID_IDENTIFIER_AUTHORITY sia;
  320. /* function body */
  321. if (!pSid)
  322. return pSid;
  323. do
  324. {
  325. if ( strSid[0] != L'S' || strSid[1] != L'-' )
  326. {
  327. bSuccess = FALSE;
  328. break;
  329. }
  330. // Read SID revision level
  331. sidSubs[0] = 0;
  332. int result = swscanf(strSid,L"S-%d-%[^-]-%ls",&dwSidRev,sidIA,sidSubs);
  333. if ( result == 3 )
  334. {
  335. // evaluate the IA
  336. if ( sidIA[1] == L'x' )
  337. {
  338. // full format
  339. result = swscanf(sidIA,L"0x%02hx%02hx%02hx%02hx%02hx%02hx",&ia0,&ia1,&ia2,&ia3,&ia4,&ia5);
  340. if ( result == 6 )
  341. {
  342. sia.Value[0] = (BYTE) ia0;
  343. sia.Value[1] = (BYTE) ia1;
  344. sia.Value[2] = (BYTE) ia2;
  345. sia.Value[3] = (BYTE) ia3;
  346. sia.Value[4] = (BYTE) ia4;
  347. sia.Value[5] = (BYTE) ia5;
  348. }
  349. else
  350. {
  351. bSuccess = FALSE;
  352. break;
  353. }
  354. }
  355. else
  356. {
  357. DWORD bignumber;
  358. result = swscanf(sidIA,L"%lu",&bignumber);
  359. sia.Value[0] = 0;
  360. sia.Value[1] = 0;
  361. sia.Value[2] = BYTE( (bignumber & 0xff000000) >> 24);
  362. sia.Value[3] = BYTE( (bignumber & 0x00ff0000) >> 16);
  363. sia.Value[4] = BYTE( (bignumber & 0x0000ff00) >> 8);
  364. sia.Value[5] = BYTE(bignumber & 0x000000ff);
  365. }
  366. // read the subauthorities
  367. DWORD subs[10];
  368. memset(subs,0,(sizeof subs));
  369. result = swscanf(sidSubs,L"%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu",&subs[0],&subs[1],&subs[2],&subs[3],&subs[4],
  370. &subs[5],&subs[6],&subs[7]);
  371. if ( result )
  372. {
  373. //initialize the new SID (result ids the number of sub authorities)
  374. if (!InitializeSid(pSid, &sia, (BYTE)result))
  375. {
  376. bSuccess = FALSE;
  377. break;
  378. }
  379. //add the sub authorities
  380. PDWORD sub;
  381. for (int ndx = 0; ndx < result; ndx++)
  382. {
  383. sub = GetSidSubAuthority(pSid, ndx);
  384. *sub = subs[ndx];
  385. }
  386. }
  387. }
  388. else
  389. {
  390. bSuccess = FALSE;
  391. break;
  392. }
  393. } while (FALSE);
  394. //if we failed above, free the sid
  395. if (!bSuccess)
  396. {
  397. free(pSid);
  398. pSid = NULL;
  399. }
  400. //see if IsValidSid also thinks this is valid
  401. if (pSid)
  402. {
  403. //if not valid, free it and return NULL
  404. if (!IsValidSid(pSid))
  405. {
  406. free(pSid);
  407. pSid = NULL;
  408. }
  409. }
  410. return pSid;
  411. }
  412. //---------------------------------------------------------------------------
  413. // SafeCopySid Function
  414. //
  415. // Synopsis
  416. // Creates a copy of the given SID if the given SID is valid.
  417. //
  418. // Arguments
  419. // IN pSidOld - the SID which is to be copied
  420. //
  421. // Return
  422. // A new SID which is a copy of the given SID. Must be freed using FreeSid().
  423. //---------------------------------------------------------------------------
  424. PSID __stdcall SafeCopySid(PSID pSidOld)
  425. {
  426. PSID pSidNew = NULL;
  427. if (pSidOld)
  428. {
  429. if (IsValidSid(pSidOld))
  430. {
  431. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NULL_SID_AUTHORITY;
  432. PUCHAR pucCount = GetSidSubAuthorityCount(pSidOld);
  433. if (AllocateAndInitializeSid(&sia, *pucCount, 0, 0, 0, 0, 0, 0, 0, 0, &pSidNew))
  434. {
  435. if (!CopySid(GetLengthSid(pSidNew), pSidNew, pSidOld))
  436. {
  437. FreeSid(pSidNew);
  438. pSidNew = NULL;
  439. }
  440. }
  441. }
  442. }
  443. return pSidNew;
  444. }