/**************************************************************************** PROGRAM: ACLEDIT.C PURPOSE: Contains routines that edit security on Nt objects ****************************************************************************/ #include "pviewp.h" #include // // 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); }