Windows2000/private/windows/shell/lmui/shareui.new/acl.cxx

652 lines
19 KiB
C++
Raw Normal View History

2001-01-01 00:00:00 +01:00
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 1995.
// File: acl.cxx
// Contents: Implementation for the Shares Acl Editor in the "Sharing"
// property page. It is just a front end for the Generic
// ACL Editor that is specific to Shares.
// History: 5-Apr-95 BruceFo Stole from net\ui\shellui\share\shareacl.cxx
#include "headers.hxx"
#pragma hdrstop
#include <lmerr.h>
extern "C"
{
#include <sedapi.h>
}
#include "resource.h"
#include "helpids.h"
#include "acl.hxx"
#include "util.hxx"
typedef
DWORD
(*SedDiscretionaryAclEditorType)(
HWND Owner,
HANDLE Instance,
LPWSTR Server,
PSED_OBJECT_TYPE_DESCRIPTOR ObjectType,
PSED_APPLICATION_ACCESSES ApplicationAccesses,
LPWSTR ObjectName,
PSED_FUNC_APPLY_SEC_CALLBACK ApplySecurityCallbackRoutine,
ULONG CallbackContext,
PSECURITY_DESCRIPTOR SecurityDescriptor,
BOOLEAN CouldntReadDacl,
BOOLEAN CantWriteDacl,
LPDWORD SEDStatusReturn,
DWORD Flags
);
// NOTE: the SedDiscretionaryAclEditor string is used in GetProcAddress to
// get the correct entrypoint. Since GetProcAddress is not UNICODE, this string
// must be ANSI.
#define ACLEDIT_DLL_STRING TEXT("acledit.dll")
#define SEDDISCRETIONARYACLEDITOR_STRING ("SedDiscretionaryAclEditor")
// Declare the callback routine based on typedef in sedapi.h.
DWORD
SedCallback(
HWND hwndParent,
HANDLE hInstance,
ULONG ulCallbackContext,
PSECURITY_DESCRIPTOR pSecDesc,
PSECURITY_DESCRIPTOR pSecDescNewObjects,
BOOLEAN fApplyToSubContainers,
BOOLEAN fApplyToSubObjects,
LPDWORD StatusReturn
);
// Structure for callback function's usage. A pointer to this is passed as
// ulCallbackContext. The callback functions sets bSecDescModified to TRUE
// and makes a copy of the security descriptor. The caller of EditShareAcl
// is responsible for deleting the memory in pSecDesc if bSecDescModified is
// TRUE. This flag will be FALSE if the user hit CANCEL in the ACL editor.
struct SHARE_CALLBACK_INFO
{
BOOL bSecDescModified;
PSECURITY_DESCRIPTOR pSecDesc;
};
// Local function prototypes
VOID
InitializeShareGenericMapping(
IN OUT PGENERIC_MAPPING pSHAREGenericMapping
);
LONG
CreateDefaultSecDesc(
OUT PSECURITY_DESCRIPTOR* ppSecDesc
);
VOID
DeleteDefaultSecDesc(
IN PSECURITY_DESCRIPTOR pSecDesc
);
// The following two arrays define the permission names for NT Files. Note
// that each index in one array corresponds to the index in the other array.
// The second array will be modifed to contain a string pointer pointing to
// a loaded string corresponding to the IDS_* in the first array.
DWORD g_dwSharePermNames[] =
{
IDS_ACLEDIT_PERM_GEN_NO_ACCESS,
IDS_ACLEDIT_PERM_GEN_READ,
IDS_ACLEDIT_PERM_GEN_MODIFY,
IDS_ACLEDIT_PERM_GEN_ALL
};
SED_APPLICATION_ACCESS g_SedAppAccessSharePerms[] =
{
{ SED_DESC_TYPE_RESOURCE, FILE_PERM_GEN_NO_ACCESS, 0, NULL },
{ SED_DESC_TYPE_RESOURCE, FILE_PERM_GEN_READ, 0, NULL },
{ SED_DESC_TYPE_RESOURCE, FILE_PERM_GEN_MODIFY, 0, NULL },
{ SED_DESC_TYPE_RESOURCE, FILE_PERM_GEN_ALL, 0, NULL }
};
// Function: EditShareAcl
// Synopsis: Invokes the generic ACL editor, specifically for NT shares
// Arguments: [hwndParent] - Parent window handle
// [pszShareName] - Fully qualified name of resource we will
// edit, basically a share name.
// [pSecDesc] - The initial security descriptor. If NULL, we will
// create a default that is "World all" access.
// [pbSecDescModified] - Set to TRUE if the security descriptor
// was modified (i.e., the user hit "OK"), or FALSE if not
// (i.e., the user hit "Cancel")
// [ppSecDesc] - *ppSecDesc points to a new security descriptor
// if *pbSecDescModified is TRUE. This memory must be freed
// by the caller.
// History:
// ChuckC 10-Aug-1992 Created. Culled from NTFS ACL code.
// Yi-HsinS 09-Oct-1992 Added ulHelpContextBase
// BruceFo 4-Apr-95 Stole and used in ntshrui.dll
LONG
EditShareAcl(
IN HWND hwndParent,
IN LPWSTR pszServerName,
IN TCHAR * pszShareName,
IN PSECURITY_DESCRIPTOR pSecDesc,
OUT BOOL* pbSecDescModified,
OUT PSECURITY_DESCRIPTOR* ppSecDesc
)
{
appAssert(NULL != pszShareName);
appDebugOut((DEB_TRACE, "EditShareAcl, share %ws\n", pszShareName));
appAssert(NULL == pSecDesc || IsValidSecurityDescriptor(pSecDesc));
appAssert(pbSecDescModified);
appAssert(ppSecDesc);
*pbSecDescModified = FALSE;
LONG err ;
PWSTR pszPermName;
BOOL bCreatedDefaultSecDesc = FALSE;
do // error breakout
{
/*
* if pSecDesc is NULL, this is new share or a share with no
* security descriptor.
* we go and create a new (default) security descriptor.
*/
if (NULL == pSecDesc)
{
LONG err = CreateDefaultSecDesc(&pSecDesc);
if (err != NERR_Success)
{
appDebugOut((DEB_ERROR, "CreateDefaultSecDesc failed, 0x%08lx\n", err));
break ;
}
appDebugOut((DEB_TRACE, "CreateDefaultSecDesc descriptor = 0x%08lx\n", pSecDesc));
bCreatedDefaultSecDesc = TRUE;
}
appAssert(IsValidSecurityDescriptor(pSecDesc));
/* Retrieve the resource strings appropriate for the type of object we
* are looking at
*/
WCHAR szTypeName[50];
LoadString(g_hInstance, IDS_ACLEDIT_TITLE, szTypeName, ARRAYLEN(szTypeName));
WCHAR szDefaultPermName[50];
LoadString(g_hInstance, IDS_ACLEDIT_PERM_GEN_READ, szDefaultPermName, ARRAYLEN(szDefaultPermName));
/*
* other misc stuff we need pass to security editor
*/
SED_OBJECT_TYPE_DESCRIPTOR sedObjDesc ;
SED_HELP_INFO sedHelpInfo ;
GENERIC_MAPPING SHAREGenericMapping ;
// setup mappings
InitializeShareGenericMapping( &SHAREGenericMapping ) ;
// setup help: BUGBUG
WCHAR szHelpFile[50];
LoadString(g_hInstance, IDS_HELPFILENAME, szHelpFile, ARRAYLEN(szHelpFile));
sedHelpInfo.pszHelpFileName = szHelpFile;
sedHelpInfo.aulHelpContext[HC_MAIN_DLG] = ACL_HC_MAIN_DLG;
sedHelpInfo.aulHelpContext[HC_ADD_USER_DLG] = ACL_HC_ADD_USER_DLG;
sedHelpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_LG_DLG] = ACL_HC_ADD_USER_MEMBERS_LG_DLG;
sedHelpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_GG_DLG] = ACL_HC_ADD_USER_MEMBERS_GG_DLG;
sedHelpInfo.aulHelpContext[HC_ADD_USER_SEARCH_DLG] = ACL_HC_ADD_USER_SEARCH_DLG;
// These are not used, set to zero
sedHelpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] = 0 ;
sedHelpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] = 0 ;
// setup the object description
sedObjDesc.Revision = SED_REVISION1 ;
sedObjDesc.IsContainer = FALSE ;
sedObjDesc.AllowNewObjectPerms = FALSE ;
sedObjDesc.MapSpecificPermsToGeneric = TRUE ;
sedObjDesc.GenericMapping = &SHAREGenericMapping ;
sedObjDesc.GenericMappingNewObjects = &SHAREGenericMapping ;
sedObjDesc.HelpInfo = &sedHelpInfo ;
sedObjDesc.ObjectTypeName = szTypeName ;
sedObjDesc.SpecialObjectAccessTitle = NULL ;
/* Now we need to load the global arrays with the permission names
* from the resource file.
*/
UINT cArrayItems = ARRAYLEN(g_SedAppAccessSharePerms);
PSED_APPLICATION_ACCESS aSedAppAccess = g_SedAppAccessSharePerms ;
/* Loop through each permission title retrieving the text from the
* resource file and setting the pointer in the array.
*/
for ( UINT i = 0 ; i < cArrayItems ; i++ )
{
pszPermName = GetResourceString(g_dwSharePermNames[i]) ;
if (NULL == pszPermName)
{
appDebugOut((DEB_ERROR, "GetResourceString failed\n"));
break ;
}
aSedAppAccess[i].PermissionTitle = pszPermName;
}
if (i < cArrayItems)
{
appDebugOut((DEB_ERROR, "failed to get all share permission names\n"));
break ;
}
SED_APPLICATION_ACCESSES sedAppAccesses ;
sedAppAccesses.Count = cArrayItems ;
sedAppAccesses.AccessGroup = aSedAppAccess ;
sedAppAccesses.DefaultPermName = szDefaultPermName;
/*
* pass this along so when the call back function is called,
* we can set it.
*/
SHARE_CALLBACK_INFO callbackinfo ;
callbackinfo.pSecDesc = NULL;
callbackinfo.bSecDescModified = FALSE;
// Now, load up the ACL editor and invoke it. We don't keep it around
// because our DLL is loaded whenever the system is, so we don't want
// the netui*.dll's hanging around as well...
HINSTANCE hInstanceAclEditor = NULL;
SedDiscretionaryAclEditorType pSedDiscretionaryAclEditor = NULL;
hInstanceAclEditor = LoadLibrary(ACLEDIT_DLL_STRING);
if (NULL == hInstanceAclEditor)
{
err = GetLastError();
appDebugOut((DEB_ERROR, "LoadLibrary of acledit.dll failed, 0x%08lx\n", err));
break;
}
pSedDiscretionaryAclEditor = (SedDiscretionaryAclEditorType)
GetProcAddress(hInstanceAclEditor,SEDDISCRETIONARYACLEDITOR_STRING);
if ( pSedDiscretionaryAclEditor == NULL )
{
err = GetLastError();
appDebugOut((DEB_ERROR, "GetProcAddress of SedDiscretionaryAclEditor failed, 0x%08lx\n", err));
break;
}
DWORD dwSedReturnStatus ;
appAssert(pSedDiscretionaryAclEditor != NULL);
err = (*pSedDiscretionaryAclEditor)(
hwndParent,
g_hInstance,
pszServerName,
&sedObjDesc,
&sedAppAccesses,
pszShareName,
SedCallback,
(ULONG) &callbackinfo,
pSecDesc,
FALSE, // always can read
FALSE, // If we can read, we can write
&dwSedReturnStatus,
0 ) ;
if (!FreeLibrary(hInstanceAclEditor))
{
LONG err2 = GetLastError();
appDebugOut((DEB_ERROR, "FreeLibrary of acledit.dll failed, 0x%08lx\n", err2));
// not fatal: continue...
}
if (0 != err)
{
appDebugOut((DEB_ERROR, "SedDiscretionaryAclEditor failed, 0x%08lx\n", err));
break ;
}
*pbSecDescModified = callbackinfo.bSecDescModified ;
if (*pbSecDescModified)
{
*ppSecDesc = callbackinfo.pSecDesc;
appDebugOut((DEB_TRACE, "After calling acl editor, *ppSecDesc = 0x%08lx\n", *ppSecDesc));
appAssert(IsValidSecurityDescriptor(*ppSecDesc));
}
} while (FALSE) ;
// Free memory...
UINT cArrayItems = ARRAYLEN(g_SedAppAccessSharePerms);
PSED_APPLICATION_ACCESS aSedAppAccess = g_SedAppAccessSharePerms ;
for ( UINT i = 0 ; i < cArrayItems ; i++ )
{
pszPermName = aSedAppAccess[i].PermissionTitle;
if (NULL == pszPermName)
{
// if we hit a NULL, that's it!
break ;
}
delete[] pszPermName;
}
if (bCreatedDefaultSecDesc)
{
DeleteDefaultSecDesc(pSecDesc);
}
appAssert(!*pbSecDescModified || IsValidSecurityDescriptor(*ppSecDesc));
if (0 != err)
{
MyErrorDialog(hwndParent, IERR_NOACLEDITOR);
}
return err;
}
// Function: SedCallback
// Synopsis: Security Editor callback for the SHARE ACL Editor
// Arguments: See sedapi.h
// History:
// ChuckC 10-Aug-1992 Created
// BruceFo 4-Apr-95 Stole and used in ntshrui.dll
DWORD
SedCallback(
HWND hwndParent,
HANDLE hInstance,
ULONG ulCallbackContext,
PSECURITY_DESCRIPTOR pSecDesc,
PSECURITY_DESCRIPTOR pSecDescNewObjects,
BOOLEAN fApplyToSubContainers,
BOOLEAN fApplyToSubObjects,
LPDWORD StatusReturn
)
{
appDebugOut((DEB_TRACE, "SedCallback, got pSecDesc = 0x%08lx\n", pSecDesc));
appAssert(IsValidSecurityDescriptor(pSecDesc));
SHARE_CALLBACK_INFO* pCallbackInfo = (SHARE_CALLBACK_INFO *)ulCallbackContext;
appAssert(NULL != pCallbackInfo);
delete[] (BYTE*)pCallbackInfo->pSecDesc;
pCallbackInfo->pSecDesc = CopySecurityDescriptor(pSecDesc);
pCallbackInfo->bSecDescModified = TRUE;
appAssert(IsValidSecurityDescriptor(pCallbackInfo->pSecDesc));
appDebugOut((DEB_TRACE, "SedCallback, return pSecDesc = 0x%08lx\n", pCallbackInfo->pSecDesc));
return NOERROR;
}
// Function: InitializeShareGenericMapping
// Synopsis: Initializes the passed generic mapping structure for shares.
// Arguments: [pSHAREGenericMapping] - Pointer to GENERIC_MAPPING to be init.
// History:
// ChuckC 10-Aug-1992 Created. Culled from NTFS ACL code.
// BruceFo 4-Apr-95 Stole and used in ntshrui.dll
VOID
InitializeShareGenericMapping(
IN OUT PGENERIC_MAPPING pSHAREGenericMapping
)
{
appDebugOut((DEB_ITRACE, "InitializeShareGenericMapping\n"));
pSHAREGenericMapping->GenericRead = FILE_GENERIC_READ ;
pSHAREGenericMapping->GenericWrite = FILE_GENERIC_WRITE ;
pSHAREGenericMapping->GenericExecute = FILE_GENERIC_EXECUTE ;
pSHAREGenericMapping->GenericAll = FILE_ALL_ACCESS ;
}
// Function: CreateDefaultSecDesc
// Synopsis: Create a default ACL for either a new share or for
// a share that dont exist.
// Arguments: [ppSecDesc] - *ppSecDesc points to a "world all" access
// security descriptor on exit. Caller is responsible for
// freeing it.
// Returns: NERR_Success if OK, api error otherwise.
// History:
// ChuckC 10-Aug-1992 Created. Culled from NTFS ACL code.
// BruceFo 4-Apr-95 Stole and used in ntshrui.dll
LONG
CreateDefaultSecDesc(
OUT PSECURITY_DESCRIPTOR* ppSecDesc
)
{
appDebugOut((DEB_ITRACE, "CreateDefaultSecDesc\n"));
appAssert(NULL != ppSecDesc) ;
appAssert(NULL == *ppSecDesc) ;
LONG err = NERR_Success;
PSECURITY_DESCRIPTOR pSecDesc = NULL;
PACL pAcl = NULL;
DWORD cbAcl;
PSID pSid = NULL;
*ppSecDesc = NULL;
do // error breakout
{
// First, create a world SID. Next, create an access allowed
// ACE with "Generic All" access with the world SID. Put the ACE in
// the ACL and the ACL in the security descriptor.
SID_IDENTIFIER_AUTHORITY IDAuthorityWorld = SECURITY_WORLD_SID_AUTHORITY;
if (!AllocateAndInitializeSid(
&IDAuthorityWorld,
1,
SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0,
&pSid))
{
err = GetLastError();
appDebugOut((DEB_ERROR, "AllocateAndInitializeSid failed, 0x%08lx\n", err));
break;
}
appAssert(IsValidSid(pSid));
cbAcl = sizeof(ACL)
+ (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD))
+ GetLengthSid(pSid)
;
pAcl = (PACL) new BYTE[cbAcl];
if (NULL == pAcl)
{
err = ERROR_OUTOFMEMORY;
appDebugOut((DEB_ERROR, "new ACL failed\n"));
break;
}
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION2))
{
err = GetLastError();
appDebugOut((DEB_ERROR, "InitializeAcl failed, 0x%08lx\n", err));
break;
}
if (!AddAccessAllowedAce(
pAcl,
ACL_REVISION2,
GENERIC_ALL,
pSid))
{
err = GetLastError();
appDebugOut((DEB_ERROR, "AddAccessAllowedAce failed, 0x%08lx\n", err));
break;
}
appAssert(IsValidAcl(pAcl));
pSecDesc = (PSECURITY_DESCRIPTOR) new BYTE[SECURITY_DESCRIPTOR_MIN_LENGTH];
if (NULL == pSecDesc)
{
err = ERROR_OUTOFMEMORY;
appDebugOut((DEB_ERROR, "new SECURITY_DESCRIPTOR failed\n"));
break;
}
if (!InitializeSecurityDescriptor(
pSecDesc,
SECURITY_DESCRIPTOR_REVISION1))
{
err = GetLastError();
appDebugOut((DEB_ERROR, "InitializeSecurityDescriptor failed, 0x%08lx\n", err));
break;
}
if (!SetSecurityDescriptorDacl(
pSecDesc,
TRUE,
pAcl,
FALSE))
{
err = GetLastError();
appDebugOut((DEB_ERROR, "SetSecurityDescriptorDacl failed, 0x%08lx\n", err));
break;
}
appAssert(IsValidSecurityDescriptor(pSecDesc));
// Make the security descriptor self-relative
DWORD dwLen = GetSecurityDescriptorLength(pSecDesc);
appDebugOut((DEB_ITRACE, "SECURITY_DESCRIPTOR length = %d\n", dwLen));
PSECURITY_DESCRIPTOR pSelfSecDesc = (PSECURITY_DESCRIPTOR) new BYTE[dwLen];
if (NULL == pSelfSecDesc)
{
err = ERROR_OUTOFMEMORY;
appDebugOut((DEB_ERROR, "new SECURITY_DESCRIPTOR (2) failed\n"));
break;
}
DWORD cbSelfSecDesc = dwLen;
if (!MakeSelfRelativeSD(pSecDesc, pSelfSecDesc, &cbSelfSecDesc))
{
err = GetLastError();
appDebugOut((DEB_ERROR, "MakeSelfRelativeSD failed, 0x%08lx\n", err));
break;
}
appAssert(IsValidSecurityDescriptor(pSelfSecDesc));
// all done: set the security descriptor
*ppSecDesc = pSelfSecDesc;
} while (FALSE) ;
if (NULL != pSid)
{
FreeSid(pSid);
}
delete[] (BYTE*)pAcl;
delete[] (BYTE*)pSecDesc;
appAssert(IsValidSecurityDescriptor(*ppSecDesc));
return err;
}
// Function: DeleteDefaultSecDesc
// Synopsis: Delete a security descriptor that was created by
// CreateDefaultSecDesc
// Arguments: [pSecDesc] - security descriptor to delete
// Returns: nothing
// History:
// BruceFo 4-Apr-95 Created
VOID
DeleteDefaultSecDesc(
IN PSECURITY_DESCRIPTOR pSecDesc
)
{
appDebugOut((DEB_ITRACE, "DeleteDefaultSecDesc\n"));
delete[] (BYTE*)pSecDesc;
}