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.

526 lines
14 KiB

  1. // PermPage.cxx : Implementation ACL Editor classes
  2. // jonn 7/14/97 copied from \nt\private\windows\shell\lmui\ntshrui\permpage.cpp
  3. #include "headers.hxx"
  4. #pragma hdrstop
  5. #include "acl.hxx"
  6. #include "resource.h" // IDS_SHAREPERM_*
  7. // definition in headers.hxx conflicts with stddef.h (atlbase.h)
  8. #undef offsetof
  9. #include <atlbase.h>
  10. CComModule _Module;
  11. #include <atlcom.h>
  12. #include <atlimpl.cpp>
  13. // need IID_ISecurityInformation
  14. #define INITGUID
  15. #include <initguid.h>
  16. #include <aclui.h>
  17. //
  18. // I define my own implementation of ISecurityInformation
  19. //
  20. class CSecurityInformation : public ISecurityInformation, public CComObjectRoot
  21. {
  22. DECLARE_NOT_AGGREGATABLE(CSecurityInformation)
  23. BEGIN_COM_MAP(CSecurityInformation)
  24. COM_INTERFACE_ENTRY(ISecurityInformation)
  25. END_COM_MAP()
  26. // *** ISecurityInformation methods ***
  27. STDMETHOD(GetObjectInformation) (PSI_OBJECT_INFO pObjectInfo ) = 0;
  28. STDMETHOD(GetSecurity) (SECURITY_INFORMATION RequestedInformation,
  29. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  30. BOOL fDefault ) = 0;
  31. STDMETHOD(SetSecurity) (SECURITY_INFORMATION SecurityInformation,
  32. PSECURITY_DESCRIPTOR pSecurityDescriptor ) = 0;
  33. STDMETHOD(GetAccessRights) (const GUID* pguidObjectType,
  34. DWORD dwFlags,
  35. PSI_ACCESS *ppAccess,
  36. ULONG *pcAccesses,
  37. ULONG *piDefaultAccess );
  38. STDMETHOD(MapGeneric) (const GUID *pguidObjectType,
  39. UCHAR *pAceFlags,
  40. ACCESS_MASK *pMask);
  41. STDMETHOD(GetInheritTypes) (PSI_INHERIT_TYPE *ppInheritTypes,
  42. ULONG *pcInheritTypes );
  43. STDMETHOD(PropertySheetPageCallback)(HWND hwnd, UINT uMsg, SI_PAGE_TYPE uPage );
  44. protected:
  45. HRESULT NewDefaultDescriptor(
  46. PSECURITY_DESCRIPTOR* ppsd,
  47. SECURITY_INFORMATION RequestedInformation
  48. );
  49. HRESULT MakeSelfRelativeCopy(
  50. PSECURITY_DESCRIPTOR psdOriginal,
  51. PSECURITY_DESCRIPTOR* ppsdNew );
  52. };
  53. class CShareSecurityInformation : public CSecurityInformation
  54. {
  55. private:
  56. LPWSTR m_strMachineName;
  57. LPWSTR m_strShareName;
  58. public:
  59. void SetMachineName( LPWSTR pszMachineName )
  60. {
  61. m_strMachineName = pszMachineName;
  62. }
  63. void SetShareName( LPWSTR pszShareName )
  64. {
  65. m_strShareName = pszShareName;
  66. }
  67. // note: these should be LPCTSTR but are left this way for convenience
  68. LPWSTR QueryMachineName()
  69. {
  70. return m_strMachineName;
  71. }
  72. LPWSTR QueryShareName()
  73. {
  74. return m_strShareName;
  75. }
  76. // *** ISecurityInformation methods ***
  77. STDMETHOD(GetObjectInformation) (PSI_OBJECT_INFO pObjectInfo );
  78. };
  79. class CSMBSecurityInformation : public CShareSecurityInformation
  80. {
  81. STDMETHOD(GetSecurity) (SECURITY_INFORMATION RequestedInformation,
  82. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  83. BOOL fDefault );
  84. STDMETHOD(SetSecurity) (SECURITY_INFORMATION SecurityInformation,
  85. PSECURITY_DESCRIPTOR pSecurityDescriptor );
  86. public:
  87. PSECURITY_DESCRIPTOR m_pInitialDescriptor;
  88. PSECURITY_DESCRIPTOR* m_ppCurrentDescriptor;
  89. CSMBSecurityInformation();
  90. ~CSMBSecurityInformation();
  91. };
  92. // ISecurityInformation interface implementation
  93. SI_ACCESS siShareAccesses[] =
  94. {
  95. { &GUID_NULL, FILE_ALL_ACCESS, MAKEINTRESOURCE(IDS_SHAREPERM_ALL), SI_ACCESS_GENERAL },
  96. { &GUID_NULL, FILE_GENERIC_WRITE | DELETE, MAKEINTRESOURCE(IDS_SHAREPERM_MODIFY), SI_ACCESS_GENERAL },
  97. { &GUID_NULL, FILE_GENERIC_READ, MAKEINTRESOURCE(IDS_SHAREPERM_READ), SI_ACCESS_GENERAL }
  98. };
  99. #define iShareDefAccess 2 // FILE_GEN_READ
  100. #ifndef ARRAYSIZE
  101. #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
  102. #endif
  103. STDMETHODIMP CSecurityInformation::GetAccessRights (
  104. const GUID* pguidObjectType,
  105. DWORD dwFlags,
  106. PSI_ACCESS *ppAccess,
  107. ULONG *pcAccesses,
  108. ULONG *piDefaultAccess )
  109. {
  110. appAssert(ppAccess != NULL);
  111. appAssert(pcAccesses != NULL);
  112. appAssert(piDefaultAccess != NULL);
  113. *ppAccess = siShareAccesses;
  114. *pcAccesses = ARRAYSIZE(siShareAccesses);
  115. *piDefaultAccess = iShareDefAccess;
  116. return S_OK;
  117. }
  118. // This is consistent with the NETUI code
  119. GENERIC_MAPPING ShareMap =
  120. {
  121. FILE_GENERIC_READ,
  122. FILE_GENERIC_WRITE,
  123. FILE_GENERIC_EXECUTE,
  124. FILE_ALL_ACCESS
  125. };
  126. STDMETHODIMP CSecurityInformation::MapGeneric (
  127. const GUID *pguidObjectType,
  128. UCHAR *pAceFlags,
  129. ACCESS_MASK *pMask)
  130. {
  131. appAssert(pMask != NULL);
  132. MapGenericMask(pMask, &ShareMap);
  133. return S_OK;
  134. }
  135. STDMETHODIMP CSecurityInformation::GetInheritTypes (
  136. PSI_INHERIT_TYPE *ppInheritTypes,
  137. ULONG *pcInheritTypes )
  138. {
  139. appAssert(FALSE);
  140. return E_NOTIMPL;
  141. }
  142. STDMETHODIMP CSecurityInformation::PropertySheetPageCallback(HWND hwnd, UINT uMsg, SI_PAGE_TYPE uPage )
  143. {
  144. return S_OK;
  145. }
  146. /*
  147. JeffreyS 1/24/97:
  148. If you don't set the SI_RESET flag in
  149. ISecurityInformation::GetObjectInformation, then fDefault should never be TRUE
  150. so you can ignore it. Returning E_NOTIMPL in this case is OK too.
  151. If you want the user to be able to reset the ACL to some default state
  152. (defined by you) then turn on SI_RESET and return your default ACL
  153. when fDefault is TRUE. This happens if/when the user pushes a button
  154. that is only visible when SI_RESET is on.
  155. */
  156. STDMETHODIMP CShareSecurityInformation::GetObjectInformation (
  157. PSI_OBJECT_INFO pObjectInfo )
  158. {
  159. appAssert(pObjectInfo != NULL &&
  160. !IsBadWritePtr(pObjectInfo, sizeof(*pObjectInfo)));
  161. pObjectInfo->dwFlags = SI_EDIT_ALL | SI_NO_ACL_PROTECT;
  162. pObjectInfo->hInstance = g_hInstance;
  163. pObjectInfo->pszServerName = QueryMachineName();
  164. pObjectInfo->pszObjectName = QueryShareName();
  165. return S_OK;
  166. }
  167. //
  168. // original code from \\marsslm\backup\src\ncpmgr\ncpmgr\shareacl.cxx
  169. // ACL-wrangling templated from \net\ui\common\src\lmobj\lmobj\security.cxx
  170. //
  171. // caller must free using LocalFree()
  172. //
  173. HRESULT CSecurityInformation::NewDefaultDescriptor(
  174. PSECURITY_DESCRIPTOR* ppsd,
  175. SECURITY_INFORMATION RequestedInformation
  176. )
  177. {
  178. *ppsd = NULL;
  179. PSID psidWorld = NULL;
  180. PSID psidAdmins = NULL;
  181. ACCESS_ALLOWED_ACE* pace = NULL;
  182. ACL* pacl = NULL;
  183. SECURITY_DESCRIPTOR sd;
  184. HRESULT hr = S_OK;
  185. do { // false loop
  186. // build World SID
  187. SID_IDENTIFIER_AUTHORITY IDAuthorityWorld = SECURITY_WORLD_SID_AUTHORITY;
  188. if ( !::AllocateAndInitializeSid(
  189. &IDAuthorityWorld,
  190. 1,
  191. SECURITY_WORLD_RID,
  192. 0,0,0,0,0,0,0,
  193. &psidWorld ) )
  194. {
  195. appAssert( FALSE );
  196. hr = E_UNEXPECTED;
  197. break;
  198. }
  199. // build Admins SID
  200. SID_IDENTIFIER_AUTHORITY IDAuthorityNT = SECURITY_NT_AUTHORITY;
  201. if ( !::AllocateAndInitializeSid(
  202. &IDAuthorityNT,
  203. 2,
  204. SECURITY_BUILTIN_DOMAIN_RID,
  205. DOMAIN_ALIAS_RID_ADMINS,
  206. 0,0,0,0,0,0,
  207. &psidAdmins ) )
  208. {
  209. appAssert( FALSE );
  210. hr = E_UNEXPECTED;
  211. break;
  212. }
  213. // build ACE
  214. DWORD cbSid = ::GetLengthSid(psidWorld);
  215. if ( 0 == cbSid )
  216. {
  217. appAssert( FALSE );
  218. hr = E_UNEXPECTED;
  219. break;
  220. }
  221. INT cbAce = sizeof(ACCESS_ALLOWED_ACE) + cbSid;
  222. pace = reinterpret_cast<ACCESS_ALLOWED_ACE*>(new BYTE[ cbAce+10 ]);
  223. if ( NULL == pace )
  224. {
  225. appAssert( FALSE );
  226. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  227. break;
  228. }
  229. ::memset((BYTE*)pace,0,cbAce+10);
  230. pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; // SetType()
  231. pace->Header.AceFlags = 0; // SetInheritFlags()
  232. pace->Header.AceSize = (WORD)cbAce; // SetSize() (in SetSID())
  233. pace->Mask = GENERIC_ALL; // SetAccessMask()
  234. ::memcpy( &(pace->SidStart), psidWorld, cbSid ); // SetSID()
  235. // build ACL
  236. DWORD cbAcl = sizeof(ACL) + cbAce + 10;
  237. pacl = reinterpret_cast<ACL*>(new BYTE[ cbAcl ]);
  238. if ( NULL == pacl )
  239. {
  240. appAssert( FALSE );
  241. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  242. break;
  243. }
  244. ::memset((BYTE*)pacl,0,cbAcl);
  245. if ( !::InitializeAcl( pacl, cbAcl, ACL_REVISION2 ) )
  246. {
  247. appAssert( FALSE );
  248. hr = E_UNEXPECTED;
  249. break;
  250. }
  251. if ( !::AddAce( pacl, ACL_REVISION2, 0, pace, cbAce ) )
  252. {
  253. appAssert( FALSE );
  254. hr = E_UNEXPECTED;
  255. break;
  256. }
  257. // build security descriptor in absolute format
  258. if ( !::InitializeSecurityDescriptor(
  259. &sd,
  260. SECURITY_DESCRIPTOR_REVISION ) )
  261. {
  262. appAssert( FALSE );
  263. hr = E_UNEXPECTED;
  264. break;
  265. }
  266. if ( !::SetSecurityDescriptorOwner( &sd, psidAdmins, FALSE )
  267. || !::SetSecurityDescriptorGroup( &sd, psidAdmins, FALSE )
  268. || !::SetSecurityDescriptorDacl( &sd, TRUE, pacl, FALSE )
  269. )
  270. {
  271. appAssert( FALSE );
  272. hr = E_UNEXPECTED;
  273. break;
  274. }
  275. // convert security descriptor to self-relative format
  276. DWORD cbSD = 0;
  277. // this call should fail and set cbSD to the correct size
  278. if ( ::MakeSelfRelativeSD( &sd, NULL, &cbSD ) || 0 == cbSD )
  279. {
  280. appAssert( FALSE );
  281. hr = E_UNEXPECTED;
  282. break;
  283. }
  284. *ppsd = reinterpret_cast<PSECURITY_DESCRIPTOR>(
  285. ::LocalAlloc( LMEM_ZEROINIT, cbSD + 20 ) );
  286. if (!*ppsd)
  287. {
  288. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  289. break;
  290. }
  291. ::memset( (BYTE*)*ppsd, 0, cbSD + 20 );
  292. if ( !::MakeSelfRelativeSD( &sd, *ppsd, &cbSD ) )
  293. {
  294. appAssert( FALSE );
  295. hr = E_UNEXPECTED;
  296. break;
  297. }
  298. } while (FALSE); // false loop
  299. // clean up
  300. if ( NULL != psidWorld ) {
  301. (void)::FreeSid( psidWorld );
  302. }
  303. if ( NULL != psidAdmins ) {
  304. (void)::FreeSid( psidAdmins );
  305. }
  306. delete pace;
  307. delete pacl;
  308. return hr;
  309. }
  310. HRESULT CSecurityInformation::MakeSelfRelativeCopy(
  311. PSECURITY_DESCRIPTOR psdOriginal,
  312. PSECURITY_DESCRIPTOR* ppsdNew )
  313. {
  314. appAssert( NULL != psdOriginal );
  315. // we have to find out whether the original is already self-relative
  316. SECURITY_DESCRIPTOR_CONTROL sdc = 0;
  317. DWORD dwRevision = 0;
  318. if ( !::GetSecurityDescriptorControl( psdOriginal, &sdc, &dwRevision ) )
  319. {
  320. appAssert( FALSE );
  321. DWORD err = ::GetLastError();
  322. return HRESULT_FROM_WIN32( err );
  323. }
  324. DWORD cb = ::GetSecurityDescriptorLength( psdOriginal ) + 20;
  325. PSECURITY_DESCRIPTOR psdSelfRelativeCopy = reinterpret_cast<PSECURITY_DESCRIPTOR>(
  326. ::LocalAlloc(LMEM_ZEROINIT, cb) );
  327. if (NULL == psdSelfRelativeCopy)
  328. {
  329. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  330. }
  331. if ( sdc & SE_SELF_RELATIVE )
  332. // the original is in self-relative format, just byte-copy it
  333. {
  334. ::memcpy( psdSelfRelativeCopy, psdOriginal, cb - 20 );
  335. }
  336. else if ( !::MakeSelfRelativeSD( psdOriginal, psdSelfRelativeCopy, &cb ) )
  337. // the original is in absolute format, convert-copy it
  338. {
  339. appAssert( FALSE );
  340. if( NULL != ::LocalFree( psdSelfRelativeCopy ) )
  341. {
  342. appAssert(FALSE);
  343. }
  344. DWORD err = ::GetLastError();
  345. return HRESULT_FROM_WIN32( err );
  346. }
  347. *ppsdNew = psdSelfRelativeCopy;
  348. return S_OK;
  349. }
  350. CSMBSecurityInformation::CSMBSecurityInformation()
  351. : CShareSecurityInformation()
  352. , m_pInitialDescriptor( NULL )
  353. , m_ppCurrentDescriptor( NULL )
  354. {
  355. }
  356. CSMBSecurityInformation::~CSMBSecurityInformation()
  357. {
  358. }
  359. STDMETHODIMP CSMBSecurityInformation::GetSecurity (
  360. SECURITY_INFORMATION RequestedInformation,
  361. PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  362. BOOL fDefault )
  363. {
  364. appAssert( NULL != m_ppCurrentDescriptor );
  365. // NOTE: we allow NULL == ppSecurityDescriptor, see SetSecurity
  366. if (0 == RequestedInformation )
  367. {
  368. appAssert(FALSE);
  369. return E_INVALIDARG;
  370. }
  371. if (fDefault)
  372. return E_NOTIMPL;
  373. if ( NULL == ppSecurityDescriptor )
  374. return S_OK;
  375. *ppSecurityDescriptor = NULL;
  376. HRESULT hr = S_OK;
  377. if (NULL != *m_ppCurrentDescriptor)
  378. {
  379. hr = MakeSelfRelativeCopy(
  380. *m_ppCurrentDescriptor,
  381. ppSecurityDescriptor );
  382. appAssert( SUCCEEDED(hr) && NULL != *ppSecurityDescriptor );
  383. }
  384. else if (NULL != m_pInitialDescriptor)
  385. {
  386. hr = MakeSelfRelativeCopy(
  387. m_pInitialDescriptor,
  388. ppSecurityDescriptor );
  389. appAssert( SUCCEEDED(hr) && NULL != *ppSecurityDescriptor );
  390. }
  391. else
  392. {
  393. hr = NewDefaultDescriptor(
  394. ppSecurityDescriptor,
  395. RequestedInformation );
  396. appAssert( SUCCEEDED(hr) && NULL != *ppSecurityDescriptor );
  397. }
  398. return hr;
  399. }
  400. STDMETHODIMP CSMBSecurityInformation::SetSecurity (
  401. SECURITY_INFORMATION SecurityInformation,
  402. PSECURITY_DESCRIPTOR pSecurityDescriptor )
  403. {
  404. appAssert( NULL != m_ppCurrentDescriptor );
  405. if (NULL != *m_ppCurrentDescriptor)
  406. {
  407. ::LocalFree(*m_ppCurrentDescriptor);
  408. *m_ppCurrentDescriptor = NULL;
  409. }
  410. HRESULT hr = MakeSelfRelativeCopy(
  411. pSecurityDescriptor,
  412. m_ppCurrentDescriptor );
  413. appAssert( SUCCEEDED(hr) && NULL != *m_ppCurrentDescriptor );
  414. return hr;
  415. }
  416. HMODULE g_hlibACLUI = NULL;
  417. typedef BOOL (*EDIT_SECURITY_PROC) ( HWND, LPSECURITYINFO );
  418. EDIT_SECURITY_PROC g_pfnEditSecurityProc;
  419. LONG
  420. EditShareAcl(
  421. IN HWND hwndParent,
  422. IN LPWSTR pszServerName,
  423. IN TCHAR * pszShareName,
  424. IN PSECURITY_DESCRIPTOR pSecDesc,
  425. OUT BOOL* pfSecDescModified,
  426. OUT PSECURITY_DESCRIPTOR* ppSecDesc
  427. )
  428. {
  429. appAssert( ppSecDesc != NULL );
  430. *ppSecDesc = NULL;
  431. if (NULL == g_hlibACLUI)
  432. {
  433. g_hlibACLUI = ::LoadLibrary(L"ACLUI.DLL");
  434. if (NULL == g_hlibACLUI)
  435. {
  436. appAssert(FALSE); // ACLUI.DLL isn't installed?
  437. return 0;
  438. }
  439. }
  440. if (NULL == g_pfnEditSecurityProc)
  441. {
  442. g_pfnEditSecurityProc = reinterpret_cast<EDIT_SECURITY_PROC>(
  443. ::GetProcAddress(g_hlibACLUI,"EditSecurity") );
  444. if (NULL == g_pfnEditSecurityProc)
  445. {
  446. appAssert(FALSE); // ACLUI.DLL is invalid?
  447. return 0;
  448. }
  449. }
  450. CComObject<CSMBSecurityInformation>* psecinfo = NULL;
  451. HRESULT hRes = CComObject<CSMBSecurityInformation>::CreateInstance(&psecinfo);
  452. if ( FAILED(hRes) )
  453. return 0;
  454. psecinfo->AddRef();
  455. psecinfo->SetMachineName( pszServerName );
  456. psecinfo->SetShareName( pszShareName );
  457. psecinfo->m_pInitialDescriptor = pSecDesc;
  458. psecinfo->m_ppCurrentDescriptor = ppSecDesc;
  459. (g_pfnEditSecurityProc)(hwndParent,psecinfo);
  460. if (NULL != pfSecDescModified)
  461. *pfSecDescModified = (NULL != *ppSecDesc);
  462. psecinfo->Release();
  463. return 0;
  464. }