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.

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