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.

1286 lines
37 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. Win9xSecurity.cpp
  5. Abstract:
  6. This class handles the importing of Win9x security data that was extracted from an old MMF format repository.
  7. History:
  8. 03/17/2001 shbrown - created
  9. --*/
  10. #include "precomp.h"
  11. #include <wbemcomn.h>
  12. #include "Win9xSecurity.h"
  13. #include <oahelp.inl>
  14. bool CWin9xSecurity::Win9xBlobFileExists()
  15. {
  16. CFileName wszFilePath;
  17. if (wszFilePath == NULL)
  18. return false;
  19. if (!GetRepositoryDirectory(wszFilePath))
  20. return false;
  21. StringCchCatW(wszFilePath, wszFilePath.Length(), BLOB9X_FILENAME);
  22. DWORD dwAttributes = GetFileAttributesW(wszFilePath);
  23. if (dwAttributes != -1)
  24. {
  25. DWORD dwMask = FILE_ATTRIBUTE_DEVICE |
  26. FILE_ATTRIBUTE_DIRECTORY |
  27. FILE_ATTRIBUTE_OFFLINE |
  28. FILE_ATTRIBUTE_REPARSE_POINT |
  29. FILE_ATTRIBUTE_SPARSE_FILE;
  30. if (!(dwAttributes & dwMask))
  31. return true;
  32. }
  33. return false;
  34. }
  35. HRESULT CWin9xSecurity::ImportWin9xSecurity()
  36. {
  37. HRESULT hRes = WBEM_S_NO_ERROR;
  38. CFileName wszFilePath;
  39. if (wszFilePath == NULL)
  40. return WBEM_E_OUT_OF_MEMORY;
  41. if (GetRepositoryDirectory(wszFilePath))
  42. {
  43. StringCchCatW(wszFilePath, wszFilePath.Length(), BLOB9X_FILENAME);
  44. m_h9xBlobFile = CreateFileW(wszFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  45. }
  46. // get a session and begin a transaction
  47. CSession* pSession = new CSession(m_pControl);
  48. if (pSession == NULL)
  49. return WBEM_E_OUT_OF_MEMORY;
  50. pSession->AddRef();
  51. CReleaseMe relMe(pSession);
  52. hRes = pSession->BeginWriteTransaction(0);
  53. if (FAILED(hRes))
  54. {
  55. return hRes;
  56. }
  57. // process the file
  58. if (m_h9xBlobFile != INVALID_HANDLE_VALUE)
  59. {
  60. try
  61. {
  62. hRes = DecodeWin9xBlobFile();
  63. }
  64. catch (...)
  65. {
  66. ERRORTRACE((LOG_WBEMCORE, "Traversal of Win9x security data import file failed\n"));
  67. hRes = WBEM_E_FAILED;
  68. }
  69. CloseHandle(m_h9xBlobFile);
  70. }
  71. else
  72. {
  73. ERRORTRACE((LOG_WBEMCORE, "Could not open the Win9x security data import file for reading\n"));
  74. hRes = WBEM_E_FAILED;
  75. }
  76. if (SUCCEEDED(hRes))
  77. {
  78. if (DeleteWin9xBlobFile())
  79. hRes = pSession->CommitTransaction(0);
  80. else
  81. {
  82. ERRORTRACE((LOG_WBEMCORE, "Win9x security data import completed but failed to delete import file\n"));
  83. pSession->AbortTransaction(0);
  84. hRes = WBEM_E_FAILED;
  85. }
  86. }
  87. else
  88. {
  89. ERRORTRACE((LOG_WBEMCORE, "Win9x security data import failed to complete\n"));
  90. pSession->AbortTransaction(0);
  91. }
  92. return hRes;
  93. }
  94. HRESULT CWin9xSecurity::DecodeWin9xBlobFile()
  95. {
  96. HRESULT hRes = WBEM_S_NO_ERROR;
  97. // read the file header
  98. if (!ReadWin9xHeader())
  99. return WBEM_E_FAILED;
  100. // import the file
  101. BLOB9X_SPACER header;
  102. DWORD dwSize;
  103. while (hRes == WBEM_S_NO_ERROR)
  104. {
  105. // this loop will be exited when we either...
  106. // - successfully process the whole import file, or
  107. // - encounter an error
  108. dwSize = 0;
  109. if ((ReadFile(m_h9xBlobFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
  110. {
  111. hRes = WBEM_E_FAILED;
  112. }
  113. else if ((header.dwSpacerType == BLOB9X_TYPE_SECURITY_INSTANCE) ||
  114. (header.dwSpacerType == BLOB9X_TYPE_SECURITY_BLOB))
  115. {
  116. hRes = ProcessWin9xBlob(&header);
  117. }
  118. else if (header.dwSpacerType == BLOB9X_TYPE_END_OF_FILE)
  119. {
  120. break;
  121. }
  122. else
  123. {
  124. hRes = WBEM_E_FAILED;
  125. }
  126. }
  127. if (SUCCEEDED(hRes))
  128. hRes = RecursiveInheritSecurity(NULL, L"root"); // force namespaces to inherit their inheritable security settings
  129. return hRes;
  130. }
  131. bool CWin9xSecurity::ReadWin9xHeader()
  132. {
  133. BLOB9X_HEADER header;
  134. DWORD dwSize = 0;
  135. if ((ReadFile(m_h9xBlobFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
  136. {
  137. ERRORTRACE((LOG_WBEMCORE, "Failed to retrieve the Win9x import file header information\n"));
  138. return false;
  139. }
  140. if (strncmp(header.szSignature, BLOB9X_SIGNATURE, 9) != 0)
  141. {
  142. ERRORTRACE((LOG_WBEMCORE, "The import file is not a Win9x import file\n"));
  143. return false;
  144. }
  145. return true;
  146. }
  147. HRESULT CWin9xSecurity::ProcessWin9xBlob(BLOB9X_SPACER* pHeader)
  148. {
  149. if (pHeader->dwNamespaceNameSize == 0)
  150. {
  151. ERRORTRACE((LOG_WBEMCORE, "Namespace name size is zero in Win9x import blob\n"));
  152. return WBEM_E_FAILED;
  153. }
  154. if (pHeader->dwBlobSize == 0)
  155. {
  156. ERRORTRACE((LOG_WBEMCORE, "Blob size is zero in Win9x import blob\n"));
  157. return WBEM_E_FAILED;
  158. }
  159. // read the namespace name
  160. wchar_t* wszNamespaceName = new wchar_t[pHeader->dwNamespaceNameSize];
  161. if (!wszNamespaceName)
  162. return WBEM_E_OUT_OF_MEMORY;
  163. CVectorDeleteMe<wchar_t> delMe1(wszNamespaceName);
  164. DWORD dwSize = 0;
  165. if ((ReadFile(m_h9xBlobFile, wszNamespaceName, pHeader->dwNamespaceNameSize, &dwSize, NULL) == 0) || (dwSize != pHeader->dwNamespaceNameSize))
  166. return WBEM_E_FAILED;
  167. // read the parent namespace name if it exists
  168. wchar_t* wszParentClass = NULL;
  169. if (pHeader->dwParentClassNameSize)
  170. {
  171. wszParentClass = new wchar_t[pHeader->dwParentClassNameSize];
  172. if (!wszParentClass)
  173. return WBEM_E_OUT_OF_MEMORY;
  174. dwSize = 0;
  175. if ((ReadFile(m_h9xBlobFile, wszParentClass, pHeader->dwParentClassNameSize, &dwSize, NULL) == 0) || (dwSize != pHeader->dwParentClassNameSize))
  176. {
  177. delete [] wszParentClass;
  178. return WBEM_E_FAILED;
  179. }
  180. }
  181. CVectorDeleteMe<wchar_t> delMe2(wszParentClass);
  182. // read in the blob
  183. char* pObjectBlob = new char[pHeader->dwBlobSize];
  184. if (!pObjectBlob)
  185. return WBEM_E_OUT_OF_MEMORY;
  186. CVectorDeleteMe<char> delMe3(pObjectBlob);
  187. dwSize = 0;
  188. if ((ReadFile(m_h9xBlobFile, pObjectBlob, pHeader->dwBlobSize, &dwSize, NULL) == 0) || (dwSize != pHeader->dwBlobSize))
  189. {
  190. ERRORTRACE((LOG_WBEMCORE, "Failed to read Win9x security blob for namespace %S\n", wszNamespaceName));
  191. return WBEM_E_FAILED;
  192. }
  193. // get handle to the namespace so it can be used below
  194. CNamespaceHandle* pNamespaceHandle = new CNamespaceHandle(m_pControl, m_pRepository);
  195. if (!pNamespaceHandle)
  196. return WBEM_E_OUT_OF_MEMORY;
  197. pNamespaceHandle->AddRef();
  198. CReleaseMe relme(pNamespaceHandle);
  199. HRESULT hRes = pNamespaceHandle->Initialize(wszNamespaceName);
  200. if (SUCCEEDED(hRes))
  201. {
  202. // process the blob according to its type
  203. if (pHeader->dwSpacerType == BLOB9X_TYPE_SECURITY_INSTANCE)
  204. hRes = ProcessWin9xSecurityInstance(pNamespaceHandle, wszParentClass, pObjectBlob, pHeader->dwBlobSize);
  205. else // (pHeader->dwSpacerType == BLOB9X_TYPE_SECURITY_BLOB)
  206. hRes = ProcessWin9xSecurityBlob(pNamespaceHandle, wszNamespaceName, pObjectBlob);
  207. }
  208. return hRes;
  209. }
  210. HRESULT CWin9xSecurity::ProcessWin9xSecurityInstance(CNamespaceHandle* pNamespaceHandle, wchar_t* wszParentClass, char* pObjectBlob, DWORD dwBlobSize)
  211. {
  212. // get parent class from the repository
  213. _IWmiObject* pParentClass = 0;
  214. HRESULT hRes = pNamespaceHandle->GetObjectByPath(wszParentClass, 0, IID_IWbemClassObject, (LPVOID*)&pParentClass);
  215. if (FAILED(hRes))
  216. {
  217. ERRORTRACE((LOG_WBEMCORE, "Failed to retrieve class %S from the repository; HRESULT = %#lx\n", wszParentClass, hRes));
  218. return hRes;
  219. }
  220. CReleaseMe relMe1(pParentClass);
  221. // merge object blob with parent class to produce instance
  222. _IWmiObject* pInstance = 0;
  223. hRes = pParentClass->Merge(WMIOBJECT_MERGE_FLAG_INSTANCE, dwBlobSize, pObjectBlob, &pInstance);
  224. if (FAILED(hRes))
  225. {
  226. ERRORTRACE((LOG_WBEMCORE, "Unable to merge instance; HRESULT = %#lx\n", hRes));
  227. return hRes;
  228. }
  229. CReleaseMe relMe2(pInstance);
  230. // convert security class instance to ACE
  231. bool bGroup = false;
  232. if(wbem_wcsicmp(L"__ntlmgroup", wszParentClass) == 0)
  233. bGroup = true;
  234. CNtAce* pAce = ConvertOldObjectToAce(pInstance, bGroup);
  235. if(!pAce)
  236. {
  237. ERRORTRACE((LOG_WBEMCORE, "Unable to convert old security instance to ACE"));
  238. return WBEM_E_FAILED;
  239. }
  240. CDeleteMe<CNtAce> delMe(pAce);
  241. // store the ACE
  242. hRes = StoreAce(pAce);
  243. if (FAILED(hRes))
  244. {
  245. ERRORTRACE((LOG_WBEMCORE, "Unable to store ACE; HRESULT = %#lx\n", hRes));
  246. return hRes;
  247. }
  248. return hRes;
  249. }
  250. // this function was stolen from coredll\secure.cpp with minor modifications to remove calls to IsNT()
  251. CNtAce* CWin9xSecurity::ConvertOldObjectToAce(_IWmiObject* pObj, bool bGroup)
  252. {
  253. // Get the properties out of the old object
  254. CVARIANT vName;
  255. if (pObj->Get(L"Name", 0, &vName, 0, 0) != 0)
  256. return NULL;
  257. LPWSTR pName = NULL;
  258. if(vName.GetType() != VT_BSTR)
  259. return NULL; // ignore this one.
  260. pName = LPWSTR(vName);
  261. CVARIANT vDomain;
  262. LPWSTR pDomain = L".";
  263. if (pObj->Get(L"Authority", 0, &vDomain, 0, 0) != 0)
  264. {
  265. return NULL;
  266. }
  267. if(vDomain.GetType() == VT_BSTR)
  268. pDomain = LPWSTR(vDomain);
  269. bool bEditSecurity = false;
  270. bool bEnabled = false;
  271. bool bExecMethods = false;
  272. DWORD dwMask = 0;
  273. CVARIANT vEnabled;
  274. CVARIANT vEditSecurity;
  275. CVARIANT vExecMethods;
  276. CVARIANT vPermission;
  277. pObj->Get(L"Enabled", 0, &vEnabled, 0, 0);
  278. pObj->Get(L"EditSecurity", 0, &vEditSecurity, 0, 0);
  279. pObj->Get(L"ExecuteMethods", 0, &vExecMethods, 0, 0);
  280. pObj->Get(L"Permissions", 0, &vPermission, 0, 0);
  281. if (vEnabled.GetType() != VT_NULL && vEnabled.GetBool())
  282. bEnabled = true;
  283. if (vEditSecurity.GetType() != VT_NULL && vEditSecurity.GetBool())
  284. bEditSecurity = true;
  285. if (vExecMethods.GetType() != VT_NULL && vExecMethods.GetBool())
  286. bExecMethods = true;
  287. DWORD dwPermission = 0;
  288. if (vPermission.GetType() != VT_NULL && vPermission.GetLONG() > dwPermission)
  289. dwPermission = vPermission.GetLONG();
  290. // Now translate the old settings into new ones
  291. if(bEnabled)
  292. dwMask = WBEM_ENABLE | WBEM_REMOTE_ACCESS | WBEM_WRITE_PROVIDER;
  293. if(bEditSecurity)
  294. dwMask |= READ_CONTROL;
  295. if(bEditSecurity && dwPermission > 0)
  296. dwMask |= WRITE_DAC;
  297. if(bExecMethods)
  298. dwMask |= WBEM_METHOD_EXECUTE;
  299. if(dwPermission >= 1)
  300. dwMask |= WBEM_PARTIAL_WRITE_REP;
  301. if(dwPermission >= 2)
  302. dwMask |= WBEM_FULL_WRITE_REP | WBEM_PARTIAL_WRITE_REP | WBEM_WRITE_PROVIDER;
  303. // By default, CNtSid will look up the group name from either the local machine,
  304. // the domain, or a trusted domain. So we need to be explicit
  305. WString wc;
  306. if(pDomain)
  307. if(wbem_wcsicmp(pDomain, L"."))
  308. {
  309. wc = pDomain;
  310. wc += L"\\";
  311. }
  312. wc += pName;
  313. // under m1, groups that were not enabled were just ignored. Therefore the bits
  314. // cannot be transfer over since m3 has allows and denies, but no noops. Also,
  315. // win9x doesnt have denies, do we want to noop those users also.
  316. if(!bEnabled && bGroup)
  317. dwMask = 0;
  318. // In general, m1 just supported allows. However, a user entry that was not enabled was
  319. // treated as a deny. Note that win9x does not allow actual denies.
  320. DWORD dwType = ACCESS_ALLOWED_ACE_TYPE;
  321. if(!bGroup && !bEnabled)
  322. {
  323. dwMask |= (WBEM_ENABLE | WBEM_REMOTE_ACCESS | WBEM_WRITE_PROVIDER);
  324. dwType = ACCESS_DENIED_ACE_TYPE;
  325. }
  326. CNtSid Sid(wc, NULL);
  327. if(Sid.GetStatus() != CNtSid::NoError)
  328. {
  329. ERRORTRACE((LOG_WBEMCORE, "Error converting m1 security ace, name = %S, error = 0x%x", wc, Sid.GetStatus()));
  330. return NULL;
  331. }
  332. CNtAce * pace = new CNtAce(dwMask, dwType, CONTAINER_INHERIT_ACE, Sid);
  333. return pace;
  334. }
  335. HRESULT CWin9xSecurity::StoreAce(CNtAce* pAce)
  336. {
  337. // get handle to the root namespace
  338. CNamespaceHandle* pRootNamespaceHandle = new CNamespaceHandle(m_pControl, m_pRepository);
  339. if (!pRootNamespaceHandle)
  340. return WBEM_E_OUT_OF_MEMORY;
  341. pRootNamespaceHandle->AddRef();
  342. CReleaseMe relme1(pRootNamespaceHandle);
  343. HRESULT hRes = pRootNamespaceHandle->Initialize(L"root");
  344. if (FAILED(hRes))
  345. {
  346. ERRORTRACE((LOG_WBEMCORE, "Failed to connect to namespace; HRESULT = %#lx\n", hRes));
  347. return hRes;
  348. }
  349. // get root namespace SD
  350. CNtSecurityDescriptor sdRoot;
  351. hRes = GetSDFromNamespace(pRootNamespaceHandle, sdRoot);
  352. if (FAILED(hRes))
  353. return hRes;
  354. // Delete all entries in the SD with the same name
  355. wchar_t* wszAccountName;
  356. hRes = pAce->GetFullUserName2(&wszAccountName);
  357. if(FAILED(hRes))
  358. return hRes;
  359. CVectorDeleteMe<wchar_t> delMe(wszAccountName);
  360. if (!StripMatchingEntries(sdRoot, wszAccountName))
  361. return WBEM_E_FAILED;
  362. // add in the new security
  363. if (!AddAceToSD(sdRoot, pAce))
  364. return WBEM_E_FAILED;
  365. // set the security
  366. hRes = SetNamespaceSecurity(pRootNamespaceHandle, sdRoot);
  367. return hRes;
  368. }
  369. bool CWin9xSecurity::StripMatchingEntries(CNtSecurityDescriptor& sd, const wchar_t* wszAccountName)
  370. {
  371. // Get the DACL
  372. CNtAcl* pAcl;
  373. pAcl = sd.GetDacl();
  374. if(!pAcl)
  375. return false;
  376. CDeleteMe<CNtAcl> dm(pAcl);
  377. // enumerate through the aces
  378. DWORD dwNumAces = pAcl->GetNumAces();
  379. BOOL bChanged = FALSE;
  380. HRESULT hRes = WBEM_S_NO_ERROR;
  381. for(long nIndex = (long)dwNumAces-1; nIndex >= 0; nIndex--)
  382. {
  383. CNtAce* pAce = pAcl->GetAce(nIndex);
  384. if(pAce)
  385. {
  386. wchar_t* wszAceListUserName;
  387. hRes = pAce->GetFullUserName2(&wszAceListUserName);
  388. if(FAILED(hRes))
  389. return false;
  390. CVectorDeleteMe<wchar_t> delMe(wszAceListUserName);
  391. if(wbem_wcsicmp(wszAceListUserName, wszAccountName) == 0)
  392. {
  393. if (!pAcl->DeleteAce(nIndex))
  394. return false;
  395. bChanged = TRUE;
  396. }
  397. }
  398. }
  399. if(bChanged)
  400. {
  401. if (!sd.SetDacl(pAcl))
  402. return false;
  403. }
  404. return true;
  405. }
  406. bool CWin9xSecurity::AddAceToSD(CNtSecurityDescriptor& sd, CNtAce* pAce)
  407. {
  408. CNtAcl* pacl = sd.GetDacl();
  409. if(!pacl)
  410. return false;
  411. CDeleteMe<CNtAcl> delMe(pacl);
  412. if (!pacl->AddAce(pAce))
  413. return false;
  414. if (!sd.SetDacl(pacl))
  415. return false;
  416. return true;
  417. }
  418. HRESULT CWin9xSecurity::ProcessWin9xSecurityBlob(CNamespaceHandle* pNamespaceHandle, const wchar_t* wszNamespaceName, const char* pObjectBlob)
  419. {
  420. HRESULT hRes = WBEM_S_NO_ERROR;
  421. // convert the Win9x security blob into a more proper NT security blob
  422. char* pNsSecurity = NULL;
  423. if (!ConvertSecurityBlob(pObjectBlob, &pNsSecurity))
  424. {
  425. ERRORTRACE((LOG_WBEMCORE, "Failed to convert Win9x security blob for namespace %S\n", wszNamespaceName));
  426. return WBEM_E_FAILED;
  427. }
  428. CVectorDeleteMe<char> delMe1(pNsSecurity);
  429. // get the parent namespace name, and if a parent exists, get a pointer to it so it can be used below
  430. CNamespaceHandle* pParentNamespaceHandle = new CNamespaceHandle(m_pControl, m_pRepository);
  431. if (!pParentNamespaceHandle)
  432. return WBEM_E_OUT_OF_MEMORY;
  433. pParentNamespaceHandle->AddRef();
  434. CReleaseMe relme(pParentNamespaceHandle);
  435. size_t dwParentNamespaceNameLen = wcslen(wszNamespaceName)+1;
  436. wchar_t* wszParentNamespaceName = new wchar_t[dwParentNamespaceNameLen];
  437. if (!wszParentNamespaceName)
  438. return WBEM_E_OUT_OF_MEMORY;
  439. CVectorDeleteMe<wchar_t> delMe2(wszParentNamespaceName);
  440. StringCchCopyW(wszParentNamespaceName, dwParentNamespaceNameLen, wszNamespaceName);
  441. wchar_t* pSlash = wcsrchr(wszParentNamespaceName, '\\');
  442. bool bRoot = true;
  443. if (pSlash)
  444. {
  445. bRoot = false;
  446. *pSlash = L'\0';
  447. hRes = pParentNamespaceHandle->Initialize(wszParentNamespaceName);
  448. if (FAILED(hRes))
  449. return hRes;
  450. }
  451. // now transform the old security blob that consisted of a header and array of ACE's
  452. // into a proper Security Descriptor that can be stored in the property
  453. CNtSecurityDescriptor mmfNsSD;
  454. hRes = TransformBlobToSD(bRoot, pParentNamespaceHandle, pNsSecurity, 0, mmfNsSD);
  455. if (FAILED(hRes))
  456. {
  457. ERRORTRACE((LOG_WBEMCORE, "Failed to convert security blob to SD for namespace %S\n", wszNamespaceName));
  458. return hRes;
  459. }
  460. // now set the security
  461. hRes = SetNamespaceSecurity(pNamespaceHandle, mmfNsSD);
  462. if (FAILED(hRes))
  463. {
  464. ERRORTRACE((LOG_WBEMCORE, "Failed to set namespace security for namespace %S\n", wszNamespaceName));
  465. return hRes;
  466. }
  467. return hRes;
  468. }
  469. bool CWin9xSecurity::ConvertSecurityBlob(const char* pOrgNsSecurity, char** ppNewNsSecurity)
  470. {
  471. // convert an old Win9x pseudo-blob into a blob with NT-style ACE's
  472. if (!pOrgNsSecurity || !ppNewNsSecurity)
  473. return false;
  474. DWORD* pdwData = (DWORD*)pOrgNsSecurity;
  475. DWORD dwSize = *pdwData;
  476. pdwData++;
  477. DWORD dwVersion = *pdwData;
  478. if(dwVersion != 1 || dwSize == 0 || dwSize > 64000)
  479. {
  480. ERRORTRACE((LOG_WBEMCORE, "Invalid security blob header\n"));
  481. return false;
  482. }
  483. pdwData++;
  484. DWORD dwStoredAsNT = *pdwData;
  485. if (dwStoredAsNT)
  486. {
  487. ERRORTRACE((LOG_WBEMCORE, "NT security blob detected; should be Win9x\n"));
  488. return false;
  489. }
  490. CFlexAceArray AceList;
  491. if (!AceList.DeserializeWin9xSecurityBlob(pOrgNsSecurity))
  492. {
  493. ERRORTRACE((LOG_WBEMCORE, "Failed to deserialize a Win9x security blob\n"));
  494. return false;
  495. }
  496. // serialize the new WinNT blob
  497. if (!AceList.SerializeWinNTSecurityBlob(ppNewNsSecurity))
  498. {
  499. ERRORTRACE((LOG_WBEMCORE, "Failed to serialize a WinNT security blob\n"));
  500. return false;
  501. }
  502. return true;
  503. }
  504. HRESULT CWin9xSecurity::TransformBlobToSD(bool bRoot, CNamespaceHandle* pParentNamespaceHandle, const char* pNsSecurity, DWORD dwStoredAsNT, CNtSecurityDescriptor& mmfNsSD)
  505. {
  506. // now transform the old security blob that consisted of a header and array of ACE's
  507. // into a proper Security Descriptor that can be stored in the property
  508. // build up an ACL from our blob, if we have one
  509. CNtAcl acl;
  510. if (pNsSecurity)
  511. {
  512. DWORD* pdwData = (DWORD*) pNsSecurity;
  513. pdwData += 3;
  514. int iAceCount = (int)*pdwData;
  515. pdwData += 2;
  516. BYTE* pAceData = (BYTE*)pdwData;
  517. PGENERIC_ACE pAce = NULL;
  518. for (int iCnt = 0; iCnt < iAceCount; iCnt++)
  519. {
  520. pAce = (PGENERIC_ACE)pAceData;
  521. if (!pAce)
  522. {
  523. ERRORTRACE((LOG_WBEMCORE, "Failed to access GENERIC_ACE within security blob\n"));
  524. return WBEM_E_FAILED;
  525. }
  526. CNtAce ace(pAce);
  527. if(ace.GetStatus() != 0)
  528. {
  529. ERRORTRACE((LOG_WBEMCORE, "Failed to construct CNtAce from GENERIC_ACE\n"));
  530. return WBEM_E_FAILED;
  531. }
  532. acl.AddAce(&ace);
  533. if (acl.GetStatus() != 0)
  534. {
  535. ERRORTRACE((LOG_WBEMCORE, "Failed to add ACE to ACL\n"));
  536. return WBEM_E_FAILED;
  537. }
  538. pAceData += ace.GetSize();
  539. }
  540. }
  541. // for Win9x, the security blob for ROOT would not have had any default
  542. // root aces for administrators and everyone, so create them
  543. if (bRoot)
  544. {
  545. if (!AddDefaultRootAces(&acl))
  546. {
  547. ERRORTRACE((LOG_WBEMCORE, "Failed to create default root ACE's\n"));
  548. return WBEM_E_FAILED;
  549. }
  550. }
  551. // a real SD was constructed and passed in by reference, now set it up properly
  552. if (!SetOwnerAndGroup(mmfNsSD))
  553. return WBEM_E_FAILED;
  554. mmfNsSD.SetDacl(&acl);
  555. if (mmfNsSD.GetStatus() != 0)
  556. {
  557. ERRORTRACE((LOG_WBEMCORE, "Failed to convert namespace security blob to SD\n"));
  558. return WBEM_E_FAILED;
  559. }
  560. // add in the parent's inheritable aces, if this is not ROOT
  561. if (!bRoot)
  562. {
  563. HRESULT hRes = GetParentsInheritableAces(pParentNamespaceHandle, mmfNsSD);
  564. if (FAILED(hRes))
  565. {
  566. ERRORTRACE((LOG_WBEMCORE, "Failed to inherit parent's inheritable ACE's; HRESULT = %#lx\n", hRes));
  567. return hRes;
  568. }
  569. }
  570. return WBEM_S_NO_ERROR;
  571. }
  572. HRESULT CWin9xSecurity::SetNamespaceSecurity(CNamespaceHandle* pNamespaceHandle, CNtSecurityDescriptor& mmfNsSD)
  573. {
  574. if (!pNamespaceHandle)
  575. return WBEM_E_FAILED;
  576. // get the singleton object
  577. IWbemClassObject* pThisNamespace = NULL;
  578. size_t dwThisNamespaceLen = wcslen(L"__thisnamespace=@")+1;
  579. wchar_t* wszThisNamespace = new wchar_t[dwThisNamespaceLen];
  580. if (wszThisNamespace == NULL)
  581. return WBEM_E_OUT_OF_MEMORY;
  582. StringCchCopyW(wszThisNamespace, dwThisNamespaceLen, L"__thisnamespace=@");
  583. HRESULT hRes = pNamespaceHandle->GetObjectByPath(wszThisNamespace, 0, IID_IWbemClassObject, (LPVOID*)&pThisNamespace);
  584. delete [] wszThisNamespace;
  585. wszThisNamespace = NULL;
  586. if (FAILED(hRes))
  587. {
  588. ERRORTRACE((LOG_WBEMCORE, "Failed to get singleton namespace object; HRESULT = %#lx\n", hRes));
  589. return hRes;
  590. }
  591. CReleaseMe relMe(pThisNamespace);
  592. // copy SD data into a safearray
  593. SAFEARRAY FAR* psa;
  594. SAFEARRAYBOUND rgsabound[1];
  595. rgsabound[0].lLbound = 0;
  596. rgsabound[0].cElements = mmfNsSD.GetSize();
  597. psa = SafeArrayCreate( VT_UI1, 1 , rgsabound );
  598. if (!psa)
  599. return WBEM_E_OUT_OF_MEMORY;
  600. char* pData = NULL;
  601. hRes = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pData);
  602. if (FAILED(hRes))
  603. {
  604. ERRORTRACE((LOG_WBEMCORE, "Failed SafeArrayAccessData; HRESULT = %#lx\n", hRes));
  605. return hRes;
  606. }
  607. memcpy(pData, mmfNsSD.GetPtr(), mmfNsSD.GetSize());
  608. hRes = SafeArrayUnaccessData(psa);
  609. if (FAILED(hRes))
  610. {
  611. ERRORTRACE((LOG_WBEMCORE, "Failed SafeArrayUnaccessData; HRESULT = %#lx\n", hRes));
  612. return hRes;
  613. }
  614. pData = NULL;
  615. // put the safearray into a variant and set the property on the instance
  616. VARIANT var;
  617. var.vt = VT_UI1|VT_ARRAY;
  618. var.parray = psa;
  619. hRes = pThisNamespace->Put(L"SECURITY_DESCRIPTOR" , 0, &var, 0);
  620. VariantClear(&var);
  621. if (FAILED(hRes))
  622. {
  623. ERRORTRACE((LOG_WBEMCORE, "Failed to put SECURITY_DESCRIPTOR property; HRESULT = %#lx\n", hRes));
  624. return hRes;
  625. }
  626. // put back the instance
  627. CEventCollector eventCollector;
  628. hRes = pNamespaceHandle->PutObject(IID_IWbemClassObject, pThisNamespace, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL, eventCollector);
  629. if (FAILED(hRes))
  630. {
  631. ERRORTRACE((LOG_WBEMCORE, "Failed to put back singleton instance; HRESULT = %#lx\n", hRes));
  632. return hRes;
  633. }
  634. return hRes;
  635. }
  636. bool CWin9xSecurity::AddDefaultRootAces(CNtAcl * pacl)
  637. {
  638. if (!pacl)
  639. return false;
  640. PSID pRawSid;
  641. // add Administrator
  642. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  643. if(AllocateAndInitializeSid( &id, 2,
  644. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  645. 0,0,0,0,0,0,&pRawSid))
  646. {
  647. CNtSid SidAdmin(pRawSid);
  648. FreeSid(pRawSid);
  649. DWORD dwMask = FULL_RIGHTS;
  650. CNtAce * pace = new CNtAce(dwMask, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE, SidAdmin);
  651. if ( NULL == pace )
  652. return false;
  653. CDeleteMe<CNtAce> dm(pace);
  654. pacl->AddAce(pace);
  655. if (pacl->GetStatus() != 0)
  656. return false;
  657. }
  658. // add Everyone
  659. SID_IDENTIFIER_AUTHORITY id2 = SECURITY_WORLD_SID_AUTHORITY;
  660. if(AllocateAndInitializeSid( &id2, 1,
  661. 0,0,0,0,0,0,0,0,&pRawSid))
  662. {
  663. CNtSid SidUsers(pRawSid);
  664. FreeSid(pRawSid);
  665. DWORD dwMask = WBEM_ENABLE | WBEM_METHOD_EXECUTE | WBEM_WRITE_PROVIDER;
  666. CNtAce * pace = new CNtAce(dwMask, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE, SidUsers);
  667. if ( NULL == pace )
  668. return false;
  669. CDeleteMe<CNtAce> dm(pace);
  670. pacl->AddAce(pace);
  671. if (pacl->GetStatus() != 0)
  672. return false;
  673. }
  674. return true;
  675. }
  676. HRESULT CWin9xSecurity::GetParentsInheritableAces(CNamespaceHandle* pParentNamespaceHandle, CNtSecurityDescriptor &sd)
  677. {
  678. if (!pParentNamespaceHandle)
  679. return WBEM_E_FAILED;
  680. // Get the parent namespace's SD
  681. CNtSecurityDescriptor sdParent;
  682. HRESULT hRes = GetSDFromNamespace(pParentNamespaceHandle, sdParent);
  683. if (FAILED(hRes))
  684. return hRes;
  685. // strip out the inherited aces so we have a consistent SD
  686. if (!StripOutInheritedAces(sd))
  687. return WBEM_E_FAILED;
  688. // Go through the parents dacl and add any inheritable aces to ours.
  689. if (!CopyInheritAces(sd, sdParent))
  690. return WBEM_E_FAILED;
  691. return hRes;
  692. }
  693. HRESULT CWin9xSecurity::GetSDFromNamespace(CNamespaceHandle* pNamespaceHandle, CNtSecurityDescriptor& sd)
  694. {
  695. if (!pNamespaceHandle)
  696. return WBEM_E_FAILED;
  697. // get the singleton object
  698. IWbemClassObject* pThisNamespace = NULL;
  699. size_t dwThisNamespaceLen = wcslen(L"__thisnamespace=@")+1;
  700. wchar_t* wszThisNamespace = new wchar_t[dwThisNamespaceLen];
  701. if (wszThisNamespace==NULL)
  702. return WBEM_E_OUT_OF_MEMORY;
  703. StringCchCopyW(wszThisNamespace, dwThisNamespaceLen, L"__thisnamespace=@");
  704. HRESULT hRes = pNamespaceHandle->GetObjectByPath(wszThisNamespace, 0, IID_IWbemClassObject, (LPVOID*)&pThisNamespace);
  705. delete [] wszThisNamespace;
  706. wszThisNamespace=NULL;
  707. if (FAILED(hRes))
  708. {
  709. ERRORTRACE((LOG_WBEMCORE, "Failed to get singleton namespace object; HRESULT = %#lx\n", hRes));
  710. return hRes;
  711. }
  712. CReleaseMe relMe(pThisNamespace);
  713. // Get the security descriptor argument
  714. VARIANT var;
  715. VariantInit(&var);
  716. hRes = pThisNamespace->Get(L"SECURITY_DESCRIPTOR", 0, &var, NULL, NULL);
  717. if (FAILED(hRes))
  718. {
  719. VariantClear(&var);
  720. ERRORTRACE((LOG_WBEMCORE, "Failed to get SECURITY_DESCRIPTOR property; HRESULT = %#lx\n", hRes));
  721. return hRes;
  722. }
  723. if(var.vt != (VT_ARRAY | VT_UI1))
  724. {
  725. VariantClear(&var);
  726. ERRORTRACE((LOG_WBEMCORE, "Failed to get SECURITY_DESCRIPTOR property due to incorrect variant type\n"));
  727. return WBEM_E_FAILED;
  728. }
  729. SAFEARRAY* psa = var.parray;
  730. PSECURITY_DESCRIPTOR pSD;
  731. hRes = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pSD);
  732. if (FAILED(hRes))
  733. {
  734. VariantClear(&var);
  735. ERRORTRACE((LOG_WBEMCORE, "GetSDFromNamespace failed SafeArrayAccessData; HRESULT = %#lx\n", hRes));
  736. return hRes;
  737. }
  738. BOOL bValid = IsValidSecurityDescriptor(pSD);
  739. if (!bValid)
  740. {
  741. VariantClear(&var);
  742. ERRORTRACE((LOG_WBEMCORE, "GetSDFromNamespace retrieved an invalid security descriptor\n"));
  743. return WBEM_E_FAILED;
  744. }
  745. CNtSecurityDescriptor sdNew(pSD);
  746. // Check to make sure the owner and group is not NULL!!!!
  747. CNtSid *pTmpSid = sdNew.GetOwner();
  748. if (pTmpSid == NULL)
  749. {
  750. ERRORTRACE((LOG_WBEMCORE, "Security descriptor was retrieved and it had no owner\n"));
  751. }
  752. delete pTmpSid;
  753. pTmpSid = sdNew.GetGroup();
  754. if (pTmpSid == NULL)
  755. {
  756. ERRORTRACE((LOG_WBEMCORE, "Security descriptor was retrieved and it had no group\n"));
  757. }
  758. delete pTmpSid;
  759. sd = sdNew;
  760. SafeArrayUnaccessData(psa);
  761. VariantClear(&var);
  762. return hRes;
  763. }
  764. bool CWin9xSecurity::StripOutInheritedAces(CNtSecurityDescriptor& sd)
  765. {
  766. // Get the DACL
  767. CNtAcl* pAcl;
  768. pAcl = sd.GetDacl();
  769. if(!pAcl)
  770. return false;
  771. CDeleteMe<CNtAcl> dm(pAcl);
  772. // enumerate through the aces
  773. DWORD dwNumAces = pAcl->GetNumAces();
  774. BOOL bChanged = FALSE;
  775. for(long nIndex = (long)dwNumAces-1; nIndex >= 0; nIndex--)
  776. {
  777. CNtAce *pAce = pAcl->GetAce(nIndex);
  778. CDeleteMe<CNtAce> dm2(pAce);
  779. if(pAce)
  780. {
  781. long lFlags = pAce->GetFlags();
  782. if(lFlags & INHERITED_ACE)
  783. {
  784. pAcl->DeleteAce(nIndex);
  785. bChanged = TRUE;
  786. }
  787. }
  788. }
  789. if(bChanged)
  790. sd.SetDacl(pAcl);
  791. return true;
  792. }
  793. bool CWin9xSecurity::CopyInheritAces(CNtSecurityDescriptor& sd, CNtSecurityDescriptor& sdParent)
  794. {
  795. // Get the acl list for both SDs
  796. CNtAcl * pacl = sd.GetDacl();
  797. if(pacl == NULL)
  798. return false;
  799. CDeleteMe<CNtAcl> dm0(pacl);
  800. CNtAcl * paclParent = sdParent.GetDacl();
  801. if(paclParent == NULL)
  802. return false;
  803. CDeleteMe<CNtAcl> dm1(paclParent);
  804. int iNumParent = paclParent->GetNumAces();
  805. for(int iCnt = 0; iCnt < iNumParent; iCnt++)
  806. {
  807. CNtAce *pParentAce = paclParent->GetAce(iCnt);
  808. CDeleteMe<CNtAce> dm2(pParentAce);
  809. long lFlags = pParentAce->GetFlags();
  810. if(lFlags & CONTAINER_INHERIT_ACE)
  811. {
  812. if(lFlags & NO_PROPAGATE_INHERIT_ACE)
  813. lFlags ^= CONTAINER_INHERIT_ACE;
  814. lFlags |= INHERITED_ACE;
  815. // If this is an inherit only ace we need to clear this
  816. // in the children.
  817. // NT RAID: 161761 [marioh]
  818. if ( lFlags & INHERIT_ONLY_ACE )
  819. lFlags ^= INHERIT_ONLY_ACE;
  820. pParentAce->SetFlags(lFlags);
  821. pacl->AddAce(pParentAce);
  822. }
  823. }
  824. sd.SetDacl(pacl);
  825. return true;
  826. }
  827. BOOL CWin9xSecurity::SetOwnerAndGroup(CNtSecurityDescriptor &sd)
  828. {
  829. PSID pRawSid;
  830. BOOL bRet = FALSE;
  831. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  832. if(AllocateAndInitializeSid( &id, 2,
  833. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  834. 0,0,0,0,0,0,&pRawSid))
  835. {
  836. CNtSid SidAdmins(pRawSid);
  837. bRet = sd.SetGroup(&SidAdmins); // Access check doesn't really care what you put,
  838. // so long as you put something for the owner
  839. if(bRet)
  840. bRet = sd.SetOwner(&SidAdmins);
  841. FreeSid(pRawSid);
  842. return bRet;
  843. }
  844. return bRet;
  845. }
  846. //
  847. // CNamespaceListSink is used by the query in RecursiveInheritSecurity below
  848. //
  849. class CNamespaceListSink : public CUnkBase<IWbemObjectSink, &IID_IWbemObjectSink>
  850. {
  851. CWStringArray &m_aNamespaceList;
  852. public:
  853. CNamespaceListSink(CWStringArray &aNamespaceList)
  854. : m_aNamespaceList(aNamespaceList)
  855. {
  856. }
  857. ~CNamespaceListSink()
  858. {
  859. }
  860. STDMETHOD(Indicate)(long lNumObjects, IWbemClassObject** apObjects)
  861. {
  862. HRESULT hRes;
  863. for (int i = 0; i != lNumObjects; i++)
  864. {
  865. if (apObjects[i] != NULL)
  866. {
  867. _IWmiObject *pInst = NULL;
  868. hRes = apObjects[i]->QueryInterface(IID__IWmiObject, (void**)&pInst);
  869. if (FAILED(hRes))
  870. return hRes;
  871. CReleaseMe rm(pInst);
  872. BSTR strKey = NULL;
  873. hRes = pInst->GetKeyString(0, &strKey);
  874. if(FAILED(hRes))
  875. return hRes;
  876. CSysFreeMe sfm(strKey);
  877. if (m_aNamespaceList.Add(strKey) != CWStringArray::no_error)
  878. return WBEM_E_OUT_OF_MEMORY;
  879. }
  880. }
  881. return WBEM_S_NO_ERROR;
  882. }
  883. STDMETHOD(SetStatus)(long lFlags, HRESULT hresResult, BSTR, IWbemClassObject*)
  884. {
  885. return WBEM_S_NO_ERROR;
  886. }
  887. };
  888. HRESULT CWin9xSecurity::RecursiveInheritSecurity(CNamespaceHandle* pParentNamespaceHandle, const wchar_t *wszNamespace)
  889. {
  890. // force namespaces to inherit their inheritable security settings
  891. HRESULT hRes = WBEM_S_NO_ERROR;
  892. // get handle to the namespace
  893. CNamespaceHandle* pNamespaceHandle = new CNamespaceHandle(m_pControl, m_pRepository);
  894. if (!pNamespaceHandle)
  895. return WBEM_E_OUT_OF_MEMORY;
  896. pNamespaceHandle->AddRef();
  897. CReleaseMe relme1(pNamespaceHandle);
  898. hRes = pNamespaceHandle->Initialize(wszNamespace);
  899. if (FAILED(hRes))
  900. {
  901. ERRORTRACE((LOG_WBEMCORE, "Failed to connect to namespace; HRESULT = %#lx\n", hRes));
  902. return hRes;
  903. }
  904. // inherit parent's inheritable security if there is a parent
  905. if (pParentNamespaceHandle)
  906. {
  907. CNtSecurityDescriptor sdNamespace;
  908. hRes = GetSDFromNamespace(pNamespaceHandle, sdNamespace);
  909. if (FAILED(hRes))
  910. return hRes;
  911. hRes = GetParentsInheritableAces(pParentNamespaceHandle, sdNamespace);
  912. if (FAILED(hRes))
  913. return hRes;
  914. hRes = SetNamespaceSecurity(pNamespaceHandle, sdNamespace);
  915. if (FAILED(hRes))
  916. return hRes;
  917. }
  918. //Enumerate child namespaces
  919. CWStringArray aListNamespaces;
  920. CNamespaceListSink* pSink = new CNamespaceListSink(aListNamespaces);
  921. if (!pSink)
  922. return WBEM_E_OUT_OF_MEMORY;
  923. pSink->AddRef();
  924. CReleaseMe relme2(pSink);
  925. if (SUCCEEDED(hRes))
  926. {
  927. IWbemQuery *pQuery = NULL;
  928. hRes = CoCreateInstance(CLSID_WbemQuery, NULL, CLSCTX_INPROC_SERVER, IID_IWbemQuery, (void **)&pQuery);
  929. if (FAILED(hRes))
  930. return hRes;
  931. CReleaseMe relme3(pQuery);
  932. hRes = pQuery->Parse(L"SQL", L"select * from __namespace", 0);
  933. if (FAILED(hRes))
  934. return hRes;
  935. hRes = pNamespaceHandle->ExecQuerySink(pQuery, 0, 0, pSink, NULL);
  936. }
  937. //Work through list and call ourselves with that namespace name
  938. if (SUCCEEDED(hRes))
  939. {
  940. for (int i = 0; i != aListNamespaces.Size(); i++)
  941. {
  942. //Build the full name of this namespace
  943. size_t dwChildNamespaceLen = wcslen(wszNamespace) + wcslen(aListNamespaces[i]) + wcslen(L"\\") + 1;
  944. wchar_t *wszChildNamespace = new wchar_t[dwChildNamespaceLen];
  945. if (wszChildNamespace == NULL)
  946. {
  947. hRes = WBEM_E_OUT_OF_MEMORY;
  948. break;
  949. }
  950. CVectorDeleteMe<wchar_t> delMe(wszChildNamespace);
  951. StringCchCopyW(wszChildNamespace, dwChildNamespaceLen, wszNamespace);
  952. StringCchCatW(wszChildNamespace, dwChildNamespaceLen,L"\\");
  953. StringCchCatW(wszChildNamespace, dwChildNamespaceLen,aListNamespaces[i]);
  954. // Do the inherit
  955. hRes = RecursiveInheritSecurity(pNamespaceHandle, wszChildNamespace);
  956. if (FAILED(hRes))
  957. break;
  958. }
  959. }
  960. return hRes;
  961. }
  962. BOOL CWin9xSecurity::DeleteWin9xBlobFile()
  963. {
  964. // delete the file
  965. CFileName wszFilePath;
  966. if (wszFilePath == NULL)
  967. return FALSE;
  968. if (!GetRepositoryDirectory(wszFilePath))
  969. return FALSE;
  970. StringCchCatW(wszFilePath, wszFilePath.Length(), BLOB9X_FILENAME);
  971. return DeleteFileW(wszFilePath);
  972. }
  973. bool CWin9xSecurity::GetRepositoryDirectory(wchar_t wszRepositoryDirectory[MAX_PATH+1])
  974. {
  975. HKEY hKey;
  976. if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\WBEM\\CIMOM", 0, KEY_READ, &hKey))
  977. return false;
  978. wchar_t wszTmp[MAX_PATH + 1];
  979. DWORD dwLen = (MAX_PATH + 1)*sizeof(wchar_t);
  980. long lRes = RegQueryValueExW(hKey, L"Repository Directory", NULL, NULL, (LPBYTE)wszTmp, &dwLen);
  981. RegCloseKey(hKey);
  982. if(lRes)
  983. return false;
  984. if (ExpandEnvironmentStringsW(wszTmp,wszRepositoryDirectory, MAX_PATH + 1) == 0)
  985. return false;
  986. return true;
  987. }
  988. //***************************************************************************
  989. //
  990. // CFlexAceArray::~CFlexAceArray()
  991. //
  992. // Cleans up safe array entries.
  993. //
  994. //***************************************************************************
  995. CFlexAceArray::~CFlexAceArray()
  996. {
  997. for(int iCnt = 0; iCnt < Size(); iCnt++)
  998. {
  999. CBaseAce* pAce = (CBaseAce*)GetAt(iCnt);
  1000. if(pAce)
  1001. delete pAce;
  1002. }
  1003. Empty();
  1004. }
  1005. //***************************************************************************
  1006. //
  1007. // bool CFlexAceArray::DeserializeWin9xSecurityBlob()
  1008. //
  1009. // Description. Deserializes the Win9x pseudo-aces out of a blob.
  1010. // The blob starts off with 5 dwords preceding the aces themselves:
  1011. // <TOTAL SIZE><VERSION><ISNT><ACE_COUNT><RESERVED><ACE> ... <ACE>
  1012. //
  1013. //***************************************************************************
  1014. bool CFlexAceArray::DeserializeWin9xSecurityBlob(const char* pData)
  1015. {
  1016. if (!pData)
  1017. return false;
  1018. DWORD* pdwData = (DWORD*)pData;
  1019. pdwData += 3;
  1020. int iAceCount = (int)*pdwData;
  1021. pdwData += 2;
  1022. // Set the ace data
  1023. BYTE* pAceData = (BYTE*)pdwData;
  1024. DWORD dwAceSize = 0;
  1025. CBaseAce* pAce = NULL;
  1026. for (int iCnt = 0; iCnt < iAceCount; iCnt++)
  1027. {
  1028. // if the user is preceeded by a ".\" advance the pointer past it
  1029. if (wbem_wcsnicmp((WCHAR*)pAceData, L".\\", 2) == 0)
  1030. pAceData += 4;
  1031. dwAceSize = 2*(wcslen((WCHAR*)pAceData) + 1) + 12;
  1032. pAce = new CNtAce();
  1033. if (!pAce)
  1034. return false;
  1035. // Deserialize Win9x pseudo ace into NT ace
  1036. pAce->Deserialize(pAceData);
  1037. // only add ACE's that we were successful in creating
  1038. if (pAce->GetStatus() == 0)
  1039. Add(pAce);
  1040. pAceData += dwAceSize;
  1041. }
  1042. return true;
  1043. }
  1044. //***************************************************************************
  1045. //
  1046. // bool CFlexAceArray::SerializeWinNTSecurityBlob()
  1047. //
  1048. // Description. Serializes the WinNT aces into a blob.
  1049. // The blob starts off with 5 dwords preceding the aces themselves:
  1050. // <TOTAL SIZE><VERSION><ISNT><ACE_COUNT><RESERVED><ACE> ... <ACE>
  1051. //
  1052. // "version" should be 1.
  1053. // "ISNT" should be 1
  1054. //
  1055. //***************************************************************************
  1056. bool CFlexAceArray::SerializeWinNTSecurityBlob(char** ppData)
  1057. {
  1058. // Start by determining the total size needed
  1059. DWORD dwSize = 5 * sizeof(DWORD); // for the header stuff
  1060. int iAceCount = Size(); // get count of aces stored in array
  1061. CBaseAce* pAce = NULL;
  1062. for (int iCnt = 0; iCnt < iAceCount; iCnt++) // add each of the ace sizes
  1063. {
  1064. pAce = (CBaseAce*)GetAt(iCnt);
  1065. if (!pAce)
  1066. return false;
  1067. dwSize += pAce->GetSerializedSize();
  1068. }
  1069. // Allocate the blob, set the pointer from the caller;
  1070. BYTE* pData = new BYTE[dwSize];
  1071. if (!pData)
  1072. return false;
  1073. *ppData = (char*)pData;
  1074. // Set the header info
  1075. DWORD* pdwData = (DWORD *)pData;
  1076. *pdwData = dwSize;
  1077. pdwData++;
  1078. *pdwData = 1; // version
  1079. pdwData++;
  1080. *pdwData = 1; // ISNT
  1081. pdwData++;
  1082. *pdwData = iAceCount;
  1083. pdwData++;
  1084. *pdwData = 0; // reserved
  1085. pdwData++;
  1086. // Set the ace data
  1087. BYTE* pAceData = (BYTE*)pdwData;
  1088. size_t leftSize = dwSize - (pAceData - pData);
  1089. for(iCnt = 0; iCnt < iAceCount; iCnt++)
  1090. {
  1091. pAce = (CBaseAce*)GetAt(iCnt);
  1092. pAce->Serialize(pAceData, leftSize);
  1093. pAceData += pAce->GetSerializedSize();;
  1094. leftSize-=pAce->GetSerializedSize();
  1095. }
  1096. return true;
  1097. }