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.

1109 lines
28 KiB

  1. #include "stdafx.h"
  2. #include "dcomperm.h"
  3. //
  4. // Check whether we are running as administrator on the machine
  5. // or not
  6. //
  7. BOOL RunningAsAdministrator(void)
  8. {
  9. BOOL fReturn = FALSE;
  10. PSID psidAdmin;
  11. DWORD err;
  12. SID_IDENTIFIER_AUTHORITY SystemSidAuthority= SECURITY_NT_AUTHORITY;
  13. if ( AllocateAndInitializeSid ( &SystemSidAuthority, 2,
  14. SECURITY_BUILTIN_DOMAIN_RID,
  15. DOMAIN_ALIAS_RID_ADMINS,
  16. 0, 0, 0, 0, 0, 0, &psidAdmin) )
  17. {
  18. if (!CheckTokenMembership( NULL, psidAdmin, &fReturn ))
  19. {
  20. err = GetLastError();
  21. }
  22. FreeSid ( psidAdmin);
  23. }
  24. return ( fReturn );
  25. }
  26. DWORD
  27. CopyACL (
  28. PACL OldACL,
  29. PACL NewACL
  30. )
  31. {
  32. ACL_SIZE_INFORMATION aclSizeInfo;
  33. LPVOID ace;
  34. ACE_HEADER *aceHeader;
  35. ULONG i;
  36. DWORD returnValue = ERROR_SUCCESS;
  37. if (0 == IsValidAcl(OldACL))
  38. {
  39. returnValue = ERROR_INVALID_ACL;
  40. return returnValue;
  41. }
  42. if (0 == GetAclInformation (OldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof (aclSizeInfo), AclSizeInformation))
  43. {
  44. returnValue = GetLastError();
  45. return returnValue;
  46. }
  47. //
  48. // Copy all of the ACEs to the new ACL
  49. //
  50. for (i = 0; i < aclSizeInfo.AceCount; i++)
  51. {
  52. //
  53. // Get the ACE and header info
  54. //
  55. if (!GetAce (OldACL, i, &ace))
  56. {
  57. returnValue = GetLastError();
  58. return returnValue;
  59. }
  60. aceHeader = (ACE_HEADER *) ace;
  61. //
  62. // Add the ACE to the new list
  63. //
  64. if (!AddAce (NewACL, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  65. {
  66. returnValue = GetLastError();
  67. return returnValue;
  68. }
  69. }
  70. return returnValue;
  71. }
  72. DWORD
  73. GetPrincipalSID (
  74. LPCTSTR Principal,
  75. PSID *Sid,
  76. BOOL *pbWellKnownSID
  77. )
  78. {
  79. DWORD returnValue=ERROR_SUCCESS;
  80. SID_IDENTIFIER_AUTHORITY SidIdentifierNTAuthority = SECURITY_NT_AUTHORITY;
  81. SID_IDENTIFIER_AUTHORITY SidIdentifierWORLDAuthority = SECURITY_WORLD_SID_AUTHORITY;
  82. PSID_IDENTIFIER_AUTHORITY pSidIdentifierAuthority;
  83. BYTE Count;
  84. DWORD dwRID[8];
  85. TCHAR pszPrincipal[MAX_PATH];
  86. *pbWellKnownSID = TRUE;
  87. memset(&(dwRID[0]), 0, 8 * sizeof(DWORD));
  88. wcscpy(pszPrincipal, Principal);
  89. _wcslwr(pszPrincipal);
  90. if ( wcsstr(pszPrincipal, TEXT("administrators")) != NULL ) {
  91. // Administrators group
  92. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  93. Count = 2;
  94. dwRID[0] = SECURITY_BUILTIN_DOMAIN_RID;
  95. dwRID[1] = DOMAIN_ALIAS_RID_ADMINS;
  96. } else if ( wcsstr(pszPrincipal, TEXT("system")) != NULL) {
  97. // SYSTEM
  98. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  99. Count = 1;
  100. dwRID[0] = SECURITY_LOCAL_SYSTEM_RID;
  101. } else if ( wcsstr(pszPrincipal, TEXT("interactive")) != NULL) {
  102. // INTERACTIVE
  103. pSidIdentifierAuthority = &SidIdentifierNTAuthority;
  104. Count = 1;
  105. dwRID[0] = SECURITY_INTERACTIVE_RID;
  106. } else if ( wcsstr(pszPrincipal, TEXT("everyone")) != NULL) {
  107. // Everyone
  108. pSidIdentifierAuthority = &SidIdentifierWORLDAuthority;
  109. Count = 1;
  110. dwRID[0] = SECURITY_WORLD_RID;
  111. } else {
  112. *pbWellKnownSID = FALSE;
  113. }
  114. if (*pbWellKnownSID) {
  115. if ( !AllocateAndInitializeSid(pSidIdentifierAuthority,
  116. (BYTE)Count,
  117. dwRID[0],
  118. dwRID[1],
  119. dwRID[2],
  120. dwRID[3],
  121. dwRID[4],
  122. dwRID[5],
  123. dwRID[6],
  124. dwRID[7],
  125. Sid) ) {
  126. returnValue = GetLastError();
  127. }
  128. } else {
  129. // get regular account sid
  130. DWORD sidSize;
  131. TCHAR refDomain [256];
  132. DWORD refDomainSize;
  133. SID_NAME_USE snu;
  134. sidSize = 0;
  135. refDomainSize = 255;
  136. LookupAccountName (NULL,
  137. pszPrincipal,
  138. *Sid,
  139. &sidSize,
  140. refDomain,
  141. &refDomainSize,
  142. &snu);
  143. returnValue = GetLastError();
  144. if (returnValue == ERROR_INSUFFICIENT_BUFFER) {
  145. *Sid = (PSID) malloc (sidSize);
  146. if (!*Sid)
  147. {
  148. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  149. return GetLastError();
  150. }
  151. refDomainSize = 255;
  152. if (!LookupAccountName (NULL,
  153. pszPrincipal,
  154. *Sid,
  155. &sidSize,
  156. refDomain,
  157. &refDomainSize,
  158. &snu))
  159. {
  160. returnValue = GetLastError();
  161. } else {
  162. returnValue = ERROR_SUCCESS;
  163. }
  164. }
  165. }
  166. return returnValue;
  167. }
  168. DWORD
  169. AddAccessDeniedACEToACL (
  170. PACL *Acl,
  171. DWORD PermissionMask,
  172. LPTSTR Principal
  173. )
  174. {
  175. ACL_SIZE_INFORMATION aclSizeInfo;
  176. int aclSize;
  177. DWORD returnValue = ERROR_SUCCESS;
  178. PSID principalSID = NULL;
  179. PACL oldACL, newACL;
  180. BOOL bWellKnownSID = FALSE;
  181. oldACL = *Acl;
  182. returnValue = GetPrincipalSID (Principal, &principalSID, &bWellKnownSID);
  183. if (returnValue != ERROR_SUCCESS)
  184. return returnValue;
  185. GetAclInformation (oldACL,
  186. (LPVOID) &aclSizeInfo,
  187. (DWORD) sizeof (ACL_SIZE_INFORMATION),
  188. AclSizeInformation);
  189. aclSize = aclSizeInfo.AclBytesInUse +
  190. sizeof (ACL) + sizeof (ACCESS_DENIED_ACE) +
  191. GetLengthSid (principalSID) - sizeof (DWORD);
  192. newACL = (PACL) new BYTE [aclSize];
  193. if (!InitializeAcl (newACL, aclSize, ACL_REVISION))
  194. {
  195. returnValue = GetLastError();
  196. goto cleanup;
  197. }
  198. if (!AddAccessDeniedAce (newACL, ACL_REVISION2, PermissionMask, principalSID))
  199. {
  200. returnValue = GetLastError();
  201. goto cleanup;
  202. }
  203. returnValue = CopyACL (oldACL, newACL);
  204. if (returnValue != ERROR_SUCCESS)
  205. {
  206. goto cleanup;
  207. }
  208. *Acl = newACL;
  209. newACL = NULL;
  210. cleanup:
  211. // BugFix: 57654 Whistler
  212. // Prefix bug leaking memory in error condition.
  213. // By setting the newACL to NULL above if we have
  214. // relinquished the memory to *Acl, we avoid releasing
  215. // memory we have passed back to the caller.
  216. // EBK 5/5/2000
  217. if (newACL)
  218. {
  219. delete[] newACL;
  220. newACL = NULL;
  221. }
  222. if (principalSID) {
  223. if (bWellKnownSID)
  224. FreeSid (principalSID);
  225. else
  226. free (principalSID);
  227. }
  228. return returnValue;
  229. }
  230. DWORD
  231. AddAccessAllowedACEToACL (
  232. PACL *Acl,
  233. DWORD PermissionMask,
  234. LPTSTR Principal
  235. )
  236. {
  237. ACL_SIZE_INFORMATION aclSizeInfo;
  238. int aclSize;
  239. DWORD returnValue = ERROR_SUCCESS;
  240. PSID principalSID = NULL;
  241. PACL oldACL = NULL;
  242. PACL newACL = NULL;
  243. BOOL bWellKnownSID = FALSE;
  244. oldACL = *Acl;
  245. // check if the acl we got passed in is valid!
  246. if (0 == IsValidAcl(oldACL))
  247. {
  248. returnValue = ERROR_INVALID_ACL;
  249. goto cleanup;
  250. }
  251. returnValue = GetPrincipalSID (Principal, &principalSID, &bWellKnownSID);
  252. if (returnValue != ERROR_SUCCESS)
  253. {
  254. return returnValue;
  255. }
  256. if (0 == GetAclInformation (oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof (ACL_SIZE_INFORMATION), AclSizeInformation))
  257. {
  258. returnValue = GetLastError();
  259. goto cleanup;
  260. }
  261. aclSize = aclSizeInfo.AclBytesInUse +
  262. sizeof (ACL) + sizeof (ACCESS_ALLOWED_ACE) +
  263. GetLengthSid (principalSID) - sizeof (DWORD);
  264. newACL = (PACL) new BYTE [aclSize];
  265. if (!InitializeAcl (newACL, aclSize, ACL_REVISION))
  266. {
  267. returnValue = GetLastError();
  268. goto cleanup;
  269. }
  270. returnValue = CopyACL (oldACL, newACL);
  271. if (returnValue != ERROR_SUCCESS)
  272. {
  273. goto cleanup;
  274. }
  275. //if (!AddAccessAllowedAce (newACL, ACL_REVISION2, PermissionMask, principalSID))
  276. if (!AddAccessAllowedAce (newACL, ACL_REVISION, PermissionMask, principalSID))
  277. {
  278. returnValue = GetLastError();
  279. goto cleanup;
  280. }
  281. // check if the acl is valid!
  282. /*
  283. if (0 == IsValidAcl(newACL))
  284. {
  285. returnValue = ERROR_INVALID_ACL;
  286. goto cleanup;
  287. }
  288. */
  289. // cleanup old memory whose pointer we're replacing
  290. // okay to leak in setup... (need to comment out or else av's)
  291. //if (*Acl) {delete(*Acl);}
  292. *Acl = newACL;
  293. newACL = NULL;
  294. cleanup:
  295. if (principalSID) {
  296. if (bWellKnownSID)
  297. FreeSid (principalSID);
  298. else
  299. free (principalSID);
  300. }
  301. if (newACL)
  302. {
  303. delete [] newACL;
  304. newACL = NULL;
  305. }
  306. return returnValue;
  307. }
  308. DWORD
  309. RemovePrincipalFromACL (
  310. PACL Acl,
  311. LPTSTR Principal
  312. )
  313. {
  314. ACL_SIZE_INFORMATION aclSizeInfo;
  315. ULONG i;
  316. LPVOID ace;
  317. ACCESS_ALLOWED_ACE *accessAllowedAce;
  318. ACCESS_DENIED_ACE *accessDeniedAce;
  319. SYSTEM_AUDIT_ACE *systemAuditAce;
  320. PSID principalSID = NULL;
  321. DWORD returnValue = ERROR_SUCCESS;
  322. ACE_HEADER *aceHeader;
  323. BOOL bWellKnownSID = FALSE;
  324. returnValue = GetPrincipalSID (Principal, &principalSID, &bWellKnownSID);
  325. if (returnValue != ERROR_SUCCESS)
  326. return returnValue;
  327. GetAclInformation (Acl,
  328. (LPVOID) &aclSizeInfo,
  329. (DWORD) sizeof (ACL_SIZE_INFORMATION),
  330. AclSizeInformation);
  331. for (i = 0; i < aclSizeInfo.AceCount; i++)
  332. {
  333. if (!GetAce (Acl, i, &ace))
  334. {
  335. returnValue = GetLastError();
  336. break;
  337. }
  338. aceHeader = (ACE_HEADER *) ace;
  339. if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  340. {
  341. accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace;
  342. if (EqualSid (principalSID, (PSID) &accessAllowedAce->SidStart))
  343. {
  344. DeleteAce (Acl, i);
  345. break;
  346. }
  347. } else
  348. if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  349. {
  350. accessDeniedAce = (ACCESS_DENIED_ACE *) ace;
  351. if (EqualSid (principalSID, (PSID) &accessDeniedAce->SidStart))
  352. {
  353. DeleteAce (Acl, i);
  354. break;
  355. }
  356. } else
  357. if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE)
  358. {
  359. systemAuditAce = (SYSTEM_AUDIT_ACE *) ace;
  360. if (EqualSid (principalSID, (PSID) &systemAuditAce->SidStart))
  361. {
  362. DeleteAce (Acl, i);
  363. break;
  364. }
  365. }
  366. }
  367. if (principalSID) {
  368. if (bWellKnownSID)
  369. FreeSid (principalSID);
  370. else
  371. free (principalSID);
  372. }
  373. return returnValue;
  374. }
  375. DWORD
  376. GetCurrentUserSID (
  377. PSID *Sid
  378. )
  379. {
  380. DWORD dwReturn = ERROR_SUCCESS;
  381. TOKEN_USER *tokenUser = NULL;
  382. HANDLE tokenHandle = NULL;
  383. DWORD tokenSize;
  384. DWORD sidLength;
  385. if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &tokenHandle))
  386. {
  387. GetTokenInformation (tokenHandle, TokenUser, tokenUser, 0, &tokenSize);
  388. tokenUser = (TOKEN_USER *) malloc (tokenSize);
  389. if (!tokenUser)
  390. {
  391. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  392. return GetLastError();
  393. }
  394. if (GetTokenInformation (tokenHandle, TokenUser, tokenUser, tokenSize, &tokenSize))
  395. {
  396. sidLength = GetLengthSid (tokenUser->User.Sid);
  397. *Sid = (PSID) malloc (sidLength);
  398. if (*Sid)
  399. {
  400. memcpy (*Sid, tokenUser->User.Sid, sidLength);
  401. }
  402. CloseHandle (tokenHandle);
  403. } else
  404. dwReturn = GetLastError();
  405. if (tokenUser)
  406. free(tokenUser);
  407. } else
  408. dwReturn = GetLastError();
  409. return dwReturn;
  410. }
  411. DWORD
  412. CreateNewSD (
  413. SECURITY_DESCRIPTOR **SD
  414. )
  415. {
  416. PACL dacl = NULL;
  417. DWORD sidLength;
  418. PSID sid;
  419. PSID groupSID;
  420. PSID ownerSID;
  421. DWORD returnValue;
  422. *SD = NULL;
  423. returnValue = GetCurrentUserSID (&sid);
  424. if (returnValue != ERROR_SUCCESS) {
  425. if (sid)
  426. free(sid);
  427. return returnValue;
  428. }
  429. sidLength = GetLengthSid (sid);
  430. *SD = (SECURITY_DESCRIPTOR *) malloc (
  431. (sizeof (ACL)+sizeof (ACCESS_ALLOWED_ACE)+sidLength) +
  432. (2 * sidLength) +
  433. sizeof (SECURITY_DESCRIPTOR));
  434. if (!*SD)
  435. {
  436. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  437. returnValue = GetLastError();
  438. return returnValue;
  439. }
  440. groupSID = (SID *) (*SD + 1);
  441. ownerSID = (SID *) (((BYTE *) groupSID) + sidLength);
  442. dacl = (ACL *) (((BYTE *) ownerSID) + sidLength);
  443. if (!InitializeSecurityDescriptor (*SD, SECURITY_DESCRIPTOR_REVISION))
  444. {
  445. free (*SD);
  446. free (sid);
  447. returnValue = GetLastError();
  448. return returnValue;
  449. }
  450. if (!InitializeAcl (dacl,
  451. sizeof (ACL)+sizeof (ACCESS_ALLOWED_ACE)+sidLength,
  452. ACL_REVISION2))
  453. {
  454. free (*SD);
  455. free (sid);
  456. returnValue = GetLastError();
  457. return returnValue;
  458. }
  459. if (!AddAccessAllowedAce (dacl,
  460. ACL_REVISION2,
  461. COM_RIGHTS_EXECUTE,
  462. sid))
  463. {
  464. free (*SD);
  465. free (sid);
  466. returnValue = GetLastError();
  467. return returnValue;
  468. }
  469. if (!SetSecurityDescriptorDacl (*SD, TRUE, dacl, FALSE))
  470. {
  471. free (*SD);
  472. free (sid);
  473. returnValue = GetLastError();
  474. return returnValue;
  475. }
  476. memcpy (groupSID, sid, sidLength);
  477. if (!SetSecurityDescriptorGroup (*SD, groupSID, FALSE))
  478. {
  479. free (*SD);
  480. free (sid);
  481. returnValue = GetLastError();
  482. return returnValue;
  483. }
  484. memcpy (ownerSID, sid, sidLength);
  485. if (!SetSecurityDescriptorOwner (*SD, ownerSID, FALSE))
  486. {
  487. free (*SD);
  488. free (sid);
  489. returnValue = GetLastError();
  490. return returnValue;
  491. }
  492. // check if everything went ok
  493. if (!IsValidSecurityDescriptor(*SD))
  494. {
  495. free (*SD);
  496. free (sid);
  497. returnValue = ERROR_INVALID_SECURITY_DESCR;
  498. return returnValue;
  499. }
  500. if (sid)
  501. free(sid);
  502. return ERROR_SUCCESS;
  503. }
  504. DWORD
  505. MakeSDAbsolute (
  506. PSECURITY_DESCRIPTOR OldSD,
  507. PSECURITY_DESCRIPTOR *NewSD
  508. )
  509. {
  510. PSECURITY_DESCRIPTOR sd = NULL;
  511. DWORD descriptorSize;
  512. DWORD daclSize;
  513. DWORD saclSize;
  514. DWORD ownerSIDSize;
  515. DWORD groupSIDSize;
  516. PACL dacl = NULL;
  517. PACL sacl = NULL;
  518. PSID ownerSID = NULL;
  519. PSID groupSID = NULL;
  520. BOOL present;
  521. BOOL systemDefault;
  522. //
  523. // Get SACL
  524. //
  525. if (!GetSecurityDescriptorSacl (OldSD, &present, &sacl, &systemDefault))
  526. return GetLastError();
  527. if (sacl && present)
  528. {
  529. saclSize = sacl->AclSize;
  530. } else saclSize = 0;
  531. //
  532. // Get DACL
  533. //
  534. if (!GetSecurityDescriptorDacl (OldSD, &present, &dacl, &systemDefault))
  535. return GetLastError();
  536. if (dacl && present)
  537. {
  538. daclSize = dacl->AclSize;
  539. } else daclSize = 0;
  540. //
  541. // Get Owner
  542. //
  543. if (!GetSecurityDescriptorOwner (OldSD, &ownerSID, &systemDefault))
  544. return GetLastError();
  545. ownerSIDSize = GetLengthSid (ownerSID);
  546. //
  547. // Get Group
  548. //
  549. if (!GetSecurityDescriptorGroup (OldSD, &groupSID, &systemDefault))
  550. return GetLastError();
  551. groupSIDSize = GetLengthSid (groupSID);
  552. //
  553. // Do the conversion
  554. //
  555. descriptorSize = 0;
  556. MakeAbsoluteSD (OldSD, sd, &descriptorSize, dacl, &daclSize, sacl,
  557. &saclSize, ownerSID, &ownerSIDSize, groupSID,
  558. &groupSIDSize);
  559. sd = (PSECURITY_DESCRIPTOR) new BYTE [SECURITY_DESCRIPTOR_MIN_LENGTH];
  560. if (!sd)
  561. {
  562. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  563. return GetLastError();
  564. }
  565. if (!InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION))
  566. return GetLastError();
  567. if (!MakeAbsoluteSD (OldSD, sd, &descriptorSize, dacl, &daclSize, sacl,
  568. &saclSize, ownerSID, &ownerSIDSize, groupSID,
  569. &groupSIDSize))
  570. return GetLastError();
  571. *NewSD = sd;
  572. return ERROR_SUCCESS;
  573. }
  574. DWORD
  575. SetNamedValueSD (
  576. HKEY RootKey,
  577. LPTSTR KeyName,
  578. LPTSTR ValueName,
  579. SECURITY_DESCRIPTOR *SD
  580. )
  581. {
  582. DWORD returnValue;
  583. DWORD disposition;
  584. HKEY registryKey;
  585. //
  586. // Create new key or open existing key
  587. //
  588. returnValue = RegCreateKeyEx (RootKey, KeyName, 0, _T(""), 0, KEY_ALL_ACCESS, NULL, &registryKey, &disposition);
  589. if (returnValue != ERROR_SUCCESS)
  590. return returnValue;
  591. //
  592. // Write the security descriptor
  593. //
  594. returnValue = RegSetValueEx (registryKey, ValueName, 0, REG_BINARY, (LPBYTE) SD, GetSecurityDescriptorLength (SD));
  595. if (returnValue != ERROR_SUCCESS)
  596. return returnValue;
  597. RegCloseKey (registryKey);
  598. return ERROR_SUCCESS;
  599. }
  600. DWORD
  601. GetNamedValueSD (
  602. HKEY RootKey,
  603. LPTSTR KeyName,
  604. LPTSTR ValueName,
  605. SECURITY_DESCRIPTOR **SD,
  606. BOOL *NewSD
  607. )
  608. {
  609. DWORD returnValue;
  610. HKEY registryKey;
  611. DWORD valueType;
  612. DWORD valueSize = 0;
  613. *NewSD = FALSE;
  614. //
  615. // Get the security descriptor from the named value. If it doesn't
  616. // exist, create a fresh one.
  617. //
  618. returnValue = RegOpenKeyEx (RootKey, KeyName, 0, KEY_ALL_ACCESS, &registryKey);
  619. if (returnValue != ERROR_SUCCESS)
  620. {
  621. if (returnValue == ERROR_FILE_NOT_FOUND)
  622. {
  623. *SD = NULL;
  624. returnValue = CreateNewSD (SD);
  625. if (returnValue != ERROR_SUCCESS) {
  626. if (*SD)
  627. free(*SD);
  628. return returnValue;
  629. }
  630. *NewSD = TRUE;
  631. return ERROR_SUCCESS;
  632. } else
  633. return returnValue;
  634. }
  635. returnValue = RegQueryValueEx (registryKey, ValueName, NULL, &valueType, NULL, &valueSize);
  636. if (returnValue && returnValue != ERROR_INSUFFICIENT_BUFFER)
  637. {
  638. *SD = NULL;
  639. returnValue = CreateNewSD (SD);
  640. if (returnValue != ERROR_SUCCESS) {
  641. if (*SD)
  642. free(*SD);
  643. return returnValue;
  644. }
  645. *NewSD = TRUE;
  646. } else
  647. {
  648. *SD = (SECURITY_DESCRIPTOR *) malloc (valueSize);
  649. if (!*SD)
  650. {
  651. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  652. return GetLastError();
  653. }
  654. returnValue = RegQueryValueEx (registryKey,
  655. ValueName,
  656. NULL,
  657. &valueType,
  658. (LPBYTE) *SD,
  659. &valueSize);
  660. if (returnValue)
  661. {
  662. if (*SD)
  663. free (*SD);
  664. *SD = NULL;
  665. returnValue = CreateNewSD (SD);
  666. if (returnValue != ERROR_SUCCESS) {
  667. if (*SD)
  668. free(*SD);
  669. return returnValue;
  670. }
  671. *NewSD = TRUE;
  672. }
  673. }
  674. RegCloseKey (registryKey);
  675. return ERROR_SUCCESS;
  676. }
  677. DWORD
  678. AddPrincipalToNamedValueSD (
  679. HKEY RootKey,
  680. LPTSTR KeyName,
  681. LPTSTR ValueName,
  682. LPTSTR Principal,
  683. BOOL Permit
  684. )
  685. {
  686. DWORD returnValue = ERROR_SUCCESS;
  687. SECURITY_DESCRIPTOR *sd = NULL;
  688. SECURITY_DESCRIPTOR *sdSelfRelative = NULL;
  689. SECURITY_DESCRIPTOR *sdAbsolute = NULL;
  690. DWORD secDescSize;
  691. BOOL present;
  692. BOOL defaultDACL;
  693. PACL dacl;
  694. BOOL newSD = FALSE;
  695. BOOL fFreeAbsolute = TRUE;
  696. returnValue = GetNamedValueSD (RootKey, KeyName, ValueName, &sd, &newSD);
  697. //
  698. // Get security descriptor from registry or create a new one
  699. //
  700. if (returnValue != ERROR_SUCCESS)
  701. return returnValue;
  702. if (!GetSecurityDescriptorDacl (sd, &present, &dacl, &defaultDACL)) {
  703. returnValue = GetLastError();
  704. goto Cleanup;
  705. }
  706. if (newSD)
  707. {
  708. AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, TEXT("SYSTEM"));
  709. AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, TEXT("INTERACTIVE"));
  710. }
  711. //
  712. // Add the Principal that the caller wants added
  713. //
  714. if (Permit)
  715. returnValue = AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, Principal);
  716. else
  717. returnValue = AddAccessDeniedACEToACL (&dacl, GENERIC_ALL, Principal);
  718. if (returnValue != ERROR_SUCCESS)
  719. goto Cleanup;
  720. //
  721. // Make the security descriptor absolute if it isn't new
  722. //
  723. if (!newSD) {
  724. MakeSDAbsolute ((PSECURITY_DESCRIPTOR) sd, (PSECURITY_DESCRIPTOR *) &sdAbsolute);
  725. fFreeAbsolute = TRUE;
  726. } else {
  727. sdAbsolute = sd;
  728. fFreeAbsolute = FALSE;
  729. }
  730. //
  731. // Set the discretionary ACL on the security descriptor
  732. //
  733. if (!SetSecurityDescriptorDacl (sdAbsolute, TRUE, dacl, FALSE)) {
  734. returnValue = GetLastError();
  735. goto Cleanup;
  736. }
  737. //
  738. // Make the security descriptor self-relative so that we can
  739. // store it in the registry
  740. //
  741. secDescSize = 0;
  742. MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize);
  743. sdSelfRelative = (SECURITY_DESCRIPTOR *) malloc (secDescSize);
  744. if (!sdSelfRelative)
  745. {
  746. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  747. returnValue = GetLastError();
  748. goto Cleanup;
  749. }
  750. if (!MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize)) {
  751. returnValue = GetLastError();
  752. goto Cleanup;
  753. }
  754. //
  755. // Store the security descriptor in the registry
  756. //
  757. SetNamedValueSD (RootKey, KeyName, ValueName, sdSelfRelative);
  758. Cleanup:
  759. if (sd)
  760. free (sd);
  761. if (sdSelfRelative)
  762. free (sdSelfRelative);
  763. if (fFreeAbsolute && sdAbsolute)
  764. free (sdAbsolute);
  765. return returnValue;
  766. }
  767. DWORD
  768. RemovePrincipalFromNamedValueSD (
  769. HKEY RootKey,
  770. LPTSTR KeyName,
  771. LPTSTR ValueName,
  772. LPTSTR Principal
  773. )
  774. {
  775. DWORD returnValue = ERROR_SUCCESS;
  776. SECURITY_DESCRIPTOR *sd = NULL;
  777. SECURITY_DESCRIPTOR *sdSelfRelative = NULL;
  778. SECURITY_DESCRIPTOR *sdAbsolute = NULL;
  779. DWORD secDescSize;
  780. BOOL present;
  781. BOOL defaultDACL;
  782. PACL dacl = NULL;
  783. BOOL newSD = FALSE;
  784. BOOL fFreeAbsolute = TRUE;
  785. returnValue = GetNamedValueSD (RootKey, KeyName, ValueName, &sd, &newSD);
  786. //
  787. // Get security descriptor from registry or create a new one
  788. //
  789. if (returnValue != ERROR_SUCCESS)
  790. return returnValue;
  791. if (!GetSecurityDescriptorDacl (sd, &present, &dacl, &defaultDACL)) {
  792. returnValue = GetLastError();
  793. goto Cleanup;
  794. }
  795. //
  796. // If the security descriptor is new, add the required Principals to it
  797. //
  798. if (newSD)
  799. {
  800. AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, TEXT("SYSTEM"));
  801. AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, TEXT("INTERACTIVE"));
  802. }
  803. //
  804. // Remove the Principal that the caller wants removed
  805. //
  806. returnValue = RemovePrincipalFromACL (dacl, Principal);
  807. if (returnValue != ERROR_SUCCESS)
  808. goto Cleanup;
  809. //
  810. // Make the security descriptor absolute if it isn't new
  811. //
  812. if (!newSD) {
  813. MakeSDAbsolute ((PSECURITY_DESCRIPTOR) sd, (PSECURITY_DESCRIPTOR *) &sdAbsolute);
  814. fFreeAbsolute = TRUE;
  815. } else {
  816. sdAbsolute = sd;
  817. fFreeAbsolute = FALSE;
  818. }
  819. //
  820. // Set the discretionary ACL on the security descriptor
  821. //
  822. if (!SetSecurityDescriptorDacl (sdAbsolute, TRUE, dacl, FALSE)) {
  823. returnValue = GetLastError();
  824. goto Cleanup;
  825. }
  826. //
  827. // Make the security descriptor self-relative so that we can
  828. // store it in the registry
  829. //
  830. secDescSize = 0;
  831. MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize);
  832. sdSelfRelative = (SECURITY_DESCRIPTOR *) malloc (secDescSize);
  833. if (!sdSelfRelative)
  834. {
  835. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  836. returnValue = GetLastError();
  837. goto Cleanup;
  838. }
  839. if (!MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize)) {
  840. returnValue = GetLastError();
  841. goto Cleanup;
  842. }
  843. //
  844. // Store the security descriptor in the registry
  845. //
  846. SetNamedValueSD (RootKey, KeyName, ValueName, sdSelfRelative);
  847. Cleanup:
  848. if (sd)
  849. free (sd);
  850. if (sdSelfRelative)
  851. free (sdSelfRelative);
  852. if (fFreeAbsolute && sdAbsolute)
  853. free (sdAbsolute);
  854. return returnValue;
  855. }
  856. DWORD
  857. ChangeAppIDAccessACL (
  858. LPTSTR AppID,
  859. LPTSTR Principal,
  860. BOOL SetPrincipal,
  861. BOOL Permit
  862. )
  863. {
  864. TCHAR keyName [256];
  865. DWORD err;
  866. wcscpy(keyName, TEXT("APPID\\"));
  867. wcscat(keyName, AppID);
  868. if (SetPrincipal)
  869. {
  870. err = RemovePrincipalFromNamedValueSD (HKEY_CLASSES_ROOT,
  871. keyName,
  872. TEXT("AccessPermission"),
  873. Principal);
  874. err = AddPrincipalToNamedValueSD (HKEY_CLASSES_ROOT,
  875. keyName,
  876. TEXT("AccessPermission"),
  877. Principal,
  878. Permit);
  879. }
  880. else
  881. {
  882. err = RemovePrincipalFromNamedValueSD (HKEY_CLASSES_ROOT,
  883. keyName,
  884. TEXT("AccessPermission"),
  885. Principal);
  886. }
  887. return err;
  888. }
  889. DWORD
  890. ChangeAppIDLaunchACL (
  891. LPTSTR AppID,
  892. LPTSTR Principal,
  893. BOOL SetPrincipal,
  894. BOOL Permit
  895. )
  896. {
  897. TCHAR keyName [256];
  898. DWORD err;
  899. wcscpy(keyName, TEXT("APPID\\"));
  900. wcscat(keyName, AppID);
  901. if (SetPrincipal)
  902. {
  903. err = RemovePrincipalFromNamedValueSD (HKEY_CLASSES_ROOT,
  904. keyName,
  905. TEXT("LaunchPermission"),
  906. Principal);
  907. err = AddPrincipalToNamedValueSD (HKEY_CLASSES_ROOT,
  908. keyName,
  909. TEXT("LaunchPermission"),
  910. Principal,
  911. Permit);
  912. }
  913. else
  914. {
  915. err = RemovePrincipalFromNamedValueSD (HKEY_CLASSES_ROOT,
  916. keyName,
  917. TEXT("LaunchPermission"),
  918. Principal);
  919. }
  920. return err;
  921. }