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.

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