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.

1655 lines
45 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. //
  4. // Copyright (C) Microsoft
  5. //
  6. // File: securd.cpp
  7. //
  8. // History: 30-March-2000 a-skuzin Created
  9. //
  10. //--------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include <winsta.h>
  13. #include <regapi.h>
  14. #include "secupgrd.h"
  15. #include "state.h"
  16. // from winnt.h
  17. #define MAXDWORD 0xffffffff
  18. //Global variables
  19. BYTE g_DefaultSD[] = { 0x01,0x00,0x14,0x80,0x88,0x00,0x00,0x00,0x94,0x00,
  20. 0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
  21. 0x02,0x00,0x74,0x00,0x05,0x00,0x00,0x00,0x00,0x00,
  22. 0x18,0x00,0xBF,0x03,0x0F,0x00,0x01,0x02,0x00,0x00,
  23. 0x00,0x00,0x00,0x05,0x20,0x00,0x00,0x00,0x20,0x02,
  24. 0x00,0x00,0x00,0x00,0x14,0x00,0xBF,0x03,0x0F,0x00,
  25. 0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x05,0x12,0x00,
  26. 0x00,0x00,0x00,0x00,0x18,0x00,0xA1,0x01,0x00,0x00,
  27. 0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x05,0x20,0x00,
  28. 0x00,0x00,0x2B,0x02,0x00,0x00,0x00,0x00,0x14,0x00,
  29. 0x81,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,
  30. 0x00,0x05,0x13,0x00,0x00,0x00,0x00,0x00,0x14,0x00,
  31. 0x81,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,
  32. 0x00,0x05,0x14,0x00,0x00,0x00,0x01,0x01,0x00,0x00,
  33. 0x00,0x00,0x00,0x05,0x12,0x00,0x00,0x00,0x01,0x01,
  34. 0x00,0x00,0x00,0x00,0x00,0x05,0x12,0x00,0x00,0x00 };
  35. BYTE g_ConsoleSD[] = { 0x01,0x00,0x14,0x80,0x70,0x00,0x00,0x00,0x7C,0x00,
  36. 0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
  37. 0x02,0x00,0x5C,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
  38. 0x18,0x00,0xBF,0x03,0x0F,0x00,0x01,0x02,0x00,0x00,
  39. 0x00,0x00,0x00,0x05,0x20,0x00,0x00,0x00,0x20,0x02,
  40. 0x00,0x00,0x00,0x00,0x14,0x00,0x81,0x00,0x00,0x00,
  41. 0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x05,0x13,0x00,
  42. 0x00,0x00,0x00,0x00,0x14,0x00,0x81,0x00,0x00,0x00,
  43. 0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x05,0x14,0x00,
  44. 0x00,0x00,0x00,0x00,0x14,0x00,0xBF,0x03,0x0F,0x00,
  45. 0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x05,0x12,0x00,
  46. 0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x05,
  47. 0x12,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,
  48. 0x00,0x05,0x12,0x00,0x00,0x00 };
  49. DWORD AreThereAnyCustomSecurityDescriptors( BOOL &any )
  50. {
  51. HKEY hKey;
  52. DWORD err;
  53. err=RegOpenKeyEx(
  54. HKEY_LOCAL_MACHINE,
  55. REG_WINSTATION_KEY,
  56. 0,
  57. KEY_READ,
  58. &hKey
  59. );
  60. if( err!=ERROR_SUCCESS )
  61. {
  62. LOGMESSAGE1(_T("Could not open TS key %d"),err);
  63. return err;
  64. }
  65. CDefaultSD DefaultSD;
  66. CDefaultSD ConsoleSD;
  67. //Load default SD from the registry, since we need to compare to this
  68. err = DefaultSD.Init(hKey,DefaultRDPSD);
  69. if( err!=ERROR_SUCCESS )
  70. {
  71. RegCloseKey(hKey);
  72. return err;
  73. }
  74. //Load default console SD from the registry, since we need to compare to this
  75. err = ConsoleSD.Init(hKey,DefaultConsoleSD);
  76. if( err!=ERROR_SUCCESS )
  77. {
  78. RegCloseKey(hKey);
  79. return err;
  80. }
  81. CNameAndSDList NameSDList;
  82. DWORD dwTotalWinStations = 0;
  83. DWORD dwDefaultWinStations = 0;
  84. err=EnumWinStationSecurityDescriptors( hKey, &NameSDList);
  85. if(err == ERROR_SUCCESS)
  86. {
  87. dwTotalWinStations = NameSDList.size();
  88. if(dwTotalWinStations)
  89. {
  90. CNameAndSDList::iterator it;
  91. for(it=NameSDList.begin();it!=NameSDList.end(); it++)
  92. {
  93. if((*it).IsDefaultOrEmpty(&DefaultSD,&ConsoleSD))
  94. {
  95. dwDefaultWinStations++;
  96. }
  97. }
  98. //If all descriptors are default
  99. if(dwDefaultWinStations == dwTotalWinStations)
  100. {
  101. any = FALSE;
  102. }
  103. else
  104. {
  105. any = TRUE;
  106. }
  107. }
  108. }
  109. RegCloseKey(hKey);
  110. return err;
  111. }
  112. /*****************************************************************************
  113. *
  114. * SetupWorker
  115. *
  116. * ENTRY:
  117. * IN const TSState &State
  118. *
  119. *
  120. * NOTES:
  121. *
  122. * EXIT:
  123. * Returns: 0 if success, error code if failure
  124. *
  125. ****************************************************************************/
  126. DWORD
  127. SetupWorker(
  128. IN const TSState &State )
  129. {
  130. DWORD Result;
  131. const BOOL bStandAlone = State.IsStandAlone();
  132. const BOOL bClean = State.IsTSFreshInstall();
  133. const BOOL bAppServer = State.IsItAppServer();
  134. const BOOL bServer = State.IsServer();
  135. LOGMESSAGE4(_T("SetupWorker( %d, %d, %d, %d )"), bClean, bStandAlone, bServer, bAppServer );
  136. if (!bStandAlone) // we are in GUI-setup mode
  137. {
  138. // clean install of OS or OS upgrade
  139. Result = SetupWorkerNotStandAlone( bClean, bServer,bAppServer );
  140. }
  141. else
  142. {
  143. // we are being called from Add/Remove Programs, which means, we are
  144. // switching modes
  145. BOOL anyCustomSDs;
  146. Result = AreThereAnyCustomSecurityDescriptors( anyCustomSDs ) ;
  147. LOGMESSAGE1(_T("AreThereAnyCustomSecurityDescriptors = %d"), anyCustomSDs );
  148. if ( Result == ERROR_SUCCESS )
  149. {
  150. if (!anyCustomSDs )
  151. {
  152. // make sure we don't have a left-over privilage on the EveryoneSID
  153. Result = GrantRemotePrivilegeToEveryone( FALSE );
  154. }
  155. if (bAppServer)
  156. {
  157. // copy the content of the Local\Users into the RDU-group if and only
  158. // if there are no custom security dscriptors.
  159. if (!anyCustomSDs ) // there are no custom security descriptors
  160. {
  161. Result = CopyUsersGroupToRDUsersGroup();
  162. }
  163. }
  164. else
  165. {
  166. // we are switching to Remote-Admin mode, secure machine by
  167. // removing the content of the RDU-Group
  168. Result = RemoveAllFromRDUsersGroup();
  169. }
  170. }
  171. else
  172. {
  173. LOGMESSAGE1(_T("AreThereAnyCustomSecurityDescriptors() returned : %d"),Result );
  174. }
  175. }
  176. return Result;
  177. }
  178. /*****************************************************************************
  179. *
  180. * SetupWorkerNoStandAlone
  181. * This will be called when machine is being upgraded or fresh OS is being installed.
  182. * It is NOT called if switching modes (AS <->RA )
  183. *
  184. * ENTRY:
  185. * none
  186. *
  187. *
  188. * NOTES:
  189. * IN BOOL bClean
  190. * IN BOOL bServer
  191. * IN BOOL bAppServer
  192. *
  193. * EXIT:
  194. * Returns: 0 if success, error code if failure
  195. *
  196. ****************************************************************************/
  197. DWORD SetupWorkerNotStandAlone(
  198. IN BOOL bClean,
  199. IN BOOL bServer,
  200. IN BOOL bAppServer)
  201. {
  202. HKEY hKey;
  203. DWORD err;
  204. err=RegOpenKeyEx(
  205. HKEY_LOCAL_MACHINE,
  206. REG_WINSTATION_KEY,
  207. 0,
  208. KEY_READ|KEY_WRITE,
  209. &hKey
  210. );
  211. if( err!=ERROR_SUCCESS )
  212. {
  213. LOGMESSAGE1(_T("Could not open TS key %d"),err);
  214. return err;
  215. }
  216. if(bClean)
  217. {
  218. if(bAppServer)
  219. {
  220. err = CopyUsersGroupToRDUsersGroup();
  221. LOGMESSAGE1(_T("CopyUsersGroupToRDUsersGroup() returned : %d"),err);
  222. if(err != ERROR_SUCCESS)
  223. {
  224. RegCloseKey(hKey);
  225. return err;
  226. }
  227. }
  228. }
  229. else
  230. {
  231. err = GrantRemoteUsersAccessToWinstations(hKey,bServer,bAppServer);
  232. LOGMESSAGE1(_T("GrantRemoteUsersAccessToWinstations() returned : %d"),err);
  233. if(err != ERROR_SUCCESS)
  234. {
  235. RegCloseKey(hKey);
  236. return err;
  237. }
  238. }
  239. err = SetNewDefaultSecurity(hKey);
  240. LOGMESSAGE1(_T("SetNewDefaultSecurity() returned : %d"),err);
  241. err = SetNewConsoleSecurity(hKey,bServer);
  242. LOGMESSAGE1(_T("SetNewConsoleSecurity() returned : %d"),err);
  243. RegCloseKey(hKey);
  244. return err;
  245. }
  246. /*****************************************************************************
  247. *
  248. * GrantRemoteUsersAccessToWinstations
  249. *
  250. * if all winstations have default SD - copies all members from "Users" to
  251. * "Remote Desktop Users", then deletes all winstation's security descriptors;
  252. * otherwise grants "Everyone" with "SeRemoteInteractiveLogonRight" privilege
  253. * and then adds "Remote Desktop Users" to each winstation's security descriptor
  254. *
  255. * ENTRY:
  256. * IN HKEY hKey - handle to HKLM\SYSTEM\CurrentControlSet\
  257. * Control\Terminal Server\WinStations
  258. * IN BOOL bAppServer
  259. *
  260. * NOTES:
  261. *
  262. *
  263. * EXIT:
  264. * Returns: 0 if success, error code if failure
  265. *
  266. ****************************************************************************/
  267. DWORD
  268. GrantRemoteUsersAccessToWinstations(
  269. IN HKEY hKey,
  270. IN BOOL bServer,
  271. IN BOOL bAppServer)
  272. {
  273. DWORD err;
  274. CDefaultSD DefaultSD;
  275. CDefaultSD ConsoleSD;
  276. //Load default SD from the registry
  277. err = DefaultSD.Init(hKey,DefaultRDPSD);
  278. if( err!=ERROR_SUCCESS )
  279. {
  280. //Default SD may not be present if TS was
  281. //never enabled.
  282. if(err == ERROR_FILE_NOT_FOUND)
  283. {
  284. err = ERROR_SUCCESS;
  285. //Copy all members of "Users" group to
  286. //"Remote Desktop Users" group.
  287. //And we are done
  288. if(bAppServer)
  289. {
  290. err = CopyUsersGroupToRDUsersGroup();
  291. }
  292. }
  293. return err;
  294. }
  295. //Load default console SD from the registry
  296. err = ConsoleSD.Init(hKey,DefaultConsoleSD);
  297. if( err!=ERROR_SUCCESS )
  298. {
  299. return err;
  300. }
  301. BOOL bDefaultSDHasRemoteUsers;
  302. err = DefaultSD.DoesDefaultSDHaveRemoteUsers(&bDefaultSDHasRemoteUsers);
  303. if( err!=ERROR_SUCCESS )
  304. {
  305. return err;
  306. }
  307. else
  308. {
  309. //in this case assume that system already has been upgraded before.
  310. if(bDefaultSDHasRemoteUsers)
  311. {
  312. return ERROR_SUCCESS;
  313. }
  314. }
  315. CNameAndSDList NameSDList;
  316. DWORD dwTotalWinStations = 0;
  317. DWORD dwDefaultWinStations = 0;
  318. err=EnumWinStationSecurityDescriptors( hKey, &NameSDList);
  319. if(err == ERROR_SUCCESS)
  320. {
  321. dwTotalWinStations = NameSDList.size();
  322. if(dwTotalWinStations)
  323. {
  324. CNameAndSDList::iterator it;
  325. for(it=NameSDList.begin();it!=NameSDList.end(); it++)
  326. {
  327. if((*it).IsDefaultOrEmpty(&DefaultSD,&ConsoleSD))
  328. {
  329. dwDefaultWinStations++;
  330. }
  331. }
  332. //If all descriptors are default
  333. if(dwDefaultWinStations == dwTotalWinStations)
  334. {
  335. //Copy all members of "Users" group to
  336. //"Remote Desktop Users" group.
  337. if(bAppServer)
  338. {
  339. err = CopyUsersGroupToRDUsersGroup();
  340. }
  341. //remove all ald default SDs (because we will have
  342. //different default SD
  343. for(it=NameSDList.begin();it!=NameSDList.end(); it++)
  344. {
  345. if((*it).m_pSD)
  346. {
  347. //in case of error, continue with other winstations
  348. //but return first error.
  349. if(!err)
  350. {
  351. err = RemoveWinstationSecurity( hKey, (*it).m_pName );
  352. }
  353. else
  354. {
  355. RemoveWinstationSecurity( hKey, (*it).m_pName );
  356. }
  357. }
  358. }
  359. }
  360. else
  361. {
  362. //Grant "SeRemoteInteractiveLogonRight" privilege to "Everyone"
  363. err = GrantRemotePrivilegeToEveryone( TRUE );
  364. //Add "Remote Desktop Users" group to WinStation's DS.
  365. //Add also "LocalService" and "NetworkService".
  366. //NOTE: (*it).m_pSD is being changed during each call
  367. //to AddLocalAndNetworkServiceToWinstationSD or
  368. //AddRemoteUsersToWinstationSD
  369. for(it=NameSDList.begin();it!=NameSDList.end(); it++)
  370. {
  371. //On server - skip console
  372. if(bServer && (*it).IsConsole())
  373. {
  374. //if SD is not NULL add "LocalService" and "NetworkService" to it
  375. if((*it).m_pSD)
  376. {
  377. if(!err)
  378. {
  379. err = AddLocalAndNetworkServiceToWinstationSD( hKey, &(*it) );
  380. }
  381. else
  382. {
  383. AddLocalAndNetworkServiceToWinstationSD( hKey, &(*it) );
  384. }
  385. }
  386. continue;
  387. }
  388. //if SD is not NULL add RDU to it
  389. if((*it).m_pSD)
  390. {
  391. //in case of error, continue with other winstations
  392. //but return first error.
  393. if(!err)
  394. {
  395. err = AddRemoteUsersToWinstationSD( hKey, &(*it) );
  396. }
  397. else
  398. {
  399. AddRemoteUsersToWinstationSD( hKey, &(*it) );
  400. }
  401. //add "LocalService" and "NetworkService" to SD
  402. if(!err)
  403. {
  404. err = AddLocalAndNetworkServiceToWinstationSD( hKey, &(*it) );
  405. }
  406. else
  407. {
  408. AddLocalAndNetworkServiceToWinstationSD( hKey, &(*it) );
  409. }
  410. }
  411. }
  412. }
  413. }
  414. }
  415. return err;
  416. }
  417. /*****************************************************************************
  418. *
  419. * AddRemoteUserToWinstationSD
  420. *
  421. * Grants "user access" permissions to a winstation to "REMOTE DESKTOP USERS"
  422. *
  423. * ENTRY:
  424. * IN HKEY hKeyParent - handle to HKLM\SYSTEM\CurrentControlSet\
  425. * Control\Terminal Server\WinStations
  426. * IN CNameAndSD *pNameSD - name and security descriptor of a winstation
  427. *
  428. *
  429. * NOTES:
  430. *
  431. *
  432. * EXIT:
  433. * Returns: 0 if success, error code if failure
  434. *
  435. *
  436. *
  437. ****************************************************************************/
  438. DWORD
  439. AddRemoteUsersToWinstationSD(
  440. IN HKEY hKeyParent,
  441. IN CNameAndSD *pNameSD)
  442. {
  443. //
  444. DWORD err = ERROR_SUCCESS;
  445. PACL pDacl = NULL;
  446. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  447. PSID pRUSid=NULL;
  448. if( !AllocateAndInitializeSid( &sia, 2,
  449. SECURITY_BUILTIN_DOMAIN_RID,
  450. DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS,
  451. 0, 0, 0, 0, 0, 0,&pRUSid ) )
  452. {
  453. return GetLastError();
  454. }
  455. //get dacl
  456. err = GetDacl(pNameSD->m_pSD, &pDacl );
  457. if( err == ERROR_SUCCESS ) {
  458. if(!pDacl)
  459. {
  460. //It shuold never be in our case
  461. //so we return error here
  462. FreeSid(pRUSid);
  463. return ERROR_INVALID_PARAMETER;
  464. }
  465. //let's add it
  466. err = AddUserToDacl( hKeyParent, pDacl, pRUSid, WINSTATION_USER_ACCESS, pNameSD );
  467. }
  468. FreeSid(pRUSid);
  469. return err;
  470. }
  471. /*****************************************************************************
  472. *
  473. * AddLocalAndNetworkServiceToWinstationSD
  474. *
  475. * Grants WINSTATION_QUERY | WINSTATION_MSG permissions to
  476. * a winstation to LocalService and NetworkService accounts
  477. *
  478. * ENTRY:
  479. * IN HKEY hKeyParent - handle to HKLM\SYSTEM\CurrentControlSet\
  480. * Control\Terminal Server\WinStations
  481. * IN CNameAndSD *pNameSD - name and security descriptor of a winstation
  482. *
  483. *
  484. * NOTES:
  485. *
  486. *
  487. * EXIT:
  488. * Returns: 0 if success, error code if failure
  489. *
  490. *
  491. *
  492. ****************************************************************************/
  493. DWORD
  494. AddLocalAndNetworkServiceToWinstationSD(
  495. IN HKEY hKeyParent,
  496. IN CNameAndSD *pNameSD)
  497. {
  498. //
  499. DWORD err = ERROR_SUCCESS;
  500. PACL pDacl = NULL;
  501. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  502. PSID pLSSid=NULL;
  503. PSID pNSSid=NULL;
  504. if( !AllocateAndInitializeSid( &sia, 1,
  505. SECURITY_LOCAL_SERVICE_RID,
  506. 0, 0, 0, 0, 0, 0, 0,&pLSSid ) )
  507. {
  508. return GetLastError();
  509. }
  510. if( !AllocateAndInitializeSid( &sia, 1,
  511. SECURITY_NETWORK_SERVICE_RID,
  512. 0, 0, 0, 0, 0, 0, 0,&pNSSid ) )
  513. {
  514. FreeSid(pLSSid);
  515. return GetLastError();
  516. }
  517. //get dacl
  518. err = GetDacl(pNameSD->m_pSD, &pDacl );
  519. if( err == ERROR_SUCCESS ) {
  520. if(!pDacl)
  521. {
  522. //It shuold never be in our case
  523. //so we return error here
  524. FreeSid(pLSSid);
  525. FreeSid(pNSSid);
  526. return ERROR_INVALID_PARAMETER;
  527. }
  528. //let's add it
  529. err = AddUserToDacl( hKeyParent, pDacl, pLSSid,
  530. WINSTATION_QUERY | WINSTATION_MSG, pNameSD );
  531. if(err == ERROR_SUCCESS)
  532. {
  533. //SD has been changed. It makes pDacl invalid.
  534. //So we need to get it again
  535. err = GetDacl(pNameSD->m_pSD, &pDacl );
  536. ASSERT(pDacl);
  537. if(err == ERROR_SUCCESS)
  538. {
  539. err = AddUserToDacl( hKeyParent, pDacl, pNSSid,
  540. WINSTATION_QUERY | WINSTATION_MSG, pNameSD );
  541. }
  542. }
  543. }
  544. FreeSid(pLSSid);
  545. FreeSid(pNSSid);
  546. return err;
  547. }
  548. /*****************************************************************************
  549. *
  550. * AddUserToDacl
  551. *
  552. * Grants
  553. * WINSTATION_USER_ACCESS
  554. * permissions to a winstation to user, defined by SID
  555. *
  556. * ENTRY:
  557. *
  558. * IN HKEY hKeyParent - handle to HKLM\SYSTEM\CurrentControlSet\
  559. * Control\Terminal Server\WinStations
  560. * IN PACL pOldACL: pointer to prewvious DACL of the key
  561. * IN PSID pSid: pointer to SID of user to grant permissions to
  562. * IN DWORD dwAccessMask: access flags for this SID
  563. * IN CNameAndSD *pNameSD - name and security descriptor of a winstation
  564. * NOTES:
  565. *
  566. * EXIT:
  567. * Returns: error code if cannot grant permissions; ERROR_SUCCESS otherwise.
  568. *
  569. ****************************************************************************/
  570. DWORD
  571. AddUserToDacl(
  572. IN HKEY hKeyParent,
  573. IN PACL pOldACL,
  574. IN PSID pSid,
  575. IN DWORD dwAccessMask,
  576. IN CNameAndSD *pNameSD)
  577. {
  578. //See if this user is already in the DACL.
  579. //In this case don't add the user
  580. //search ACL for "REMOTE USERS" SID
  581. ACL_SIZE_INFORMATION asiAclSize;
  582. DWORD dwBufLength=sizeof(asiAclSize);
  583. ACCESS_ALLOWED_ACE *paaAllowedAce;
  584. DWORD dwAcl_i;
  585. ASSERT(pOldACL);
  586. if (GetAclInformation(pOldACL,
  587. (LPVOID)&asiAclSize,
  588. (DWORD)dwBufLength,
  589. (ACL_INFORMATION_CLASS)AclSizeInformation))
  590. {
  591. for (dwAcl_i = 0; dwAcl_i < asiAclSize.AceCount; dwAcl_i++)
  592. {
  593. if(GetAce( pOldACL, dwAcl_i, (LPVOID *)&paaAllowedAce))
  594. {
  595. if(EqualSid((PSID)&(paaAllowedAce->SidStart),pSid))
  596. {
  597. //some permission already exist, we don't need to
  598. //do anything (even if it is a different permission!)
  599. return ERROR_SUCCESS;
  600. }
  601. }
  602. }
  603. }
  604. DWORD err=ERROR_SUCCESS;
  605. PACL pNewACL;
  606. ACCESS_ALLOWED_ACE *pNewACE;
  607. //calculate space needed for 1 additional ACE
  608. WORD wSidSize=(WORD)GetLengthSid( pSid);
  609. WORD wAceSize=(sizeof(ACCESS_ALLOWED_ACE)+wSidSize-sizeof( DWORD ));
  610. pNewACL=(PACL)LocalAlloc(LPTR,pOldACL->AclSize+wAceSize);
  611. if(!pNewACL)
  612. {
  613. return GetLastError();
  614. }
  615. //copy old ACL to new ACL
  616. memcpy(pNewACL,pOldACL,pOldACL->AclSize);
  617. //correct size
  618. pNewACL->AclSize+=wAceSize;
  619. //prepare new ACE
  620. //----------------------------------------------------------
  621. pNewACE=(ACCESS_ALLOWED_ACE*)LocalAlloc(LPTR,wAceSize);
  622. if(!pNewACE)
  623. {
  624. LocalFree(pNewACL);
  625. return GetLastError();
  626. }
  627. pNewACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  628. pNewACE->Header.AceFlags = 0;
  629. pNewACE->Header.AceSize = wAceSize;
  630. pNewACE->Mask = dwAccessMask;
  631. CopySid( wSidSize, (PSID) &(pNewACE->SidStart), pSid);
  632. //append new ACE to the ACL
  633. if(!AddAce(pNewACL,pNewACL->AclRevision,MAXDWORD,pNewACE,wAceSize))
  634. {
  635. err=GetLastError();
  636. }
  637. else
  638. {
  639. //create new security descriptor
  640. SECURITY_DESCRIPTOR NewAbsSD;
  641. if(InitializeSecurityDescriptor(&NewAbsSD, SECURITY_DESCRIPTOR_REVISION) &&
  642. SetSecurityDescriptorDacl(&NewAbsSD,TRUE,pNewACL,FALSE) )
  643. {
  644. //---------------------------------------------------------
  645. //Copy all other stuff from the old SD to the new SD
  646. SECURITY_DESCRIPTOR_CONTROL sdc;
  647. DWORD dwRevision;
  648. if(GetSecurityDescriptorControl(pNameSD->m_pSD,&sdc,&dwRevision))
  649. {
  650. //Clear SE_SELF_RELATIVE flag
  651. sdc &=~SE_SELF_RELATIVE;
  652. SetSecurityDescriptorControl(&NewAbsSD,sdc,sdc);
  653. }
  654. PSID pSid = NULL;
  655. BOOL bDefaulted;
  656. if(GetSecurityDescriptorOwner(pNameSD->m_pSD,&pSid,&bDefaulted) && pSid)
  657. {
  658. SetSecurityDescriptorOwner(&NewAbsSD,pSid,bDefaulted);
  659. }
  660. pSid = NULL;
  661. if(GetSecurityDescriptorGroup(pNameSD->m_pSD,&pSid,&bDefaulted) && pSid)
  662. {
  663. SetSecurityDescriptorGroup(&NewAbsSD,pSid,bDefaulted);
  664. }
  665. PACL pSacl = NULL;
  666. BOOL bSaclPresent;
  667. if(GetSecurityDescriptorSacl(pNameSD->m_pSD,&bSaclPresent,&pSacl,&bDefaulted))
  668. {
  669. SetSecurityDescriptorSacl(&NewAbsSD,bSaclPresent,pSacl,bDefaulted);
  670. }
  671. //---------------------------------------------------------
  672. DWORD dwSDLen = GetSecurityDescriptorLength( &NewAbsSD );
  673. PSECURITY_DESCRIPTOR pSD;
  674. pSD = ( PSECURITY_DESCRIPTOR )LocalAlloc(LPTR,dwSDLen);
  675. if(pSD)
  676. {
  677. if(MakeSelfRelativeSD( &NewAbsSD , pSD , &dwSDLen ))
  678. {
  679. err = SetWinStationSecurity(hKeyParent, pNameSD->m_pName, pSD );
  680. if(err == ERROR_SUCCESS)
  681. {
  682. pNameSD->SetSD(pSD);
  683. }
  684. }
  685. else
  686. {
  687. err=GetLastError();
  688. }
  689. }
  690. else
  691. {
  692. err=GetLastError();
  693. }
  694. }
  695. else
  696. {
  697. err=GetLastError();
  698. }
  699. }
  700. LocalFree(pNewACE);
  701. LocalFree(pNewACL);
  702. return err;
  703. }
  704. /*****************************************************************************
  705. *
  706. * GetDacl
  707. *
  708. * Gets security descriptor DACL.
  709. *
  710. * ENTRY:
  711. *
  712. * IN PSECURITY_DESCRIPTOR *pSD: pointer to SD
  713. * OUT PACL *ppDacl: pointer to pointer to DACL inside SD
  714. *
  715. * NOTES:
  716. * Do not try to free DACL!
  717. *
  718. * EXIT:
  719. * Returns: error code if cannot get DACL; ERROR_SUCCESS otherwise.
  720. *
  721. ****************************************************************************/
  722. DWORD
  723. GetDacl(
  724. IN PSECURITY_DESCRIPTOR pSD,
  725. OUT PACL *ppDacl)
  726. {
  727. BOOL bDaclPresent;
  728. BOOL bDaclDefaulted;
  729. *ppDacl=NULL;
  730. if(GetSecurityDescriptorDacl(pSD,&bDaclPresent,ppDacl,&bDaclDefaulted)) {
  731. if(!bDaclPresent){
  732. *ppDacl=NULL;
  733. }
  734. } else {
  735. return GetLastError();
  736. }
  737. return ERROR_SUCCESS;
  738. }
  739. /*****************************************************************************
  740. *
  741. * GetSacl
  742. *
  743. * Gets security descriptor SACL.
  744. *
  745. * ENTRY:
  746. *
  747. * IN PSECURITY_DESCRIPTOR *pSD: pointer to SD
  748. * OUT PACL *ppSacl: pointer to pointer to SACL inside SD
  749. *
  750. * NOTES:
  751. * Do not try to free SACL!
  752. *
  753. * EXIT:
  754. * Returns: error code if cannot get SACL; ERROR_SUCCESS otherwise.
  755. *
  756. ****************************************************************************/
  757. DWORD
  758. GetSacl(
  759. IN PSECURITY_DESCRIPTOR pSD,
  760. OUT PACL *ppSacl)
  761. {
  762. BOOL bSaclPresent;
  763. BOOL bSaclDefaulted;
  764. *ppSacl=NULL;
  765. if(GetSecurityDescriptorSacl(pSD,&bSaclPresent,ppSacl,&bSaclDefaulted)) {
  766. if(!bSaclPresent){
  767. *ppSacl=NULL;
  768. }
  769. } else {
  770. return GetLastError();
  771. }
  772. return ERROR_SUCCESS;
  773. }
  774. /*****************************************************************************
  775. *
  776. * EnumWinStationSecurityDescriptors
  777. *
  778. * Enumerates winstations and gets their security descriptors
  779. *
  780. * ENTRY:
  781. *
  782. * IN HKEY hKeyParent - handle to HKLM\SYSTEM\CurrentControlSet\
  783. * Control\Terminal Server\WinStations
  784. * OUT CNameAndSDList - name and security descriptor of a winstation
  785. * NOTES:
  786. * Call LocalFree function to free SD, do not try to free DACL!
  787. *
  788. * EXIT:
  789. * Returns: error code or ERROR_SUCCESS
  790. *
  791. ****************************************************************************/
  792. DWORD
  793. EnumWinStationSecurityDescriptors(
  794. IN HKEY hKeyParent,
  795. OUT CNameAndSDList *pNameSDList)
  796. {
  797. DWORD err;
  798. DWORD dwIndex;
  799. TCHAR wszTmpName[MAX_PATH+1];
  800. DWORD cbTmpName=MAX_PATH;
  801. FILETIME ftLastWriteTime;
  802. for(dwIndex=0;;dwIndex++)
  803. {
  804. cbTmpName=MAX_PATH;
  805. err=RegEnumKeyEx(
  806. hKeyParent, // handle of key to enumerate
  807. dwIndex, // index of subkey to enumerate
  808. wszTmpName, // address of buffer for subkey name
  809. &cbTmpName, // address for size of subkey buffer
  810. NULL, // reserved
  811. NULL, // address of buffer for class string
  812. NULL, // address for size of class buffer
  813. &ftLastWriteTime // address for time key last written to
  814. );
  815. if((err!=ERROR_SUCCESS)&&
  816. (err!=ERROR_MORE_DATA)&&
  817. (err!=ERROR_NO_MORE_ITEMS))
  818. {
  819. return err;
  820. }
  821. if(err==ERROR_NO_MORE_ITEMS)
  822. break;
  823. else
  824. {
  825. CNameAndSD Entry(wszTmpName);
  826. err = GetWinStationSecurity(hKeyParent, Entry.m_pName,
  827. _T("Security"), &(Entry.m_pSD));
  828. if( err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND )
  829. {
  830. pNameSDList->push_back(Entry);
  831. }
  832. }
  833. }
  834. return ERROR_SUCCESS;
  835. }
  836. /*****************************************************************************
  837. *
  838. * GetWinStationSecurity
  839. *
  840. * Returns WinStation's security descriptor.
  841. *
  842. * ENTRY:
  843. *
  844. * IN HKEY hKeyParent - handle to HKLM\SYSTEM\CurrentControlSet\
  845. * Control\Terminal Server\WinStations
  846. * IN PWINSTATIONNAMEW pWSName - name of a winstation
  847. * if pWSName is NULL - function returns default SD
  848. * OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor - pointer to pointer to SD
  849. *
  850. * NOTES:
  851. * Call LocalFree function to free SD!
  852. *
  853. * EXIT:
  854. * Returns: error code or ERROR_SUCCESS
  855. *
  856. ****************************************************************************/
  857. DWORD
  858. GetWinStationSecurity(
  859. IN HKEY hKeyParent,
  860. IN PWINSTATIONNAME pWSName,
  861. IN LPCTSTR szValueName,
  862. OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
  863. {
  864. DWORD SDLength = 0;
  865. DWORD ValueType =0;
  866. HKEY hKey = NULL;
  867. DWORD err;
  868. *ppSecurityDescriptor = NULL;
  869. if(pWSName)
  870. {
  871. err = RegOpenKeyEx(hKeyParent, pWSName, 0,KEY_READ, &hKey );
  872. }
  873. else
  874. {
  875. //If pWSName - get defauilt SD
  876. hKey = hKeyParent;
  877. err = ERROR_SUCCESS;
  878. }
  879. if(err == ERROR_SUCCESS)
  880. {
  881. err = RegQueryValueEx( hKey, szValueName, NULL, &ValueType,NULL, &SDLength );
  882. if(err == ERROR_SUCCESS )
  883. {
  884. //Return error if not correct data type
  885. if (ValueType == REG_BINARY)
  886. {
  887. //Allocate a buffer to read the Security info and read it
  888. // ACLUI uses LocalFree
  889. *ppSecurityDescriptor = ( PSECURITY_DESCRIPTOR )LocalAlloc( LMEM_FIXED , SDLength );
  890. if ( *ppSecurityDescriptor )
  891. {
  892. err = RegQueryValueEx( hKey, szValueName, NULL, &ValueType,
  893. (BYTE *) *ppSecurityDescriptor, &SDLength );
  894. if(err == ERROR_SUCCESS )
  895. {
  896. //Check for a valid SD before returning.
  897. if(! IsValidSecurityDescriptor( *ppSecurityDescriptor ) )
  898. {
  899. LocalFree(*ppSecurityDescriptor);
  900. *ppSecurityDescriptor = NULL;
  901. err = ERROR_INVALID_DATA;
  902. }
  903. }
  904. else
  905. {
  906. LocalFree(*ppSecurityDescriptor);
  907. *ppSecurityDescriptor = NULL;
  908. }
  909. }
  910. else
  911. {
  912. err = ERROR_NOT_ENOUGH_MEMORY;
  913. }
  914. }
  915. else
  916. {
  917. err = ERROR_INVALID_DATA;
  918. }
  919. }
  920. if(hKey != hKeyParent)
  921. {
  922. RegCloseKey(hKey);
  923. }
  924. }
  925. return err;
  926. } // GetWinStationSecurity
  927. /*****************************************************************************
  928. *
  929. * SetWinStationSecurity
  930. *
  931. * Writes winstation security descriptor to the registry
  932. *
  933. * ENTRY:
  934. *
  935. * IN HKEY hKeyParent - handle to HKLM\SYSTEM\CurrentControlSet\
  936. * Control\Terminal Server\WinStations
  937. * IN PWINSTATIONNAMEW pWSName - name of a winstation
  938. * IN PSECURITY_DESCRIPTOR pSecurityDescriptor - pointer to SD
  939. *
  940. * NOTES:
  941. * Call LocalFree function to free SD, do not try to free DACL!
  942. *
  943. * EXIT:
  944. * Returns: 0: if success
  945. * Error code: otherwise
  946. *
  947. ****************************************************************************/
  948. DWORD
  949. SetWinStationSecurity(
  950. IN HKEY hKeyParent,
  951. IN PWINSTATIONNAME pWSName,
  952. IN PSECURITY_DESCRIPTOR pSecurityDescriptor )
  953. {
  954. HKEY hKey = NULL;
  955. DWORD err;
  956. err = RegOpenKeyEx(hKeyParent, pWSName, 0,KEY_WRITE, &hKey );
  957. if(err == ERROR_SUCCESS)
  958. {
  959. err = RegSetValueEx(hKey, _T("Security"),0,REG_BINARY,(LPBYTE)pSecurityDescriptor,
  960. GetSecurityDescriptorLength(pSecurityDescriptor));
  961. RegCloseKey(hKey);
  962. }
  963. return err;
  964. } // SetWinStationSecurity
  965. /*****************************************************************************
  966. *
  967. * RemoveWinStationSecurity
  968. *
  969. * Removes winstation's security descriptor from the registry
  970. *
  971. * ENTRY:
  972. *
  973. * IN HKEY hKeyParent - handle to HKLM\SYSTEM\CurrentControlSet\
  974. * Control\Terminal Server\WinStations
  975. * IN PWINSTATIONNAMEW pWSName - name of a winstation
  976. *
  977. * NOTES:
  978. *
  979. *
  980. * EXIT:
  981. * Returns: 0: if success
  982. * Error code: otherwise
  983. *
  984. ****************************************************************************/
  985. DWORD
  986. RemoveWinstationSecurity(
  987. IN HKEY hKeyParent,
  988. IN PWINSTATIONNAME pWSName)
  989. {
  990. HKEY hKey = NULL;
  991. DWORD err;
  992. err = RegOpenKeyEx(hKeyParent, pWSName, 0,KEY_WRITE, &hKey );
  993. if(err == ERROR_SUCCESS)
  994. {
  995. err = RegDeleteValue(hKey, _T("Security"));
  996. RegCloseKey(hKey);
  997. }
  998. return err;
  999. }
  1000. /*****************************************************************************
  1001. *
  1002. * SetNewDefaultSecurity
  1003. *
  1004. * Sets new default security descriptor
  1005. *
  1006. * ENTRY:
  1007. *
  1008. * IN HKEY hKeyParent - handle to HKLM\SYSTEM\CurrentControlSet\
  1009. * Control\Terminal Server\WinStations
  1010. *
  1011. * NOTES:
  1012. *
  1013. *
  1014. * EXIT:
  1015. * Returns: 0: if success
  1016. * Error code: otherwise
  1017. *
  1018. ****************************************************************************/
  1019. DWORD
  1020. SetNewDefaultSecurity(
  1021. IN HKEY hKey)
  1022. {
  1023. //
  1024. DWORD err;
  1025. err = RegSetValueEx(hKey, _T("DefaultSecurity"), 0, REG_BINARY,
  1026. (LPBYTE)g_DefaultSD, sizeof(g_DefaultSD));
  1027. return err;
  1028. }
  1029. /*****************************************************************************
  1030. *
  1031. * SetNewConsoleSecurity
  1032. *
  1033. * Sets new console security descriptor
  1034. *
  1035. * ENTRY:
  1036. *
  1037. * IN HKEY hKeyParent - handle to HKLM\SYSTEM\CurrentControlSet\
  1038. * Control\Terminal Server\WinStations
  1039. * IN BOOL bServer
  1040. * NOTES:
  1041. *
  1042. *
  1043. * EXIT:
  1044. * Returns: 0: if success
  1045. * Error code: otherwise
  1046. *
  1047. ****************************************************************************/
  1048. DWORD
  1049. SetNewConsoleSecurity(
  1050. IN HKEY hKeyParent,
  1051. IN BOOL bServer)
  1052. {
  1053. //
  1054. DWORD err;
  1055. //Set default console security
  1056. if(bServer)
  1057. {
  1058. err = RegSetValueEx(hKeyParent, _T("ConsoleSecurity"), 0, REG_BINARY,
  1059. (LPBYTE)g_ConsoleSD, sizeof(g_ConsoleSD));
  1060. }
  1061. else
  1062. {
  1063. // on Professional it's the same as "DefaultSecurity"
  1064. err = RegSetValueEx(hKeyParent, _T("ConsoleSecurity"), 0, REG_BINARY,
  1065. (LPBYTE)g_DefaultSD, sizeof(g_DefaultSD));
  1066. }
  1067. return err;
  1068. }
  1069. /*****************************************************************************
  1070. *
  1071. * CDefaultSD::DoesDefaultSDHaveRemoteUsers
  1072. *
  1073. * Checks if defauilt SD has "Remote Desktop Users" SID.
  1074. *
  1075. * ENTRY:
  1076. * OUT LPBOOL pbHas - TRUE if defauilt SD has "Remote Desktop Users" SID.
  1077. *
  1078. * NOTES:
  1079. *
  1080. * EXIT:
  1081. * Returns: 0: if success
  1082. * Error code: otherwise
  1083. *
  1084. ****************************************************************************/
  1085. DWORD
  1086. CDefaultSD::DoesDefaultSDHaveRemoteUsers(
  1087. OUT LPBOOL pbHas)
  1088. {
  1089. *pbHas = FALSE;
  1090. //
  1091. DWORD err = ERROR_SUCCESS;
  1092. PACL pDacl = NULL;
  1093. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  1094. PSID pRUSid=NULL;
  1095. if( !AllocateAndInitializeSid( &sia, 2,
  1096. SECURITY_BUILTIN_DOMAIN_RID,
  1097. DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS,
  1098. 0, 0, 0, 0, 0, 0,&pRUSid ) )
  1099. {
  1100. return GetLastError();
  1101. }
  1102. //get dacl
  1103. err = GetDacl(m_pSD, &pDacl );
  1104. if( err == ERROR_SUCCESS ) {
  1105. //search ACL for "REMOTE USERS" SID
  1106. ACL_SIZE_INFORMATION asiAclSize;
  1107. DWORD dwBufLength=sizeof(asiAclSize);
  1108. ACCESS_ALLOWED_ACE *paaAllowedAce;
  1109. DWORD dwAcl_i;
  1110. if(!pDacl)
  1111. {
  1112. //It shuold never be in our case
  1113. //so we return error here
  1114. FreeSid(pRUSid);
  1115. return ERROR_INVALID_PARAMETER;
  1116. }
  1117. else
  1118. //DACL present
  1119. {
  1120. if (GetAclInformation(pDacl,
  1121. (LPVOID)&asiAclSize,
  1122. (DWORD)dwBufLength,
  1123. (ACL_INFORMATION_CLASS)AclSizeInformation))
  1124. {
  1125. for (dwAcl_i = 0; dwAcl_i < asiAclSize.AceCount; dwAcl_i++)
  1126. {
  1127. if(GetAce( pDacl, dwAcl_i, (LPVOID *)&paaAllowedAce))
  1128. {
  1129. if(EqualSid((PSID)&(paaAllowedAce->SidStart),pRUSid))
  1130. {
  1131. //permission already exist, we don't need to
  1132. //do anything
  1133. *pbHas = TRUE;
  1134. }
  1135. }
  1136. }
  1137. }
  1138. }
  1139. }
  1140. FreeSid(pRUSid);
  1141. return err;
  1142. }
  1143. //*************************************************************
  1144. //
  1145. // LookupSid()
  1146. //
  1147. // Purpose: Given SID allocates and returns string containing
  1148. // name of the user in format DOMAINNAME\USERNAME
  1149. //
  1150. // Parameters: IN PSID pSid
  1151. // OUT LPWSTR ppName
  1152. // OUT SID_NAME_USE *peUse
  1153. //
  1154. // Return: TRUE if success, FALSE otherwise
  1155. //
  1156. // Comments:
  1157. //
  1158. // History: Date Author Comment
  1159. // 10/23/00 skuzin Created
  1160. //
  1161. //*************************************************************
  1162. BOOL
  1163. LookupSid(
  1164. IN PSID pSid,
  1165. OUT LPWSTR *ppName,
  1166. OUT SID_NAME_USE *peUse)
  1167. {
  1168. LPWSTR szName = NULL;
  1169. DWORD cName = 0;
  1170. LPWSTR szDomainName = NULL;
  1171. DWORD cDomainName = 0;
  1172. *ppName = NULL;
  1173. if(!LookupAccountSidW(NULL,pSid,
  1174. szName,&cName,
  1175. szDomainName,&cDomainName,
  1176. peUse) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  1177. {
  1178. //cName and cDomainName include terminating 0
  1179. *ppName = (LPWSTR)LocalAlloc(LPTR,(cName+cDomainName)*sizeof(WCHAR));
  1180. if(*ppName)
  1181. {
  1182. szDomainName = *ppName;
  1183. szName = &(*ppName)[cDomainName];
  1184. if(LookupAccountSidW(NULL,pSid,
  1185. szName,&cName,
  1186. szDomainName,&cDomainName,
  1187. peUse))
  1188. {
  1189. //user name now in format DOMAINNAME\0USERNAME
  1190. //let's replace '\0' with '\\'
  1191. //now cName and cDomainName do not include terminating 0
  1192. //very confusing
  1193. if(cDomainName)
  1194. {
  1195. (*ppName)[cDomainName] = L'\\';
  1196. }
  1197. return TRUE;
  1198. }
  1199. else
  1200. {
  1201. LocalFree(*ppName);
  1202. *ppName = NULL;
  1203. }
  1204. }
  1205. }
  1206. return FALSE;
  1207. }
  1208. //*************************************************************
  1209. //
  1210. // IsLocal()
  1211. //
  1212. // Purpose:
  1213. //
  1214. // Parameters: wszDomainandname - domain\user
  1215. // determines whether the user is local or not
  1216. // if local - cuts out domain name
  1217. //
  1218. // Return: NONE
  1219. //
  1220. // Comments:
  1221. //
  1222. // History: Date Author Comment
  1223. // 03/13/01 skuzin Created
  1224. //
  1225. //*************************************************************
  1226. BOOL
  1227. IsLocal(
  1228. IN LPWSTR wszLocalCompName,
  1229. IN OUT LPWSTR wszDomainandname)
  1230. {
  1231. LPWSTR wszTmp = wcschr(wszDomainandname,L'\\');
  1232. if(!wszTmp)
  1233. {
  1234. return TRUE;
  1235. }
  1236. if(!_wcsnicmp(wszDomainandname, wszLocalCompName,wcslen(wszLocalCompName) ))
  1237. {
  1238. //get rid of useless domain name
  1239. wcscpy(wszDomainandname,wszTmp+1);
  1240. return TRUE;
  1241. }
  1242. return FALSE;
  1243. }
  1244. //*************************************************************
  1245. //
  1246. // GetAbsoluteSD()
  1247. //
  1248. // Purpose: Converts self-relative SD to absolute SD
  1249. // returns pointers to SACL DACL Owner and Group
  1250. // of the absolute SD.
  1251. //
  1252. // Parameters:
  1253. // IN PSECURITY_DESCRIPTOR pSelfRelativeSD
  1254. // OUT PSECURITY_DESCRIPTOR *ppAbsoluteSD
  1255. // OUT PACL *ppDacl
  1256. // OUT PACL *ppSacl
  1257. // OUT PSID *ppOwner
  1258. // OUT PSID *ppPrimaryGroup
  1259. //
  1260. // Return: error code if fails, ERROR_SUCCESS otherwise
  1261. //
  1262. // Comments: caller needs to free
  1263. // every returned pointer using LocalFree function.
  1264. //
  1265. // History: Date Author Comment
  1266. // 03/13/01 skuzin Created
  1267. //
  1268. //*************************************************************
  1269. DWORD
  1270. GetAbsoluteSD(
  1271. IN PSECURITY_DESCRIPTOR pSelfRelativeSD,
  1272. OUT PSECURITY_DESCRIPTOR *ppAbsoluteSD,
  1273. OUT PACL *ppDacl,
  1274. OUT PACL *ppSacl,
  1275. OUT PSID *ppOwner,
  1276. OUT PSID *ppPrimaryGroup)
  1277. {
  1278. DWORD dwAbsoluteSDSize = 0; // absolute SD size
  1279. DWORD dwDaclSize = 0; // size of DACL
  1280. DWORD dwSaclSize = 0; // size of SACL
  1281. DWORD dwOwnerSize = 0; // size of owner SID
  1282. DWORD dwPrimaryGroupSize = 0; // size of group SID
  1283. *ppAbsoluteSD = NULL;
  1284. *ppDacl = NULL;
  1285. *ppSacl = NULL;
  1286. *ppOwner = NULL;
  1287. *ppPrimaryGroup = NULL;
  1288. MakeAbsoluteSD(
  1289. pSelfRelativeSD, // self-relative SD
  1290. NULL, // absolute SD
  1291. &dwAbsoluteSDSize, // absolute SD size
  1292. NULL, // DACL
  1293. &dwDaclSize, // size of DACL
  1294. NULL, // SACL
  1295. &dwSaclSize, // size of SACL
  1296. NULL, // owner SID
  1297. &dwOwnerSize, // size of owner SID
  1298. NULL, // primary-group SID
  1299. &dwPrimaryGroupSize // size of group SID
  1300. );
  1301. try
  1302. {
  1303. if(dwAbsoluteSDSize)
  1304. {
  1305. *ppAbsoluteSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,dwAbsoluteSDSize);
  1306. if(!(*ppAbsoluteSD))
  1307. {
  1308. throw GetLastError();
  1309. }
  1310. }
  1311. if(dwDaclSize)
  1312. {
  1313. *ppDacl = (PACL)LocalAlloc(LPTR,dwDaclSize);
  1314. if(!(*ppDacl))
  1315. {
  1316. throw GetLastError();
  1317. }
  1318. }
  1319. if(dwSaclSize)
  1320. {
  1321. *ppSacl = (PACL)LocalAlloc(LPTR,dwSaclSize);
  1322. if(!(*ppSacl))
  1323. {
  1324. throw GetLastError();
  1325. }
  1326. }
  1327. if(dwOwnerSize)
  1328. {
  1329. *ppOwner = (PSID)LocalAlloc(LPTR,dwOwnerSize);
  1330. if(!(*ppOwner))
  1331. {
  1332. throw GetLastError();
  1333. }
  1334. }
  1335. if(dwPrimaryGroupSize)
  1336. {
  1337. *ppPrimaryGroup = (PSID)LocalAlloc(LPTR,dwPrimaryGroupSize);
  1338. if(!(*ppPrimaryGroup))
  1339. {
  1340. throw GetLastError();
  1341. }
  1342. }
  1343. if(!MakeAbsoluteSD(
  1344. pSelfRelativeSD, // self-relative SD
  1345. *ppAbsoluteSD, // absolute SD
  1346. &dwAbsoluteSDSize, // absolute SD size
  1347. *ppDacl, // DACL
  1348. &dwDaclSize, // size of DACL
  1349. *ppSacl, // SACL
  1350. &dwSaclSize, // size of SACL
  1351. *ppOwner, // owner SID
  1352. &dwOwnerSize, // size of owner SID
  1353. *ppPrimaryGroup, // primary-group SID
  1354. &dwPrimaryGroupSize // size of group SID
  1355. ))
  1356. {
  1357. throw GetLastError();
  1358. }
  1359. }
  1360. catch(DWORD ret)
  1361. {
  1362. if(*ppAbsoluteSD)
  1363. {
  1364. LocalFree(*ppAbsoluteSD);
  1365. *ppAbsoluteSD = NULL;
  1366. }
  1367. if(*ppDacl)
  1368. {
  1369. LocalFree(*ppDacl);
  1370. *ppDacl = NULL;
  1371. }
  1372. if(*ppSacl)
  1373. {
  1374. LocalFree(*ppSacl);
  1375. *ppSacl = NULL;
  1376. }
  1377. if(*ppOwner)
  1378. {
  1379. LocalFree(*ppOwner);
  1380. *ppOwner = NULL;
  1381. }
  1382. if(*ppPrimaryGroup)
  1383. {
  1384. LocalFree(*ppPrimaryGroup);
  1385. *ppPrimaryGroup = NULL;
  1386. }
  1387. return ret;
  1388. }
  1389. return ERROR_SUCCESS;
  1390. }
  1391. //*************************************************************
  1392. //
  1393. // GetAbsoluteSD()
  1394. //
  1395. // Purpose: Converts absolute SD to self-relative SD
  1396. // returns pointer to self-relative SD.
  1397. //
  1398. // Parameters:
  1399. // IN PSECURITY_DESCRIPTOR pAbsoluteSD,
  1400. // OUT PSECURITY_DESCRIPTOR *ppSelfRelativeSD
  1401. //
  1402. // Return: error code if fails, ERROR_SUCCESS otherwise
  1403. //
  1404. // Comments: caller needs to free
  1405. // returned pointer using LocalFree function.
  1406. //
  1407. // History: Date Author Comment
  1408. // 03/13/01 skuzin Created
  1409. //
  1410. //*************************************************************
  1411. DWORD
  1412. GetSelfRelativeSD(
  1413. IN PSECURITY_DESCRIPTOR pAbsoluteSD,
  1414. OUT PSECURITY_DESCRIPTOR *ppSelfRelativeSD)
  1415. {
  1416. DWORD dwBufferLength = 0;
  1417. *ppSelfRelativeSD = NULL;
  1418. MakeSelfRelativeSD(pAbsoluteSD, NULL, &dwBufferLength);
  1419. if(dwBufferLength)
  1420. {
  1421. *ppSelfRelativeSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,dwBufferLength);
  1422. if(*ppSelfRelativeSD)
  1423. {
  1424. if(!MakeSelfRelativeSD(pAbsoluteSD, *ppSelfRelativeSD, &dwBufferLength))
  1425. {
  1426. DWORD dwResult = GetLastError();
  1427. LocalFree(*ppSelfRelativeSD);
  1428. return dwResult;
  1429. }
  1430. }
  1431. }
  1432. else
  1433. {
  1434. return GetLastError();
  1435. }
  1436. return ERROR_SUCCESS;
  1437. }