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.

841 lines
26 KiB

  1. #include "stdafx.h"
  2. #include "macros.h"
  3. USE_HANDLE_MACROS("SCHMMGMT(aclpage.cpp)")
  4. #include "dataobj.h"
  5. #include "compdata.h"
  6. #include "cookie.h"
  7. #include "snapmgr.h"
  8. #include "schmutil.h"
  9. #include "cache.h"
  10. #include "relation.h"
  11. #include "attrpage.h"
  12. #include "advui.h"
  13. #include "aclpage.h"
  14. #include "ntsecapi.h"
  15. #include "sddlp.h"
  16. HRESULT
  17. GetDomainSid(LPCWSTR pszLdapPath, PSID *ppSid);
  18. //
  19. // CDynamicLibraryBase
  20. // This is the base class for CDSSecDll and CAclUiDll.
  21. // This was taken from the dnsmgr snap in.
  22. //
  23. class CDynamicLibraryBase {
  24. public:
  25. CDynamicLibraryBase() {
  26. m_lpszLibraryName = NULL;
  27. m_lpszFunctionName = NULL;
  28. m_hLibrary = NULL;
  29. m_pfFunction = NULL;
  30. }
  31. virtual ~CDynamicLibraryBase() {
  32. if ( m_hLibrary != NULL ) {
  33. ::FreeLibrary(m_hLibrary);
  34. m_hLibrary = NULL;
  35. }
  36. }
  37. //
  38. // Load a DLL and get a single entry point.
  39. //
  40. BOOL Load() {
  41. if (m_hLibrary != NULL)
  42. return TRUE; // already loaded
  43. ASSERT(m_lpszLibraryName != NULL);
  44. m_hLibrary = ::LoadLibrary(m_lpszLibraryName);
  45. if (NULL == m_hLibrary) {
  46. // The library is not present
  47. return FALSE;
  48. }
  49. ASSERT(m_lpszFunctionName != NULL);
  50. ASSERT(m_pfFunction == NULL);
  51. m_pfFunction = ::GetProcAddress(m_hLibrary, m_lpszFunctionName );
  52. if ( NULL == m_pfFunction ) {
  53. // The library is present but does not have the entry point
  54. ::FreeLibrary( m_hLibrary );
  55. m_hLibrary = NULL;
  56. return FALSE;
  57. }
  58. ASSERT(m_hLibrary != NULL);
  59. ASSERT(m_pfFunction != NULL);
  60. return TRUE;
  61. }
  62. protected:
  63. LPCSTR m_lpszFunctionName;
  64. LPCTSTR m_lpszLibraryName;
  65. FARPROC m_pfFunction;
  66. HMODULE m_hLibrary;
  67. };
  68. //
  69. // CDsSecDLL - Holds the wrapper for the ACL editor wrapper.
  70. //
  71. class CDsSecDLL : public CDynamicLibraryBase {
  72. public:
  73. CDsSecDLL() {
  74. m_lpszLibraryName = _T("dssec.dll");
  75. m_lpszFunctionName = "DSCreateISecurityInfoObject";
  76. }
  77. HRESULT DSCreateISecurityInfoObject( LPCWSTR pwszObjectPath, // in
  78. LPCWSTR pwszObjectClass, // in
  79. DWORD dwFlags, // in
  80. LPSECURITYINFO* ppISecurityInfo, // out
  81. PFNREADOBJECTSECURITY pfnReadSd, // in
  82. PFNWRITEOBJECTSECURITY pfnWriteSd, // in
  83. LPARAM lpContext ); // in
  84. };
  85. HRESULT
  86. CDsSecDLL::DSCreateISecurityInfoObject( LPCWSTR pwszObjectPath, // in
  87. LPCWSTR pwszObjectClass, // in
  88. DWORD dwFlags, // in
  89. LPSECURITYINFO* ppISecurityInfo, // out
  90. PFNREADOBJECTSECURITY pfnReadSd, // in
  91. PFNWRITEOBJECTSECURITY pfnWriteSd,// in
  92. LPARAM lpContext // in
  93. ) {
  94. //
  95. // Call the function of the same name.
  96. //
  97. ASSERT(m_hLibrary != NULL);
  98. ASSERT(m_pfFunction != NULL);
  99. return ((PFNDSCREATEISECINFO)m_pfFunction)(
  100. pwszObjectPath,
  101. pwszObjectClass,
  102. dwFlags,
  103. ppISecurityInfo,
  104. pfnReadSd,
  105. pfnWriteSd,
  106. lpContext );
  107. }
  108. //
  109. // CAclUiDLL - Where the UI Actually Lives.
  110. //
  111. class CAclUiDLL : public CDynamicLibraryBase {
  112. public:
  113. CAclUiDLL() {
  114. m_lpszLibraryName = _T("aclui.dll");
  115. m_lpszFunctionName = "CreateSecurityPage";
  116. }
  117. HPROPSHEETPAGE CreateSecurityPage( LPSECURITYINFO psi );
  118. };
  119. HPROPSHEETPAGE CAclUiDLL::CreateSecurityPage( LPSECURITYINFO psi ) {
  120. ASSERT(m_hLibrary != NULL);
  121. ASSERT(m_pfFunction != NULL);
  122. return ((ACLUICREATESECURITYPAGEPROC)m_pfFunction) (psi);
  123. }
  124. //
  125. // CISecurityInformationWrapper - The wrapper for the routine that gets
  126. // sent to CreateSecurityPage().
  127. //
  128. class CISecurityInformationWrapper : public ISecurityInformation {
  129. public:
  130. CISecurityInformationWrapper( CAclEditorPage* pAclEditorPage ) {
  131. m_dwRefCount = 0;
  132. ASSERT(pAclEditorPage != NULL);
  133. m_pAclEditorPage = pAclEditorPage;
  134. m_pISecInfo = NULL;
  135. }
  136. ~CISecurityInformationWrapper() {
  137. ASSERT(m_dwRefCount == 0);
  138. if (m_pISecInfo != NULL)
  139. m_pISecInfo->Release();
  140. }
  141. public:
  142. //
  143. // *** IUnknown methods ***
  144. // Call through to the to actual SecurityInformation interface.
  145. //
  146. STDMETHOD(QueryInterface) (REFIID riid, LPVOID * ppvObj) {
  147. return m_pISecInfo->QueryInterface(riid, ppvObj);
  148. }
  149. STDMETHOD_(ULONG,AddRef) () {
  150. m_dwRefCount++;
  151. return m_pISecInfo->AddRef();
  152. }
  153. STDMETHOD_(ULONG,Release) () {
  154. m_dwRefCount--;
  155. ISecurityInformation* pISecInfo = m_pISecInfo;
  156. return pISecInfo->Release();
  157. }
  158. //
  159. // *** ISecurityInformation methods ***
  160. // These are also call through.
  161. //
  162. STDMETHOD(GetObjectInformation) (PSI_OBJECT_INFO pObjectInfo ) {
  163. HRESULT hr = m_pISecInfo->GetObjectInformation(pObjectInfo);
  164. if (m_szPageTitle.IsEmpty())
  165. {
  166. m_szPageTitle.LoadString(IDS_DEFAULT_SECURITY);
  167. }
  168. pObjectInfo->dwFlags |= SI_PAGE_TITLE;
  169. pObjectInfo->pszPageTitle = (PWSTR)(PCWSTR)m_szPageTitle;
  170. return hr;
  171. }
  172. STDMETHOD(GetAccessRights) (const GUID* pguidObjectType,
  173. DWORD dwFlags, // SI_EDIT_AUDITS, SI_EDIT_PROPERTIES
  174. PSI_ACCESS *ppAccess,
  175. ULONG *pcAccesses,
  176. ULONG *piDefaultAccess ) {
  177. return m_pISecInfo->GetAccessRights(pguidObjectType,
  178. dwFlags,
  179. ppAccess,
  180. pcAccesses,
  181. piDefaultAccess);
  182. }
  183. STDMETHOD(MapGeneric) (const GUID *pguidObjectType,
  184. UCHAR *pAceFlags,
  185. ACCESS_MASK *pMask) {
  186. return m_pISecInfo->MapGeneric(pguidObjectType,
  187. pAceFlags,
  188. pMask);
  189. }
  190. STDMETHOD(GetInheritTypes) (PSI_INHERIT_TYPE *ppInheritTypes,
  191. ULONG *pcInheritTypes ) {
  192. return m_pISecInfo->GetInheritTypes(ppInheritTypes,
  193. pcInheritTypes);
  194. }
  195. STDMETHOD(PropertySheetPageCallback)(HWND hwnd, UINT uMsg, SI_PAGE_TYPE uPage ) {
  196. return m_pISecInfo->PropertySheetPageCallback(hwnd, uMsg, uPage);
  197. }
  198. STDMETHOD(GetSecurity) (SECURITY_INFORMATION RequestedInformation,
  199. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  200. BOOL fDefault) {
  201. return m_pISecInfo->GetSecurity( RequestedInformation,
  202. ppSecurityDescriptor,
  203. fDefault );
  204. }
  205. STDMETHOD(SetSecurity) (SECURITY_INFORMATION securityInformation,
  206. PSECURITY_DESCRIPTOR pSecurityDescriptor ) {
  207. return m_pISecInfo->SetSecurity( securityInformation,
  208. pSecurityDescriptor );
  209. }
  210. private:
  211. DWORD m_dwRefCount;
  212. ISecurityInformation* m_pISecInfo; // interface pointer to the wrapped interface
  213. CAclEditorPage* m_pAclEditorPage; // back pointer
  214. CString m_szPageTitle;
  215. friend class CAclEditorPage;
  216. };
  217. //
  218. // Static instances of the dynamically loaded DLLs.
  219. //
  220. CDsSecDLL g_DsSecDLL;
  221. CAclUiDLL g_AclUiDLL;
  222. //
  223. // CAclEditorPage Routines.
  224. //
  225. HRESULT
  226. CAclEditorPage::CreateInstance(
  227. CAclEditorPage ** ppAclPage,
  228. LPCTSTR lpszLDAPPath,
  229. LPCTSTR lpszObjectClass
  230. ) {
  231. HRESULT hr = S_OK;
  232. CAclEditorPage* pAclEditorPage = new CAclEditorPage;
  233. if (pAclEditorPage != NULL) {
  234. hr = pAclEditorPage->Initialize( lpszLDAPPath, lpszObjectClass );
  235. if ( SUCCEEDED(hr) )
  236. {
  237. *ppAclPage = pAclEditorPage;
  238. }
  239. else
  240. {
  241. delete pAclEditorPage;
  242. pAclEditorPage = NULL;
  243. }
  244. }
  245. else
  246. hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  247. return hr;
  248. }
  249. CAclEditorPage::CAclEditorPage() {
  250. m_pISecInfoWrap = new CISecurityInformationWrapper(this);
  251. }
  252. CAclEditorPage::~CAclEditorPage() {
  253. delete m_pISecInfoWrap;
  254. }
  255. HRESULT
  256. ReadSecurity( LPCWSTR lpszLdapPath,
  257. SECURITY_INFORMATION RequestedInformation,
  258. PSECURITY_DESCRIPTOR *ppSecDesc,
  259. LPARAM lpContext );
  260. HRESULT
  261. WriteSecurity( LPCWSTR lpszLdapPath,
  262. SECURITY_INFORMATION securityInformation,
  263. PSECURITY_DESCRIPTOR pSecDesc,
  264. LPARAM lpContext );
  265. HRESULT
  266. GetObjectSecurityDescriptor( LPCWSTR lpszLdapPath,
  267. PSECURITY_DESCRIPTOR * ppSecDesc,
  268. IADs ** ppIADsObject = NULL );
  269. HRESULT
  270. CAclEditorPage::Initialize(
  271. LPCTSTR lpszLDAPPath,
  272. LPCTSTR lpszObjectClass
  273. ) {
  274. //
  275. // Get ISecurityInfo* for this object from DSSEC.DLL
  276. //
  277. if (!g_DsSecDLL.Load())
  278. return E_INVALIDARG;
  279. ASSERT(m_pISecInfoWrap->m_pISecInfo == NULL);
  280. return g_DsSecDLL.DSCreateISecurityInfoObject( lpszLDAPPath,
  281. lpszObjectClass,
  282. DSSI_NO_ACCESS_CHECK | DSSI_NO_EDIT_OWNER |
  283. ( IsReadOnly(lpszLDAPPath) ? DSSI_READ_ONLY : 0 ),
  284. &(m_pISecInfoWrap->m_pISecInfo),
  285. ReadSecurity,
  286. WriteSecurity,
  287. 0 );
  288. }
  289. HPROPSHEETPAGE CAclEditorPage::CreatePage() {
  290. ASSERT(m_pISecInfoWrap->m_pISecInfo != NULL);
  291. if (!g_AclUiDLL.Load())
  292. return NULL;
  293. //
  294. // Call into ACLUI.DLL to create the page
  295. // passing the wrapper interface.
  296. //
  297. return g_AclUiDLL.CreateSecurityPage(m_pISecInfoWrap);
  298. }
  299. HRESULT
  300. ReadSecurity(
  301. LPCWSTR lpszLdapPath,
  302. SECURITY_INFORMATION /*RequestedInformation*/, // ignoring...
  303. PSECURITY_DESCRIPTOR* ppSecDesc,
  304. LPARAM /*lpContext*/)
  305. {
  306. return GetObjectSecurityDescriptor( lpszLdapPath,
  307. ppSecDesc );
  308. }
  309. #define BREAK_ON_FAILED_BOOL(fResult) \
  310. if ( !fResult ) \
  311. { \
  312. ASSERT( FALSE ); \
  313. break; \
  314. }
  315. const SECURITY_INFORMATION ALL_SECURITY_INFORMATION = OWNER_SECURITY_INFORMATION |
  316. GROUP_SECURITY_INFORMATION |
  317. DACL_SECURITY_INFORMATION |
  318. SACL_SECURITY_INFORMATION;
  319. HRESULT
  320. WriteSecurity(
  321. LPCWSTR lpszLdapPath,
  322. SECURITY_INFORMATION securityInformation,
  323. PSECURITY_DESCRIPTOR pModificationDescriptor,
  324. LPARAM /*lpContext*/)
  325. {
  326. HRESULT hr = S_OK;
  327. BOOL fResult = TRUE;
  328. IADs * pIADsObject = NULL;
  329. PSECURITY_DESCRIPTOR pSecDesc = NULL;
  330. LPWSTR pstrSecDesc = NULL;
  331. const UINT cAbsoluteSecDescSize = 5;
  332. struct
  333. {
  334. PVOID pData;
  335. DWORD dwDataSize;
  336. } absSecDesc[cAbsoluteSecDescSize];
  337. const PSECURITY_DESCRIPTOR & pAbsSecDesc = (PSECURITY_DESCRIPTOR) absSecDesc[0].pData;
  338. ZeroMemory( absSecDesc, sizeof(absSecDesc) );
  339. // we only support changes in DACL & SACL
  340. ASSERT( securityInformation & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION) );
  341. ASSERT( IsValidSecurityDescriptor(pModificationDescriptor) );
  342. do
  343. {
  344. hr = GetObjectSecurityDescriptor( lpszLdapPath,
  345. &pSecDesc,
  346. &pIADsObject );
  347. BREAK_ON_FAILED_HRESULT(hr);
  348. ASSERT(pIADsObject);
  349. fResult = MakeAbsoluteSD( pSecDesc,
  350. (PSECURITY_DESCRIPTOR) absSecDesc[0].pData, &absSecDesc[0].dwDataSize,
  351. (PACL) absSecDesc[1].pData, &absSecDesc[1].dwDataSize,
  352. (PACL) absSecDesc[2].pData, &absSecDesc[2].dwDataSize,
  353. (PSID) absSecDesc[3].pData, &absSecDesc[3].dwDataSize,
  354. (PSID) absSecDesc[4].pData, &absSecDesc[4].dwDataSize );
  355. ASSERT( !fResult ); // the call must fail the first time
  356. hr = HRESULT_FROM_WIN32(::GetLastError());
  357. if( ERROR_INSUFFICIENT_BUFFER != HRESULT_CODE(hr) )
  358. BREAK_ON_FAILED_HRESULT(hr);
  359. fResult = TRUE;
  360. hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  361. // allocate memory for the security descriptor
  362. for( UINT i = 0; i < cAbsoluteSecDescSize; i++ )
  363. if( absSecDesc[i].dwDataSize > 0 )
  364. if( NULL == (absSecDesc[i].pData = new BYTE[ absSecDesc[i].dwDataSize ]) )
  365. break;// NTRAID#NTBUG9-540268-2002/02/13-dantra Out of memory condition masked when building the SECURITY_DESCRIPTOR
  366. hr = S_OK;
  367. fResult = MakeAbsoluteSD( pSecDesc,
  368. (PSECURITY_DESCRIPTOR) absSecDesc[0].pData, &absSecDesc[0].dwDataSize,
  369. (PACL) absSecDesc[1].pData, &absSecDesc[1].dwDataSize,
  370. (PACL) absSecDesc[2].pData, &absSecDesc[2].dwDataSize,
  371. (PSID) absSecDesc[3].pData, &absSecDesc[3].dwDataSize,
  372. (PSID) absSecDesc[4].pData, &absSecDesc[4].dwDataSize );
  373. BREAK_ON_FAILED_BOOL( fResult );
  374. // for convinience, have another reference.
  375. ASSERT( absSecDesc[0].pData == pAbsSecDesc );
  376. ASSERT( IsValidSecurityDescriptor(pAbsSecDesc) );
  377. // Apply DACL changes
  378. if( securityInformation & DACL_SECURITY_INFORMATION )
  379. {
  380. BOOL bDaclPresent = FALSE;
  381. PACL pDacl = NULL;
  382. BOOL bDaclDefaulted = FALSE;
  383. SECURITY_DESCRIPTOR_CONTROL control = 0;
  384. DWORD dwRevision = 0;
  385. fResult = GetSecurityDescriptorDacl( pModificationDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted );
  386. BREAK_ON_FAILED_BOOL( fResult );
  387. fResult = SetSecurityDescriptorDacl( pAbsSecDesc, bDaclPresent, pDacl, bDaclDefaulted );
  388. BREAK_ON_FAILED_BOOL( fResult );
  389. fResult = GetSecurityDescriptorControl( pModificationDescriptor, &control, &dwRevision );
  390. BREAK_ON_FAILED_BOOL( fResult );
  391. fResult = SetSecurityDescriptorControl( pAbsSecDesc, SE_DACL_PROTECTED, control & SE_DACL_PROTECTED );
  392. BREAK_ON_FAILED_BOOL( fResult );
  393. }
  394. // Apply SACL changes
  395. if( securityInformation & SACL_SECURITY_INFORMATION )
  396. {
  397. BOOL bSaclPresent = FALSE;
  398. PACL pSacl = NULL;
  399. BOOL bSaclDefaulted = FALSE;
  400. SECURITY_DESCRIPTOR_CONTROL control = 0;
  401. DWORD dwRevision = 0;
  402. fResult = GetSecurityDescriptorSacl( pModificationDescriptor, &bSaclPresent, &pSacl, &bSaclDefaulted );
  403. BREAK_ON_FAILED_BOOL( fResult );
  404. fResult = SetSecurityDescriptorSacl( pAbsSecDesc, bSaclPresent, pSacl, bSaclDefaulted );
  405. BREAK_ON_FAILED_BOOL( fResult );
  406. fResult = GetSecurityDescriptorControl( pModificationDescriptor, &control, &dwRevision );
  407. BREAK_ON_FAILED_BOOL( fResult );
  408. fResult = SetSecurityDescriptorControl( pAbsSecDesc, SE_SACL_PROTECTED, control & SE_SACL_PROTECTED );
  409. BREAK_ON_FAILED_BOOL( fResult );
  410. }
  411. // Convert Security Descriptor to string format
  412. fResult = ConvertSecurityDescriptorToStringSecurityDescriptor(
  413. pAbsSecDesc,
  414. SDDL_REVISION,
  415. ALL_SECURITY_INFORMATION,
  416. &pstrSecDesc,
  417. NULL );
  418. BREAK_ON_FAILED_BOOL( fResult );
  419. ASSERT(pstrSecDesc);
  420. CComVariant v(pstrSecDesc);
  421. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  422. hr = pIADsObject->Put( CComBSTR(g_DefaultAcl), v);
  423. BREAK_ON_FAILED_HRESULT(hr);
  424. hr = pIADsObject->SetInfo( );
  425. }
  426. while (0);
  427. if( !fResult )
  428. hr = HRESULT_FROM_WIN32(::GetLastError());
  429. if( pIADsObject )
  430. pIADsObject->Release();
  431. if( pstrSecDesc )
  432. LocalFree( pstrSecDesc );
  433. for( UINT i = 0; i < cAbsoluteSecDescSize; i++ )
  434. if( absSecDesc[i].pData )
  435. delete absSecDesc[i].pData;
  436. return hr;
  437. }
  438. HRESULT
  439. GetObjectSecurityDescriptor(
  440. LPCWSTR lpszLdapPath,
  441. PSECURITY_DESCRIPTOR * ppSecDesc,
  442. IADs ** ppIADsObject /* = NULL */) // returns pIADsObject for future use.
  443. {
  444. HRESULT hr = S_OK;
  445. IADs * pIADsObject = NULL;
  446. CComVariant AdsResult;
  447. PSID pDomainSid = NULL;
  448. *ppSecDesc = NULL;
  449. do
  450. {
  451. hr = SchemaOpenObject( const_cast<LPWSTR>((LPCWSTR) lpszLdapPath),
  452. IID_IADs,
  453. (void **) &pIADsObject );
  454. BREAK_ON_FAILED_HRESULT(hr);
  455. ASSERT(pIADsObject);
  456. // NTRAID#NTBUG9-540866-2002/02/13-dantra-Schema Manager: passing WCHAR * instead of BSTR to method requiring a BSTR
  457. hr = pIADsObject->Get( CComBSTR(g_DefaultAcl),&AdsResult);
  458. if (hr == E_ADS_PROPERTY_NOT_FOUND)
  459. {
  460. hr = S_OK;
  461. PSECURITY_DESCRIPTOR
  462. pSecDescTmp = (PSECURITY_DESCRIPTOR)LocalAlloc
  463. (
  464. LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH
  465. );
  466. if(pSecDescTmp==NULL) {hr=E_OUTOFMEMORY;break;}
  467. do
  468. {
  469. if(!InitializeSecurityDescriptor(pSecDescTmp,
  470. SECURITY_DESCRIPTOR_REVISION))
  471. {
  472. hr = HRESULT_FROM_WIN32(::GetLastError());
  473. ASSERT(FAILED(hr));
  474. break;
  475. }
  476. DWORD size=0;
  477. BOOL fResult = MakeSelfRelativeSD(pSecDescTmp,*ppSecDesc,&size);
  478. ASSERT(!fResult); //ERROR_INSUFFICIENT_BUFFER is expected at first.
  479. hr = HRESULT_FROM_WIN32(::GetLastError());
  480. if( HRESULT_CODE(hr) != ERROR_INSUFFICIENT_BUFFER)
  481. BREAK_ON_FAILED_HRESULT(hr);
  482. hr = S_OK;
  483. *ppSecDesc=(PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,size);
  484. if(*ppSecDesc==NULL) {hr=E_OUTOFMEMORY;break;}
  485. fResult = MakeSelfRelativeSD(pSecDescTmp,*ppSecDesc,&size);
  486. if(!fResult)
  487. {
  488. hr = HRESULT_FROM_WIN32(::GetLastError());
  489. ASSERT(FAILED(hr));
  490. // NTRAID#NTBUG9-542445-2002/03/04-dantra-Memory Leak in Error path of aclpage.cpp::GetObjectSecurityDescriptor
  491. LocalFree(*ppSecDesc);
  492. *ppSecDesc=NULL;
  493. break;
  494. }
  495. } while(0);
  496. LocalFree(pSecDescTmp);
  497. BREAK_ON_FAILED_HRESULT(hr);
  498. }
  499. else if(FAILED(hr)) break;
  500. else
  501. {
  502. pDomainSid = NULL;
  503. GetDomainSid(lpszLdapPath, &pDomainSid);
  504. if(pDomainSid)
  505. {
  506. if(!ConvertStringSDToSDDomain(pDomainSid,
  507. NULL,
  508. V_BSTR(&AdsResult),
  509. SDDL_REVISION,
  510. ppSecDesc,
  511. NULL ))
  512. {
  513. ASSERT( FALSE );
  514. hr = HRESULT_FROM_WIN32(::GetLastError());
  515. break;
  516. }
  517. }
  518. else if( !ConvertStringSecurityDescriptorToSecurityDescriptor(
  519. V_BSTR(&AdsResult),
  520. SDDL_REVISION,
  521. ppSecDesc,
  522. NULL ) )
  523. {
  524. ASSERT( FALSE );
  525. hr = HRESULT_FROM_WIN32(::GetLastError());
  526. break;
  527. }
  528. }
  529. ASSERT( IsValidSecurityDescriptor(*ppSecDesc) );
  530. }
  531. while (0);
  532. if( pIADsObject )
  533. {
  534. ASSERT( SUCCEEDED(hr) );
  535. if( !ppIADsObject ) // if caller doesn't need pIADsObject
  536. {
  537. pIADsObject->Release(); // release it
  538. }
  539. else
  540. {
  541. *ppIADsObject = pIADsObject; // otherwise, return it
  542. }
  543. }
  544. if(pDomainSid)
  545. LocalFree(pDomainSid);
  546. return hr;
  547. }
  548. BOOL CAclEditorPage::IsReadOnly( LPCTSTR lpszLDAPPath )
  549. {
  550. ASSERT( lpszLDAPPath );
  551. HRESULT hr = S_OK;
  552. BOOL fFound = FALSE;
  553. CComPtr<IADs> ipADs;
  554. CStringList strlist;
  555. do
  556. {
  557. //
  558. // Open the schema container.
  559. //
  560. hr = SchemaOpenObject( (LPWSTR)(LPCWSTR)lpszLDAPPath,
  561. IID_IADs,
  562. (void **)&ipADs );
  563. BREAK_ON_FAILED_HRESULT(hr);
  564. // extract the list of allowed classes
  565. hr = GetStringListElement( ipADs, &g_allowedAttributesEffective, strlist );
  566. BREAK_ON_FAILED_HRESULT(hr);
  567. // search for needed attributes
  568. for( POSITION pos = strlist.GetHeadPosition(); !fFound && pos != NULL; )
  569. {
  570. CString * pstr = &strlist.GetNext( pos );
  571. fFound = !pstr->CompareNoCase( g_DefaultAcl );
  572. }
  573. } while( FALSE );
  574. return !fFound; // in case something fails, make read-only.
  575. }
  576. LSA_HANDLE
  577. GetLSAConnection(LPCTSTR pszServer, DWORD dwAccessDesired)
  578. {
  579. LSA_HANDLE hPolicy = NULL;
  580. LSA_UNICODE_STRING uszServer = {0};
  581. LSA_UNICODE_STRING *puszServer = NULL;
  582. LSA_OBJECT_ATTRIBUTES oa;
  583. SECURITY_QUALITY_OF_SERVICE sqos;
  584. sqos.Length = sizeof(sqos);
  585. sqos.ImpersonationLevel = SecurityImpersonation;
  586. sqos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  587. sqos.EffectiveOnly = FALSE;
  588. InitializeObjectAttributes(&oa, NULL, 0, NULL, NULL);
  589. oa.SecurityQualityOfService = &sqos;
  590. if (pszServer &&
  591. *pszServer &&
  592. RtlCreateUnicodeString(&uszServer, pszServer))
  593. {
  594. puszServer = &uszServer;
  595. }
  596. LsaOpenPolicy(puszServer, &oa, dwAccessDesired, &hPolicy);
  597. if (puszServer)
  598. RtlFreeUnicodeString(puszServer);
  599. return hPolicy;
  600. }
  601. HRESULT
  602. GetDomainSid(LPCWSTR pszLdapPath, PSID *ppSid)
  603. {
  604. HRESULT hr = S_OK;
  605. NTSTATUS nts = STATUS_SUCCESS;
  606. PPOLICY_ACCOUNT_DOMAIN_INFO pDomainInfo = NULL;
  607. LSA_HANDLE hLSA = 0;
  608. if(!pszLdapPath || !ppSid)
  609. return E_INVALIDARG;
  610. *ppSid = NULL;
  611. IADsPathname *pPath = NULL;
  612. BSTR bstrServer = NULL;
  613. CoCreateInstance(CLSID_Pathname,
  614. NULL,
  615. CLSCTX_INPROC_SERVER,
  616. IID_IADsPathname,
  617. (LPVOID*)&pPath);
  618. if(pPath)
  619. {
  620. if(SUCCEEDED(pPath->Set((BSTR)pszLdapPath,ADS_SETTYPE_FULL)))
  621. {
  622. if(SUCCEEDED(pPath->Retrieve(ADS_FORMAT_SERVER, &bstrServer)))
  623. {
  624. hLSA = GetLSAConnection(bstrServer, POLICY_VIEW_LOCAL_INFORMATION);
  625. if (!hLSA)
  626. {
  627. hr = E_FAIL;
  628. goto exit_gracefully;
  629. }
  630. nts = LsaQueryInformationPolicy(hLSA,
  631. PolicyAccountDomainInformation,
  632. (PVOID*)&pDomainInfo);
  633. if(nts != STATUS_SUCCESS)
  634. {
  635. hr = E_FAIL;
  636. goto exit_gracefully;
  637. }
  638. if (pDomainInfo && pDomainInfo->DomainSid)
  639. {
  640. ULONG cbSid = GetLengthSid(pDomainInfo->DomainSid);
  641. *ppSid = (PSID) LocalAlloc(LPTR, cbSid);
  642. if (!*ppSid)
  643. {
  644. hr = E_OUTOFMEMORY;
  645. goto exit_gracefully;
  646. }
  647. // NOTE: Safe use of CopyMemory
  648. CopyMemory(*ppSid, pDomainInfo->DomainSid, cbSid);
  649. }
  650. }
  651. }
  652. }
  653. exit_gracefully:
  654. if(pDomainInfo)
  655. LsaFreeMemory(pDomainInfo);
  656. if(hLSA)
  657. LsaClose(hLSA);
  658. if(bstrServer)
  659. SysFreeString(bstrServer);
  660. if(pPath)
  661. pPath->Release();
  662. return hr;
  663. }