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.

321 lines
10 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. BOOL
  21. GetTextualSid(
  22. PSID pSid, // in - binary Sid
  23. LPTSTR TextualSid, // i/o- buffer for Textual representation of Sid
  24. LPDWORD lpdwBufferLen // in - required/provided TextualSid buffersize
  25. )
  26. {
  27. PSID_IDENTIFIER_AUTHORITY psia;
  28. DWORD dwSubAuthorities;
  29. DWORD dwSidRev=SID_REVISION;
  30. DWORD dwCounter;
  31. DWORD dwSidSize;
  32. // Validate the binary SID.
  33. if(!IsValidSid(pSid))
  34. return FALSE;
  35. // Get the identifier authority value from the SID.
  36. psia = GetSidIdentifierAuthority(pSid);
  37. // Get the number of subauthorities in the SID.
  38. dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
  39. // Compute the buffer length.
  40. // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
  41. dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
  42. // Check input buffer length.
  43. // If too small, indicate the proper size and set last error.
  44. if (*lpdwBufferLen < dwSidSize)
  45. {
  46. *lpdwBufferLen = dwSidSize;
  47. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  48. return FALSE;
  49. }
  50. // Add 'S' prefix and revision number to the string.
  51. dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
  52. // Add SID identifier authority to the string.
  53. if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
  54. {
  55. dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
  56. TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
  57. (USHORT)psia->Value[0],
  58. (USHORT)psia->Value[1],
  59. (USHORT)psia->Value[2],
  60. (USHORT)psia->Value[3],
  61. (USHORT)psia->Value[4],
  62. (USHORT)psia->Value[5]);
  63. }
  64. else
  65. {
  66. dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
  67. TEXT("%lu"),
  68. (ULONG)(psia->Value[5] ) +
  69. (ULONG)(psia->Value[4] << 8) +
  70. (ULONG)(psia->Value[3] << 16) +
  71. (ULONG)(psia->Value[2] << 24) );
  72. }
  73. // Add SID subauthorities to the string. //
  74. for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
  75. {
  76. dwSidSize+=wsprintf(TextualSid + dwSidSize, TEXT("-%lu"),
  77. *GetSidSubAuthority(pSid, dwCounter) );
  78. }
  79. return TRUE;
  80. }
  81. PSID // ret- binary representation of SID, or NULL
  82. SidFromString(
  83. WCHAR const * strSid // in - string representation of SID
  84. )
  85. {
  86. BOOL bSuccess = TRUE;
  87. PSID pSid = NULL;
  88. DWORD dwSidRev;
  89. // WCHAR * strPtr = NULL;
  90. WCHAR sidIA[100];
  91. WCHAR sidSubs[100];
  92. int ia0,ia1,ia2,ia3,ia4,ia5;
  93. SID_IDENTIFIER_AUTHORITY sia;
  94. do
  95. {
  96. if ( strSid[0] != L'S' || strSid[1] != L'-' )
  97. {
  98. bSuccess = FALSE;
  99. break;
  100. }
  101. // Read SID revision level
  102. sidSubs[0] = 0;
  103. int result = swscanf(strSid,L"S-%d-%[^-]-%ls",&dwSidRev,sidIA,sidSubs);
  104. if ( result == 3 )
  105. {
  106. // evaluate the IA
  107. if ( sidIA[1] == L'x' )
  108. {
  109. // full format
  110. result = swscanf(sidIA,L"0x%02hx%02hx%02hx%02hx%02hx%02hx",&ia0,&ia1,&ia2,&ia3,&ia4,&ia5);
  111. if ( result == 6 )
  112. {
  113. sia.Value[0] = (BYTE) ia0;
  114. sia.Value[1] = (BYTE) ia1;
  115. sia.Value[2] = (BYTE) ia2;
  116. sia.Value[3] = (BYTE) ia3;
  117. sia.Value[4] = (BYTE) ia4;
  118. sia.Value[5] = (BYTE) ia5;
  119. }
  120. else
  121. {
  122. bSuccess = FALSE;
  123. break;
  124. }
  125. }
  126. else
  127. {
  128. DWORD bignumber;
  129. result = swscanf(sidIA,L"%lu",&bignumber);
  130. sia.Value[0] = 0;
  131. sia.Value[1] = 0;
  132. sia.Value[2] = BYTE( (bignumber & 0xff000000) >> 24);
  133. sia.Value[3] = BYTE( (bignumber & 0x00ff0000) >> 16);
  134. sia.Value[4] = BYTE( (bignumber & 0x0000ff00) >> 8);
  135. sia.Value[5] = BYTE(bignumber & 0x000000ff);
  136. }
  137. // read the subauthorities
  138. DWORD subs[10];
  139. memset(subs,0,(sizeof subs));
  140. result = swscanf(sidSubs,L"%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu",&subs[0],&subs[1],&subs[2],&subs[3],&subs[4],
  141. &subs[5],&subs[6],&subs[7]);
  142. if ( result )
  143. {
  144. if ( !AllocateAndInitializeSid(&sia,(BYTE)result,subs[0],subs[1],subs[2],subs[3],subs[4],subs[5],subs[6],subs[7],&pSid) )
  145. {
  146. pSid = NULL;
  147. bSuccess = FALSE;
  148. }
  149. }
  150. }
  151. } while ( false);
  152. //see if IsValidSid also thinks this is valid
  153. if (pSid)
  154. {
  155. //if not valid, free it and return NULL
  156. if (!IsValidSid(pSid))
  157. {
  158. FreeSid(pSid);
  159. pSid = NULL;
  160. }
  161. }
  162. return pSid;
  163. }
  164. /*****************************************************************************************************/
  165. /* DomainizeSid:
  166. Takes a domain sid, and verifies that its last subauthority value is -1. If the RID is not
  167. -1, DomainizeSid adds a -1 to the end.
  168. /*****************************************************************************************************/
  169. PSID // ret -the sid with RID = -1
  170. DomainizeSid(
  171. PSID psid, // in -sid to check and possibly fix
  172. BOOL freeOldSid // in -whether to free the old sid
  173. )
  174. {
  175. MCSASSERT(psid);
  176. UCHAR len = (* GetSidSubAuthorityCount(psid));
  177. PDWORD sub = GetSidSubAuthority(psid,len-1);
  178. if ( *sub != -1 )
  179. {
  180. DWORD sdsize = GetSidLengthRequired(len+1); // sid doesn't already have -1 as rid
  181. PSID newsid = (SID *)malloc(sdsize); // copy the sid, and add -1 to the end
  182. if (newsid)
  183. {
  184. if ( ! InitializeSid(newsid,GetSidIdentifierAuthority(psid),len+1) ) // make a bigger sid w/same IA
  185. {
  186. MCSASSERT(false);
  187. }
  188. for ( DWORD i = 0 ; i < len ; i++ )
  189. {
  190. sub = GetSidSubAuthority(newsid,i); // copy subauthorities
  191. (*sub) = (*GetSidSubAuthority(psid,i));
  192. }
  193. sub = GetSidSubAuthority(newsid,len);
  194. *sub = -1; // set rid =-1
  195. if ( freeOldSid )
  196. {
  197. FreeSid(psid);
  198. }
  199. psid = newsid;
  200. len++;
  201. }
  202. }
  203. return psid;
  204. }
  205. /*********************************************************************
  206. * *
  207. * Written by: Paul Thompson *
  208. * Date: 4 OCT 2000 *
  209. * *
  210. * This function is responsible for taking the given source and *
  211. * target account SIDs and breaking them up and returning the src *
  212. * domain sid, src account rid, tgt domain sid, and tgt account rid. *
  213. * The caller must call "FreeSid" on the src and tgt domain sid *
  214. * pointers. *
  215. * *
  216. *********************************************************************/
  217. //BEGIN SplitAccountSids
  218. BOOL // ret - Success ? TRUE | FALSE
  219. SplitAccountSids(
  220. PSID srcSid, // in - src account sid
  221. WCHAR *srcDomainSid, // out - src domain sid textual
  222. DWORD *srcRid, // out - src account rid
  223. PSID tgtSid, // in - tgt account sid
  224. WCHAR *tgtDomainSid, // out - tgt domain sid textual
  225. DWORD *tgtRid // out - tgt account rid
  226. )
  227. {
  228. /* local variables */
  229. DWORD sidLen;
  230. UCHAR Count;
  231. PDWORD psubAuth;
  232. BOOL bSuccess = TRUE;
  233. DWORD lenTxt = MAX_PATH;
  234. /* function body */
  235. if ((!IsValidSid(srcSid)) && (!IsValidSid(tgtSid)))
  236. return FALSE;
  237. //split up the src account sid
  238. sidLen = GetLengthSid(srcSid);
  239. PSID srcDomSid = new BYTE[sidLen+1];
  240. if (!srcDomSid)
  241. return FALSE;
  242. if (!CopySid(sidLen+1, srcDomSid, srcSid))
  243. {
  244. delete [] srcDomSid;
  245. return FALSE;
  246. }
  247. //get the RID out of the SID and get the domain SID
  248. Count = (* GetSidSubAuthorityCount(srcDomSid));
  249. psubAuth = GetSidSubAuthority(srcDomSid, Count-1);
  250. if (psubAuth)
  251. {
  252. *srcRid = *psubAuth;
  253. *psubAuth = -1;
  254. }
  255. //convert domain sid to text format
  256. if (srcDomSid)
  257. {
  258. GetTextualSid(srcDomSid,srcDomainSid,&lenTxt);
  259. delete [] srcDomSid;
  260. }
  261. //split up the tgt account sid
  262. sidLen = GetLengthSid(tgtSid);
  263. PSID tgtDomSid = new BYTE[sidLen+1];
  264. if (!tgtDomSid)
  265. return FALSE;
  266. if (!CopySid(sidLen+1, tgtDomSid, tgtSid))
  267. {
  268. delete [] tgtDomSid;
  269. return FALSE;
  270. }
  271. //get the RID out of the SID and get the domain SID
  272. Count = (* GetSidSubAuthorityCount(tgtDomSid));
  273. psubAuth = GetSidSubAuthority(tgtDomSid, Count-1);
  274. if (psubAuth)
  275. {
  276. *tgtRid = *psubAuth;
  277. *psubAuth = -1;
  278. }
  279. //convert domain sid to text format
  280. lenTxt = MAX_PATH;
  281. if (tgtDomSid)
  282. {
  283. GetTextualSid(tgtDomSid,tgtDomainSid,&lenTxt);
  284. delete [] tgtDomSid;
  285. }
  286. return bSuccess;
  287. }
  288. //END SplitAccountSids