454 lines
12 KiB
C
454 lines
12 KiB
C
/****************************************************************************
|
|
|
|
PROGRAM: TOKEN.C
|
|
|
|
PURPOSE: Contains routines that manipulate tokens
|
|
|
|
****************************************************************************/
|
|
|
|
#include "SECEDIT.h"
|
|
#include <sedapi.h>
|
|
|
|
BOOL
|
|
EditTokenDefaultAcl(
|
|
HWND Owner,
|
|
HANDLE Instance,
|
|
LPWSTR ObjectName,
|
|
HANDLE Token,
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
DWORD *EditResult
|
|
);
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* ApplySecurity
|
|
*
|
|
* Purpose : Called by ACL editor to set new default DACL on token
|
|
*
|
|
* Returns ERROR_SUCCESS or win error code.
|
|
*
|
|
* History:
|
|
* 09-17-92 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
DWORD
|
|
ApplySecurity(
|
|
HWND hwndParent,
|
|
HANDLE hInstance,
|
|
ULONG CallbackContext,
|
|
PSECURITY_DESCRIPTOR SecDesc,
|
|
PSECURITY_DESCRIPTOR SecDescNewObjects,
|
|
BOOLEAN ApplyToSubContainers,
|
|
BOOLEAN ApplyToSubObjects,
|
|
LPDWORD StatusReturn
|
|
)
|
|
{
|
|
HANDLE MyToken = (HANDLE)CallbackContext;
|
|
HANDLE Token = NULL;
|
|
PTOKEN_DEFAULT_DACL DefaultDacl = NULL;
|
|
NTSTATUS Status;
|
|
BOOLEAN DaclPresent;
|
|
BOOLEAN DaclDefaulted;
|
|
|
|
*StatusReturn = SED_STATUS_FAILED_TO_MODIFY;
|
|
|
|
//
|
|
// Get a handle to the token
|
|
//
|
|
|
|
Token = OpenToken(MyToken, TOKEN_ADJUST_DEFAULT);
|
|
|
|
if (Token == NULL) {
|
|
DbgPrint("SECEDIT : Failed to open the token for TOKEN_ADJUST_DEFAULT access\n");
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
DefaultDacl = Alloc(sizeof(TOKEN_DEFAULT_DACL));
|
|
if (DefaultDacl == NULL) {
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
Status = RtlGetDaclSecurityDescriptor (
|
|
SecDesc,
|
|
&DaclPresent,
|
|
&DefaultDacl->DefaultDacl,
|
|
&DaclDefaulted
|
|
);
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
ASSERT(DaclPresent);
|
|
|
|
if (SetTokenInfo(Token, TokenDefaultDacl, (PVOID)DefaultDacl)) {
|
|
*StatusReturn = SED_STATUS_MODIFIED;
|
|
}
|
|
|
|
CleanupAndExit:
|
|
|
|
if (Token != NULL) {
|
|
CloseToken(Token);
|
|
}
|
|
if (DefaultDacl != NULL) {
|
|
Free(DefaultDacl);
|
|
}
|
|
|
|
if (*StatusReturn != SED_STATUS_MODIFIED) {
|
|
MessageBox(hwndParent, "Failed to set default DACL", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
|
|
}
|
|
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* EditDefaultAcl
|
|
*
|
|
* Purpose : Displays and allows the user to edit the default Acl on the
|
|
* passed token.
|
|
*
|
|
* Returns TRUE on success, FALSE on failure (Use GetLastError for detail)
|
|
*
|
|
* History:
|
|
* 09-17-92 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL
|
|
EditDefaultDacl(
|
|
HWND hwndOwner,
|
|
HANDLE Instance,
|
|
HANDLE MyToken
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
BOOL Success = FALSE;
|
|
DWORD EditResult;
|
|
HANDLE Token = NULL;
|
|
PTOKEN_DEFAULT_DACL DefaultDacl = NULL;
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|
PTOKEN_OWNER Owner = NULL;
|
|
PTOKEN_PRIMARY_GROUP PrimaryGroup = NULL;
|
|
WCHAR string[MAX_STRING_LENGTH];
|
|
|
|
//
|
|
// Get the window text so we can use it as the token name
|
|
//
|
|
|
|
GetWindowTextW(((PMYTOKEN)MyToken)->hwnd, string, sizeof(string)/sizeof(*string));
|
|
|
|
|
|
//
|
|
// Get a handle to the token
|
|
//
|
|
|
|
Token = OpenToken(MyToken, TOKEN_QUERY);
|
|
|
|
if (Token == NULL) {
|
|
DbgPrint("SECEDIT : Failed to open the token with TOKEN_QUERY access\n");
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Read the default DACL from the token
|
|
//
|
|
|
|
if (!GetTokenInfo(Token, TokenDefaultDacl, (PPVOID)&DefaultDacl)) {
|
|
DbgPrint("SECEDIT : Failed to read default DACL from token\n");
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the owner and group of the token
|
|
//
|
|
|
|
if (!GetTokenInfo(Token, TokenOwner, (PPVOID)&Owner)) {
|
|
DbgPrint("SECEDIT : Failed to read owner from token\n");
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
if (!GetTokenInfo(Token, TokenPrimaryGroup, (PPVOID)&PrimaryGroup)) {
|
|
DbgPrint("SECEDIT : Failed to read primary group from token\n");
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// Create a security descriptor
|
|
//
|
|
|
|
SecurityDescriptor = Alloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
|
|
|
|
if (SecurityDescriptor == NULL) {
|
|
DbgPrint("SECEDIT : 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));
|
|
|
|
//
|
|
// Put the owner and group in the security descriptor to keep the
|
|
// ACL editor happy
|
|
//
|
|
|
|
Status = RtlSetOwnerSecurityDescriptor(
|
|
SecurityDescriptor,
|
|
Owner->Owner,
|
|
FALSE // Owner defaulted
|
|
);
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
|
|
Status = RtlSetGroupSecurityDescriptor(
|
|
SecurityDescriptor,
|
|
PrimaryGroup->PrimaryGroup,
|
|
FALSE // Owner defaulted
|
|
);
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
|
|
|
|
ASSERT(RtlValidSecurityDescriptor(SecurityDescriptor));
|
|
|
|
//
|
|
// Call the ACL editor, it will call our ApplySecurity function
|
|
// to store any ACL changes in the token.
|
|
//
|
|
|
|
Success = EditTokenDefaultAcl(
|
|
hwndOwner,
|
|
Instance,
|
|
string,
|
|
MyToken,
|
|
SecurityDescriptor,
|
|
&EditResult
|
|
);
|
|
if (!Success) {
|
|
DbgPrint("SECEDIT: Failed to edit token DACL\n");
|
|
}
|
|
|
|
CleanupAndExit:
|
|
|
|
if (DefaultDacl != NULL) {
|
|
FreeTokenInfo(DefaultDacl);
|
|
}
|
|
if (SecurityDescriptor != NULL) {
|
|
FreeTokenInfo(SecurityDescriptor);
|
|
}
|
|
if (PrimaryGroup != NULL) {
|
|
FreeTokenInfo(PrimaryGroup);
|
|
}
|
|
if (Owner != NULL) {
|
|
FreeTokenInfo(Owner);
|
|
}
|
|
|
|
if (Token != NULL) {
|
|
CloseToken(Token);
|
|
}
|
|
|
|
|
|
return(Success);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* EditTokenDefaultAcl
|
|
*
|
|
* Purpose : Displays and allows the user to edit the default Acl on the
|
|
* passed token.
|
|
*
|
|
* Returns TRUE on success, FALSE on failure (Use GetLastError for detail)
|
|
*
|
|
* History:
|
|
* 09-17-92 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL
|
|
EditTokenDefaultAcl(
|
|
HWND Owner,
|
|
HANDLE Instance,
|
|
LPWSTR ObjectName,
|
|
HANDLE MyToken,
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
DWORD *EditResult
|
|
)
|
|
{
|
|
DWORD Result;
|
|
SED_OBJECT_TYPE_DESCRIPTOR sedobjdesc;
|
|
GENERIC_MAPPING GenericMapping;
|
|
SED_HELP_INFO sedhelpinfo ;
|
|
SED_APPLICATION_ACCESSES SedAppAccesses ;
|
|
SED_APPLICATION_ACCESS SedAppAccess[20];
|
|
ULONG i;
|
|
|
|
//
|
|
// Initialize the application accesses
|
|
//
|
|
|
|
i=0;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE_SPECIAL;
|
|
SedAppAccess[i].AccessMask1 = TOKEN_ASSIGN_PRIMARY;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"Assign Primary";
|
|
i++;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE_SPECIAL;
|
|
SedAppAccess[i].AccessMask1 = TOKEN_DUPLICATE;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"Duplicate";
|
|
i++;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE_SPECIAL;
|
|
SedAppAccess[i].AccessMask1 = TOKEN_IMPERSONATE;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"Impersonate";
|
|
i++;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE_SPECIAL;
|
|
SedAppAccess[i].AccessMask1 = TOKEN_QUERY;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"Query";
|
|
i++;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE_SPECIAL;
|
|
SedAppAccess[i].AccessMask1 = TOKEN_QUERY_SOURCE;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"Query source";
|
|
i++;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE_SPECIAL;
|
|
SedAppAccess[i].AccessMask1 = TOKEN_ADJUST_PRIVILEGES;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"Adjust Privileges";
|
|
i++;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE_SPECIAL;
|
|
SedAppAccess[i].AccessMask1 = TOKEN_ADJUST_GROUPS;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"Adjust Groups";
|
|
i++;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE_SPECIAL;
|
|
SedAppAccess[i].AccessMask1 = TOKEN_ADJUST_DEFAULT;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"Adjust Default";
|
|
i++;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE;
|
|
SedAppAccess[i].AccessMask1 = GENERIC_ALL;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"All Access";
|
|
i++;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE;
|
|
SedAppAccess[i].AccessMask1 = TOKEN_READ;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"Read";
|
|
i++;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE;
|
|
SedAppAccess[i].AccessMask1 = TOKEN_WRITE;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"Write";
|
|
i++;
|
|
|
|
SedAppAccess[i].Type = SED_DESC_TYPE_RESOURCE;
|
|
SedAppAccess[i].AccessMask1 = 0;
|
|
SedAppAccess[i].AccessMask2 = 0;
|
|
SedAppAccess[i].PermissionTitle = L"None";
|
|
i++;
|
|
|
|
ASSERT((sizeof(SedAppAccess)/sizeof(*SedAppAccess)) >= i);
|
|
|
|
|
|
SedAppAccesses.Count = i;
|
|
SedAppAccesses.AccessGroup = SedAppAccess;
|
|
SedAppAccesses.DefaultPermName = L"Read";
|
|
|
|
|
|
//
|
|
// Initialize generic mapping
|
|
//
|
|
|
|
GenericMapping.GenericRead = TOKEN_READ;
|
|
GenericMapping.GenericWrite = TOKEN_WRITE;
|
|
GenericMapping.GenericExecute = TOKEN_EXECUTE;
|
|
GenericMapping.GenericAll = TOKEN_ALL_ACCESS;
|
|
|
|
//
|
|
// Initialize help info
|
|
//
|
|
|
|
sedhelpinfo.pszHelpFileName = L"secedit.hlp";
|
|
sedhelpinfo.aulHelpContext[HC_MAIN_DLG] = 0 ;
|
|
sedhelpinfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] = 0 ;
|
|
sedhelpinfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] = 0 ;
|
|
sedhelpinfo.aulHelpContext[HC_ADD_USER_DLG] = 0 ;
|
|
|
|
|
|
//
|
|
// Initialize object description
|
|
//
|
|
|
|
sedobjdesc.Revision = SED_REVISION1;
|
|
sedobjdesc.IsContainer = FALSE;
|
|
sedobjdesc.AllowNewObjectPerms = FALSE;
|
|
sedobjdesc.MapSpecificPermsToGeneric = FALSE;
|
|
sedobjdesc.GenericMapping = &GenericMapping;
|
|
sedobjdesc.GenericMappingNewObjects = &GenericMapping;
|
|
sedobjdesc.HelpInfo = &sedhelpinfo;
|
|
sedobjdesc.ObjectTypeName = L"Token";
|
|
sedobjdesc.ApplyToSubContainerTitle = L"ApplyToSubContainerTitle";
|
|
sedobjdesc.ApplyToSubContainerHelpText = L"ApplyToSubContainerHelpText";
|
|
sedobjdesc.ApplyToSubContainerConfirmation = L"ApplyToSubContainerConfirmation";
|
|
sedobjdesc.SpecialObjectAccessTitle = L"Special...";
|
|
sedobjdesc.SpecialNewObjectAccessTitle = L"SpecialNewObjectAccessTitle";
|
|
|
|
|
|
//
|
|
// Call the ACL editor, it will call our ApplySecurity function
|
|
// to store any ACL changes in the token.
|
|
//
|
|
|
|
Result = SedDiscretionaryAclEditor(
|
|
Owner,
|
|
Instance,
|
|
NULL, // server
|
|
&sedobjdesc, // object type
|
|
&SedAppAccesses, // application accesses
|
|
ObjectName,
|
|
ApplySecurity, // Callback
|
|
(ULONG_PTR)MyToken, // Context
|
|
SecurityDescriptor,
|
|
FALSE, // Couldn't read DACL
|
|
EditResult
|
|
);
|
|
|
|
if (Result != ERROR_SUCCESS) {
|
|
DbgPrint("SECEDIT: Acleditor failed, error = %d\n", Result);
|
|
SetLastError(Result);
|
|
}
|
|
|
|
return (Result == ERROR_SUCCESS);
|
|
|
|
}
|