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.

712 lines
20 KiB

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