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.

1990 lines
63 KiB

  1. #include "stdafx.h"
  2. #include <conio.h>
  3. #include "dcomperm.h"
  4. #define _WIN32_DCOM
  5. #include <objbase.h>
  6. #define MY_DCOM_PERSIST_FLAG _T("PREEXIST")
  7. int IsValidDaclInSD(PSECURITY_DESCRIPTOR pSD)
  8. {
  9. int iReturn = TRUE;
  10. BOOL present = FALSE;
  11. BOOL defaultDACL = FALSE;
  12. PACL dacl = NULL;
  13. // Check if the SD is valid
  14. if (!IsValidSecurityDescriptor(pSD))
  15. {
  16. iisDebugOut((LOG_TYPE_ERROR, _T("IsValidDaclInSD:IsValidSecurityDescriptor FAILED")));
  17. iReturn = FALSE;
  18. }
  19. else
  20. {
  21. // Check if the dacl we got is valid...
  22. if (!GetSecurityDescriptorDacl (pSD, &present, &dacl, &defaultDACL))
  23. {
  24. iisDebugOut((LOG_TYPE_ERROR, _T("IsValidDaclInSD:GetSecurityDescriptorDacl FAILED")));
  25. iReturn = FALSE;
  26. }
  27. else
  28. {
  29. if (present)
  30. {
  31. // check if our sd is valid after call
  32. if (!IsValidSecurityDescriptor(pSD))
  33. {
  34. iisDebugOut((LOG_TYPE_ERROR, _T("IsValidDaclInSD:IsValidSecurityDescriptor FAILED")));
  35. iReturn = FALSE;
  36. }
  37. else
  38. {
  39. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsValidDaclInSD:SD has valid dacl")));
  40. }
  41. }
  42. }
  43. }
  44. return iReturn;
  45. }
  46. DWORD
  47. CopyACL (
  48. PACL OldACL,
  49. PACL NewACL
  50. )
  51. {
  52. ACL_SIZE_INFORMATION aclSizeInfo;
  53. LPVOID ace;
  54. ACE_HEADER *aceHeader;
  55. ULONG i;
  56. DWORD returnValue = ERROR_SUCCESS;
  57. if (0 == IsValidAcl(OldACL))
  58. {
  59. iisDebugOut((LOG_TYPE_ERROR, _T("CopyACL:IsValidAcl.FAILED.ACL is bad.")));
  60. returnValue = ERROR_INVALID_ACL;
  61. return returnValue;
  62. }
  63. if (0 == GetAclInformation (OldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof (aclSizeInfo), AclSizeInformation))
  64. {
  65. returnValue = GetLastError();
  66. iisDebugOut((LOG_TYPE_ERROR, _T("CopyACL:GetAclInformation.FAILED.Return=0x%x."), returnValue));
  67. return returnValue;
  68. }
  69. //
  70. // Copy all of the ACEs to the new ACL
  71. //
  72. for (i = 0; i < aclSizeInfo.AceCount; i++)
  73. {
  74. //
  75. // Get the ACE and header info
  76. //
  77. if (!GetAce (OldACL, i, &ace))
  78. {
  79. returnValue = GetLastError();
  80. iisDebugOut((LOG_TYPE_ERROR, _T("CopyACL:GetAce.FAILED.Return=0x%x."), returnValue));
  81. return returnValue;
  82. }
  83. aceHeader = (ACE_HEADER *) ace;
  84. //
  85. // Add the ACE to the new list
  86. //
  87. if (!AddAce (NewACL, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  88. {
  89. returnValue = GetLastError();
  90. iisDebugOut((LOG_TYPE_ERROR, _T("CopyACL:AddAce.FAILED.Return=0x%x."), returnValue));
  91. return returnValue;
  92. }
  93. }
  94. return returnValue;
  95. }
  96. //
  97. // Ace's within in ACL must be ordered in a particular way.
  98. // if they are not then you will get errors when you try to look at the
  99. // security on the file/dir/object.
  100. //
  101. // They should be ordered this way:
  102. // -------------
  103. // 1. on the top are non-inheritied ACE's
  104. // Access-denied ACEs that apply to the object itself
  105. // Access-denied ACEs that apply to a subobject of the object, such as a property set or property
  106. // Access-allowed ACEs that apply to the object itself
  107. // Access-allowed ACEs that apply to a subobject of the object
  108. // 2. on the bottom are non-inheritied ACE's
  109. // Access-denied ACEs that apply to the object itself
  110. // Access-denied ACEs that apply to a subobject of the object, such as a property set or property
  111. // Access-allowed ACEs that apply to the object itself
  112. // Access-allowed ACEs that apply to a subobject of the object
  113. //
  114. // returns ERROR_SUCCESS if the acl is successfully reordered into the newAcl
  115. // otherwise, returns an error with nothing in the newacl
  116. //
  117. // WARNING: the OldACL that is passed in should have been alloced with LocalAlloc(), since it
  118. // Will be freed with LocalFree()
  119. //
  120. DWORD
  121. ReOrderACL(
  122. PACL *ACLtoReplace
  123. )
  124. {
  125. DWORD returnValue = ERROR_INVALID_PARAMETER;
  126. ACL_SIZE_INFORMATION aclSizeInfo;
  127. LPVOID ace = NULL;
  128. ACE_HEADER *aceHeader = NULL;
  129. ULONG i = 0;
  130. DWORD dwLength = 0;
  131. PACL NewACL = NULL;
  132. PACL New_ACL_AccessDenied = NULL;
  133. PACL New_ACL_AccessAllowed = NULL;
  134. PACL New_ACL_InheritedAccessDenied = NULL;
  135. PACL New_ACL_InheritedAccessAllowed = NULL;
  136. ULONG lAllowCount = 0L;
  137. ULONG lDenyCount = 0L;
  138. ULONG lInheritedAllowCount = 0L;
  139. ULONG lInheritedDenyCount = 0L;
  140. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ReOrderACL:start\n")));
  141. if (0 == IsValidAcl(*ACLtoReplace))
  142. {
  143. returnValue = ERROR_INVALID_ACL;
  144. goto ReOrderACL_Exit;
  145. }
  146. if (0 == GetAclInformation (*ACLtoReplace, (LPVOID) &aclSizeInfo, (DWORD) sizeof (aclSizeInfo), AclSizeInformation))
  147. {
  148. returnValue = GetLastError();
  149. goto ReOrderACL_Exit;
  150. }
  151. // There are four main types of ACE's we are concerned with:
  152. // access denied,
  153. // access allowed,
  154. // inherited access denied
  155. // inherited access allowed.
  156. //
  157. // We will construct 4 arrays and copy elements
  158. // into them, then recopy to the original.
  159. //
  160. // If, along the way, we encounter a system audit type ace, just stick it in the access denied list,
  161. // as we are dealing in that case with a SACL, for which there is no proper ordering.
  162. dwLength = aclSizeInfo.AclBytesInUse;
  163. // Create a new ACL that we we eventually copy everything in to and hand back.
  164. NewACL = (PACL) LocalAlloc(LMEM_FIXED, dwLength);
  165. if(NewACL == NULL) {returnValue = ERROR_NOT_ENOUGH_MEMORY;goto ReOrderACL_Exit;}
  166. if(!InitializeAcl(NewACL, dwLength, ACL_REVISION)) {returnValue = GetLastError();goto ReOrderACL_Exit;}
  167. // Create a new ACL for Access Denied
  168. New_ACL_AccessDenied = (PACL) LocalAlloc(LMEM_FIXED, dwLength);
  169. if(New_ACL_AccessDenied == NULL) {returnValue = ERROR_NOT_ENOUGH_MEMORY;goto ReOrderACL_Exit;}
  170. if(!InitializeAcl(New_ACL_AccessDenied, dwLength, ACL_REVISION)) {returnValue = GetLastError();goto ReOrderACL_Exit;}
  171. // Create a new ACL for Access Allowed
  172. New_ACL_AccessAllowed = (PACL) LocalAlloc(LMEM_FIXED, dwLength);
  173. if(New_ACL_AccessAllowed == NULL) {returnValue = ERROR_NOT_ENOUGH_MEMORY;goto ReOrderACL_Exit;}
  174. if(!InitializeAcl(New_ACL_AccessAllowed, dwLength, ACL_REVISION)) {returnValue = GetLastError();goto ReOrderACL_Exit;}
  175. // Create a new ACL for Inherited Access Denied
  176. New_ACL_InheritedAccessDenied = (PACL) LocalAlloc(LMEM_FIXED, dwLength);
  177. if(New_ACL_InheritedAccessDenied == NULL) {returnValue = ERROR_NOT_ENOUGH_MEMORY;goto ReOrderACL_Exit;}
  178. if(!InitializeAcl(New_ACL_InheritedAccessDenied, dwLength, ACL_REVISION)) {returnValue = GetLastError();goto ReOrderACL_Exit;}
  179. // Create a new ACL for Inherited Access Allowed
  180. New_ACL_InheritedAccessAllowed = (PACL) LocalAlloc(LMEM_FIXED, dwLength);
  181. if(New_ACL_InheritedAccessAllowed == NULL) {returnValue = ERROR_NOT_ENOUGH_MEMORY;goto ReOrderACL_Exit;}
  182. if(!InitializeAcl(New_ACL_InheritedAccessAllowed, dwLength, ACL_REVISION)) {returnValue = GetLastError();goto ReOrderACL_Exit;}
  183. //
  184. // Copy all of the ACEs to the new ACLs
  185. //
  186. for (i = 0; i < aclSizeInfo.AceCount; i++)
  187. {
  188. //
  189. // Get the ACE and header info
  190. //
  191. ace = NULL;
  192. if (!GetAce (*ACLtoReplace, i, &ace))
  193. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  194. // Get the header
  195. aceHeader = (ACE_HEADER *) ace;
  196. // Check the type
  197. if(aceHeader->AceType == ACCESS_DENIED_ACE_TYPE || aceHeader->AceType == ACCESS_DENIED_OBJECT_ACE_TYPE)
  198. {
  199. if(aceHeader->AceFlags & INHERITED_ACE)
  200. {
  201. // Add the ACE to the appropriate ACL
  202. if (!AddAce (New_ACL_InheritedAccessDenied, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  203. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  204. lInheritedDenyCount++;
  205. }
  206. else
  207. {
  208. // Add the ACE to the appropriate ACL
  209. if (!AddAce (New_ACL_AccessDenied, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  210. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  211. lDenyCount++;
  212. }
  213. }
  214. else if(aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE || aceHeader->AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE)
  215. {
  216. if(aceHeader->AceFlags & INHERITED_ACE)
  217. {
  218. // Add the ACE to the appropriate ACL
  219. if (!AddAce (New_ACL_InheritedAccessAllowed, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  220. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  221. lInheritedAllowCount++;
  222. }
  223. else
  224. {
  225. // Add the ACE to the appropriate ACL
  226. if (!AddAce (New_ACL_AccessAllowed, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  227. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  228. lAllowCount++;
  229. }
  230. }
  231. else if(aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE)
  232. {
  233. // This doesn't matter
  234. // so lets just add this all to the New_ACL_AccessDenied list
  235. if (!AddAce (New_ACL_AccessDenied, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  236. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  237. lDenyCount++;
  238. }
  239. else
  240. {
  241. returnValue = ERROR_INVALID_PARAMETER;
  242. goto ReOrderACL_Exit;
  243. }
  244. }
  245. if(lDenyCount || lAllowCount || lInheritedDenyCount || lInheritedAllowCount)
  246. {
  247. DWORD dwTotalCount = 0;
  248. aceHeader = NULL;
  249. // First copy over the local deny aces...
  250. for (i = 0; i < lDenyCount; i++)
  251. {
  252. ace = NULL;
  253. if (!GetAce (New_ACL_AccessDenied, i, &ace))
  254. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  255. aceHeader = (ACE_HEADER *) ace;
  256. if (!AddAce (NewACL, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  257. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  258. dwTotalCount++;
  259. }
  260. // Then copy over the local allow aces...
  261. for (i = 0; i < lAllowCount; i++)
  262. {
  263. ace = NULL;
  264. if (!GetAce (New_ACL_AccessAllowed, i, &ace))
  265. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  266. aceHeader = (ACE_HEADER *) ace;
  267. if (!AddAce (NewACL, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  268. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  269. dwTotalCount++;
  270. }
  271. // Then copy over the inherited deny aces...
  272. for (i = 0; i < lInheritedDenyCount; i++)
  273. {
  274. ace = NULL;
  275. if (!GetAce (New_ACL_InheritedAccessDenied, i, &ace))
  276. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  277. aceHeader = (ACE_HEADER *) ace;
  278. if (!AddAce (NewACL, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  279. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  280. dwTotalCount++;
  281. }
  282. // Then copy over the inherited allow aces...
  283. for (i = 0; i < lInheritedAllowCount; i++)
  284. {
  285. ace = NULL;
  286. if (!GetAce (New_ACL_InheritedAccessAllowed, i, &ace))
  287. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  288. aceHeader = (ACE_HEADER *) ace;
  289. if (!AddAce (NewACL, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  290. {returnValue = GetLastError();goto ReOrderACL_Exit;}
  291. dwTotalCount++;
  292. }
  293. // Remove the old ACL, and set it to the new acl
  294. if (*ACLtoReplace){LocalFree(*ACLtoReplace);*ACLtoReplace=NULL;}
  295. *ACLtoReplace = NewACL;
  296. if (*ACLtoReplace)
  297. {
  298. returnValue = ERROR_SUCCESS;
  299. }
  300. // Verify that amount of ACE's going out
  301. // are the same that came in..
  302. if (aclSizeInfo.AceCount != dwTotalCount)
  303. {
  304. // There is something majorly wrong
  305. iisDebugOut((LOG_TYPE_ERROR, _T("ReOrderACL:in diff from out\n")));
  306. }
  307. }
  308. else
  309. {
  310. returnValue = ERROR_INVALID_ACL;
  311. }
  312. ReOrderACL_Exit:
  313. if (New_ACL_AccessDenied){LocalFree(New_ACL_AccessDenied);New_ACL_AccessDenied=NULL;}
  314. if (New_ACL_AccessAllowed){LocalFree(New_ACL_AccessAllowed);New_ACL_AccessAllowed=NULL;}
  315. if (New_ACL_InheritedAccessDenied){LocalFree(New_ACL_InheritedAccessDenied);New_ACL_InheritedAccessDenied=NULL;}
  316. if (New_ACL_InheritedAccessAllowed){LocalFree(New_ACL_InheritedAccessAllowed);New_ACL_InheritedAccessAllowed=NULL;}
  317. if (returnValue != ERROR_SUCCESS)
  318. {
  319. iisDebugOut((LOG_TYPE_ERROR, _T("ReOrderACL:FAILED with code=0x%x\n"), returnValue));
  320. }
  321. return returnValue;
  322. }
  323. DWORD
  324. AddAccessDeniedACEToACL (
  325. PACL *Acl,
  326. DWORD PermissionMask,
  327. LPTSTR Principal
  328. )
  329. {
  330. ACL_SIZE_INFORMATION aclSizeInfo;
  331. int aclSize;
  332. DWORD returnValue = ERROR_SUCCESS;
  333. PSID principalSID = NULL;
  334. PACL newACL = NULL;
  335. PACL oldACL = NULL;
  336. BOOL bWellKnownSID = FALSE;
  337. oldACL = *Acl;
  338. returnValue = GetPrincipalSID (Principal, &principalSID, &bWellKnownSID);
  339. if (returnValue != ERROR_SUCCESS)
  340. return returnValue;
  341. if (0 == IsValidAcl(oldACL))
  342. {
  343. iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessDeniedACEToACL:IsValidAcl.FAILED.ACL is bad.")));
  344. returnValue = ERROR_INVALID_ACL;
  345. return returnValue;
  346. }
  347. if (0 == GetAclInformation (oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof (ACL_SIZE_INFORMATION), AclSizeInformation))
  348. {
  349. returnValue = GetLastError();
  350. goto cleanup;
  351. }
  352. aclSize = aclSizeInfo.AclBytesInUse +
  353. sizeof (ACL) + sizeof (ACCESS_DENIED_ACE) +
  354. GetLengthSid (principalSID) - sizeof (DWORD);
  355. newACL = (PACL) new BYTE [aclSize];
  356. if (!InitializeAcl (newACL, aclSize, ACL_REVISION))
  357. {
  358. returnValue = GetLastError();
  359. goto cleanup;
  360. }
  361. if (!AddAccessDeniedAce (newACL, ACL_REVISION, PermissionMask, principalSID))
  362. {
  363. returnValue = GetLastError();
  364. goto cleanup;
  365. }
  366. returnValue = CopyACL (oldACL, newACL);
  367. if (returnValue != ERROR_SUCCESS)
  368. {
  369. goto cleanup;
  370. }
  371. // cleanup old memory whose pointer we're replacing
  372. // okay to leak in setup... (need to comment out or else av's)
  373. //if (*Acl) {delete(*Acl);}
  374. *Acl = newACL;
  375. newACL = NULL;
  376. cleanup:
  377. if (principalSID) {
  378. if (bWellKnownSID)
  379. FreeSid (principalSID);
  380. else
  381. free (principalSID);
  382. }
  383. if (newACL)
  384. {
  385. delete [] newACL;
  386. newACL = NULL;
  387. }
  388. return returnValue;
  389. }
  390. DWORD
  391. AddAccessAllowedACEToACL (
  392. PACL *Acl,
  393. DWORD PermissionMask,
  394. LPTSTR Principal
  395. )
  396. {
  397. ACL_SIZE_INFORMATION aclSizeInfo;
  398. int aclSize;
  399. DWORD returnValue = ERROR_SUCCESS;
  400. PSID principalSID = NULL;
  401. PACL oldACL = NULL;
  402. PACL newACL = NULL;
  403. BOOL bWellKnownSID = FALSE;
  404. oldACL = *Acl;
  405. // check if the acl we got passed in is valid!
  406. if (0 == IsValidAcl(oldACL))
  407. {
  408. returnValue = ERROR_INVALID_ACL;
  409. iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedACEToACL:IsValidAcl.FAILED.ACL we got passed in is bad1.")));
  410. goto cleanup;
  411. }
  412. returnValue = GetPrincipalSID (Principal, &principalSID, &bWellKnownSID);
  413. if (returnValue != ERROR_SUCCESS)
  414. {
  415. iisDebugOut((LOG_TYPE_ERROR, _T("GetPrincipalSID.FAILED.Return=0x%x."), returnValue));
  416. return returnValue;
  417. }
  418. if (0 == GetAclInformation (oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof (ACL_SIZE_INFORMATION), AclSizeInformation))
  419. {
  420. returnValue = GetLastError();
  421. iisDebugOut((LOG_TYPE_ERROR, _T("GetAclInformation.FAILED.Return=0x%x."), returnValue));
  422. goto cleanup;
  423. }
  424. aclSize = aclSizeInfo.AclBytesInUse +
  425. sizeof (ACL) + sizeof (ACCESS_ALLOWED_ACE) +
  426. GetLengthSid (principalSID) - sizeof (DWORD);
  427. newACL = (PACL) new BYTE [aclSize];
  428. if (!InitializeAcl (newACL, aclSize, ACL_REVISION))
  429. {
  430. returnValue = GetLastError();
  431. iisDebugOut((LOG_TYPE_ERROR, _T("InitializeAcl.FAILED.Return=0x%x."), returnValue));
  432. goto cleanup;
  433. }
  434. returnValue = CopyACL (oldACL, newACL);
  435. if (returnValue != ERROR_SUCCESS)
  436. {
  437. iisDebugOut((LOG_TYPE_ERROR, _T("CopyACL.FAILED.Return=0x%x."), returnValue));
  438. goto cleanup;
  439. }
  440. //if (!AddAccessAllowedAce (newACL, ACL_REVISION2, PermissionMask, principalSID))
  441. if (!AddAccessAllowedAce (newACL, ACL_REVISION, PermissionMask, principalSID))
  442. {
  443. returnValue = GetLastError();
  444. iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedAce.FAILED.Return=0x%x."), returnValue));
  445. goto cleanup;
  446. }
  447. // check if the acl is valid!
  448. /*
  449. if (0 == IsValidAcl(newACL))
  450. {
  451. returnValue = ERROR_INVALID_ACL;
  452. iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedACEToACL:IsValidAcl.FAILED.ACL we are pasing out is bad.")));
  453. goto cleanup;
  454. }
  455. */
  456. // cleanup old memory whose pointer we're replacing
  457. // okay to leak in setup... (need to comment out or else av's)
  458. //if (*Acl) {delete(*Acl);}
  459. *Acl = newACL;
  460. newACL = NULL;
  461. cleanup:
  462. if (principalSID) {
  463. if (bWellKnownSID)
  464. FreeSid (principalSID);
  465. else
  466. free (principalSID);
  467. }
  468. if (newACL)
  469. {
  470. delete [] newACL;
  471. newACL = NULL;
  472. }
  473. return returnValue;
  474. }
  475. DWORD
  476. RemovePrincipalFromACL (
  477. PACL Acl,
  478. LPTSTR Principal,
  479. BOOL *pbUserExistsToBeDeleted
  480. )
  481. {
  482. ACL_SIZE_INFORMATION aclSizeInfo;
  483. ULONG i;
  484. LPVOID ace;
  485. ACCESS_ALLOWED_ACE *accessAllowedAce;
  486. ACCESS_DENIED_ACE *accessDeniedAce;
  487. SYSTEM_AUDIT_ACE *systemAuditAce;
  488. PSID principalSID = NULL;
  489. DWORD returnValue = ERROR_SUCCESS;
  490. ACE_HEADER *aceHeader;
  491. BOOL bWellKnownSID = FALSE;
  492. *pbUserExistsToBeDeleted = FALSE;
  493. returnValue = GetPrincipalSID (Principal, &principalSID, &bWellKnownSID);
  494. if (returnValue != ERROR_SUCCESS)
  495. return returnValue;
  496. // check if the acl we got passed in is valid!
  497. if (0 == IsValidAcl(Acl))
  498. {
  499. iisDebugOut((LOG_TYPE_ERROR, _T("RemovePrincipalFromACL:IsValidAcl.FAILED.ACL is bad.")));
  500. returnValue = ERROR_INVALID_ACL;
  501. return returnValue;
  502. }
  503. if (0 == GetAclInformation (Acl, (LPVOID) &aclSizeInfo, (DWORD) sizeof (ACL_SIZE_INFORMATION), AclSizeInformation))
  504. {
  505. returnValue = GetLastError();
  506. return returnValue;
  507. }
  508. for (i = 0; i < aclSizeInfo.AceCount; i++)
  509. {
  510. if (!GetAce (Acl, i, &ace))
  511. {
  512. returnValue = GetLastError();
  513. break;
  514. }
  515. aceHeader = (ACE_HEADER *) ace;
  516. if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  517. {
  518. accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace;
  519. if (EqualSid (principalSID, (PSID) &accessAllowedAce->SidStart))
  520. {
  521. DeleteAce (Acl, i);
  522. *pbUserExistsToBeDeleted = TRUE;
  523. break;
  524. }
  525. } else
  526. if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  527. {
  528. accessDeniedAce = (ACCESS_DENIED_ACE *) ace;
  529. if (EqualSid (principalSID, (PSID) &accessDeniedAce->SidStart))
  530. {
  531. DeleteAce (Acl, i);
  532. *pbUserExistsToBeDeleted = TRUE;
  533. break;
  534. }
  535. } else
  536. if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE)
  537. {
  538. systemAuditAce = (SYSTEM_AUDIT_ACE *) ace;
  539. if (EqualSid (principalSID, (PSID) &systemAuditAce->SidStart))
  540. {
  541. DeleteAce (Acl, i);
  542. *pbUserExistsToBeDeleted = TRUE;
  543. break;
  544. }
  545. }
  546. }
  547. if (principalSID) {
  548. if (bWellKnownSID)
  549. FreeSid (principalSID);
  550. else
  551. free (principalSID);
  552. }
  553. return returnValue;
  554. }
  555. DWORD
  556. GetCurrentUserSID (
  557. PSID *Sid
  558. )
  559. {
  560. DWORD dwReturn = ERROR_SUCCESS;
  561. TOKEN_USER *tokenUser = NULL;
  562. HANDLE tokenHandle = NULL;
  563. DWORD tokenSize;
  564. DWORD sidLength;
  565. if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &tokenHandle))
  566. {
  567. GetTokenInformation (tokenHandle, TokenUser, tokenUser, 0, &tokenSize);
  568. tokenUser = (TOKEN_USER *) malloc (tokenSize);
  569. if (!tokenUser)
  570. {
  571. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  572. return GetLastError();
  573. }
  574. if (GetTokenInformation (tokenHandle, TokenUser, tokenUser, tokenSize, &tokenSize))
  575. {
  576. sidLength = GetLengthSid (tokenUser->User.Sid);
  577. *Sid = (PSID) malloc (sidLength);
  578. if (*Sid)
  579. {
  580. memcpy (*Sid, tokenUser->User.Sid, sidLength);
  581. }
  582. CloseHandle (tokenHandle);
  583. } else
  584. dwReturn = GetLastError();
  585. if (tokenUser)
  586. free(tokenUser);
  587. } else
  588. dwReturn = GetLastError();
  589. return dwReturn;
  590. }
  591. DWORD
  592. GetPrincipalSID (
  593. LPTSTR Principal,
  594. PSID *Sid,
  595. BOOL *pbWellKnownSID
  596. )
  597. {
  598. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetPrincipalSID():Principal=%s\n"), Principal));
  599. DWORD returnValue=ERROR_SUCCESS;
  600. TSTR strPrincipal;
  601. SID_IDENTIFIER_AUTHORITY SidIdentifierNTAuthority = SECURITY_NT_AUTHORITY;
  602. SID_IDENTIFIER_AUTHORITY SidIdentifierWORLDAuthority = SECURITY_WORLD_SID_AUTHORITY;
  603. PSID_IDENTIFIER_AUTHORITY pSidIdentifierAuthority;
  604. BYTE Count;
  605. DWORD dwRID[8];
  606. if ( !strPrincipal.Copy( Principal ) )
  607. {
  608. return ERROR_NOT_ENOUGH_MEMORY;
  609. }
  610. *pbWellKnownSID = TRUE;
  611. memset(&(dwRID[0]), 0, 8 * sizeof(DWORD));
  612. if ( strPrincipal.SubStringExists( _T("administrators"), FALSE ) ) {
  613. // Administrators group
  614. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  615. Count = 2;
  616. dwRID[0] = SECURITY_BUILTIN_DOMAIN_RID;
  617. dwRID[1] = DOMAIN_ALIAS_RID_ADMINS;
  618. } else if ( strPrincipal.SubStringExists( _T("system"), FALSE ) ) {
  619. // SYSTEM
  620. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  621. Count = 1;
  622. dwRID[0] = SECURITY_LOCAL_SYSTEM_RID;
  623. } else if ( strPrincipal.SubStringExists( _T("networkservice"), FALSE ) ) {
  624. // SYSTEM
  625. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  626. Count = 1;
  627. dwRID[0] = SECURITY_NETWORK_SERVICE_RID;
  628. } else if ( strPrincipal.SubStringExists( _T("service"), FALSE ) ) {
  629. // SYSTEM
  630. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  631. Count = 1;
  632. dwRID[0] = SECURITY_LOCAL_SERVICE_RID;
  633. } else if ( strPrincipal.SubStringExists( _T("interactive"), FALSE ) ) {
  634. // INTERACTIVE
  635. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  636. Count = 1;
  637. dwRID[0] = SECURITY_INTERACTIVE_RID;
  638. } else if ( strPrincipal.SubStringExists( _T("everyone"), FALSE ) ) {
  639. // Everyone
  640. pSidIdentifierAuthority = &SidIdentifierWORLDAuthority;
  641. Count = 1;
  642. dwRID[0] = SECURITY_WORLD_RID;
  643. } else {
  644. *pbWellKnownSID = FALSE;
  645. }
  646. if (*pbWellKnownSID) {
  647. if ( !AllocateAndInitializeSid(pSidIdentifierAuthority,
  648. (BYTE)Count,
  649. dwRID[0],
  650. dwRID[1],
  651. dwRID[2],
  652. dwRID[3],
  653. dwRID[4],
  654. dwRID[5],
  655. dwRID[6],
  656. dwRID[7],
  657. Sid) ) {
  658. returnValue = GetLastError();
  659. }
  660. } else {
  661. // get regular account sid
  662. DWORD sidSize;
  663. TCHAR refDomain [256];
  664. DWORD refDomainSize;
  665. SID_NAME_USE snu;
  666. sidSize = 0;
  667. refDomainSize = 255;
  668. LookupAccountName (NULL,
  669. Principal,
  670. *Sid,
  671. &sidSize,
  672. refDomain,
  673. &refDomainSize,
  674. &snu);
  675. returnValue = GetLastError();
  676. if (returnValue == ERROR_INSUFFICIENT_BUFFER) {
  677. *Sid = (PSID) malloc (sidSize);
  678. if (!*Sid)
  679. {
  680. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  681. return GetLastError();
  682. }
  683. refDomainSize = 255;
  684. if (!LookupAccountName (NULL,
  685. Principal,
  686. *Sid,
  687. &sidSize,
  688. refDomain,
  689. &refDomainSize,
  690. &snu))
  691. {
  692. returnValue = GetLastError();
  693. } else {
  694. returnValue = ERROR_SUCCESS;
  695. }
  696. }
  697. }
  698. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetPrincipalSID():Ret=0x%x."), returnValue));
  699. return returnValue;
  700. }
  701. DWORD
  702. CreateNewSD (
  703. SECURITY_DESCRIPTOR **SD
  704. )
  705. {
  706. PACL dacl = NULL;
  707. DWORD sidLength;
  708. PSID sid;
  709. PSID groupSID;
  710. PSID ownerSID;
  711. DWORD returnValue;
  712. *SD = NULL;
  713. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("CreateNewSD()")));
  714. returnValue = GetCurrentUserSID (&sid);
  715. if (returnValue != ERROR_SUCCESS) {
  716. if (sid)
  717. free(sid);
  718. iisDebugOut((LOG_TYPE_ERROR, _T("CreateNewSD.FAILED1.Return=0x%x."), returnValue));
  719. return returnValue;
  720. }
  721. sidLength = GetLengthSid (sid);
  722. *SD = (SECURITY_DESCRIPTOR *) malloc (
  723. (sizeof (ACL)+sizeof (ACCESS_ALLOWED_ACE)+sidLength) +
  724. (2 * sidLength) +
  725. sizeof (SECURITY_DESCRIPTOR));
  726. if (!*SD)
  727. {
  728. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  729. returnValue = GetLastError();
  730. iisDebugOut((LOG_TYPE_ERROR, _T("CreateNewSD.FAILED2.Return=0x%x."), returnValue));
  731. return returnValue;
  732. }
  733. groupSID = (SID *) (*SD + 1);
  734. ownerSID = (SID *) (((BYTE *) groupSID) + sidLength);
  735. dacl = (ACL *) (((BYTE *) ownerSID) + sidLength);
  736. if (!InitializeSecurityDescriptor (*SD, SECURITY_DESCRIPTOR_REVISION))
  737. {
  738. free (*SD);
  739. free (sid);
  740. returnValue = GetLastError();
  741. iisDebugOut((LOG_TYPE_ERROR, _T("CreateNewSD.FAILED3.Return=0x%x."), returnValue));
  742. return returnValue;
  743. }
  744. if (!InitializeAcl (dacl,
  745. sizeof (ACL)+sizeof (ACCESS_ALLOWED_ACE)+sidLength,
  746. ACL_REVISION2))
  747. {
  748. free (*SD);
  749. free (sid);
  750. returnValue = GetLastError();
  751. iisDebugOut((LOG_TYPE_ERROR, _T("CreateNewSD.FAILED4.Return=0x%x."), returnValue));
  752. return returnValue;
  753. }
  754. if (!AddAccessAllowedAce (dacl,
  755. ACL_REVISION2,
  756. COM_RIGHTS_EXECUTE,
  757. sid))
  758. {
  759. free (*SD);
  760. free (sid);
  761. returnValue = GetLastError();
  762. iisDebugOut((LOG_TYPE_ERROR, _T("CreateNewSD.FAILED5.Return=0x%x."), returnValue));
  763. return returnValue;
  764. }
  765. if (!SetSecurityDescriptorDacl (*SD, TRUE, dacl, FALSE))
  766. {
  767. free (*SD);
  768. free (sid);
  769. returnValue = GetLastError();
  770. iisDebugOut((LOG_TYPE_ERROR, _T("CreateNewSD.FAILED6.Return=0x%x."), returnValue));
  771. return returnValue;
  772. }
  773. memcpy (groupSID, sid, sidLength);
  774. if (!SetSecurityDescriptorGroup (*SD, groupSID, FALSE))
  775. {
  776. free (*SD);
  777. free (sid);
  778. returnValue = GetLastError();
  779. iisDebugOut((LOG_TYPE_ERROR, _T("CreateNewSD.FAILED7.Return=0x%x."), returnValue));
  780. return returnValue;
  781. }
  782. memcpy (ownerSID, sid, sidLength);
  783. if (!SetSecurityDescriptorOwner (*SD, ownerSID, FALSE))
  784. {
  785. free (*SD);
  786. free (sid);
  787. returnValue = GetLastError();
  788. iisDebugOut((LOG_TYPE_ERROR, _T("CreateNewSD.FAILED8.Return=0x%x."), returnValue));
  789. return returnValue;
  790. }
  791. // check if everything went ok
  792. if (!IsValidSecurityDescriptor(*SD))
  793. {
  794. free (*SD);
  795. free (sid);
  796. returnValue = ERROR_INVALID_SECURITY_DESCR;
  797. iisDebugOut((LOG_TYPE_ERROR, _T("CreateNewSD.IsValidDaclInSD.FAILED.Return=0x%x."), returnValue));
  798. return returnValue;
  799. }
  800. if (sid)
  801. free(sid);
  802. return ERROR_SUCCESS;
  803. }
  804. DWORD
  805. MakeSDAbsolute (
  806. PSECURITY_DESCRIPTOR OldSD,
  807. PSECURITY_DESCRIPTOR *NewSD
  808. )
  809. {
  810. PSECURITY_DESCRIPTOR sd = NULL;
  811. DWORD descriptorSize;
  812. DWORD daclSize;
  813. DWORD saclSize;
  814. DWORD ownerSIDSize;
  815. DWORD groupSIDSize;
  816. PACL dacl = NULL;
  817. PACL sacl = NULL;
  818. PSID ownerSID = NULL;
  819. PSID groupSID = NULL;
  820. BOOL present;
  821. BOOL systemDefault;
  822. //
  823. // Get SACL
  824. //
  825. if (!GetSecurityDescriptorSacl (OldSD, &present, &sacl, &systemDefault))
  826. return GetLastError();
  827. if (sacl && present)
  828. {
  829. saclSize = sacl->AclSize;
  830. } else saclSize = 0;
  831. //
  832. // Get DACL
  833. //
  834. if (!GetSecurityDescriptorDacl (OldSD, &present, &dacl, &systemDefault))
  835. return GetLastError();
  836. if (dacl && present)
  837. {
  838. daclSize = dacl->AclSize;
  839. } else daclSize = 0;
  840. //
  841. // Get Owner
  842. //
  843. if (!GetSecurityDescriptorOwner (OldSD, &ownerSID, &systemDefault))
  844. return GetLastError();
  845. ownerSIDSize = GetLengthSid (ownerSID);
  846. //
  847. // Get Group
  848. //
  849. if (!GetSecurityDescriptorGroup (OldSD, &groupSID, &systemDefault))
  850. return GetLastError();
  851. groupSIDSize = GetLengthSid (groupSID);
  852. //
  853. // Do the conversion
  854. //
  855. descriptorSize = 0;
  856. MakeAbsoluteSD (OldSD, sd, &descriptorSize, dacl, &daclSize, sacl,
  857. &saclSize, ownerSID, &ownerSIDSize, groupSID,
  858. &groupSIDSize);
  859. sd = (PSECURITY_DESCRIPTOR) new BYTE [SECURITY_DESCRIPTOR_MIN_LENGTH];
  860. if (!sd)
  861. {
  862. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  863. return GetLastError();
  864. }
  865. if (!InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION))
  866. return GetLastError();
  867. if (!MakeAbsoluteSD (OldSD, sd, &descriptorSize, dacl, &daclSize, sacl,
  868. &saclSize, ownerSID, &ownerSIDSize, groupSID,
  869. &groupSIDSize))
  870. return GetLastError();
  871. *NewSD = sd;
  872. return ERROR_SUCCESS;
  873. }
  874. DWORD
  875. SetNamedValueSD (
  876. HKEY RootKey,
  877. LPTSTR KeyName,
  878. LPTSTR ValueName,
  879. SECURITY_DESCRIPTOR *SD
  880. )
  881. {
  882. DWORD returnValue;
  883. DWORD disposition;
  884. HKEY registryKey;
  885. //
  886. // Create new key or open existing key
  887. //
  888. returnValue = RegCreateKeyEx (RootKey, KeyName, 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &registryKey, &disposition);
  889. if (returnValue != ERROR_SUCCESS)
  890. return returnValue;
  891. //
  892. // Write the security descriptor
  893. //
  894. returnValue = RegSetValueEx (registryKey, ValueName, 0, REG_BINARY, (LPBYTE) SD, GetSecurityDescriptorLength (SD));
  895. if (returnValue != ERROR_SUCCESS)
  896. return returnValue;
  897. RegCloseKey (registryKey);
  898. return ERROR_SUCCESS;
  899. }
  900. DWORD
  901. GetNamedValueSD (
  902. HKEY RootKey,
  903. LPTSTR KeyName,
  904. LPTSTR ValueName,
  905. SECURITY_DESCRIPTOR **SD,
  906. BOOL *NewSD,
  907. BOOL bCreateNewIfNotExist
  908. )
  909. {
  910. DWORD returnValue = ERROR_INVALID_PARAMETER;
  911. HKEY registryKey;
  912. DWORD valueType = 0;
  913. DWORD valueSize = 0;
  914. *NewSD = FALSE;
  915. //
  916. // Get the security descriptor from the named value. If it doesn't
  917. // exist, create a fresh one.
  918. //
  919. returnValue = RegOpenKeyEx (RootKey, KeyName, 0, KEY_ALL_ACCESS, &registryKey);
  920. if (returnValue != ERROR_SUCCESS)
  921. {
  922. if (returnValue == ERROR_FILE_NOT_FOUND)
  923. {
  924. // okay it doesn't exist
  925. // shall we create a new one???
  926. if (TRUE == bCreateNewIfNotExist)
  927. {
  928. *SD = NULL;
  929. returnValue = CreateNewSD (SD);
  930. if (returnValue != ERROR_SUCCESS)
  931. {
  932. if (*SD){free(*SD);*SD=NULL;}
  933. goto GetNamedValueSD_Exit;
  934. }
  935. *NewSD = TRUE;
  936. returnValue = ERROR_SUCCESS;
  937. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetNamedValueSD:key not exist.New SD created")));
  938. goto GetNamedValueSD_Exit;
  939. }
  940. else
  941. {
  942. return ERROR_FILE_NOT_FOUND;
  943. }
  944. }
  945. else
  946. {
  947. goto GetNamedValueSD_Exit;
  948. }
  949. }
  950. returnValue = RegQueryValueEx (registryKey, ValueName, NULL, &valueType, NULL, &valueSize);
  951. if (returnValue && returnValue != ERROR_INSUFFICIENT_BUFFER)
  952. {
  953. if (returnValue == ERROR_FILE_NOT_FOUND)
  954. {
  955. // okay it doesn't exist
  956. // shall we create a new one???
  957. if (TRUE == bCreateNewIfNotExist)
  958. {
  959. *SD = NULL;
  960. returnValue = CreateNewSD (SD);
  961. if (returnValue != ERROR_SUCCESS)
  962. {
  963. if (*SD){free(*SD);*SD=NULL;}
  964. goto GetNamedValueSD_Exit;
  965. }
  966. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetNamedValueSD:key exist, but value not found.New SD created")));
  967. *NewSD = TRUE;
  968. }
  969. else
  970. {
  971. return ERROR_FILE_NOT_FOUND;
  972. }
  973. }
  974. else
  975. {
  976. goto GetNamedValueSD_Exit;
  977. }
  978. }
  979. else
  980. {
  981. *SD = (SECURITY_DESCRIPTOR *) malloc (valueSize);
  982. if (!*SD)
  983. {
  984. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  985. returnValue = ERROR_NOT_ENOUGH_MEMORY;
  986. goto GetNamedValueSD_Exit;
  987. }
  988. // get the SD from the registry
  989. returnValue = RegQueryValueEx (registryKey, ValueName, NULL, &valueType, (LPBYTE) *SD, &valueSize);
  990. if (returnValue != ERROR_SUCCESS)
  991. {
  992. if (*SD){free(*SD);*SD=NULL;}
  993. *SD = NULL;
  994. returnValue = CreateNewSD (SD);
  995. if (returnValue != ERROR_SUCCESS)
  996. {
  997. if (*SD){free(*SD);*SD=NULL;}
  998. goto GetNamedValueSD_Exit;
  999. }
  1000. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetNamedValueSD:key exist,no mem.New SD created")));
  1001. *NewSD = TRUE;
  1002. }
  1003. else
  1004. {
  1005. // otherwise, we successfully got the SD from an existing key!
  1006. // let's test if the one we got is valid.
  1007. // if it's not then log the error and create a new one.
  1008. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetNamedValueSD:key exist using SD from reg")));
  1009. // check if our sd we got or created is valid
  1010. if (!IsValidDaclInSD(*SD))
  1011. {
  1012. returnValue = ERROR_INVALID_SECURITY_DESCR;
  1013. iisDebugOut((LOG_TYPE_ERROR, _T("Security Descriptor at [%s\\%s] is not valid.creating a new one temporarily to work around problem"),KeyName,ValueName));
  1014. // try to just create a new one!
  1015. if (*SD){free(*SD);*SD=NULL;}
  1016. *SD = NULL;
  1017. returnValue = CreateNewSD (SD);
  1018. if (returnValue != ERROR_SUCCESS)
  1019. {
  1020. if (*SD){free(*SD);*SD=NULL;}
  1021. goto GetNamedValueSD_Exit;
  1022. }
  1023. *NewSD = TRUE;
  1024. }
  1025. }
  1026. }
  1027. RegCloseKey (registryKey);
  1028. returnValue = ERROR_SUCCESS;
  1029. GetNamedValueSD_Exit:
  1030. return returnValue;
  1031. }
  1032. DWORD
  1033. AddPrincipalToNamedValueSD (
  1034. HKEY RootKey,
  1035. LPTSTR KeyName,
  1036. LPTSTR ValueName,
  1037. LPTSTR Principal,
  1038. BOOL Permit,
  1039. BOOL AddInteractiveforDefault
  1040. )
  1041. {
  1042. DWORD returnValue = ERROR_SUCCESS;
  1043. SECURITY_DESCRIPTOR *sd = NULL;
  1044. SECURITY_DESCRIPTOR *sdSelfRelative = NULL;
  1045. SECURITY_DESCRIPTOR *sdAbsolute = NULL;
  1046. DWORD secDescSize;
  1047. BOOL present;
  1048. BOOL defaultDACL;
  1049. PACL dacl = NULL;
  1050. BOOL newSD = FALSE;
  1051. BOOL fFreeAbsolute = TRUE;
  1052. BOOL fCreateNewSDIfOneInRegNotThere = TRUE;
  1053. //
  1054. // Get security descriptor from registry or create a new one
  1055. //
  1056. returnValue = GetNamedValueSD (RootKey, KeyName, ValueName, &sd, &newSD, fCreateNewSDIfOneInRegNotThere);
  1057. if (returnValue != ERROR_SUCCESS)
  1058. {
  1059. iisDebugOut((LOG_TYPE_ERROR, _T("GetNamedValueSD.FAILED.Return=0x%x."), returnValue));
  1060. return returnValue;
  1061. }
  1062. if (!GetSecurityDescriptorDacl (sd, &present, &dacl, &defaultDACL)) {
  1063. returnValue = GetLastError();
  1064. iisDebugOut((LOG_TYPE_ERROR, _T("GetSecurityDescriptorDacl.FAILED.Return=0x%x."), returnValue));
  1065. goto Cleanup;
  1066. }
  1067. if (newSD)
  1068. {
  1069. returnValue = AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, _T("SYSTEM"));
  1070. if (returnValue != ERROR_SUCCESS)
  1071. {
  1072. iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedACEToACL(SYSTEM).FAILED.Return=0x%x."), returnValue));
  1073. }
  1074. if ( AddInteractiveforDefault )
  1075. {
  1076. returnValue = AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, _T("INTERACTIVE"));
  1077. if (returnValue != ERROR_SUCCESS)
  1078. {
  1079. iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedACEToACL(INTERACTIVE).FAILED.Return=0x%x."), returnValue));
  1080. }
  1081. }
  1082. }
  1083. //
  1084. // Add the Principal that the caller wants added
  1085. //
  1086. if (Permit)
  1087. {
  1088. returnValue = AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, Principal);
  1089. if (returnValue != ERROR_SUCCESS)
  1090. {
  1091. iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedACEToACL(%s).FAILED.Return=0x%x."), Principal,returnValue));
  1092. }
  1093. }
  1094. else
  1095. {
  1096. returnValue = AddAccessDeniedACEToACL (&dacl, GENERIC_ALL, Principal);
  1097. }
  1098. if (returnValue != ERROR_SUCCESS)
  1099. {
  1100. goto Cleanup;
  1101. }
  1102. //
  1103. // Make the security descriptor absolute if it isn't new
  1104. //
  1105. if (!newSD) {
  1106. MakeSDAbsolute ((PSECURITY_DESCRIPTOR) sd, (PSECURITY_DESCRIPTOR *) &sdAbsolute);
  1107. fFreeAbsolute = TRUE;
  1108. } else {
  1109. sdAbsolute = sd;
  1110. fFreeAbsolute = FALSE;
  1111. }
  1112. //
  1113. // Set the discretionary ACL on the security descriptor
  1114. //
  1115. if (!SetSecurityDescriptorDacl (sdAbsolute, TRUE, dacl, FALSE)) {
  1116. returnValue = GetLastError();
  1117. iisDebugOut((LOG_TYPE_ERROR, _T("SetSecurityDescriptorDacl.FAILED.Return=0x%x."), returnValue));
  1118. goto Cleanup;
  1119. }
  1120. //
  1121. // Make the security descriptor self-relative so that we can
  1122. // store it in the registry
  1123. //
  1124. secDescSize = 0;
  1125. MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize);
  1126. sdSelfRelative = (SECURITY_DESCRIPTOR *) malloc (secDescSize);
  1127. if (!sdSelfRelative)
  1128. {
  1129. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1130. returnValue = GetLastError();
  1131. iisDebugOut((LOG_TYPE_ERROR, _T("MakeSelfRelativeSD.FAILED.Return=0x%x."), returnValue));
  1132. goto Cleanup;
  1133. }
  1134. if (!MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize)) {
  1135. returnValue = GetLastError();
  1136. iisDebugOut((LOG_TYPE_ERROR, _T("MakeSelfRelativeSD.FAILED.Return=0x%x."), returnValue));
  1137. goto Cleanup;
  1138. }
  1139. //
  1140. // Store the security descriptor in the registry
  1141. //
  1142. returnValue = SetNamedValueSD (RootKey, KeyName, ValueName, sdSelfRelative);
  1143. if (ERROR_SUCCESS != returnValue)
  1144. {
  1145. iisDebugOut((LOG_TYPE_ERROR, _T("SetNamedValueSD.FAILED.Return=0x%x."), returnValue));
  1146. }
  1147. Cleanup:
  1148. if (sd)
  1149. free (sd);
  1150. if (sdSelfRelative)
  1151. free (sdSelfRelative);
  1152. if (fFreeAbsolute && sdAbsolute)
  1153. free (sdAbsolute);
  1154. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("AddPrincipalToNamedValueSD:%s.end\n"), Principal));
  1155. return returnValue;
  1156. }
  1157. DWORD
  1158. RemovePrincipalFromNamedValueSD (
  1159. HKEY RootKey,
  1160. LPTSTR KeyName,
  1161. LPTSTR ValueName,
  1162. LPTSTR Principal,
  1163. BOOL * pbUserExistsToBeDeleted
  1164. )
  1165. {
  1166. DWORD returnValue = ERROR_SUCCESS;
  1167. SECURITY_DESCRIPTOR *sd = NULL;
  1168. SECURITY_DESCRIPTOR *sdSelfRelative = NULL;
  1169. SECURITY_DESCRIPTOR *sdAbsolute = NULL;
  1170. DWORD secDescSize;
  1171. BOOL present;
  1172. BOOL defaultDACL;
  1173. PACL dacl = NULL;
  1174. BOOL newSD = FALSE;
  1175. BOOL fFreeAbsolute = TRUE;
  1176. BOOL fCreateNewSDIfOneInRegNotThere = FALSE;
  1177. *pbUserExistsToBeDeleted = FALSE;
  1178. //
  1179. returnValue = GetNamedValueSD (RootKey, KeyName, ValueName, &sd, &newSD, fCreateNewSDIfOneInRegNotThere);
  1180. if (returnValue == ERROR_FILE_NOT_FOUND)
  1181. {
  1182. // this means that there is no SD in registry, so
  1183. // there is nothing to remove from it, just exit with successs!
  1184. returnValue = ERROR_SUCCESS;
  1185. goto Cleanup;
  1186. }
  1187. //
  1188. // Get security descriptor from registry or create a new one
  1189. //
  1190. if (returnValue != ERROR_SUCCESS)
  1191. {
  1192. return returnValue;
  1193. }
  1194. if (!GetSecurityDescriptorDacl (sd, &present, &dacl, &defaultDACL)) {
  1195. returnValue = GetLastError();
  1196. goto Cleanup;
  1197. }
  1198. // check if the acl we got passed in is valid!
  1199. if (present && dacl)
  1200. {
  1201. if (0 == IsValidAcl(dacl))
  1202. {
  1203. returnValue = ERROR_INVALID_ACL;
  1204. goto Cleanup;
  1205. }
  1206. }
  1207. //
  1208. // If the security descriptor is new, add the required Principals to it
  1209. //
  1210. if (newSD)
  1211. {
  1212. // but if this is a removal, then don't add system and interactive!
  1213. // AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, _T("SYSTEM"));
  1214. // AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, _T("INTERACTIVE"));
  1215. }
  1216. //
  1217. // Remove the Principal that the caller wants removed
  1218. //
  1219. returnValue = RemovePrincipalFromACL (dacl, Principal,pbUserExistsToBeDeleted);
  1220. if (returnValue != ERROR_SUCCESS)
  1221. goto Cleanup;
  1222. //
  1223. // Make the security descriptor absolute if it isn't new
  1224. //
  1225. if (!newSD) {
  1226. MakeSDAbsolute ((PSECURITY_DESCRIPTOR) sd, (PSECURITY_DESCRIPTOR *) &sdAbsolute);
  1227. fFreeAbsolute = TRUE;
  1228. } else {
  1229. sdAbsolute = sd;
  1230. fFreeAbsolute = FALSE;
  1231. }
  1232. //
  1233. // Set the discretionary ACL on the security descriptor
  1234. //
  1235. if (!SetSecurityDescriptorDacl (sdAbsolute, TRUE, dacl, FALSE)) {
  1236. returnValue = GetLastError();
  1237. goto Cleanup;
  1238. }
  1239. //
  1240. // Make the security descriptor self-relative so that we can
  1241. // store it in the registry
  1242. //
  1243. secDescSize = 0;
  1244. MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize);
  1245. sdSelfRelative = (SECURITY_DESCRIPTOR *) malloc (secDescSize);
  1246. if (!sdSelfRelative)
  1247. {
  1248. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1249. returnValue = GetLastError();
  1250. goto Cleanup;
  1251. }
  1252. if (!MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize)) {
  1253. returnValue = GetLastError();
  1254. goto Cleanup;
  1255. }
  1256. //
  1257. // Store the security descriptor in the registry
  1258. //
  1259. SetNamedValueSD (RootKey, KeyName, ValueName, sdSelfRelative);
  1260. Cleanup:
  1261. if (sd)
  1262. free (sd);
  1263. if (sdSelfRelative)
  1264. free (sdSelfRelative);
  1265. if (fFreeAbsolute && sdAbsolute)
  1266. free (sdAbsolute);
  1267. return returnValue;
  1268. }
  1269. DWORD
  1270. ChangeAppIDAccessACL (
  1271. LPTSTR AppID,
  1272. LPTSTR Principal,
  1273. BOOL SetPrincipal,
  1274. BOOL Permit,
  1275. BOOL bDumbCall
  1276. )
  1277. {
  1278. BOOL bUserExistsToBeDeleted = FALSE;
  1279. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ChangeAppIDAccessACL():APPID=%s,Principal=%s. \n"), AppID, Principal));
  1280. TSTR strKeyName(256);
  1281. TSTR strFullKey;
  1282. CString csData;
  1283. DWORD err = ERROR_SUCCESS;
  1284. if ( !strKeyName.Format( AppID[0] == _T('{') ? _T("APPID\\%s") : _T("APPID\\{%s}") ,
  1285. AppID ) )
  1286. {
  1287. return ERROR_NOT_ENOUGH_MEMORY;
  1288. }
  1289. if ( !strFullKey.Copy( strKeyName ) ||
  1290. !strFullKey.Append( _T(":A:") ) ||
  1291. !strFullKey.Append( Principal )
  1292. )
  1293. {
  1294. return ERROR_NOT_ENOUGH_MEMORY;
  1295. }
  1296. if (SetPrincipal)
  1297. {
  1298. err = RemovePrincipalFromNamedValueSD (HKEY_CLASSES_ROOT, strKeyName.QueryStr() , _T("AccessPermission"), Principal,&bUserExistsToBeDeleted);
  1299. if (TRUE == bUserExistsToBeDeleted)
  1300. {
  1301. // this means that in fact the user was already in there!
  1302. // so we now have to add it back in!
  1303. // we just want to make sure we know that it was already in there
  1304. // so when we do an uninstall -- we don't delete the value if it was already in there!
  1305. if (FALSE == bDumbCall)
  1306. {
  1307. // Do not set this on an upgrade!
  1308. if (g_pTheApp->m_eInstallMode != IM_UPGRADE)
  1309. {
  1310. g_pTheApp->UnInstallList_Add(strFullKey.QueryStr(),MY_DCOM_PERSIST_FLAG);
  1311. }
  1312. }
  1313. }
  1314. err = AddPrincipalToNamedValueSD (HKEY_CLASSES_ROOT, strKeyName.QueryStr() , _T("AccessPermission"), Principal, Permit);
  1315. if (FAILED(err))
  1316. {
  1317. iisDebugOut((LOG_TYPE_ERROR, _T("AddPrincipalToNamedValueSD():Principal=%s.End.FAILED.Return=0x%x."), Principal, err));
  1318. }
  1319. }
  1320. else
  1321. {
  1322. if (TRUE == bDumbCall)
  1323. {
  1324. csData = g_pTheApp->UnInstallList_QueryKey( strFullKey.QueryStr() );
  1325. if (_tcsicmp(csData, MY_DCOM_PERSIST_FLAG) == 0)
  1326. {
  1327. // don't remove it!! it was already there before we even added it!
  1328. err = ERROR_SUCCESS;
  1329. }
  1330. else
  1331. {
  1332. err = RemovePrincipalFromNamedValueSD (HKEY_CLASSES_ROOT, strKeyName.QueryStr() , _T("AccessPermission"), Principal,&bUserExistsToBeDeleted);
  1333. }
  1334. g_pTheApp->UnInstallList_DelKey(strFullKey.QueryStr());
  1335. }
  1336. else
  1337. {
  1338. err = RemovePrincipalFromNamedValueSD (HKEY_CLASSES_ROOT, strKeyName.QueryStr() , _T("AccessPermission"), Principal,&bUserExistsToBeDeleted);
  1339. }
  1340. }
  1341. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ChangeAppIDAccessACL():APPID=%s,Principal=%s. End. Return=0x%x\n"), AppID, Principal, err));
  1342. return err;
  1343. }
  1344. DWORD
  1345. ChangeAppIDLaunchACL (
  1346. LPTSTR AppID,
  1347. LPTSTR Principal,
  1348. BOOL SetPrincipal,
  1349. BOOL Permit,
  1350. BOOL bDumbCall,
  1351. BOOL bAddInteractivebyDefault
  1352. )
  1353. {
  1354. BOOL bUserExistsToBeDeleted = FALSE;
  1355. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ChangeAppIDLaunchACL():APPID=%s,Principal=%s. Start."), AppID, Principal));
  1356. TSTR strKeyName(256);
  1357. TSTR strFullKey;
  1358. CString csData;
  1359. DWORD err = ERROR_SUCCESS;
  1360. if ( !strKeyName.Format( AppID[0] == _T('{') ? _T("APPID\\%s") : _T("APPID\\{%s}") ,
  1361. AppID ) )
  1362. {
  1363. return ERROR_NOT_ENOUGH_MEMORY;
  1364. }
  1365. if ( !strFullKey.Copy( strKeyName ) ||
  1366. !strFullKey.Append( _T(":L:") ) ||
  1367. !strFullKey.Append( Principal )
  1368. )
  1369. {
  1370. return ERROR_NOT_ENOUGH_MEMORY;
  1371. }
  1372. if (SetPrincipal)
  1373. {
  1374. err = RemovePrincipalFromNamedValueSD (HKEY_CLASSES_ROOT, strKeyName.QueryStr() , _T("LaunchPermission"), Principal,&bUserExistsToBeDeleted);
  1375. if (TRUE == bUserExistsToBeDeleted)
  1376. {
  1377. // this means that in fact the user was already in there!
  1378. // so we now have to add it back in!
  1379. // we just want to make sure we know that it was already in there
  1380. // so when we do an uninstall -- we don't delete the value if it was already in there!
  1381. if (FALSE == bDumbCall)
  1382. {
  1383. // Do not set this on an upgrade!
  1384. if (g_pTheApp->m_eInstallMode != IM_UPGRADE)
  1385. {
  1386. g_pTheApp->UnInstallList_Add(strFullKey.QueryStr(),MY_DCOM_PERSIST_FLAG);
  1387. }
  1388. }
  1389. }
  1390. err = AddPrincipalToNamedValueSD (HKEY_CLASSES_ROOT, strKeyName.QueryStr(), _T("LaunchPermission"), Principal, Permit, bAddInteractivebyDefault);
  1391. if (FAILED(err))
  1392. {
  1393. iisDebugOut((LOG_TYPE_ERROR, _T("AddPrincipalToNamedValueSD():Principal=%s.End.FAILED.Return=0x%x."), Principal, err));
  1394. }
  1395. }
  1396. else
  1397. {
  1398. if (TRUE == bDumbCall)
  1399. {
  1400. err = RemovePrincipalFromNamedValueSD (HKEY_CLASSES_ROOT, strKeyName.QueryStr() , _T("LaunchPermission"), Principal,&bUserExistsToBeDeleted);
  1401. }
  1402. else
  1403. {
  1404. csData = g_pTheApp->UnInstallList_QueryKey( strFullKey.QueryStr() );
  1405. if (_tcsicmp(csData, MY_DCOM_PERSIST_FLAG) == 0)
  1406. {
  1407. // don't remove it!! it was already there before we even added it!
  1408. err = ERROR_SUCCESS;
  1409. }
  1410. else
  1411. {
  1412. err = RemovePrincipalFromNamedValueSD (HKEY_CLASSES_ROOT, strKeyName.QueryStr() , _T("LaunchPermission"), Principal,&bUserExistsToBeDeleted);
  1413. }
  1414. g_pTheApp->UnInstallList_DelKey(strFullKey.QueryStr());
  1415. }
  1416. }
  1417. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ChangeAppIDLaunchACL():APPID=%s,Principal=%s.End. Return=0x%x"), AppID, Principal, err));
  1418. return err;
  1419. }
  1420. DWORD
  1421. ChangeDCOMAccessACL (
  1422. LPTSTR Principal,
  1423. BOOL SetPrincipal,
  1424. BOOL Permit,
  1425. BOOL bDumbCall
  1426. )
  1427. {
  1428. BOOL bUserExistsToBeDeleted = FALSE;
  1429. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ChangeDCOMAccessACL():Principal=%s. Start.\n"), Principal));
  1430. TSTR strKeyName(256);
  1431. TSTR strFullKey;
  1432. DWORD err;
  1433. CString csData;
  1434. if ( !strKeyName.Copy( _T("Software\\Microsoft\\OLE") ) )
  1435. {
  1436. return ERROR_NOT_ENOUGH_MEMORY;
  1437. }
  1438. if ( !strFullKey.Copy( _T("DCOM_DA:") ) ||
  1439. !strFullKey.Append( Principal )
  1440. )
  1441. {
  1442. return ERROR_NOT_ENOUGH_MEMORY;
  1443. }
  1444. if (SetPrincipal)
  1445. {
  1446. err = RemovePrincipalFromNamedValueSD (HKEY_LOCAL_MACHINE, strKeyName.QueryStr() , _T("DefaultAccessPermission"), Principal,&bUserExistsToBeDeleted);
  1447. if (TRUE == bUserExistsToBeDeleted)
  1448. {
  1449. // this means that in fact the user was already in there!
  1450. // so we now have to add it back in!
  1451. // we just want to make sure we know that it was already in there
  1452. // so when we do an uninstall -- we don't delete the value if it was already in there!
  1453. if (FALSE == bDumbCall)
  1454. {
  1455. // Do not set this on an upgrade!
  1456. if (g_pTheApp->m_eInstallMode != IM_UPGRADE)
  1457. {
  1458. g_pTheApp->UnInstallList_Add(strFullKey.QueryStr(),MY_DCOM_PERSIST_FLAG);
  1459. }
  1460. }
  1461. }
  1462. err = AddPrincipalToNamedValueSD (HKEY_LOCAL_MACHINE, strKeyName.QueryStr() , _T("DefaultAccessPermission"), Principal, Permit);
  1463. if (FAILED(err))
  1464. {
  1465. iisDebugOut((LOG_TYPE_ERROR, _T("ChangeDCOMAccessACL():Principal=%s.End.FAILED.Return=0x%x."), Principal, err));
  1466. }
  1467. }
  1468. else
  1469. {
  1470. // Should we remove this principle from there?
  1471. // we should only do it if we actually had added them.
  1472. // the problem is that before iis5.1 we didn't have this information
  1473. // so when we go look in the registry to find "DCOM_DA:iusr_computername", we won't find it
  1474. // because iis5.1 setup hasn't been run yet.
  1475. // if "DCOM_DA:IUSR_COMPUTERNAME" exists and it is = MY_DCOM_PERSIST_FLAG
  1476. // then do not allow the entry to be deleted!
  1477. // that's because iis5.1 when trying to add the entry -- found that it was already there!
  1478. if (TRUE == bDumbCall)
  1479. {
  1480. err = RemovePrincipalFromNamedValueSD (HKEY_LOCAL_MACHINE, strKeyName.QueryStr() , _T("DefaultAccessPermission"), Principal,&bUserExistsToBeDeleted);
  1481. }
  1482. else
  1483. {
  1484. csData = g_pTheApp->UnInstallList_QueryKey(strFullKey.QueryStr());
  1485. if (_tcsicmp(csData, MY_DCOM_PERSIST_FLAG) == 0)
  1486. {
  1487. // don't remove it!! it was already there before we even added it!
  1488. err = ERROR_SUCCESS;
  1489. }
  1490. else
  1491. {
  1492. err = RemovePrincipalFromNamedValueSD (HKEY_LOCAL_MACHINE, strKeyName.QueryStr() , _T("DefaultAccessPermission"), Principal,&bUserExistsToBeDeleted);
  1493. }
  1494. g_pTheApp->UnInstallList_DelKey(strFullKey.QueryStr());
  1495. }
  1496. }
  1497. iisDebugOut((LOG_TYPE_TRACE, _T("ChangeDCOMAccessACL():End.Return=0x%x"), err));
  1498. return err;
  1499. }
  1500. DWORD
  1501. ChangeDCOMLaunchACL (
  1502. LPTSTR Principal,
  1503. BOOL SetPrincipal,
  1504. BOOL Permit,
  1505. BOOL bDumbCall
  1506. )
  1507. {
  1508. BOOL bUserExistsToBeDeleted = FALSE;
  1509. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ChangeDCOMLaunchACL():Principal=%s. Start.\n"), Principal));
  1510. TCHAR keyName [256] = _T("Software\\Microsoft\\OLE");
  1511. DWORD err;
  1512. CString csKey;
  1513. CString csData;
  1514. csKey = _T("DCOM_DL:");
  1515. csKey += Principal;
  1516. if (SetPrincipal)
  1517. {
  1518. err = RemovePrincipalFromNamedValueSD (HKEY_LOCAL_MACHINE, keyName, _T("DefaultLaunchPermission"), Principal,&bUserExistsToBeDeleted);
  1519. if (TRUE == bUserExistsToBeDeleted)
  1520. {
  1521. // this means that in fact the user was already in there!
  1522. // so we now have to add it back in!
  1523. // we just want to make sure we know that it was already in there
  1524. // so when we do an uninstall -- we don't delete the value if it was already in there!
  1525. if (FALSE == bDumbCall)
  1526. {
  1527. // Do not set this on an upgrade!
  1528. if (g_pTheApp->m_eInstallMode != IM_UPGRADE)
  1529. {
  1530. g_pTheApp->UnInstallList_Add(csKey,MY_DCOM_PERSIST_FLAG);
  1531. }
  1532. }
  1533. }
  1534. err = AddPrincipalToNamedValueSD (HKEY_LOCAL_MACHINE, keyName, _T("DefaultLaunchPermission"), Principal, Permit);
  1535. if (FAILED(err))
  1536. {
  1537. iisDebugOut((LOG_TYPE_ERROR, _T("ChangeDCOMLaunchACL():Principal=%s.End.FAILED.Return=0x%x"), Principal, err));
  1538. }
  1539. }
  1540. else
  1541. {
  1542. // Should we remove this principle from there?
  1543. // we should only do it if we actually had added them.
  1544. // the problem is that before iis5.1 we didn't have this information
  1545. // so when we go look in the registry to find "DCOM_DL:iusr_computername", we won't find it
  1546. // because iis5.1 setup hasn't been run yet.
  1547. // if "DCOM_DL:IUSR_COMPUTERNAME" exists and it is = MY_DCOM_PERSIST_FLAG
  1548. // then do not allow the entry to be deleted!
  1549. // that's because iis5.1 when trying to add the entry -- found that it was already there!
  1550. if (TRUE == bDumbCall)
  1551. {
  1552. err = RemovePrincipalFromNamedValueSD (HKEY_LOCAL_MACHINE, keyName, _T("DefaultLaunchPermission"), Principal,&bUserExistsToBeDeleted);
  1553. }
  1554. else
  1555. {
  1556. csData = g_pTheApp->UnInstallList_QueryKey(csKey);
  1557. if (_tcsicmp(csData, MY_DCOM_PERSIST_FLAG) == 0)
  1558. {
  1559. // don't remove it!! it was already there before we even added it!
  1560. err = ERROR_SUCCESS;
  1561. }
  1562. else
  1563. {
  1564. err = RemovePrincipalFromNamedValueSD (HKEY_LOCAL_MACHINE, keyName, _T("DefaultLaunchPermission"), Principal,&bUserExistsToBeDeleted);
  1565. }
  1566. g_pTheApp->UnInstallList_DelKey(csKey);
  1567. }
  1568. }
  1569. iisDebugOut((LOG_TYPE_TRACE, _T("ChangeDCOMLaunchACL():End.\n"), err));
  1570. return err;
  1571. }
  1572. BOOL
  1573. MakeAbsoluteCopyFromRelative(
  1574. PSECURITY_DESCRIPTOR psdOriginal,
  1575. PSECURITY_DESCRIPTOR* ppsdNew
  1576. )
  1577. {
  1578. // we have to find out whether the original is already self-relative
  1579. SECURITY_DESCRIPTOR_CONTROL sdc = 0;
  1580. PSECURITY_DESCRIPTOR psdAbsoluteCopy = NULL;
  1581. DWORD dwRevision = 0;
  1582. DWORD cb = 0;
  1583. PACL Dacl = NULL, Sacl = NULL;
  1584. BOOL bDefaulted;
  1585. PSID Owner = NULL, Group = NULL;
  1586. DWORD dwDaclSize = 0;
  1587. BOOL bDaclPresent = FALSE;
  1588. DWORD dwSaclSize = 0;
  1589. BOOL bSaclPresent = FALSE;
  1590. DWORD dwOwnerSize = 0;
  1591. DWORD dwPrimaryGroupSize = 0;
  1592. if( !IsValidSecurityDescriptor( psdOriginal ) ) {
  1593. return FALSE;
  1594. }
  1595. if( !GetSecurityDescriptorControl( psdOriginal, &sdc, &dwRevision ) ) {
  1596. DWORD err = GetLastError();
  1597. goto cleanup;
  1598. }
  1599. if( sdc & SE_SELF_RELATIVE ) {
  1600. // the original is in self-relative format, build an absolute copy
  1601. // get the dacl
  1602. if( !GetSecurityDescriptorDacl(
  1603. psdOriginal, // address of security descriptor
  1604. &bDaclPresent, // address of flag for presence of disc. ACL
  1605. &Dacl, // address of pointer to ACL
  1606. &bDefaulted // address of flag for default disc. ACL
  1607. )
  1608. ) {
  1609. goto cleanup;
  1610. }
  1611. // get the sacl
  1612. if( !GetSecurityDescriptorSacl(
  1613. psdOriginal, // address of security descriptor
  1614. &bSaclPresent, // address of flag for presence of disc. ACL
  1615. &Sacl, // address of pointer to ACL
  1616. &bDefaulted // address of flag for default disc. ACL
  1617. )
  1618. ) {
  1619. goto cleanup;
  1620. }
  1621. // get the owner
  1622. if( !GetSecurityDescriptorOwner(
  1623. psdOriginal, // address of security descriptor
  1624. &Owner, // address of pointer to owner security
  1625. // identifier (SID)
  1626. &bDefaulted // address of flag for default
  1627. )
  1628. ) {
  1629. goto cleanup;
  1630. }
  1631. // get the group
  1632. if( !GetSecurityDescriptorGroup(
  1633. psdOriginal, // address of security descriptor
  1634. &Group, // address of pointer to owner security
  1635. // identifier (SID)
  1636. &bDefaulted // address of flag for default
  1637. )
  1638. ) {
  1639. goto cleanup;
  1640. }
  1641. // get required buffer size
  1642. cb = 0;
  1643. MakeAbsoluteSD(
  1644. psdOriginal, // address of self-relative SD
  1645. psdAbsoluteCopy, // address of absolute SD
  1646. &cb, // address of size of absolute SD
  1647. NULL, // address of discretionary ACL
  1648. &dwDaclSize, // address of size of discretionary ACL
  1649. NULL, // address of system ACL
  1650. &dwSaclSize, // address of size of system ACL
  1651. NULL, // address of owner SID
  1652. &dwOwnerSize, // address of size of owner SID
  1653. NULL, // address of primary-group SID
  1654. &dwPrimaryGroupSize // address of size of group SID
  1655. );
  1656. // alloc the memory
  1657. psdAbsoluteCopy = (PSECURITY_DESCRIPTOR) malloc( cb );
  1658. Dacl = (PACL) malloc( dwDaclSize );
  1659. Sacl = (PACL) malloc( dwSaclSize );
  1660. Owner = (PSID) malloc( dwOwnerSize );
  1661. Group = (PSID) malloc( dwPrimaryGroupSize );
  1662. if(NULL == psdAbsoluteCopy ||
  1663. NULL == Dacl ||
  1664. NULL == Sacl ||
  1665. NULL == Owner ||
  1666. NULL == Group
  1667. ) {
  1668. goto cleanup;
  1669. }
  1670. // make the copy
  1671. if( !MakeAbsoluteSD(
  1672. psdOriginal, // address of self-relative SD
  1673. psdAbsoluteCopy, // address of absolute SD
  1674. &cb, // address of size of absolute SD
  1675. Dacl, // address of discretionary ACL
  1676. &dwDaclSize, // address of size of discretionary ACL
  1677. Sacl, // address of system ACL
  1678. &dwSaclSize, // address of size of system ACL
  1679. Owner, // address of owner SID
  1680. &dwOwnerSize, // address of size of owner SID
  1681. Group, // address of primary-group SID
  1682. &dwPrimaryGroupSize // address of size of group SID
  1683. )
  1684. ) {
  1685. goto cleanup;
  1686. }
  1687. } else {
  1688. // the original is in absolute format, fail
  1689. goto cleanup;
  1690. }
  1691. *ppsdNew = psdAbsoluteCopy;
  1692. // paranoia check
  1693. if( !IsValidSecurityDescriptor( *ppsdNew ) ) {
  1694. goto cleanup;
  1695. }
  1696. if( !IsValidSecurityDescriptor( psdOriginal ) ) {
  1697. goto cleanup;
  1698. }
  1699. return(TRUE);
  1700. cleanup:
  1701. if( Dacl != NULL ) {
  1702. free((PVOID) Dacl );
  1703. Dacl = NULL;
  1704. }
  1705. if( Sacl != NULL ) {
  1706. free((PVOID) Sacl );
  1707. Sacl = NULL;
  1708. }
  1709. if( Owner != NULL ) {
  1710. free((PVOID) Owner );
  1711. Owner = NULL;
  1712. }
  1713. if( Group != NULL ) {
  1714. free((PVOID) Group );
  1715. Group = NULL;
  1716. }
  1717. if( psdAbsoluteCopy != NULL ) {
  1718. free((PVOID) psdAbsoluteCopy );
  1719. psdAbsoluteCopy = NULL;
  1720. }
  1721. return (FALSE);
  1722. }