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.

1420 lines
44 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // EditAcl.cpp
  7. //
  8. // Abstract:
  9. // Implementation of ACL editor methods.
  10. //
  11. // Author:
  12. // David Potter (davidp) October 9, 1996
  13. // From \nt\private\window\shell\lmui\ntshrui\acl.cxx
  14. // by BruceFo
  15. //
  16. // Revision History:
  17. // Rodsh 04-Apr-1997 Modified to handle deletion of Registry SD.
  18. // Rodsh 09-Apr-1997 Modified to ensure that at least one user
  19. // is granted access to cluster.
  20. // Rodsh 29-Apr-1997 Modified to prevent the selection of local accounts
  21. // in the permissions of dialog
  22. //
  23. // Notes:
  24. //
  25. /////////////////////////////////////////////////////////////////////////////
  26. #include "stdafx.h"
  27. #include <lmerr.h>
  28. extern "C"
  29. {
  30. #include <sedapi.h>
  31. }
  32. #include "EditAcl.h"
  33. #include "AclHelp.h"
  34. #include "TraceTag.h"
  35. #include "ExcOper.h"
  36. #include "resource.h"
  37. #define _RESOURCE_H_
  38. #ifdef _DEBUG
  39. #define new DEBUG_NEW
  40. #undef THIS_FILE
  41. static char THIS_FILE[] = __FILE__;
  42. #endif
  43. //////////////////////////////////////////////////////////////////////////////
  44. // Global Variables
  45. //////////////////////////////////////////////////////////////////////////////
  46. #ifdef _DEBUG
  47. CTraceTag g_tagEditClusterAcl(_T("ACL"), _T("Cluster ACL Editor"), 0);
  48. #endif
  49. //////////////////////////////////////////////////////////////////////////////
  50. //////////////////////////////////////////////////////////////////////////////
  51. #define ARRAYLEN(a) (sizeof(a) / sizeof((a)[0]))
  52. enum MAP_DIRECTION
  53. {
  54. SPECIFIC_TO_GENERIC = 0,
  55. GENERIC_TO_SPECIFIC = 1
  56. };
  57. const DWORD CLUSTER_INACCESSIBLE = 1L;
  58. const DWORD LOCAL_ACCOUNTS_FILTERED = 2L;
  59. BOOL MapBitsInSD(PSECURITY_DESCRIPTOR pSecDesc, MAP_DIRECTION direction);
  60. BOOL MapBitsInACL(PACL paclACL, MAP_DIRECTION direction);
  61. BOOL MapSpecificBitsInAce(PACCESS_ALLOWED_ACE pAce);
  62. BOOL MapGenericBitsInAce(PACCESS_ALLOWED_ACE pAce);
  63. typedef
  64. DWORD
  65. (*SedDiscretionaryAclEditorType)(
  66. HWND Owner,
  67. HANDLE Instance,
  68. LPWSTR Server,
  69. PSED_OBJECT_TYPE_DESCRIPTOR ObjectType,
  70. PSED_APPLICATION_ACCESSES ApplicationAccesses,
  71. LPWSTR ObjectName,
  72. PSED_FUNC_APPLY_SEC_CALLBACK ApplySecurityCallbackRoutine,
  73. ULONG CallbackContext,
  74. PSECURITY_DESCRIPTOR SecurityDescriptor,
  75. BOOLEAN CouldntReadDacl,
  76. BOOLEAN CantWriteDacl,
  77. LPDWORD SEDStatusReturn,
  78. DWORD Flags
  79. );
  80. // NOTE: the SedDiscretionaryAclEditor string is used in GetProcAddress to
  81. // get the correct entrypoint. Since GetProcAddress is not UNICODE, this string
  82. // must be ANSI.
  83. #define ACLEDIT_DLL_STRING TEXT("acledit.dll")
  84. #define ACLEDIT_HELPFILENAME TEXT("ntshrui.hlp")
  85. #define SEDDISCRETIONARYACLEDITOR_STRING ("SedDiscretionaryAclEditor")
  86. //
  87. // Declare the callback routine based on typedef in sedapi.h.
  88. //
  89. DWORD
  90. SedCallback(
  91. HWND hwndParent,
  92. HANDLE hInstance,
  93. ULONG ulCallbackContext,
  94. PSECURITY_DESCRIPTOR pSecDesc,
  95. PSECURITY_DESCRIPTOR pSecDescNewObjects,
  96. BOOLEAN fApplyToSubContainers,
  97. BOOLEAN fApplyToSubObjects,
  98. LPDWORD StatusReturn
  99. );
  100. //
  101. // Structure for callback function's usage. A pointer to this is passed as
  102. // ulCallbackContext. The callback functions sets bSecDescModified to TRUE
  103. // and makes a copy of the security descriptor. The caller of EditClusterAcl
  104. // is responsible for deleting the memory in pSecDesc if bSecDescModified is
  105. // TRUE. This flag will be FALSE if the user hit CANCEL in the ACL editor.
  106. //
  107. struct CLUSTER_ACL_CALLBACK_INFO
  108. {
  109. BOOL bSecDescModified;
  110. PSECURITY_DESCRIPTOR pSecDesc;
  111. LPCTSTR pszClusterNameNode;
  112. };
  113. //
  114. // Local function prototypes
  115. //
  116. VOID
  117. InitializeClusterGenericMapping(
  118. IN OUT PGENERIC_MAPPING pClusterGenericMapping
  119. );
  120. DWORD
  121. MakeEmptySecDesc(
  122. OUT PSECURITY_DESCRIPTOR * ppSecDesc
  123. );
  124. PWSTR
  125. GetResourceString(
  126. IN DWORD dwId
  127. );
  128. PWSTR
  129. NewDup(
  130. IN const WCHAR* psz
  131. );
  132. //
  133. // The following two arrays define the permission names for NT Files. Note
  134. // that each index in one array corresponds to the index in the other array.
  135. // The second array will be modifed to contain a string pointer pointing to
  136. // a loaded string corresponding to the IDS_* in the first array.
  137. //
  138. DWORD g_dwClusterPermNames[] =
  139. {
  140. IDS_ACLEDIT_PERM_GEN_NO_ACCESS,
  141. IDS_ACLEDIT_PERM_GEN_ALL
  142. } ;
  143. SED_APPLICATION_ACCESS g_SedAppAccessClusterPerms[] =
  144. {
  145. { SED_DESC_TYPE_RESOURCE, GENERIC_EXECUTE,0, NULL },
  146. { SED_DESC_TYPE_RESOURCE, GENERIC_ALL, 0, NULL }
  147. };
  148. //+-------------------------------------------------------------------------
  149. //
  150. // Function: EditClusterAcl
  151. //
  152. // Synopsis: Invokes the generic ACL editor, specifically for clusters
  153. //
  154. // Arguments: [hwndParent] - Parent window handle
  155. // [pszServerName] - Name of server on which the object resides.
  156. // [pszClusterName] - Fully qualified name of resource we will
  157. // edit, basically a cluster name.
  158. // [pszClusterNameNode] - Name of node on which the cluster name
  159. // resource is online (used for local account check).
  160. // [pSecDesc] - The initial security descriptor. If NULL, we will
  161. // create a default that is "World all" access.
  162. // [pbSecDescModified] - Set to TRUE if the security descriptor
  163. // was modified (i.e., the user hit "OK"), or FALSE if not
  164. // (i.e., the user hit "Cancel")
  165. // [ppSecDesc] - *ppSecDesc points to a new security descriptor
  166. // if *pbSecDescModified is TRUE. This memory must be freed
  167. // by the caller.
  168. //
  169. // History:
  170. // ChuckC 10-Aug-1992 Created. Culled from NTFS ACL code.
  171. // Yi-HsinS 09-Oct-1992 Added ulHelpContextBase
  172. // BruceFo 4-Apr-95 Stole and used in ntshrui.dll
  173. // DavidP 10-Oct-1996 Modified for use with CLUADMIN
  174. // Rodsh 04-12-1997 Added calls to function to map to/from specific/generic
  175. //
  176. //--------------------------------------------------------------------------
  177. LONG
  178. EditClusterAcl(
  179. IN HWND hwndParent,
  180. IN LPCTSTR pszServerName,
  181. IN LPCTSTR pszClusterName,
  182. IN LPCTSTR pszClusterNameNode,
  183. IN PSECURITY_DESCRIPTOR pSecDesc,
  184. OUT BOOL * pbSecDescModified,
  185. OUT PSECURITY_DESCRIPTOR * ppSecDesc
  186. )
  187. {
  188. ASSERT(pszClusterName != NULL);
  189. ASSERT(pszClusterNameNode != NULL);
  190. Trace(g_tagEditClusterAcl, _T("EditClusterAcl, cluster %ws"), pszClusterName);
  191. ASSERT((pSecDesc == NULL) || IsValidSecurityDescriptor(pSecDesc));
  192. ASSERT(pbSecDescModified != NULL);
  193. ASSERT(ppSecDesc != NULL);
  194. *pbSecDescModified = FALSE;
  195. LONG err = 0 ;
  196. PWSTR pszPermName;
  197. do // error breakout
  198. {
  199. /*
  200. * if pSecDesc is NULL, this is new cluster or a cluster with no
  201. * security descriptor.
  202. * we go and create a new (default) security descriptor.
  203. */
  204. if( NULL == pSecDesc )
  205. {
  206. Trace(g_tagEditClusterAcl, _T("Security Descriptor is NULL. Deny everyone Access") );
  207. LONG err = MakeEmptySecDesc( &pSecDesc );
  208. if (err != NERR_Success)
  209. {
  210. err = GetLastError();
  211. Trace(g_tagEditClusterAcl, _T("makeEmptySecDesc failed, 0x%08lx"), err);
  212. break;
  213. }
  214. }
  215. ASSERT(IsValidSecurityDescriptor(pSecDesc));
  216. /* Retrieve the resource strings appropriate for the type of object we
  217. * are looking at
  218. */
  219. CString strTypeName;
  220. CString strDefaultPermName;
  221. try
  222. {
  223. strTypeName.LoadString(IDS_ACLEDIT_TITLE);
  224. strDefaultPermName.LoadString(IDS_ACLEDIT_PERM_GEN_ALL);
  225. } // try
  226. catch (CMemoryException * pme)
  227. {
  228. pme->Delete();
  229. }
  230. /*
  231. * other misc stuff we need pass to security editor
  232. */
  233. SED_OBJECT_TYPE_DESCRIPTOR sedObjDesc ;
  234. SED_HELP_INFO sedHelpInfo ;
  235. GENERIC_MAPPING ClusterGenericMapping ;
  236. // setup mappings
  237. InitializeClusterGenericMapping( &ClusterGenericMapping ) ;
  238. WCHAR szHelpFile[50] = ACLEDIT_HELPFILENAME;
  239. sedHelpInfo.pszHelpFileName = szHelpFile;
  240. sedHelpInfo.aulHelpContext[HC_MAIN_DLG] = HC_UI_SHELL_BASE + HC_NTSHAREPERMS ;
  241. sedHelpInfo.aulHelpContext[HC_ADD_USER_DLG] = HC_UI_SHELL_BASE + HC_SHAREADDUSER ;
  242. sedHelpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_GG_DLG] = HC_UI_SHELL_BASE + HC_SHAREADDUSER_GLOBALGROUP ;
  243. sedHelpInfo.aulHelpContext[HC_ADD_USER_SEARCH_DLG] = HC_UI_SHELL_BASE + HC_SHAREADDUSER_FINDUSER ;
  244. // These are not used, set to zero
  245. sedHelpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] = 0 ;
  246. sedHelpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] = 0 ;
  247. // setup the object description
  248. sedObjDesc.Revision = SED_REVISION1 ;
  249. sedObjDesc.IsContainer = TRUE ;
  250. sedObjDesc.AllowNewObjectPerms = FALSE ;
  251. sedObjDesc.MapSpecificPermsToGeneric = TRUE;
  252. sedObjDesc.GenericMapping = &ClusterGenericMapping ;
  253. sedObjDesc.GenericMappingNewObjects = NULL;
  254. sedObjDesc.ObjectTypeName = (LPWSTR) (LPCWSTR) strTypeName ;
  255. sedObjDesc.HelpInfo = &sedHelpInfo ;
  256. sedObjDesc.ApplyToSubContainerTitle = NULL ;
  257. sedObjDesc.ApplyToObjectsTitle = NULL ;
  258. sedObjDesc.ApplyToSubContainerConfirmation = NULL ;
  259. sedObjDesc.SpecialObjectAccessTitle = NULL ;
  260. sedObjDesc.SpecialNewObjectAccessTitle = NULL ;
  261. /* Now we need to load the global arrays with the permission names
  262. * from the resource file.
  263. */
  264. UINT cArrayItems = ARRAYLEN(g_SedAppAccessClusterPerms);
  265. PSED_APPLICATION_ACCESS aSedAppAccess = g_SedAppAccessClusterPerms ;
  266. /* Loop through each permission title retrieving the text from the
  267. * resource file and setting the pointer in the array.
  268. */
  269. for ( UINT i = 0 ; i < cArrayItems ; i++ )
  270. {
  271. pszPermName = GetResourceString(g_dwClusterPermNames[i]) ;
  272. if (NULL == pszPermName)
  273. {
  274. Trace(g_tagEditClusterAcl, _T("GetResourceString failed"));
  275. break ;
  276. }
  277. aSedAppAccess[i].PermissionTitle = pszPermName;
  278. }
  279. if (i < cArrayItems)
  280. {
  281. Trace(g_tagEditClusterAcl, _T("failed to get all cluster permission names"));
  282. break ;
  283. }
  284. SED_APPLICATION_ACCESSES sedAppAccesses ;
  285. sedAppAccesses.Count = cArrayItems ;
  286. sedAppAccesses.AccessGroup = aSedAppAccess ;
  287. sedAppAccesses.DefaultPermName = (LPWSTR) (LPCWSTR) strDefaultPermName;
  288. /*
  289. * pass this along so when the call back function is called,
  290. * we can set it.
  291. */
  292. CLUSTER_ACL_CALLBACK_INFO callbackinfo ;
  293. callbackinfo.pSecDesc = NULL;
  294. callbackinfo.bSecDescModified = FALSE;
  295. callbackinfo.pszClusterNameNode = pszClusterNameNode;
  296. //
  297. // Now, load up the ACL editor and invoke it. We don't keep it around
  298. // because our DLL is loaded whenever the system is, so we don't want
  299. // the netui*.dll's hanging around as well...
  300. //
  301. HINSTANCE hInstanceAclEditor = NULL;
  302. SedDiscretionaryAclEditorType pSedDiscretionaryAclEditor = NULL;
  303. hInstanceAclEditor = LoadLibrary(ACLEDIT_DLL_STRING);
  304. if (NULL == hInstanceAclEditor)
  305. {
  306. err = GetLastError();
  307. Trace(g_tagEditClusterAcl, _T("LoadLibrary of acledit.dll failed, 0x%08lx"), err);
  308. break;
  309. }
  310. pSedDiscretionaryAclEditor = (SedDiscretionaryAclEditorType)
  311. GetProcAddress(hInstanceAclEditor,SEDDISCRETIONARYACLEDITOR_STRING);
  312. if ( pSedDiscretionaryAclEditor == NULL )
  313. {
  314. err = GetLastError();
  315. Trace(g_tagEditClusterAcl, _T("GetProcAddress of SedDiscretionaryAclEditor failed, 0x%08lx"), err);
  316. break;
  317. }
  318. MapBitsInSD( pSecDesc, SPECIFIC_TO_GENERIC );
  319. DWORD dwSedReturnStatus ;
  320. ASSERT(pSedDiscretionaryAclEditor != NULL);
  321. err = (*pSedDiscretionaryAclEditor)(
  322. hwndParent,
  323. AfxGetInstanceHandle(),
  324. (LPTSTR) pszServerName,
  325. &sedObjDesc,
  326. &sedAppAccesses,
  327. (LPTSTR) pszClusterName,
  328. SedCallback,
  329. (ULONG) &callbackinfo,
  330. pSecDesc,
  331. FALSE, // always can read
  332. FALSE, // If we can read, we can write
  333. (LPDWORD) &dwSedReturnStatus,
  334. 0 ) ;
  335. MapBitsInSD( pSecDesc, GENERIC_TO_SPECIFIC );
  336. if (!FreeLibrary(hInstanceAclEditor))
  337. {
  338. LONG err2 = GetLastError();
  339. Trace(g_tagEditClusterAcl, _T("FreeLibrary of acledit.dll failed, 0x%08lx"), err2);
  340. // not fatal: continue...
  341. }
  342. if (0 != err)
  343. {
  344. Trace(g_tagEditClusterAcl, _T("SedDiscretionaryAclEditor failed, 0x%08lx"), err);
  345. break ;
  346. }
  347. *pbSecDescModified = callbackinfo.bSecDescModified ;
  348. if (*pbSecDescModified)
  349. {
  350. *ppSecDesc = callbackinfo.pSecDesc;
  351. MapBitsInSD( *ppSecDesc, GENERIC_TO_SPECIFIC );
  352. Trace(g_tagEditClusterAcl, _T("After calling acl editor, *ppSecDesc = 0x%08lx"), *ppSecDesc);
  353. ASSERT(IsValidSecurityDescriptor(*ppSecDesc));
  354. }
  355. } while (FALSE) ;
  356. //
  357. // Free memory...
  358. //
  359. UINT cArrayItems = ARRAYLEN(g_SedAppAccessClusterPerms);
  360. PSED_APPLICATION_ACCESS aSedAppAccess = g_SedAppAccessClusterPerms ;
  361. for ( UINT i = 0 ; i < cArrayItems ; i++ )
  362. {
  363. pszPermName = aSedAppAccess[i].PermissionTitle;
  364. if (NULL == pszPermName)
  365. {
  366. // if we hit a NULL, that's it!
  367. break ;
  368. }
  369. delete[] pszPermName;
  370. }
  371. ASSERT(!*pbSecDescModified || IsValidSecurityDescriptor(*ppSecDesc));
  372. if (0 != err)
  373. {
  374. CString strMsg;
  375. try
  376. {
  377. strMsg.LoadString(IDS_NOACLEDITOR);
  378. AfxMessageBox(strMsg, MB_OK | MB_ICONSTOP);
  379. } // try
  380. catch (CException * pe)
  381. {
  382. pe->Delete();
  383. } // catch: CException
  384. }
  385. return err;
  386. } //*** EditClusterAcl()
  387. BOOL BClusterAccessible(PSECURITY_DESCRIPTOR pSD)
  388. {
  389. /*++
  390. Routine Description:
  391. Determines if the SD has at least one entry in its ACL with Access to the cluster
  392. Added this function in order to validate Security Descriptors after the ACL editor has been called.
  393. Rod Sharper 03/27/97
  394. Arguments:
  395. pSD - Security Descriptor to be checked.
  396. Return Value:
  397. TRUE if at least one ACE is in the ACL with access to the cluster, False otherwise.
  398. --*/
  399. PACL paclDACL = NULL;
  400. BOOL bHasDACL = FALSE;
  401. BOOL bDaclDefaulted = FALSE;
  402. BOOL bPermissionFound= FALSE;
  403. BOOL bRtn = FALSE;
  404. ACL_SIZE_INFORMATION asiAclSize;
  405. DWORD dwBufLength;
  406. DWORD dwACL_Index = 0L;
  407. ACCESS_ALLOWED_ACE *paaAllowedAce;
  408. bRtn = IsValidSecurityDescriptor(pSD);
  409. ASSERT(bRtn);
  410. if( !bRtn )
  411. return FALSE;
  412. bRtn = GetSecurityDescriptorDacl(pSD,
  413. (LPBOOL)&bHasDACL,
  414. (PACL *)&paclDACL,
  415. (LPBOOL)&bDaclDefaulted);
  416. ASSERT(bRtn);
  417. if( !bRtn )
  418. return FALSE;
  419. if (NULL == paclDACL)
  420. return FALSE;
  421. bRtn = IsValidAcl(paclDACL);
  422. ASSERT(bRtn);
  423. if( !bRtn )
  424. return FALSE;
  425. dwBufLength = sizeof(asiAclSize);
  426. bRtn = GetAclInformation(paclDACL,
  427. (LPVOID)&asiAclSize,
  428. (DWORD)dwBufLength,
  429. (ACL_INFORMATION_CLASS)AclSizeInformation);
  430. ASSERT(bRtn);
  431. if( !bRtn )
  432. return FALSE;
  433. // Search the ACL for an ACE containing permission to access the cluster
  434. //
  435. bPermissionFound = FALSE;
  436. while( dwACL_Index < asiAclSize.AceCount && !bPermissionFound )
  437. {
  438. if (!GetAce(paclDACL,
  439. dwACL_Index,
  440. (LPVOID *)&paaAllowedAce))
  441. {
  442. ASSERT(FALSE);
  443. return FALSE;
  444. }
  445. if( paaAllowedAce->Mask == GENERIC_ALL )
  446. bPermissionFound = TRUE;
  447. dwACL_Index++;
  448. }
  449. return bPermissionFound;
  450. } //*** BClusterAccessible()
  451. BOOL BLocalAccountsInSD(PSECURITY_DESCRIPTOR pSD, LPCTSTR pszClusterNameNode)
  452. {
  453. /*++
  454. Routine Description:
  455. Determines if any ACEs for local accounts are in DACL stored in from
  456. Security Descriptor (pSD) after the ACL editor has been called
  457. Added this function in order to prevent users from selecting local accounts in
  458. permissions dialog.
  459. Rod Sharper 04/29/97
  460. Arguments:
  461. pSD - Security Descriptor to be checked.
  462. Return Value:
  463. TRUE if at least one ACE was removed from the DACL, False otherwise.
  464. --*/
  465. PACL paclDACL = NULL;
  466. BOOL bHasDACL = FALSE;
  467. BOOL bDaclDefaulted = FALSE;
  468. BOOL bLocalAccountInACL = FALSE;
  469. BOOL bRtn = FALSE;
  470. ACL_SIZE_INFORMATION asiAclSize;
  471. DWORD dwBufLength;
  472. DWORD dwACL_Index = 0L;
  473. ACCESS_ALLOWED_ACE * paaAllowedAce;
  474. TCHAR szUserName[128];
  475. TCHAR szDomainName[128];
  476. DWORD cbUser = 128;
  477. DWORD cbDomain = 128;
  478. SID_NAME_USE SidType;
  479. PUCHAR pnSubAuthorityCount;
  480. PULONG pnSubAuthority0;
  481. PULONG pnSubAuthority1;
  482. bRtn = IsValidSecurityDescriptor(pSD);
  483. ASSERT(bRtn);
  484. if( !bRtn )
  485. return FALSE;
  486. bRtn = GetSecurityDescriptorDacl(
  487. pSD,
  488. (LPBOOL)&bHasDACL,
  489. (PACL *)&paclDACL,
  490. (LPBOOL)&bDaclDefaulted);
  491. ASSERT(bRtn);
  492. if( !bRtn )
  493. return FALSE;
  494. if (NULL == paclDACL)
  495. return FALSE;
  496. bRtn = IsValidAcl(paclDACL);
  497. ASSERT(bRtn);
  498. if( !bRtn )
  499. return FALSE;
  500. dwBufLength = sizeof(asiAclSize);
  501. bRtn = GetAclInformation(
  502. paclDACL,
  503. (LPVOID)&asiAclSize,
  504. (DWORD)dwBufLength,
  505. (ACL_INFORMATION_CLASS)AclSizeInformation);
  506. ASSERT(bRtn);
  507. if( !bRtn )
  508. return FALSE;
  509. // Search the ACL for local account ACEs
  510. //
  511. PSID pSID;
  512. while( dwACL_Index < asiAclSize.AceCount )
  513. {
  514. if (!GetAce(paclDACL, dwACL_Index, (LPVOID *)&paaAllowedAce))
  515. {
  516. ASSERT(FALSE);
  517. return FALSE;
  518. }
  519. if((((PACE_HEADER)paaAllowedAce)->AceType) == ACCESS_ALLOWED_ACE_TYPE)
  520. {
  521. //
  522. //Get SID from ACE
  523. //
  524. pSID=(PSID)&((PACCESS_ALLOWED_ACE)paaAllowedAce)->SidStart;
  525. cbUser = 128;
  526. cbDomain = 128;
  527. if (LookupAccountSid(NULL,
  528. pSID,
  529. szUserName,
  530. &cbUser,
  531. szDomainName,
  532. &cbDomain,
  533. &SidType))
  534. {
  535. if (lstrcmpi(szDomainName, _T("BUILTIN")) == 0)
  536. {
  537. pnSubAuthorityCount = GetSidSubAuthorityCount( pSID );
  538. if ( (pnSubAuthorityCount != NULL) && (*pnSubAuthorityCount == 2) )
  539. {
  540. // Check to see if this is the local Administrators group.
  541. pnSubAuthority0 = GetSidSubAuthority( pSID, 0 );
  542. pnSubAuthority1 = GetSidSubAuthority( pSID, 1 );
  543. if ( (pnSubAuthority0 == NULL)
  544. || (pnSubAuthority1 == NULL)
  545. || ( (*pnSubAuthority0 != SECURITY_BUILTIN_DOMAIN_RID)
  546. && (*pnSubAuthority1 != SECURITY_BUILTIN_DOMAIN_RID))
  547. || ( (*pnSubAuthority0 != DOMAIN_ALIAS_RID_ADMINS)
  548. && (*pnSubAuthority1 != DOMAIN_ALIAS_RID_ADMINS)))
  549. {
  550. bLocalAccountInACL = TRUE;
  551. break;
  552. } // if: not the local Administrators group
  553. } // if: exactly 2 sub-authorities
  554. else
  555. {
  556. bLocalAccountInACL = TRUE;
  557. break;
  558. } // else: unexpected # of sub-authorities
  559. } // if: built-in user or group
  560. else if ( (lstrcmpi(szDomainName, pszClusterNameNode) == 0)
  561. && (SidType != SidTypeDomain) )
  562. {
  563. // The domain name is the name of the node on which the
  564. // cluster name resource is online, so this is a local
  565. // user or group.
  566. bLocalAccountInACL = TRUE;
  567. break;
  568. } // else if: domain is cluster name resource node and not a Domain SID
  569. } // if: LookupAccountSid succeeded
  570. else
  571. {
  572. // If LookupAccountSid failed, assume that the SID is for
  573. // a user or group that is local to a machine to which we
  574. // don't have access.
  575. bLocalAccountInACL = TRUE;
  576. break;
  577. } // else: LookupAccountSid failed
  578. }
  579. dwACL_Index++;
  580. }
  581. return bLocalAccountInACL;
  582. } //*** BLocalAccountsInSD()
  583. //+-------------------------------------------------------------------------
  584. //
  585. // Function: SedCallback
  586. //
  587. // Synopsis: Security Editor callback for the Cluster ACL Editor
  588. //
  589. // Arguments: See sedapi.h
  590. //
  591. // History:
  592. // ChuckC 10-Aug-1992 Created
  593. // BruceFo 4-Apr-95 Stole and used in ntshrui.dll
  594. // DavidP 10-Oct-1996 Modified for use with CLUADMIN
  595. // Rodsh 29-Apr-1996 Modified to detect local accounts in the SD
  596. //
  597. //--------------------------------------------------------------------------
  598. DWORD
  599. SedCallback(
  600. HWND hwndParent,
  601. HANDLE hInstance,
  602. ULONG ulCallbackContext,
  603. PSECURITY_DESCRIPTOR pSecDesc,
  604. PSECURITY_DESCRIPTOR pSecDescNewObjects,
  605. BOOLEAN fApplyToSubContainers,
  606. BOOLEAN fApplyToSubObjects,
  607. LPDWORD StatusReturn
  608. )
  609. {
  610. CLUSTER_ACL_CALLBACK_INFO * pCallbackInfo = (CLUSTER_ACL_CALLBACK_INFO *)ulCallbackContext;
  611. Trace(g_tagEditClusterAcl, _T("SedCallback, got pSecDesc = 0x%08lx"), pSecDesc);
  612. ASSERT(pCallbackInfo != NULL);
  613. ASSERT(IsValidSecurityDescriptor(pSecDesc));
  614. if ( BLocalAccountsInSD(pSecDesc, pCallbackInfo->pszClusterNameNode) )
  615. {
  616. CString strMsg;
  617. strMsg.LoadString(IDS_LOCAL_ACCOUNTS_SPECIFIED);
  618. AfxMessageBox(strMsg, MB_OK | MB_ICONSTOP);
  619. return LOCAL_ACCOUNTS_FILTERED;
  620. } // if: local users or groups were specified
  621. if ( BClusterAccessible(pSecDesc) )
  622. {
  623. delete[] (BYTE*)pCallbackInfo->pSecDesc;
  624. pCallbackInfo->pSecDesc = CopySecurityDescriptor(pSecDesc);
  625. pCallbackInfo->bSecDescModified = TRUE;
  626. ASSERT(IsValidSecurityDescriptor(pCallbackInfo->pSecDesc));
  627. Trace(g_tagEditClusterAcl, _T("SedCallback, return pSecDesc = 0x%08lx"), pCallbackInfo->pSecDesc);
  628. return NOERROR;
  629. } // if: at least one Full Control entry is specified
  630. else
  631. {
  632. CString strMsg;
  633. strMsg.LoadString(IDS_NO_ACCESS_GRANTED);
  634. AfxMessageBox(strMsg, MB_OK | MB_ICONSTOP);
  635. return CLUSTER_INACCESSIBLE;
  636. } // else: this change would make cluster inaccessible
  637. } //*** SedCallback()
  638. //+-------------------------------------------------------------------------
  639. //
  640. // Function: InitializeClusterGenericMapping
  641. //
  642. // Synopsis: Initializes the passed generic mapping structure for clusters.
  643. //
  644. // Arguments: [pClusterGenericMapping] - Pointer to GENERIC_MAPPING to init.
  645. //
  646. // History:
  647. // ChuckC 10-Aug-1992 Created. Culled from NTFS ACL code.
  648. // BruceFo 4-Apr-95 Stole and used in ntshrui.dll
  649. // DavidP 10-Oct-1996 Modified for use with CLUADMIN
  650. //
  651. //--------------------------------------------------------------------------
  652. VOID
  653. InitializeClusterGenericMapping(
  654. IN OUT PGENERIC_MAPPING pClusterGenericMapping
  655. )
  656. {
  657. Trace(g_tagEditClusterAcl, _T("InitializeClusterGenericMapping"));
  658. pClusterGenericMapping->GenericRead = GENERIC_READ;
  659. pClusterGenericMapping->GenericWrite = GENERIC_WRITE;
  660. pClusterGenericMapping->GenericExecute = GENERIC_EXECUTE;
  661. pClusterGenericMapping->GenericAll = GENERIC_ALL;
  662. } //*** InitializeClusterGenericMapping()
  663. //-------------------------------------------------------------------------
  664. //
  665. // Function: MakeEmptySecDesc
  666. //
  667. // Synopsis: Create a Security Descriptor with an empty DACL. The object
  668. // associated with this SD will deny access to everyone.
  669. //
  670. // Arguments: [ppSecDesc] - *ppSecDesc points to an empty security descriptor
  671. // on exit. Caller is responsible for freeing it.
  672. //
  673. // Returns: NERR_Success if OK, api error otherwise.
  674. //
  675. // History:
  676. // RodSh 26-Mar-1997 Created.
  677. //
  678. //
  679. //--------------------------------------------------------------------------
  680. DWORD MakeEmptySecDesc( OUT PSECURITY_DESCRIPTOR * ppSecDesc )
  681. {
  682. LONG err = NERR_Success;
  683. PSECURITY_DESCRIPTOR pSecDesc = NULL;
  684. PACL pAcl = NULL;
  685. DWORD cbAcl = 0L;
  686. PSID pSid = NULL;
  687. PSID pEveryoneSid = NULL;
  688. PSID pAdminSid = NULL;
  689. PACCESS_ALLOWED_ACE pAce = NULL;
  690. PULONG pSubAuthority = NULL;
  691. *ppSecDesc = NULL;
  692. SID_IDENTIFIER_AUTHORITY SidIdentifierNtAuth = SECURITY_NT_AUTHORITY;
  693. SID_IDENTIFIER_AUTHORITY SidIdentifierEveryoneAuth = SECURITY_WORLD_SID_AUTHORITY;
  694. do // error breakout
  695. {
  696. //
  697. // Create the admins SID.
  698. //
  699. pAdminSid = LocalAlloc(LMEM_FIXED, GetSidLengthRequired( 2 ));
  700. if (pAdminSid == NULL) {
  701. err = ERROR_NOT_ENOUGH_MEMORY;
  702. break;
  703. }
  704. if (!InitializeSid(pAdminSid, &SidIdentifierNtAuth, 2)) {
  705. err = GetLastError();
  706. break;
  707. }
  708. ASSERT(IsValidSid(pAdminSid));
  709. //
  710. // Set the sub-authorities
  711. //
  712. pSubAuthority = GetSidSubAuthority( pAdminSid, 0 );
  713. *pSubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
  714. pSubAuthority = GetSidSubAuthority( pAdminSid, 1 );
  715. *pSubAuthority = DOMAIN_ALIAS_RID_ADMINS;
  716. //
  717. // Create the SID which will deny everyone access.
  718. //
  719. pEveryoneSid = (PSID)LocalAlloc( LMEM_FIXED, GetSidLengthRequired( 1 ) );
  720. if (pEveryoneSid == NULL) {
  721. err = ERROR_NOT_ENOUGH_MEMORY;
  722. break;
  723. }
  724. if ( !InitializeSid( pEveryoneSid, &SidIdentifierEveryoneAuth, 1 ) ) {
  725. err = GetLastError();
  726. break;
  727. }
  728. ASSERT(IsValidSid(pEveryoneSid));
  729. //
  730. // Set the sub-authorities
  731. //
  732. pSubAuthority = GetSidSubAuthority( pEveryoneSid, 0 );
  733. *pSubAuthority = SECURITY_WORLD_RID;
  734. //
  735. // Set up the DACL that will allow admins with the above SID all access
  736. // It should be large enough to hold all ACEs.
  737. //
  738. cbAcl = sizeof(ACL)
  739. + (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD))
  740. + GetLengthSid(pEveryoneSid)
  741. ;
  742. try
  743. {
  744. pAcl = (PACL) new BYTE[cbAcl];
  745. if ( pAcl == NULL )
  746. {
  747. AfxThrowMemoryException();
  748. } // if: error allocating the ACL buffer
  749. } // try
  750. catch (CMemoryException * pme)
  751. {
  752. err = ERROR_OUTOFMEMORY;
  753. Trace(g_tagEditClusterAcl, _T("new ACL failed"));
  754. pme->Delete();
  755. break;
  756. } // catch: CMemoryException
  757. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION2))
  758. {
  759. err = GetLastError();
  760. Trace(g_tagEditClusterAcl, _T("InitializeAcl failed, 0x%08lx"), err);
  761. break;
  762. }
  763. ASSERT(IsValidAcl(pAcl));
  764. if ( !AddAccessAllowedAce( pAcl,
  765. ACL_REVISION,
  766. CLUSAPI_NO_ACCESS, // Deny everyone full control
  767. pEveryoneSid ))
  768. {
  769. err = GetLastError();
  770. Trace(g_tagEditClusterAcl, _T("AddAccessAllowedAce failed, 0x%08lx"), err);
  771. break;
  772. }
  773. GetAce(pAcl, 0, (PVOID *)&pAce);
  774. pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  775. //
  776. // Create the security descriptor and put the DACL in it.
  777. //
  778. try
  779. {
  780. pSecDesc = (PSECURITY_DESCRIPTOR) new BYTE[SECURITY_DESCRIPTOR_MIN_LENGTH];
  781. if ( pSecDesc == NULL )
  782. {
  783. AfxThrowMemoryException();
  784. } // if: error allocating the security descriptor buffer
  785. } // try
  786. catch (CMemoryException * pme)
  787. {
  788. err = ERROR_OUTOFMEMORY;
  789. Trace(g_tagEditClusterAcl, _T("new SECURITY_DESCRIPTOR failed"));
  790. pme->Delete();
  791. break;
  792. } // catch: CMemoryException
  793. if (!InitializeSecurityDescriptor(
  794. pSecDesc,
  795. SECURITY_DESCRIPTOR_REVISION1))
  796. {
  797. err = GetLastError();
  798. Trace(g_tagEditClusterAcl, _T("InitializeSecurityDescriptor failed, 0x%08lx"), err);
  799. break;
  800. }
  801. if (!SetSecurityDescriptorDacl(
  802. pSecDesc,
  803. TRUE,
  804. pAcl,
  805. FALSE))
  806. {
  807. err = GetLastError();
  808. Trace(g_tagEditClusterAcl, _T("SetSecurityDescriptorDacl failed, 0x%08lx"), err);
  809. break;
  810. }
  811. ASSERT(IsValidSecurityDescriptor(pSecDesc));
  812. //
  813. // Set owner for the descriptor
  814. //
  815. if (!SetSecurityDescriptorOwner(pSecDesc,
  816. pAdminSid,
  817. FALSE)) {
  818. err = GetLastError();
  819. break;
  820. }
  821. //
  822. // Set group for the descriptor
  823. //
  824. if (!SetSecurityDescriptorGroup(pSecDesc,
  825. pAdminSid,
  826. FALSE)) {
  827. err = GetLastError();
  828. break;
  829. }
  830. // Make the security descriptor self-relative
  831. DWORD dwLen = GetSecurityDescriptorLength(pSecDesc);
  832. Trace(g_tagEditClusterAcl, _T("SECURITY_DESCRIPTOR length = %d"), dwLen);
  833. PSECURITY_DESCRIPTOR pSelfSecDesc = NULL;
  834. try
  835. {
  836. pSelfSecDesc = (PSECURITY_DESCRIPTOR) new BYTE[dwLen];
  837. if ( pSelfSecDesc == NULL )
  838. {
  839. AfxThrowMemoryException();
  840. } // if: error allocating the security descriptor buffer
  841. } // try
  842. catch (CMemoryException * pme)
  843. {
  844. err = ERROR_OUTOFMEMORY;
  845. Trace(g_tagEditClusterAcl, _T("new SECURITY_DESCRIPTOR (2) failed"));
  846. pme->Delete();
  847. break;
  848. } // catch: CMemoryException
  849. DWORD cbSelfSecDesc = dwLen;
  850. if (!MakeSelfRelativeSD(pSecDesc, pSelfSecDesc, &cbSelfSecDesc))
  851. {
  852. err = GetLastError();
  853. Trace(g_tagEditClusterAcl, _T("MakeSelfRelativeSD failed, 0x%08lx"), err);
  854. break;
  855. }
  856. ASSERT(IsValidSecurityDescriptor(pSelfSecDesc));
  857. //
  858. // all done: set the security descriptor
  859. //
  860. *ppSecDesc = pSelfSecDesc;
  861. } while (FALSE) ;
  862. if (NULL != pAdminSid)
  863. {
  864. FreeSid(pAdminSid);
  865. }
  866. if (NULL != pEveryoneSid)
  867. {
  868. FreeSid(pEveryoneSid);
  869. }
  870. delete[] (BYTE*)pAcl;
  871. delete[] (BYTE*)pSecDesc;
  872. ASSERT(IsValidSecurityDescriptor(*ppSecDesc));
  873. return err;
  874. }
  875. //+-------------------------------------------------------------------------
  876. //
  877. // Function: DeleteDefaultSecDesc
  878. //
  879. // Synopsis: Delete a security descriptor that was created by
  880. // CreateDefaultSecDesc
  881. //
  882. // Arguments: [pSecDesc] - security descriptor to delete
  883. //
  884. // Returns: nothing
  885. //
  886. // History:
  887. // BruceFo 4-Apr-95 Created
  888. // DavidP 10-Oct-1996 Modified for use with CLUADMIN
  889. //
  890. //--------------------------------------------------------------------------
  891. VOID
  892. DeleteDefaultSecDesc(
  893. IN PSECURITY_DESCRIPTOR pSecDesc
  894. )
  895. {
  896. Trace(g_tagEditClusterAcl, _T("DeleteDefaultSecDesc"));
  897. delete[] (BYTE*)pSecDesc;
  898. } //*** DeleteDefaultSecDesc()
  899. //+-------------------------------------------------------------------------
  900. //
  901. // Member: CopySecurityDescriptor, public
  902. //
  903. // Synopsis: Copy an NT security descriptor. The security descriptor must
  904. // be in self-relative (not absolute) form. Delete the result
  905. // using "delete[] (BYTE*)pSecDesc".
  906. //
  907. // History: 19-Apr-95 BruceFo Created
  908. // 10-Oct-1996 DavidP Modified for use with CLUADMIN
  909. //
  910. //--------------------------------------------------------------------------
  911. PSECURITY_DESCRIPTOR
  912. CopySecurityDescriptor(
  913. IN PSECURITY_DESCRIPTOR pSecDesc
  914. )
  915. {
  916. Trace(g_tagEditClusterAcl, _T("CopySecurityDescriptor, pSecDesc = 0x%08lx"), pSecDesc);
  917. if (NULL == pSecDesc)
  918. {
  919. return NULL;
  920. }
  921. ASSERT(IsValidSecurityDescriptor(pSecDesc));
  922. DWORD dwLen = GetSecurityDescriptorLength(pSecDesc);
  923. PSECURITY_DESCRIPTOR pSelfSecDesc = NULL;
  924. try
  925. {
  926. pSelfSecDesc = (PSECURITY_DESCRIPTOR) new BYTE[dwLen];
  927. if ( pSelfSecDesc == NULL )
  928. {
  929. AfxThrowMemoryException();
  930. } // if: error allocating the security descriptor buffer
  931. }
  932. catch (CMemoryException * pme)
  933. {
  934. Trace(g_tagEditClusterAcl, _T("new SECURITY_DESCRIPTOR (2) failed"));
  935. pme->Delete();
  936. return NULL; // actually, should probably return an error
  937. } // catch: CMemoryException
  938. DWORD cbSelfSecDesc = dwLen;
  939. if (!MakeSelfRelativeSD(pSecDesc, pSelfSecDesc, &cbSelfSecDesc))
  940. {
  941. Trace(g_tagEditClusterAcl, _T("MakeSelfRelativeSD failed, 0x%08lx"), GetLastError());
  942. // assume it failed because it was already self-relative
  943. CopyMemory(pSelfSecDesc, pSecDesc, dwLen);
  944. }
  945. ASSERT(IsValidSecurityDescriptor(pSelfSecDesc));
  946. return pSelfSecDesc;
  947. } //*** CopySecurityDescriptor()
  948. //+---------------------------------------------------------------------------
  949. //
  950. // Function: GetResourceString
  951. //
  952. // Synopsis: Load a resource string, are return a "new"ed copy
  953. //
  954. // Arguments: [dwId] -- a resource string ID
  955. //
  956. // Returns: new memory copy of a string
  957. //
  958. // History: 5-Apr-95 BruceFo Created
  959. // 10-Oct-1996 DavidP Modified for CLUADMIN
  960. //
  961. //----------------------------------------------------------------------------
  962. PWSTR
  963. GetResourceString(
  964. IN DWORD dwId
  965. )
  966. {
  967. CString str;
  968. if (str.LoadString(dwId))
  969. return NewDup(str);
  970. else
  971. return NULL;
  972. } //*** GetResourceString()
  973. //+---------------------------------------------------------------------------
  974. //
  975. // Function: NewDup
  976. //
  977. // Synopsis: Duplicate a string using '::new'
  978. //
  979. // History: 28-Dec-94 BruceFo Created
  980. // 10-Oct-1996 DavidP Modified for CLUADMIN
  981. //
  982. //----------------------------------------------------------------------------
  983. PWSTR
  984. NewDup(
  985. IN const WCHAR* psz
  986. )
  987. {
  988. PWSTR pszRet = NULL;
  989. if (NULL == psz)
  990. {
  991. Trace(g_tagEditClusterAcl, _T("Illegal string to duplicate: NULL"));
  992. return NULL;
  993. }
  994. try
  995. {
  996. pszRet = new WCHAR[wcslen(psz) + 1];
  997. if ( pszRet == NULL )
  998. {
  999. AfxThrowMemoryException();
  1000. } // if: error allocating memory
  1001. }
  1002. catch (CMemoryException * pme)
  1003. {
  1004. Trace(g_tagEditClusterAcl, _T("OUT OF MEMORY"));
  1005. pme->Delete();
  1006. return NULL;
  1007. } // catch: CMemoryException
  1008. wcscpy(pszRet, psz);
  1009. return pszRet;
  1010. } //*** NewDup()
  1011. //+-------------------------------------------------------------------------
  1012. //
  1013. // Function: MapBitsInSD
  1014. //
  1015. // Synopsis: Maps Specific bits to Generic bit when MAP_DIRECTION is SPECIFIC_TO_GENERIC
  1016. // Maps Generic bits to Specific bit when MAP_DIRECTION is GENERIC_TO_SPECIFIC
  1017. //
  1018. // Arguments: [pSecDesc] - SECURITY_DESCIRPTOR to be modified
  1019. // [direction] - indicates whether bits are mapped from specific to generic
  1020. // or generic to specific.
  1021. // Author:
  1022. // Roderick Sharper (rodsh) April 12, 1997
  1023. //
  1024. // History:
  1025. //
  1026. //--------------------------------------------------------------------------
  1027. BOOL MapBitsInSD(PSECURITY_DESCRIPTOR pSecDesc, MAP_DIRECTION direction)
  1028. {
  1029. PACL paclDACL = NULL;
  1030. BOOL bHasDACL = FALSE;
  1031. BOOL bDaclDefaulted = FALSE;
  1032. BOOL bRtn = FALSE;
  1033. if (!IsValidSecurityDescriptor(pSecDesc))
  1034. return FALSE;
  1035. if (!GetSecurityDescriptorDacl(pSecDesc,
  1036. (LPBOOL)&bHasDACL,
  1037. (PACL *)&paclDACL,
  1038. (LPBOOL)&bDaclDefaulted))
  1039. return FALSE;
  1040. if (paclDACL)
  1041. bRtn = MapBitsInACL(paclDACL, direction);
  1042. return bRtn;
  1043. }
  1044. //+-------------------------------------------------------------------------
  1045. //
  1046. // Function: MapBitsInACL
  1047. //
  1048. // Synopsis: Maps Specific bits to Generic bit when MAP_DIRECTION is SPECIFIC_TO_GENERIC
  1049. // Maps Generic bits to Specific bit when MAP_DIRECTION is GENERIC_TO_SPECIFIC
  1050. //
  1051. //
  1052. // Arguments: [paclACL] - ACL (Access Control List) to be modified
  1053. // [direction] - indicates whether bits are mapped from specific to generic
  1054. // or generic to specific.
  1055. // Author:
  1056. // Roderick Sharper (rodsh) April 12, 1997
  1057. //
  1058. // History:
  1059. //
  1060. //--------------------------------------------------------------------------
  1061. BOOL MapBitsInACL(PACL paclACL, MAP_DIRECTION direction)
  1062. {
  1063. ACL_SIZE_INFORMATION asiAclSize;
  1064. BOOL bRtn = FALSE;
  1065. DWORD dwBufLength;
  1066. DWORD dwACL_Index;
  1067. ACCESS_ALLOWED_ACE *paaAllowedAce;
  1068. if (!IsValidAcl(paclACL))
  1069. return FALSE;
  1070. dwBufLength = sizeof(asiAclSize);
  1071. if (!GetAclInformation(paclACL,
  1072. (LPVOID)&asiAclSize,
  1073. (DWORD)dwBufLength,
  1074. (ACL_INFORMATION_CLASS)AclSizeInformation))
  1075. return FALSE;
  1076. for (dwACL_Index = 0; dwACL_Index < asiAclSize.AceCount; dwACL_Index++)
  1077. {
  1078. if (!GetAce(paclACL,
  1079. dwACL_Index,
  1080. (LPVOID *)&paaAllowedAce))
  1081. return FALSE;
  1082. if( direction == SPECIFIC_TO_GENERIC )
  1083. bRtn = MapSpecificBitsInAce( paaAllowedAce );
  1084. else if( direction == GENERIC_TO_SPECIFIC )
  1085. bRtn = MapGenericBitsInAce( paaAllowedAce );
  1086. else
  1087. bRtn = FALSE;
  1088. }
  1089. return bRtn;
  1090. }
  1091. //+-------------------------------------------------------------------------
  1092. //
  1093. // Function: MapSpecificBitsInAce
  1094. //
  1095. // Synopsis: Maps specific bits in ACE to generic bits
  1096. //
  1097. // Arguments: [paaAllowedAce] - ACE (Access Control Entry) to be modified
  1098. // [direction] - indicates whether bits are mapped from specific to generic
  1099. // or generic to specific.
  1100. // Author:
  1101. // Roderick Sharper (rodsh) April 12, 1997
  1102. //
  1103. // History:
  1104. //
  1105. //--------------------------------------------------------------------------
  1106. BOOL MapSpecificBitsInAce(PACCESS_ALLOWED_ACE paaAllowedAce)
  1107. {
  1108. ACCESS_MASK amMask = paaAllowedAce->Mask;
  1109. BOOL bRtn = FALSE;
  1110. DWORD dwGenericBits;
  1111. DWORD dwSpecificBits;
  1112. dwSpecificBits = (amMask & SPECIFIC_RIGHTS_ALL);
  1113. dwGenericBits = 0;
  1114. switch( dwSpecificBits )
  1115. {
  1116. case CLUSAPI_READ_ACCESS: dwGenericBits = GENERIC_READ; // GENERIC_READ == 0x80000000L
  1117. bRtn = TRUE;
  1118. break;
  1119. case CLUSAPI_CHANGE_ACCESS: dwGenericBits = GENERIC_WRITE; // GENERIC_WRITE == 0x40000000L
  1120. bRtn = TRUE;
  1121. break;
  1122. case CLUSAPI_NO_ACCESS: dwGenericBits = GENERIC_EXECUTE;// GENERIC_EXECUTE == 0x20000000L
  1123. bRtn = TRUE;
  1124. break;
  1125. case CLUSAPI_ALL_ACCESS: dwGenericBits = GENERIC_ALL; // GENERIC_ALL == 0x10000000L
  1126. bRtn = TRUE;
  1127. break;
  1128. default: dwGenericBits = 0x00000000L; // Invalid,assign no rights.
  1129. bRtn = FALSE;
  1130. break;
  1131. }
  1132. amMask = dwGenericBits;
  1133. paaAllowedAce->Mask = amMask;
  1134. return bRtn;
  1135. }
  1136. //+-------------------------------------------------------------------------
  1137. //
  1138. // Function: MapGenericBitsInAce
  1139. //
  1140. // Synopsis: Maps generic bits in ACE to specific bits
  1141. //
  1142. // Arguments: [paaAllowedAce] - ACE (Access Control Entry) to be modified
  1143. // [direction] - indicates whether bits are mapped from specific to generic
  1144. // or generic to specific.
  1145. // Author:
  1146. // Roderick Sharper (rodsh) April 12, 1997
  1147. //
  1148. // History:
  1149. //
  1150. //--------------------------------------------------------------------------
  1151. BOOL MapGenericBitsInAce (PACCESS_ALLOWED_ACE paaAllowedAce)
  1152. {
  1153. #define GENERIC_RIGHTS_ALL_THE_BITS 0xF0000000L
  1154. ACCESS_MASK amMask = paaAllowedAce->Mask;
  1155. BOOL bRtn = FALSE;
  1156. DWORD dwGenericBits;
  1157. DWORD dwSpecificBits;
  1158. dwSpecificBits = 0;
  1159. dwGenericBits = (amMask & GENERIC_RIGHTS_ALL_THE_BITS);
  1160. switch( dwGenericBits )
  1161. {
  1162. case GENERIC_ALL: dwSpecificBits = CLUSAPI_ALL_ACCESS; // CLUSAPI_ALL_ACCESS == 3
  1163. bRtn = TRUE;
  1164. break;
  1165. case GENERIC_EXECUTE: dwSpecificBits = CLUSAPI_NO_ACCESS; // CLUSAPI_NO_ACCESS == 4
  1166. bRtn = TRUE;
  1167. break;
  1168. case GENERIC_WRITE: dwSpecificBits = CLUSAPI_CHANGE_ACCESS; // CLUSAPI_CHANGE_ACCESS == 2
  1169. bRtn = TRUE;
  1170. break;
  1171. case GENERIC_READ: dwSpecificBits = CLUSAPI_READ_ACCESS; // CLUSAPI_READ_ACCESS == 1
  1172. bRtn = TRUE;
  1173. break;
  1174. default: dwSpecificBits = 0x00000000L; // Invalid, assign no rights.
  1175. bRtn = FALSE;
  1176. break;
  1177. }
  1178. amMask = dwSpecificBits;
  1179. paaAllowedAce->Mask = amMask;
  1180. return bRtn;
  1181. }