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.

677 lines
25 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // AclBase.cpp
  7. //
  8. // Description:
  9. // Implementation of the ISecurityInformation interface. This interface
  10. // is the new common security UI in NT 5.0.
  11. //
  12. // Author:
  13. // Galen Barbee (galenb) February 6, 1998
  14. // From \nt\private\admin\snapin\filemgmt\permpage.cpp
  15. // by JonN
  16. //
  17. // Revision History:
  18. //
  19. // Notes:
  20. //
  21. /////////////////////////////////////////////////////////////////////////////
  22. #include "stdafx.h"
  23. #include "AclBase.h"
  24. #include "AclUtils.h"
  25. #include "resource.h"
  26. #include <DsGetDC.h>
  27. #include <lmcons.h>
  28. #include <lmapibuf.h>
  29. #include "CluAdmx.h"
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CSecurityInformation
  32. /////////////////////////////////////////////////////////////////////////////
  33. /////////////////////////////////////////////////////////////////////////////
  34. //++
  35. //
  36. // CSecurityInformation::CSecurityInformation
  37. //
  38. // Routine Description:
  39. // ctor
  40. //
  41. // Arguments:
  42. // none.
  43. //
  44. // Return Value:
  45. // none.
  46. //
  47. //--
  48. /////////////////////////////////////////////////////////////////////////////
  49. CSecurityInformation::CSecurityInformation(
  50. void
  51. ) : m_pShareMap( NULL ), m_dwFlags( 0 ), m_nDefAccess( 0 ), m_psiAccess( NULL ), m_pObjectPicker( NULL ), m_cRef( 1 )
  52. {
  53. m_nLocalSIDErrorMessageID = 0;
  54. } //*** CSecurityInformation::CSecurityInformation()
  55. /////////////////////////////////////////////////////////////////////////////
  56. //++
  57. //
  58. // CSecurityInformation::~CSecurityInformation
  59. //
  60. // Routine Description:
  61. // dtor
  62. //
  63. // Arguments:
  64. // none.
  65. //
  66. // Return Value:
  67. // none.
  68. //
  69. //--
  70. /////////////////////////////////////////////////////////////////////////////
  71. CSecurityInformation::~CSecurityInformation(
  72. void
  73. )
  74. {
  75. if ( m_pObjectPicker != NULL )
  76. {
  77. m_pObjectPicker->Release();
  78. m_pObjectPicker = NULL;
  79. } // if:
  80. } //*** CSecurityInformation::CSecurityInformation()
  81. /////////////////////////////////////////////////////////////////////////////
  82. //++
  83. //
  84. // CSecurityInformation::MapGeneric
  85. //
  86. // Routine Description:
  87. // Maps specific rights to generic rights
  88. //
  89. // Arguments:
  90. // pguidObjectType [IN]
  91. // pAceFlags [IN]
  92. // pMask [OUT]
  93. //
  94. // Return Value:
  95. // S_OK
  96. //
  97. //--
  98. /////////////////////////////////////////////////////////////////////////////
  99. STDMETHODIMP
  100. CSecurityInformation::MapGeneric(
  101. IN const GUID *, //pguidObjectType,
  102. IN UCHAR *, //pAceFlags,
  103. OUT ACCESS_MASK *pMask
  104. )
  105. {
  106. ASSERT( pMask != NULL );
  107. ASSERT( m_pShareMap != NULL );
  108. AFX_MANAGE_STATE( AfxGetStaticModuleState() );
  109. ::MapGenericMask( pMask, m_pShareMap );
  110. return S_OK;
  111. } //*** CSecurityInformation::MapGeneric()
  112. /////////////////////////////////////////////////////////////////////////////
  113. //++
  114. //
  115. // CSecurityInformation::GetInheritTypes
  116. //
  117. // Routine Description:
  118. //
  119. //
  120. // Arguments:
  121. // None.
  122. //
  123. // Return Value:
  124. // E_NOTIMPL
  125. //
  126. //--
  127. /////////////////////////////////////////////////////////////////////////////
  128. STDMETHODIMP
  129. CSecurityInformation::GetInheritTypes(
  130. PSI_INHERIT_TYPE *, //ppInheritTypes,
  131. ULONG * //pcInheritTypes
  132. )
  133. {
  134. ASSERT( FALSE );
  135. AFX_MANAGE_STATE( AfxGetStaticModuleState() );
  136. return E_NOTIMPL;
  137. } //*** CSecurityInformation::GetInheritTypes()
  138. /////////////////////////////////////////////////////////////////////////////
  139. //++
  140. //
  141. // CSecurityInformation::PropertySheetPageCallback
  142. //
  143. // Routine Description:
  144. // This method is called by the ACL editor when something interesting
  145. // happens.
  146. //
  147. // Arguments:
  148. // hwnd [IN] ACL editor window (currently NULL)
  149. // uMsg [IN] reason for call back
  150. // uPage [IN] kind of page we are dealing with
  151. //
  152. // Return Value:
  153. // S_OK. Want to keep everything movin' along
  154. //
  155. //--
  156. /////////////////////////////////////////////////////////////////////////////
  157. STDMETHODIMP
  158. CSecurityInformation::PropertySheetPageCallback(
  159. IN HWND hwnd,
  160. IN UINT uMsg,
  161. IN SI_PAGE_TYPE uPage
  162. )
  163. {
  164. AFX_MANAGE_STATE( AfxGetStaticModuleState() );
  165. return S_OK;
  166. } //*** CSecurityInformation::PropertySheetPageCallback()
  167. /////////////////////////////////////////////////////////////////////////////
  168. //++
  169. //
  170. // CSecurityInformation::GetObjectInformation
  171. //
  172. // Routine Description:
  173. //
  174. //
  175. // Arguments:
  176. // pObjectInfo [IN OUT]
  177. //
  178. // Return Value:
  179. // S_OK. Want to keep everything movin' along
  180. //
  181. //--
  182. /////////////////////////////////////////////////////////////////////////////
  183. STDMETHODIMP
  184. CSecurityInformation::GetObjectInformation(
  185. IN OUT PSI_OBJECT_INFO pObjectInfo
  186. )
  187. {
  188. ASSERT( pObjectInfo != NULL && !IsBadWritePtr( pObjectInfo, sizeof( *pObjectInfo ) ) );
  189. ASSERT( !m_strServer.IsEmpty() );
  190. ASSERT( m_dwFlags != 0 );
  191. AFX_MANAGE_STATE( AfxGetStaticModuleState() );
  192. pObjectInfo->dwFlags = m_dwFlags; // SI_EDIT_PERMS | SI_NO_ACL_PROTECT;
  193. pObjectInfo->hInstance = AfxGetInstanceHandle();
  194. pObjectInfo->pszServerName = (LPTSTR)(LPCTSTR) m_strServer;
  195. // pObjectInfo->pszObjectName =
  196. /*
  197. pObjectInfo->dwUgopServer = UGOP_BUILTIN_GROUPS
  198. //| UGOP_USERS
  199. //| UGOP_COMPUTERS
  200. //| UGOP_WELL_KNOWN_PRINCIPALS_USERS
  201. //| UGOP_GLOBAL_GROUPS
  202. //| UGOP_USER_WORLD
  203. //| UGOP_USER_AUTHENTICATED_USER
  204. //| UGOP_USER_ANONYMOUS
  205. //| UGOP_USER_DIALUP
  206. //| UGOP_USER_NETWORK
  207. //| UGOP_USER_BATCH
  208. //| UGOP_USER_INTERACTIVE
  209. | UGOP_USER_SERVICE
  210. | UGOP_USER_SYSTEM
  211. | UGOP_LOCAL_GROUPS
  212. //| UGOP_UNIVERSAL_GROUPS
  213. //| UGOP_UNIVERSAL_GROUPS_SE
  214. //| UGOP_ACCOUNT_GROUPS
  215. //| UGOP_ACCOUNT_GROUPS_SE
  216. //| UGOP_RESOURCE_GROUPS
  217. //| UGOP_RESOURCE_GROUPS_SE
  218. ;
  219. pObjectInfo->dwUgopOther = ( NT5_UGOP_FLAGS | NT4_UGOP_FLAGS ) &~ UGOP_COMPUTERS;
  220. */
  221. return S_OK;
  222. } //*** CSecurityInformation::GetObjectInformation()
  223. /////////////////////////////////////////////////////////////////////////////
  224. //++
  225. //
  226. // CSecurityInformation::SetSecurity
  227. //
  228. // Routine Description:
  229. // ISecurityInformation is giving back the edited security descriptor
  230. // and we need to validate it. A valid SD is one that doesn't contain
  231. // any local SIDs.
  232. //
  233. // Arguments:
  234. // SecurityInformation [IN]
  235. // pSecurityDescriptor [IN OUT]
  236. //
  237. // Return Value:
  238. // E_FAIL for error and S_OK for success and S_FALSE for SD no good.
  239. //
  240. //--
  241. /////////////////////////////////////////////////////////////////////////////
  242. STDMETHODIMP
  243. CSecurityInformation::SetSecurity(
  244. IN SECURITY_INFORMATION SecurityInformation,
  245. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  246. )
  247. {
  248. ASSERT( m_nLocalSIDErrorMessageID != 0 );
  249. AFX_MANAGE_STATE( ::AfxGetStaticModuleState() );
  250. HRESULT hr = S_OK;
  251. BOOL bFound = FALSE;
  252. hr = HrLocalAccountsInSD( pSecurityDescriptor, &bFound );
  253. if ( SUCCEEDED( hr ) )
  254. {
  255. if ( bFound )
  256. {
  257. CString strMsg;
  258. strMsg.LoadString( m_nLocalSIDErrorMessageID );
  259. AfxMessageBox( strMsg, MB_OK | MB_ICONSTOP );
  260. hr = S_FALSE; // if there are local accounts then return S_FALSE to keep AclUi alive.
  261. }
  262. }
  263. else
  264. {
  265. CString strMsg;
  266. CString strMsgIdFmt;
  267. CString strMsgId;
  268. CString strErrorMsg;
  269. strMsg.LoadString( IDS_ERROR_VALIDATING_CLUSTER_SECURITY_DESCRIPTOR );
  270. FormatError( strErrorMsg, hr );
  271. strMsgIdFmt.LoadString( IDS_ERROR_MSG_ID );
  272. strMsgId.Format( strMsgIdFmt, hr, hr);
  273. strMsg.Format( _T("%s\n\n%s%s"), strMsg, strErrorMsg, strMsgId );
  274. AfxMessageBox( strMsg );
  275. hr = S_FALSE; // return S_FALSE to keep AclUi alive.
  276. }
  277. return hr;
  278. } //*** CSecurityInformation::SetSecurity()
  279. /////////////////////////////////////////////////////////////////////////////
  280. //++
  281. //
  282. // CSecurityInformation::GetAccessRights
  283. //
  284. // Routine Description:
  285. // Return the access rights that you want the user to be able to set.
  286. //
  287. // Arguments:
  288. // pguidObjectType [IN]
  289. // dwFlags [IN]
  290. // ppAccess [OUT]
  291. // pcAccesses [OUT]
  292. // piDefaultAccess [OUT]
  293. //
  294. // Return Value:
  295. // S_OK. Want to keep everything movin' along
  296. //
  297. //--
  298. /////////////////////////////////////////////////////////////////////////////
  299. STDMETHODIMP
  300. CSecurityInformation::GetAccessRights(
  301. IN const GUID * pguidObjectType,
  302. IN DWORD dwFlags,
  303. OUT PSI_ACCESS * ppAccess,
  304. OUT ULONG * pcAccesses,
  305. OUT ULONG * piDefaultAccess
  306. )
  307. {
  308. ASSERT( ppAccess != NULL );
  309. ASSERT( pcAccesses != NULL );
  310. ASSERT( piDefaultAccess != NULL );
  311. ASSERT( m_psiAccess != NULL );
  312. ASSERT( m_nAccessElems > 0 );
  313. AFX_MANAGE_STATE( AfxGetStaticModuleState() );
  314. *ppAccess = m_psiAccess;
  315. *pcAccesses = m_nAccessElems;
  316. *piDefaultAccess = m_nDefAccess;
  317. return S_OK;
  318. } //*** CSecurityInformation::GetAccessRights()
  319. /////////////////////////////////////////////////////////////////////////////
  320. //++
  321. //
  322. // CSecurityInformation::Initialize
  323. //
  324. // Routine Description:
  325. // Initialize.
  326. //
  327. // Arguments:
  328. // pInitInfo [IN] - Info to use for initialization.
  329. //
  330. // Return Value:
  331. // S_OK if successful, or HRESULT error if not.
  332. //
  333. //--
  334. /////////////////////////////////////////////////////////////////////////////
  335. STDMETHODIMP CSecurityInformation::Initialize( IN PDSOP_INIT_INFO pInitInfo )
  336. {
  337. HRESULT hr = S_OK;
  338. DSOP_INIT_INFO InitInfo;
  339. PDSOP_SCOPE_INIT_INFO pDSOPScopes = NULL;
  340. if ( m_pObjectPicker == NULL )
  341. {
  342. hr = CoCreateInstance( CLSID_DsObjectPicker,
  343. NULL,
  344. CLSCTX_INPROC_SERVER,
  345. IID_IDsObjectPicker,
  346. (LPVOID *) &m_pObjectPicker
  347. );
  348. }
  349. if ( SUCCEEDED( hr ) )
  350. {
  351. //
  352. // Make a local copy of the InitInfo so we can modify it safely
  353. //
  354. CopyMemory( &InitInfo, pInitInfo, min( pInitInfo->cbSize, sizeof( InitInfo ) ) );
  355. //
  356. // Make a local copy of g_aDSOPScopes so we can modify it safely.
  357. // Note also that m_pObjectPicker->Initialize returns HRESULTs
  358. // in this buffer.
  359. //
  360. pDSOPScopes = (PDSOP_SCOPE_INIT_INFO) ::LocalAlloc( LPTR, sizeof( g_aDSOPScopes ) );
  361. if (pDSOPScopes != NULL )
  362. {
  363. CopyMemory( pDSOPScopes, g_aDSOPScopes, sizeof( g_aDSOPScopes ) );
  364. //
  365. // Override the ACLUI default scopes, but don't touch
  366. // the other stuff.
  367. //
  368. // pDSOPScopes->pwzDcName = m_strServer;
  369. InitInfo.cDsScopeInfos = ARRAYSIZE( g_aDSOPScopes );
  370. InitInfo.aDsScopeInfos = pDSOPScopes;
  371. InitInfo.pwzTargetComputer = m_strServer;
  372. hr = m_pObjectPicker->Initialize( &InitInfo );
  373. ::LocalFree( pDSOPScopes );
  374. }
  375. else
  376. {
  377. hr = HRESULT_FROM_WIN32( ::GetLastError() );
  378. } // else:
  379. }
  380. return hr;
  381. } //*** CSecurityInformation::Initialize()
  382. /////////////////////////////////////////////////////////////////////////////
  383. //++
  384. //
  385. // CSecurityInformation::InvokeDialog
  386. //
  387. // Routine Description:
  388. // Forward the InvokeDialog call into the contained object.
  389. //
  390. // Arguments:
  391. // hwndParent [IN]
  392. // ppdoSelection [IN]
  393. //
  394. // Return Value:
  395. // E_POINTER if m_pObjectPicker is NULL, or the return from
  396. // m_pObjectPicker->InvokeDialog().
  397. //
  398. //--
  399. /////////////////////////////////////////////////////////////////////////////
  400. STDMETHODIMP CSecurityInformation::InvokeDialog(
  401. IN HWND hwndParent,
  402. IN IDataObject ** ppdoSelection
  403. )
  404. {
  405. HRESULT hr = E_POINTER;
  406. if ( m_pObjectPicker != NULL )
  407. {
  408. hr = m_pObjectPicker->InvokeDialog( hwndParent, ppdoSelection );
  409. } // if:
  410. return hr;
  411. } //*** CSecurityInformation::InvokeDialog()
  412. /////////////////////////////////////////////////////////////////////////////
  413. //++
  414. //
  415. // CSecurityInformation::HrLocalAccountsInSD
  416. //
  417. // Routine Description:
  418. // Determines if any ACEs for local accounts are in DACL stored in
  419. // Security Descriptor (pSD) after the ACL editor has been called
  420. //
  421. // Arguments:
  422. // pSD [IN] - Security Descriptor to be checked.
  423. // pbFound [OUT] - catches the "local account" found flag.
  424. //
  425. // Return Value:
  426. // ERROR_SUCCESS or other Win32 error.
  427. //
  428. // NB:
  429. //
  430. // I took this code verbatim from EditAcl.cpp and it really needs some
  431. // clean up and style upgrades!
  432. //
  433. //--
  434. /////////////////////////////////////////////////////////////////////////////
  435. HRESULT
  436. CSecurityInformation::HrLocalAccountsInSD(
  437. PSECURITY_DESCRIPTOR pSD,
  438. PBOOL pbFound
  439. )
  440. {
  441. ASSERT( !m_strNode.IsEmpty() );
  442. HRESULT hr = E_POINTER;
  443. if ( pbFound != NULL )
  444. {
  445. BOOL bLocalAccountInAcl = FALSE;
  446. DWORD dwError = NO_ERROR;
  447. PSID pAdminSid = NULL;
  448. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  449. if ( ::AllocateAndInitializeSid( &siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSid ) )
  450. {
  451. PSID pSystemSid = NULL;
  452. if ( ::AllocateAndInitializeSid( &siaNtAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSystemSid ) )
  453. {
  454. PSID pServiceSid = NULL;
  455. if ( ::AllocateAndInitializeSid( &siaNtAuthority, 1, SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &pServiceSid ) )
  456. {
  457. if ( ::IsValidSecurityDescriptor( pSD ) )
  458. {
  459. PACL paclDACL = NULL;
  460. BOOL bHasDACL = FALSE;
  461. BOOL bDaclDefaulted = FALSE;
  462. if ( ::GetSecurityDescriptorDacl( pSD, (LPBOOL) &bHasDACL, (PACL *) &paclDACL, (LPBOOL) &bDaclDefaulted ) )
  463. {
  464. if ( ::IsValidAcl( paclDACL ) )
  465. {
  466. ACL_SIZE_INFORMATION asiAclSize;
  467. DWORD dwBufLength;
  468. dwBufLength = sizeof( asiAclSize );
  469. if ( ::GetAclInformation( paclDACL, (LPVOID) &asiAclSize, (DWORD) dwBufLength, (ACL_INFORMATION_CLASS) AclSizeInformation ) )
  470. {
  471. PDOMAIN_CONTROLLER_INFO pdci = NULL;
  472. GUID guid;
  473. dwError = ::DsGetDcName( NULL, NULL, &guid, NULL, 0, &pdci );
  474. if ( dwError == ERROR_SUCCESS )
  475. {
  476. ACCESS_ALLOWED_ACE * paaAllowedAce;
  477. DWORD dwACL_Index = 0L;
  478. WCHAR szUser [256];
  479. WCHAR szDomain [256];
  480. DWORD cchUser = sizeof( szUser ) / sizeof( szUser[0] );
  481. DWORD cchDomain = sizeof( szDomain ) / sizeof( szDomain [0] );
  482. SID_NAME_USE snu;
  483. PSID psid = NULL;
  484. //
  485. // Search the ACL for local account ACEs
  486. //
  487. for ( dwACL_Index = 0; dwACL_Index < asiAclSize.AceCount; dwACL_Index++ )
  488. {
  489. if ( ::GetAce( paclDACL, dwACL_Index, (LPVOID *) &paaAllowedAce ) )
  490. {
  491. //
  492. // Get SID from ACE
  493. //
  494. psid = &paaAllowedAce->SidStart;
  495. if ( ::EqualSid( psid, pAdminSid ) )
  496. {
  497. continue; // allowed
  498. } // if: is this the local admin SID?
  499. else if ( ::EqualSid( psid, pSystemSid ) )
  500. {
  501. continue; // allowed
  502. } // else if: is this the local system SID?
  503. else if ( ::EqualSid( psid, pServiceSid ) )
  504. {
  505. continue; // allowed
  506. } // else if: is this the service SID?
  507. else
  508. {
  509. if ( ::LookupAccountSidW( pdci->DomainControllerName, psid, szUser, &cchUser, szDomain, &cchDomain, &snu ) )
  510. {
  511. if ( ( ::lstrcmpiW( szDomain, m_strNode ) == 0 ) && ( snu != SidTypeDomain ) )
  512. {
  513. bLocalAccountInAcl = TRUE;
  514. break;
  515. } // if: the domain name and the node name are the same and the SID_NAME_USE is not SidTypeDomain then it's a local SID
  516. } // if: LookupAccountSid() succeeded
  517. else
  518. {
  519. //if ( ::LookupAccountSidW( m_strNode, psid, szUser, &cchUser, szDomain, &cchDomain, &snu ) )
  520. //{
  521. PUCHAR pnSubAuthorityCount = GetSidSubAuthorityCount( psid );
  522. if ( pnSubAuthorityCount != NULL )
  523. {
  524. PULONG pnSubAuthority0 = GetSidSubAuthority( psid, 0 );
  525. if ( pnSubAuthority0 != NULL )
  526. {
  527. if ( ( *pnSubAuthorityCount == 2 ) && ( *pnSubAuthority0 == SECURITY_BUILTIN_DOMAIN_RID ) )
  528. {
  529. bLocalAccountInAcl = TRUE;
  530. break;
  531. } // if: this SID has 2 sub authorites and is from the built in domain it must be local
  532. } // if: got the first sub authority
  533. else
  534. {
  535. dwError = ::GetLastError();
  536. break;
  537. } // else: could not get the first sub authority
  538. } // if: got the sub authority count
  539. else
  540. {
  541. dwError = ::GetLastError();
  542. break;
  543. } // else: could not get the sub authority count
  544. //} // if: LookupAccountSid on the cluster machine failed
  545. //else
  546. //{
  547. // dwError = ::GetLastError();
  548. // break;
  549. //} // else: failed
  550. } // else: LookupAccountSid() failed, could be a local SID
  551. } // else: not local admin and not local system
  552. } // if: GetAce() Succeeded
  553. else
  554. {
  555. dwError = ::GetLastError();
  556. break;
  557. } // else: failed
  558. } // for:
  559. ::NetApiBufferFree( (LPVOID) pdci );
  560. } // if: DsGetDcName succeeded
  561. } // if: GetAclInformation() succeeded
  562. else
  563. {
  564. dwError = ::GetLastError();
  565. } // else: failed
  566. } // if: IsValidAcl() succeeded
  567. else
  568. {
  569. dwError = ::GetLastError();
  570. } // else: failed
  571. } // if: GetSecurityDescriptorDacl() succeeded
  572. else
  573. {
  574. dwError = ::GetLastError();
  575. } // else: failed
  576. } // if: Is ValidSecurityDescriptor() succeeded
  577. else
  578. {
  579. dwError = ::GetLastError();
  580. } // else: failed
  581. ::FreeSid( pServiceSid );
  582. } // if: Create Service SID
  583. else
  584. {
  585. dwError = ::GetLastError();
  586. } // else: failed
  587. ::FreeSid( pSystemSid );
  588. } // if: Create local system SID
  589. else
  590. {
  591. dwError = ::GetLastError();
  592. } // else: failed
  593. ::FreeSid( pAdminSid );
  594. } // if: Create local admin SID
  595. else
  596. {
  597. dwError = ::GetLastError();
  598. } // else: failed
  599. *pbFound = bLocalAccountInAcl;
  600. hr = HRESULT_FROM_WIN32( dwError );
  601. } // if: pbFound != NULL
  602. return hr;
  603. } //*** CSecurityInformation::HrLocalAccountsInSD()