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.
1389 lines
40 KiB
1389 lines
40 KiB
/****************************************************************************
|
|
|
|
PROGRAM: ACLEDIT.C
|
|
|
|
PURPOSE: Contains routines that edit security on Nt objects
|
|
|
|
****************************************************************************/
|
|
|
|
#include "pviewp.h"
|
|
#include <sedapi.h>
|
|
|
|
|
|
//
|
|
// Define the type of a pointer to the DACL editor fn
|
|
//
|
|
|
|
typedef DWORD (*LPFNDACLEDITOR) ( HWND,
|
|
HANDLE,
|
|
LPWSTR,
|
|
PSED_OBJECT_TYPE_DESCRIPTOR,
|
|
PSED_APPLICATION_ACCESSES,
|
|
LPWSTR,
|
|
PSED_FUNC_APPLY_SEC_CALLBACK,
|
|
ULONG_PTR,
|
|
PSECURITY_DESCRIPTOR,
|
|
BOOLEAN,
|
|
BOOLEAN, // CantWriteDacl
|
|
LPDWORD,
|
|
DWORD );
|
|
|
|
|
|
//
|
|
// Declare globals used to reference dynamically loaded ACLEditor module
|
|
//
|
|
|
|
HMODULE hModAclEditor = NULL;
|
|
LPFNDACLEDITOR lpfnDaclEditor = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Define security information for each type of object
|
|
//
|
|
|
|
|
|
|
|
//
|
|
// Define the maximum number of accesses per object type
|
|
//
|
|
|
|
#define MAX_ACCESSES 30
|
|
|
|
|
|
//
|
|
// Define structure to contain the security information for
|
|
// an object type
|
|
//
|
|
|
|
typedef struct _OBJECT_TYPE_SECURITY_INFO {
|
|
LPWSTR TypeName;
|
|
SED_HELP_INFO HelpInfo ;
|
|
SED_OBJECT_TYPE_DESCRIPTOR SedObjectTypeDescriptor;
|
|
GENERIC_MAPPING GenericMapping;
|
|
SED_APPLICATION_ACCESSES AppAccesses ;
|
|
SED_APPLICATION_ACCESS AppAccess[MAX_ACCESSES];
|
|
|
|
} OBJECT_TYPE_SECURITY_INFO, *POBJECT_TYPE_SECURITY_INFO;
|
|
|
|
|
|
//
|
|
// Define name of help file
|
|
//
|
|
|
|
#define HELP_FILENAME L"pview.hlp"
|
|
|
|
|
|
|
|
//
|
|
// Define dummy access (used as filler)
|
|
//
|
|
|
|
#define DUMMY_ACCESS \
|
|
{ \
|
|
0, \
|
|
0, \
|
|
0, \
|
|
NULL \
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Define generic accesses
|
|
//
|
|
|
|
#define GENERIC_ACCESSES_5(Type) \
|
|
{ \
|
|
Type, \
|
|
GENERIC_ALL, \
|
|
0, \
|
|
L"All Access" \
|
|
}, \
|
|
{ \
|
|
Type, \
|
|
GENERIC_READ, \
|
|
0, \
|
|
L"Read" \
|
|
}, \
|
|
{ \
|
|
Type, \
|
|
GENERIC_WRITE, \
|
|
0, \
|
|
L"Write" \
|
|
}, \
|
|
{ \
|
|
Type, \
|
|
GENERIC_EXECUTE, \
|
|
0, \
|
|
L"Execute" \
|
|
}, \
|
|
{ \
|
|
Type, \
|
|
0, \
|
|
0, \
|
|
L"None" \
|
|
}
|
|
|
|
|
|
//
|
|
// Define generic accesses to be shown in special access dialog
|
|
//
|
|
|
|
#define SPECIAL_GENERIC_ACCESSES_4(Type) \
|
|
{ \
|
|
Type, \
|
|
GENERIC_ALL, \
|
|
0, \
|
|
L"Generic All" \
|
|
}, \
|
|
{ \
|
|
Type, \
|
|
GENERIC_READ, \
|
|
0, \
|
|
L"Generic Read" \
|
|
}, \
|
|
{ \
|
|
Type, \
|
|
GENERIC_WRITE, \
|
|
0, \
|
|
L"Generic Write" \
|
|
}, \
|
|
{ \
|
|
Type, \
|
|
GENERIC_EXECUTE, \
|
|
0, \
|
|
L"Generic Execute" \
|
|
}
|
|
|
|
|
|
//
|
|
// Define standard accesses
|
|
//
|
|
|
|
#define STANDARD_ACCESSES_5(Type) \
|
|
{ \
|
|
Type, \
|
|
DELETE, \
|
|
0, \
|
|
L"Delete" \
|
|
}, \
|
|
{ \
|
|
Type, \
|
|
READ_CONTROL, \
|
|
0, \
|
|
L"Read Control" \
|
|
}, \
|
|
{ \
|
|
Type, \
|
|
WRITE_DAC, \
|
|
0, \
|
|
L"Write DAC" \
|
|
}, \
|
|
{ \
|
|
Type, \
|
|
WRITE_OWNER, \
|
|
0, \
|
|
L"Write Owner" \
|
|
}, \
|
|
{ \
|
|
Type, \
|
|
SYNCHRONIZE, \
|
|
0, \
|
|
L"Synchronize" \
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// Define security info for 'DEFAULT' ACLs found in tokens
|
|
//
|
|
|
|
OBJECT_TYPE_SECURITY_INFO DefaultSecurityInfo = {
|
|
|
|
//
|
|
// Type name
|
|
//
|
|
|
|
L"DEFAULT",
|
|
|
|
//
|
|
// Help info
|
|
//
|
|
|
|
{
|
|
HELP_FILENAME,
|
|
{0, 0, 0, 0, 0, 0, 0}
|
|
},
|
|
|
|
|
|
|
|
//
|
|
// Acleditor object type descriptor
|
|
//
|
|
|
|
{
|
|
SED_REVISION1, // Revision
|
|
FALSE, // Is container
|
|
FALSE, // AllowNewObjectPermissions
|
|
FALSE, // MapSpecificPermsToGeneric
|
|
NULL, // Pointer to generic mapping
|
|
NULL, // Pointer to generic mapping for new objects
|
|
L"Default", // Object type name
|
|
NULL, // Pointer to help info
|
|
NULL, // ApplyToSubContainerTitle
|
|
NULL, // ApplyToObjectsTitle
|
|
NULL, // ApplyToSubContainerConfirmation
|
|
L"Special...", // SpecialObjectAccessTitle
|
|
NULL // SpecialNewObjectAccessTitle
|
|
},
|
|
|
|
|
|
|
|
//
|
|
// Generic mapping
|
|
//
|
|
|
|
{
|
|
STANDARD_RIGHTS_READ,
|
|
STANDARD_RIGHTS_WRITE,
|
|
STANDARD_RIGHTS_EXECUTE,
|
|
STANDARD_RIGHTS_ALL
|
|
},
|
|
|
|
|
|
//
|
|
// Application access structure
|
|
//
|
|
|
|
{
|
|
14, // Access count (must match list below)
|
|
NULL, // Pointer to accesses
|
|
L"Read", // Default new access
|
|
},
|
|
|
|
|
|
//
|
|
// Application accesses
|
|
//
|
|
|
|
{
|
|
GENERIC_ACCESSES_5(SED_DESC_TYPE_RESOURCE),
|
|
STANDARD_ACCESSES_5(SED_DESC_TYPE_RESOURCE_SPECIAL),
|
|
SPECIAL_GENERIC_ACCESSES_4(SED_DESC_TYPE_RESOURCE_SPECIAL),
|
|
|
|
DUMMY_ACCESS, // 15
|
|
DUMMY_ACCESS, // 16
|
|
DUMMY_ACCESS, // 17
|
|
DUMMY_ACCESS, // 18
|
|
DUMMY_ACCESS, // 19
|
|
DUMMY_ACCESS, // 20
|
|
DUMMY_ACCESS, // 21
|
|
DUMMY_ACCESS, // 22
|
|
DUMMY_ACCESS, // 23
|
|
DUMMY_ACCESS, // 24
|
|
DUMMY_ACCESS, // 25
|
|
DUMMY_ACCESS, // 26
|
|
DUMMY_ACCESS, // 27
|
|
DUMMY_ACCESS, // 28
|
|
DUMMY_ACCESS, // 29
|
|
DUMMY_ACCESS // 30
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Define security info for each type of object
|
|
//
|
|
|
|
OBJECT_TYPE_SECURITY_INFO ObjectTypeSecurityInfo[] = {
|
|
|
|
//
|
|
// PROCESS
|
|
//
|
|
|
|
{
|
|
//
|
|
// Type name
|
|
//
|
|
|
|
L"Process",
|
|
|
|
//
|
|
// Help info
|
|
//
|
|
|
|
{
|
|
HELP_FILENAME,
|
|
{0, 0, 0, 0, 0, 0, 0}
|
|
},
|
|
|
|
|
|
|
|
//
|
|
// Acleditor object type descriptor
|
|
//
|
|
|
|
{
|
|
SED_REVISION1, // Revision
|
|
FALSE, // Is container
|
|
FALSE, // AllowNewObjectPermissions
|
|
FALSE, // MapSpecificPermsToGeneric
|
|
NULL, // Pointer to generic mapping
|
|
NULL, // Pointer to generic mapping for new objects
|
|
L"Process", // Object type name
|
|
NULL, // Pointer to help info
|
|
NULL, // ApplyToSubContainerTitle
|
|
NULL, // ApplyToObjectsTitle
|
|
NULL, // ApplyToSubContainerConfirmation
|
|
L"Special...", // SpecialObjectAccessTitle
|
|
NULL // SpecialNewObjectAccessTitle
|
|
},
|
|
|
|
|
|
|
|
//
|
|
// Generic mapping
|
|
//
|
|
|
|
{
|
|
PROCESS_QUERY_INFORMATION | STANDARD_RIGHTS_READ,
|
|
PROCESS_SET_INFORMATION | STANDARD_RIGHTS_WRITE,
|
|
STANDARD_RIGHTS_EXECUTE,
|
|
PROCESS_ALL_ACCESS
|
|
},
|
|
|
|
|
|
//
|
|
// Application access structure
|
|
//
|
|
|
|
{
|
|
21, // Access count (must match list below)
|
|
NULL, // Pointer to accesses
|
|
L"Read", // Default new access
|
|
},
|
|
|
|
|
|
//
|
|
// Application accesses
|
|
//
|
|
|
|
{
|
|
GENERIC_ACCESSES_5(SED_DESC_TYPE_RESOURCE),
|
|
STANDARD_ACCESSES_5(SED_DESC_TYPE_RESOURCE_SPECIAL),
|
|
|
|
{ // 11
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
PROCESS_TERMINATE,
|
|
0,
|
|
L"Terminate"
|
|
},
|
|
{ // 12
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
PROCESS_CREATE_THREAD,
|
|
0,
|
|
L"Create thread"
|
|
},
|
|
{ // 13
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
PROCESS_VM_OPERATION,
|
|
0,
|
|
L"VM Operation"
|
|
},
|
|
{ // 14
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
PROCESS_VM_READ,
|
|
0,
|
|
L"VM Read"
|
|
},
|
|
{ // 15
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
PROCESS_VM_WRITE,
|
|
0,
|
|
L"VM Write"
|
|
},
|
|
{ // 16
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
PROCESS_DUP_HANDLE,
|
|
0,
|
|
L"Duplicate handle"
|
|
},
|
|
{ // 17
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
PROCESS_CREATE_PROCESS,
|
|
0,
|
|
L"Create process",
|
|
},
|
|
{ // 18
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
PROCESS_SET_QUOTA,
|
|
0,
|
|
L"Set quota"
|
|
},
|
|
{ // 19
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
PROCESS_SET_INFORMATION,
|
|
0,
|
|
L"Set information"
|
|
},
|
|
{ // 20
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
PROCESS_QUERY_INFORMATION,
|
|
0,
|
|
L"Query information"
|
|
},
|
|
{ // 21
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
PROCESS_SET_PORT,
|
|
0,
|
|
L"Set port"
|
|
},
|
|
|
|
DUMMY_ACCESS, // 22
|
|
DUMMY_ACCESS, // 23
|
|
DUMMY_ACCESS, // 24
|
|
DUMMY_ACCESS, // 25
|
|
DUMMY_ACCESS, // 26
|
|
DUMMY_ACCESS, // 27
|
|
DUMMY_ACCESS, // 28
|
|
DUMMY_ACCESS, // 29
|
|
DUMMY_ACCESS // 30
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// THREAD
|
|
//
|
|
|
|
{
|
|
//
|
|
// Type name
|
|
//
|
|
|
|
L"Thread",
|
|
|
|
//
|
|
// Help info
|
|
//
|
|
|
|
{
|
|
HELP_FILENAME,
|
|
{0, 0, 0, 0, 0, 0, 0}
|
|
},
|
|
|
|
|
|
|
|
//
|
|
// Acleditor object type descriptor
|
|
//
|
|
|
|
{
|
|
SED_REVISION1, // Revision
|
|
FALSE, // Is container
|
|
FALSE, // AllowNewObjectPermissions
|
|
FALSE, // MapSpecificPermsToGeneric
|
|
NULL, // Pointer to generic mapping
|
|
NULL, // Pointer to generic mapping for new objects
|
|
L"Thread", // Object type name
|
|
NULL, // Pointer to help info
|
|
NULL, // ApplyToSubContainerTitle
|
|
NULL, // ApplyToObjectsTitle
|
|
NULL, // ApplyToSubContainerConfirmation
|
|
L"Special...", // SpecialObjectAccessTitle
|
|
NULL // SpecialNewObjectAccessTitle
|
|
},
|
|
|
|
|
|
|
|
//
|
|
// Generic mapping
|
|
//
|
|
|
|
{
|
|
THREAD_QUERY_INFORMATION | STANDARD_RIGHTS_READ,
|
|
THREAD_SET_INFORMATION | STANDARD_RIGHTS_WRITE,
|
|
STANDARD_RIGHTS_EXECUTE,
|
|
THREAD_ALL_ACCESS
|
|
},
|
|
|
|
|
|
//
|
|
// Application access structure
|
|
//
|
|
|
|
{
|
|
20, // Access count (must match list below)
|
|
NULL, // Pointer to accesses
|
|
L"Read", // Default new access
|
|
},
|
|
|
|
|
|
//
|
|
// Application accesses
|
|
//
|
|
|
|
{
|
|
GENERIC_ACCESSES_5(SED_DESC_TYPE_RESOURCE),
|
|
STANDARD_ACCESSES_5(SED_DESC_TYPE_RESOURCE_SPECIAL),
|
|
|
|
{ // 11
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
THREAD_TERMINATE,
|
|
0,
|
|
L"Terminate"
|
|
},
|
|
{ // 12
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
THREAD_SUSPEND_RESUME,
|
|
0,
|
|
L"Suspend/Resume"
|
|
},
|
|
{ // 13
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
THREAD_ALERT,
|
|
0,
|
|
L"Alert"
|
|
},
|
|
{ // 14
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
THREAD_GET_CONTEXT,
|
|
0,
|
|
L"Get context"
|
|
},
|
|
{ // 15
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
THREAD_SET_CONTEXT,
|
|
0,
|
|
L"Set context"
|
|
},
|
|
{ // 16
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
THREAD_SET_INFORMATION,
|
|
0,
|
|
L"Set information"
|
|
},
|
|
{ // 17
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
THREAD_QUERY_INFORMATION,
|
|
0,
|
|
L"Query information"
|
|
},
|
|
{ // 18
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
THREAD_SET_THREAD_TOKEN,
|
|
0,
|
|
L"Set token"
|
|
},
|
|
{ // 19
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
THREAD_IMPERSONATE,
|
|
0,
|
|
L"Impersonate"
|
|
},
|
|
{ // 20
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
THREAD_DIRECT_IMPERSONATION,
|
|
0,
|
|
L"Direct impersonation"
|
|
},
|
|
|
|
DUMMY_ACCESS, // 21
|
|
DUMMY_ACCESS, // 22
|
|
DUMMY_ACCESS, // 23
|
|
DUMMY_ACCESS, // 24
|
|
DUMMY_ACCESS, // 25
|
|
DUMMY_ACCESS, // 26
|
|
DUMMY_ACCESS, // 27
|
|
DUMMY_ACCESS, // 28
|
|
DUMMY_ACCESS, // 29
|
|
DUMMY_ACCESS // 30
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// TOKEN
|
|
//
|
|
|
|
{
|
|
//
|
|
// Type name
|
|
//
|
|
|
|
L"Token",
|
|
|
|
//
|
|
// Help info
|
|
//
|
|
|
|
{
|
|
HELP_FILENAME,
|
|
{0, 0, 0, 0, 0, 0, 0}
|
|
},
|
|
|
|
|
|
|
|
//
|
|
// Acleditor object type descriptor
|
|
//
|
|
|
|
{
|
|
SED_REVISION1, // Revision
|
|
FALSE, // Is container
|
|
FALSE, // AllowNewObjectPermissions
|
|
FALSE, // MapSpecificPermsToGeneric
|
|
NULL, // Pointer to generic mapping
|
|
NULL, // Pointer to generic mapping for new objects
|
|
L"Token", // Object type name
|
|
NULL, // Pointer to help info
|
|
NULL, // ApplyToSubContainerTitle
|
|
NULL, // ApplyToObjectsTitle
|
|
NULL, // ApplyToSubContainerConfirmation
|
|
L"Special...", // SpecialObjectAccessTitle
|
|
NULL // SpecialNewObjectAccessTitle
|
|
},
|
|
|
|
|
|
|
|
//
|
|
// Generic mapping
|
|
//
|
|
|
|
{
|
|
TOKEN_READ,
|
|
TOKEN_WRITE,
|
|
TOKEN_EXECUTE,
|
|
TOKEN_ALL_ACCESS
|
|
},
|
|
|
|
|
|
//
|
|
// Application access structure
|
|
//
|
|
|
|
{
|
|
18, // Access count (must match list below)
|
|
NULL, // Pointer to accesses
|
|
L"Read", // Default new access
|
|
},
|
|
|
|
|
|
//
|
|
// Application accesses
|
|
//
|
|
|
|
{
|
|
GENERIC_ACCESSES_5(SED_DESC_TYPE_RESOURCE),
|
|
STANDARD_ACCESSES_5(SED_DESC_TYPE_RESOURCE_SPECIAL),
|
|
|
|
{ // 11
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
TOKEN_ASSIGN_PRIMARY,
|
|
0,
|
|
L"Assign primary"
|
|
},
|
|
{ // 12
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
TOKEN_DUPLICATE,
|
|
0,
|
|
L"Duplicate"
|
|
},
|
|
{ // 13
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
TOKEN_IMPERSONATE,
|
|
0,
|
|
L"Impersonate"
|
|
},
|
|
{ // 14
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
TOKEN_QUERY,
|
|
0,
|
|
L"Query"
|
|
},
|
|
{ // 15
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
TOKEN_QUERY_SOURCE,
|
|
0,
|
|
L"Query source"
|
|
},
|
|
{ // 16
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
TOKEN_ADJUST_PRIVILEGES,
|
|
0,
|
|
L"Adjust Privileges"
|
|
},
|
|
{ // 17
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
TOKEN_ADJUST_GROUPS,
|
|
0,
|
|
L"Adjust Groups"
|
|
},
|
|
{ // 18
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL,
|
|
TOKEN_ADJUST_DEFAULT,
|
|
0,
|
|
L"Adjust Default"
|
|
},
|
|
|
|
DUMMY_ACCESS, // 19
|
|
DUMMY_ACCESS, // 20
|
|
DUMMY_ACCESS, // 21
|
|
DUMMY_ACCESS, // 22
|
|
DUMMY_ACCESS, // 23
|
|
DUMMY_ACCESS, // 24
|
|
DUMMY_ACCESS, // 25
|
|
DUMMY_ACCESS, // 26
|
|
DUMMY_ACCESS, // 27
|
|
DUMMY_ACCESS, // 28
|
|
DUMMY_ACCESS, // 29
|
|
DUMMY_ACCESS // 30
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/***************************************************************************\
|
|
* InitializeACLEditor
|
|
*
|
|
* Purpose : Initializes this module.
|
|
*
|
|
* Returns TRUE on success, FALSE on failure
|
|
*
|
|
* History:
|
|
* 09-17-92 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL
|
|
InitializeAclEditor(
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// Load the acleditor module and get the proc addresses we need
|
|
//
|
|
|
|
hModAclEditor = LoadLibrary(TEXT("acledit.dll"));
|
|
if (hModAclEditor == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
lpfnDaclEditor = (LPFNDACLEDITOR)GetProcAddress(hModAclEditor,
|
|
TEXT("SedDiscretionaryAclEditor"));
|
|
if (lpfnDaclEditor == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* FindObjectSecurityInfo
|
|
*
|
|
* Purpose : Searches for object type in our security info table and
|
|
* returns pointer to security info if found.
|
|
* Any pointers in the security info are initialized by this routine.
|
|
*
|
|
* Returns pointer to security info or NULL on failure
|
|
*
|
|
* History:
|
|
* 09-17-92 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
POBJECT_TYPE_SECURITY_INFO
|
|
FindObjectSecurityInfo(
|
|
HANDLE Object
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
POBJECT_TYPE_SECURITY_INFO SecurityInfo;
|
|
POBJECT_TYPE_INFORMATION TypeInfo;
|
|
ULONG Length;
|
|
BOOL Found;
|
|
ULONG i;
|
|
|
|
//
|
|
// Get the object type
|
|
//
|
|
|
|
Status = NtQueryObject(
|
|
Object,
|
|
ObjectTypeInformation,
|
|
NULL,
|
|
0,
|
|
&Length
|
|
);
|
|
if (Status != STATUS_INFO_LENGTH_MISMATCH) {
|
|
DbgPrint("NtQueryObject failed, status = 0x%lx\n", Status);
|
|
return(NULL);
|
|
}
|
|
|
|
TypeInfo = Alloc(Length);
|
|
if (TypeInfo == NULL) {
|
|
DbgPrint("Failed to allocate %ld bytes for object type\n", Length);
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
Status = NtQueryObject(
|
|
Object,
|
|
ObjectTypeInformation,
|
|
TypeInfo,
|
|
Length,
|
|
NULL
|
|
);
|
|
if (!NT_SUCCESS(Status)) {
|
|
DbgPrint("NtQueryObject failed, status = 0x%lx\n", Status);
|
|
Free(TypeInfo);
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
//
|
|
// Search for the type in our array of security info
|
|
//
|
|
|
|
Found = FALSE;
|
|
for ( i=0;
|
|
i < (sizeof(ObjectTypeSecurityInfo) / sizeof(*ObjectTypeSecurityInfo));
|
|
i++
|
|
) {
|
|
|
|
UNICODE_STRING FoundType;
|
|
|
|
SecurityInfo = &ObjectTypeSecurityInfo[i];
|
|
|
|
RtlInitUnicodeString(&FoundType, SecurityInfo->TypeName);
|
|
|
|
if (RtlEqualUnicodeString(&TypeInfo->TypeName, &FoundType, TRUE)) {
|
|
Found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Free(TypeInfo);
|
|
|
|
return(Found ? SecurityInfo : NULL);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* EditObjectDacl
|
|
*
|
|
* Purpose : Displays and allows the user to edit the Dacl on an object
|
|
*
|
|
* Returns TRUE on success, FALSE on failure (Use GetLastError for detail)
|
|
*
|
|
* History:
|
|
* 09-17-92 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL
|
|
EditObjectDacl(
|
|
HWND Owner,
|
|
LPWSTR ObjectName,
|
|
HANDLE Object,
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
POBJECT_TYPE_SECURITY_INFO SecurityInfo,
|
|
PSED_FUNC_APPLY_SEC_CALLBACK SetSecurityCallback,
|
|
DWORD *EditResult
|
|
)
|
|
{
|
|
DWORD Result;
|
|
HANDLE Instance;
|
|
|
|
//
|
|
// Initialize the pointer fields in the security info structure
|
|
//
|
|
|
|
SecurityInfo->AppAccesses.AccessGroup = SecurityInfo->AppAccess;
|
|
SecurityInfo->SedObjectTypeDescriptor.GenericMapping =
|
|
&SecurityInfo->GenericMapping;
|
|
SecurityInfo->SedObjectTypeDescriptor.GenericMappingNewObjects =
|
|
&SecurityInfo->GenericMapping;
|
|
SecurityInfo->SedObjectTypeDescriptor.HelpInfo =
|
|
&SecurityInfo->HelpInfo;
|
|
|
|
//
|
|
// Get the application instance handle
|
|
//
|
|
|
|
Instance = (HANDLE)(NtCurrentPeb()->ImageBaseAddress);
|
|
ASSERT(Instance != 0);
|
|
|
|
|
|
//
|
|
// Call the ACL editor, it will call our ApplyNtObjectSecurity function
|
|
// to store any ACL changes in the token.
|
|
//
|
|
|
|
Result = (*lpfnDaclEditor)(
|
|
Owner,
|
|
Instance,
|
|
NULL, // server
|
|
&SecurityInfo->SedObjectTypeDescriptor, // object type
|
|
&SecurityInfo->AppAccesses, // application accesses
|
|
ObjectName,
|
|
SetSecurityCallback, // Callback
|
|
(ULONG_PTR)Object, // Context
|
|
SecurityDescriptor,
|
|
(BOOLEAN)(SecurityDescriptor == NULL), // Couldn't read DACL
|
|
FALSE, // CantWriteDacl
|
|
EditResult,
|
|
0
|
|
);
|
|
|
|
if (Result != ERROR_SUCCESS) {
|
|
DbgPrint("DAcleditor failed, error = %d\n", Result);
|
|
SetLastError(Result);
|
|
}
|
|
|
|
return (Result == ERROR_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* ApplyNtObjectSecurity
|
|
*
|
|
* Purpose : Called by ACL editor to set new security on an object
|
|
*
|
|
* Returns ERROR_SUCCESS or win error code.
|
|
*
|
|
* History:
|
|
* 09-17-92 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
DWORD
|
|
ApplyNtObjectSecurity(
|
|
HWND hwndParent,
|
|
HANDLE hInstance,
|
|
ULONG_PTR CallbackContext,
|
|
PSECURITY_DESCRIPTOR SecDesc,
|
|
PSECURITY_DESCRIPTOR SecDescNewObjects,
|
|
BOOLEAN ApplyToSubContainers,
|
|
BOOLEAN ApplyToSubObjects,
|
|
LPDWORD StatusReturn
|
|
)
|
|
{
|
|
HANDLE Object = (HANDLE)CallbackContext;
|
|
NTSTATUS Status;
|
|
|
|
*StatusReturn = SED_STATUS_FAILED_TO_MODIFY;
|
|
|
|
//
|
|
// Set the new DACL on the object
|
|
//
|
|
|
|
Status = NtSetSecurityObject(Object,
|
|
DACL_SECURITY_INFORMATION,
|
|
SecDesc);
|
|
if (NT_SUCCESS(Status)) {
|
|
*StatusReturn = SED_STATUS_MODIFIED;
|
|
} else {
|
|
DbgPrint("Failed to set new ACL on object, status = 0x%lx\n", Status);
|
|
if (Status == STATUS_ACCESS_DENIED) {
|
|
MessageBox(hwndParent,
|
|
"You do not have permission to set the permissions on this object",
|
|
NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
|
} else {
|
|
MessageBox(hwndParent,
|
|
"Unable to set object security",
|
|
NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
|
}
|
|
}
|
|
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* EditNtObjectDacl
|
|
*
|
|
* Purpose : Displays and allows the user to edit the Dacl on an NT object
|
|
*
|
|
* Returns TRUE on success, FALSE on failure (Use GetLastError for detail)
|
|
*
|
|
* History:
|
|
* 09-17-92 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL
|
|
EditNtObjectDacl(
|
|
HWND Owner,
|
|
LPWSTR ObjectName,
|
|
HANDLE Object,
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
DWORD *EditResult
|
|
)
|
|
{
|
|
BOOL Result;
|
|
POBJECT_TYPE_SECURITY_INFO SecurityInfo;
|
|
|
|
|
|
//
|
|
// Lookup our security info for an object of this type
|
|
//
|
|
|
|
SecurityInfo = FindObjectSecurityInfo(Object);
|
|
if (SecurityInfo == NULL) {
|
|
MessageBox(Owner, "Unable to edit the security on an object of this type",
|
|
NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
//
|
|
// Edit the ACL. Our callback function will be called to change the
|
|
// new permissions
|
|
//
|
|
|
|
Result = EditObjectDacl(
|
|
Owner,
|
|
ObjectName,
|
|
Object,
|
|
SecurityDescriptor,
|
|
SecurityInfo,
|
|
ApplyNtObjectSecurity,
|
|
EditResult
|
|
);
|
|
return (Result);
|
|
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* EditNtObjectSecurity
|
|
*
|
|
* Purpose : Displays and allows the user to edit the protection on an NT object
|
|
*
|
|
* Parameters:
|
|
*
|
|
* hwndOwner - Owner window for dialog
|
|
* Object - handle to NT object. Should have been opened for MAXIMUM_ALLOWED
|
|
* Name - Name of object
|
|
*
|
|
* Returns TRUE on success, FALSE on failure (Use GetLastError for detail)
|
|
*
|
|
* History:
|
|
* 09-17-92 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL
|
|
EditNtObjectSecurity(
|
|
HWND hwndOwner,
|
|
HANDLE Object,
|
|
LPWSTR ObjectName
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
BOOL Success = FALSE;
|
|
DWORD EditResult;
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|
ULONG Length;
|
|
|
|
//
|
|
// If we don't have an address for the DACL editor, we can't do anything
|
|
//
|
|
|
|
if (lpfnDaclEditor == NULL) {
|
|
DbgPrint("EditNtObjectSecurity - no ACL editor loaded\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Read the existing security from the object
|
|
//
|
|
|
|
Status = NtQuerySecurityObject(Object,
|
|
OWNER_SECURITY_INFORMATION |
|
|
GROUP_SECURITY_INFORMATION |
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
0,
|
|
&Length);
|
|
ASSERT(!NT_SUCCESS(Status));
|
|
|
|
if (Status != STATUS_BUFFER_TOO_SMALL) {
|
|
DbgPrint("Failed to query object security, status = 0x%lx\n", Status);
|
|
} else {
|
|
|
|
SecurityDescriptor = Alloc(Length);
|
|
if (SecurityDescriptor == NULL) {
|
|
DbgPrint("Failed to allocate %ld bytes for object SD\n", Length);
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
Status = NtQuerySecurityObject(Object,
|
|
OWNER_SECURITY_INFORMATION |
|
|
GROUP_SECURITY_INFORMATION |
|
|
DACL_SECURITY_INFORMATION,
|
|
SecurityDescriptor,
|
|
Length,
|
|
&Length);
|
|
if (!NT_SUCCESS(Status)) {
|
|
DbgPrint("Failed to query object security, status = 0x%lx\n", Status);
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
ASSERT(RtlValidSecurityDescriptor(SecurityDescriptor));
|
|
}
|
|
|
|
//
|
|
// Call the ACL editor, it will call our ApplyNtObjectSecurity function
|
|
// to store any ACL changes in the object.
|
|
//
|
|
|
|
Success = EditNtObjectDacl(
|
|
hwndOwner,
|
|
ObjectName,
|
|
Object,
|
|
SecurityDescriptor,
|
|
&EditResult
|
|
);
|
|
if (!Success) {
|
|
DbgPrint("PVIEW: Failed to edit object DACL\n");
|
|
}
|
|
|
|
CleanupAndExit:
|
|
|
|
if (SecurityDescriptor != NULL) {
|
|
Free(SecurityDescriptor);
|
|
}
|
|
|
|
return(Success);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* ApplyTokenDefaultDacl
|
|
*
|
|
* Purpose : Called by ACL editor to set new security on an object
|
|
*
|
|
* Returns ERROR_SUCCESS or win error code.
|
|
*
|
|
* History:
|
|
* 09-17-92 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
DWORD
|
|
ApplyTokenDefaultDacl(
|
|
HWND hwndParent,
|
|
HANDLE hInstance,
|
|
ULONG_PTR CallbackContext,
|
|
PSECURITY_DESCRIPTOR SecDesc,
|
|
PSECURITY_DESCRIPTOR SecDescNewObjects,
|
|
BOOLEAN ApplyToSubContainers,
|
|
BOOLEAN ApplyToSubObjects,
|
|
LPDWORD StatusReturn
|
|
)
|
|
{
|
|
HANDLE Token = (HANDLE)CallbackContext;
|
|
TOKEN_DEFAULT_DACL DefaultDacl;
|
|
NTSTATUS Status;
|
|
BOOLEAN DaclPresent;
|
|
BOOLEAN DaclDefaulted;
|
|
|
|
Status = RtlGetDaclSecurityDescriptor (
|
|
SecDesc,
|
|
&DaclPresent,
|
|
&DefaultDacl.DefaultDacl,
|
|
&DaclDefaulted
|
|
);
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
ASSERT(DaclPresent);
|
|
|
|
|
|
Status = NtSetInformationToken(
|
|
Token, // Handle
|
|
TokenDefaultDacl, // TokenInformationClass
|
|
&DefaultDacl, // TokenInformation
|
|
sizeof(DefaultDacl) // TokenInformationLength
|
|
);
|
|
if (NT_SUCCESS(Status)) {
|
|
*StatusReturn = SED_STATUS_MODIFIED;
|
|
} else {
|
|
DbgPrint("SetInformationToken failed, status = 0x%lx\n", Status);
|
|
*StatusReturn = SED_STATUS_FAILED_TO_MODIFY;
|
|
|
|
if (Status == STATUS_ACCESS_DENIED) {
|
|
MessageBox(hwndParent,
|
|
"You do not have permission to set the default ACL in this token",
|
|
NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
|
} else {
|
|
MessageBox(hwndParent,
|
|
"Unable to set default ACL in token",
|
|
NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
|
}
|
|
}
|
|
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* EditTokenDefaultAcl
|
|
*
|
|
* Purpose : Displays and allows the user to edit the default ACL in a token
|
|
*
|
|
* Parameters:
|
|
*
|
|
* hwndOwner - Owner window for dialog
|
|
* Object - handle to token - opened for TOKEN_QUERY access
|
|
* Name - Name of token
|
|
*
|
|
* Returns TRUE on success, FALSE on failure (Use GetLastError for detail)
|
|
*
|
|
* History:
|
|
* 09-17-92 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL
|
|
EditTokenDefaultDacl(
|
|
HWND hwndOwner,
|
|
HANDLE Token,
|
|
LPWSTR ObjectName
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
BOOL Result = FALSE;
|
|
DWORD EditResult;
|
|
PTOKEN_DEFAULT_DACL DefaultDacl = NULL;
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|
ULONG InfoLength;
|
|
|
|
//
|
|
// If we don't have an address for the DACL editor, we can't do anything
|
|
//
|
|
|
|
if (lpfnDaclEditor == NULL) {
|
|
DbgPrint("EditNtObjectSecurity - no ACL editor loaded\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Read the default DACL from the token
|
|
//
|
|
|
|
Status = NtQueryInformationToken(
|
|
Token, // Handle
|
|
TokenDefaultDacl, // TokenInformationClass
|
|
NULL, // TokenInformation
|
|
0, // TokenInformationLength
|
|
&InfoLength // ReturnLength
|
|
);
|
|
|
|
ASSERT(!NT_SUCCESS(Status));
|
|
|
|
if (Status == STATUS_BUFFER_TOO_SMALL) {
|
|
|
|
DefaultDacl = Alloc(InfoLength);
|
|
if (DefaultDacl == NULL) {
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
Status = NtQueryInformationToken(
|
|
Token, // Handle
|
|
TokenDefaultDacl, // TokenInformationClass
|
|
DefaultDacl, // TokenInformation
|
|
InfoLength, // TokenInformationLength
|
|
&InfoLength // ReturnLength
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
DbgPrint("NtQueryInformationToken failed, status = 0x%lx\n", Status);
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Create a security descriptor
|
|
//
|
|
|
|
SecurityDescriptor = Alloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
|
|
|
|
if (SecurityDescriptor == NULL) {
|
|
DbgPrint("Failed to allocate security descriptor\n");
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
Status = RtlCreateSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
|
|
//
|
|
// Set the DACL on the security descriptor
|
|
//
|
|
|
|
Status = RtlSetDaclSecurityDescriptor(
|
|
SecurityDescriptor,
|
|
TRUE, // DACL present
|
|
DefaultDacl->DefaultDacl,
|
|
FALSE // DACL defaulted
|
|
);
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
ASSERT(RtlValidSecurityDescriptor(SecurityDescriptor));
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Call the ACL editor, it will call our ApplyTokenDefaultAcl function
|
|
// to store any default ACL changes in the token.
|
|
//
|
|
|
|
Result = EditObjectDacl(
|
|
hwndOwner,
|
|
ObjectName,
|
|
Token,
|
|
SecurityDescriptor,
|
|
&DefaultSecurityInfo,
|
|
ApplyTokenDefaultDacl,
|
|
&EditResult
|
|
);
|
|
if (!Result) {
|
|
DbgPrint("Failed to edit token default ACL\n");
|
|
}
|
|
|
|
CleanupAndExit:
|
|
|
|
if (SecurityDescriptor != NULL) {
|
|
Free(SecurityDescriptor);
|
|
}
|
|
if (DefaultDacl != NULL) {
|
|
Free(DefaultDacl);
|
|
}
|
|
|
|
return(Result);
|
|
}
|