2160 lines
67 KiB
C
2160 lines
67 KiB
C
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1996.
|
|
//
|
|
// File: ACLAPI.C
|
|
//
|
|
// Contents: Implements the drt for MARTA and Win32Ex APIs
|
|
//
|
|
// History: 14-Sep-96 MacM Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <aclapi.h>
|
|
#include <marta.h>
|
|
#include <seopaque.h>
|
|
#include <ntrtl.h>
|
|
|
|
|
|
#define EVERYONE L"EVERYONE"
|
|
#define EVERYONE_A "EVERYONE"
|
|
#define GUEST L"GUEST"
|
|
#define GUEST_A "GUEST"
|
|
#define GUEST_COMPARE L"GUEST"
|
|
#define SYSTEM L"SYSTEM"
|
|
#define SYSTEM_A "SYSTEM"
|
|
#define MAX_LINE 256
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
BOOL fVerbose = FALSE;
|
|
|
|
//
|
|
// Function prototypes
|
|
//
|
|
DWORD Nt4BuildW(PACL *ppAcl);
|
|
DWORD Nt4BuildA(PACL *ppAcl);
|
|
DWORD Nt5BuildW(PACTRL_ACCESSW *ppAccess);
|
|
DWORD Nt5BuildA(PACTRL_ACCESSA *ppAccess);
|
|
DWORD Nt4DrtW(PACL pAcl,
|
|
PSTR pszObject,
|
|
SE_OBJECT_TYPE ObjType);
|
|
|
|
DWORD Nt4DrtA(PACL pAcl,
|
|
PSTR pszObject,
|
|
SE_OBJECT_TYPE ObjType);
|
|
|
|
DWORD Nt5DrtW(PACTRL_ACCESSW pAccess,
|
|
PSTR pszObject,
|
|
SE_OBJECT_TYPE ObjType);
|
|
|
|
DWORD Nt5DrtA(PACTRL_ACCESSA pAccess,
|
|
PSTR pszObject,
|
|
SE_OBJECT_TYPE ObjType);
|
|
|
|
VOID
|
|
ConvertAccessMaskToAccessRight(IN ACCESS_MASK AccessMask,
|
|
OUT PACCESS_RIGHTS pAccessRight);
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: main
|
|
//
|
|
// Synopsis: The main
|
|
//
|
|
// Arguments: [IN argc] -- Count of arguments
|
|
// [IN argv] -- List of arguments
|
|
//
|
|
// Returns: 0 -- Success
|
|
// non-0 -- Failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
__cdecl main(INT argc, CHAR *argv[])
|
|
{
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
PACL pNt4AclW = NULL, pNt4AclA = NULL;
|
|
PACTRL_ACCESSW pNt5AccessW = NULL;
|
|
PACTRL_ACCESSA pNt5AccessA = NULL;
|
|
FILE *fp = NULL;
|
|
SE_OBJECT_TYPE ObjType;
|
|
CHAR szBuff[MAX_LINE];
|
|
|
|
if (argc < 2 || argc > 3)
|
|
{
|
|
fprintf(stderr,"USAGE: aclexdrt input_file [verbose]\n");
|
|
exit(1);
|
|
}
|
|
|
|
if(argc == 3)
|
|
{
|
|
fVerbose = TRUE;
|
|
}
|
|
|
|
AccProvInit(dwErr);
|
|
|
|
//
|
|
// Do the Nt4 style build routines
|
|
//
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = Nt4BuildW(&pNt4AclW);
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = Nt4BuildA(&pNt4AclA);
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = Nt5BuildW(&pNt5AccessW);
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = Nt5BuildA(&pNt5AccessA);
|
|
}
|
|
|
|
//
|
|
// Now, open the file and process it...
|
|
//
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
fp = fopen(argv[1], "r");
|
|
if(fp == NULL)
|
|
{
|
|
fprintf(stderr, "File %s not found\n", argv[1]);
|
|
dwErr = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
while(dwErr == ERROR_SUCCESS && fgets(szBuff, MAX_LINE, fp) != NULL)
|
|
{
|
|
BOOL fIsDSObj = FALSE;
|
|
PSTR pszType;
|
|
PSTR pszObject = strtok(szBuff, " ");
|
|
if(pszObject != NULL)
|
|
{
|
|
pszType = strtok(NULL," \n\r\0");
|
|
}
|
|
|
|
if(pszObject == NULL && pszType == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
else if(pszObject == NULL || pszType == NULL)
|
|
{
|
|
fprintf(stderr,
|
|
"Invalid entry %s in input file %s\n",
|
|
szBuff,
|
|
argv[1]);
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
else
|
|
{
|
|
if(_stricmp(pszType, "FILE") == 0)
|
|
{
|
|
ObjType = SE_FILE_OBJECT;
|
|
}
|
|
else if(_stricmp(pszType, "SERVICE") == 0)
|
|
{
|
|
ObjType = SE_SERVICE;
|
|
}
|
|
else if(_stricmp(pszType, "PRINTER") == 0)
|
|
{
|
|
ObjType = SE_PRINTER;
|
|
}
|
|
else if (_stricmp(pszType, "REGISTRY_KEY") == 0)
|
|
{
|
|
ObjType = SE_REGISTRY_KEY;
|
|
}
|
|
else if(_stricmp(pszType, "SHARE") == 0)
|
|
{
|
|
ObjType = SE_LMSHARE;
|
|
}
|
|
else if(_stricmp(pszType, "DSOBJ") == 0)
|
|
{
|
|
ObjType = SE_DS_OBJECT;
|
|
fIsDSObj = TRUE;
|
|
}
|
|
else if(_stricmp(pszType, "DSOBJALL") == 0)
|
|
{
|
|
ObjType = SE_DS_OBJECT_ALL;
|
|
fIsDSObj = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "Invalid object type %s\n", pszType);
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If it worked, do the tests...
|
|
//
|
|
if(dwErr == ERROR_SUCCESS && fIsDSObj == FALSE)
|
|
{
|
|
dwErr = Nt4DrtW(pNt4AclW,
|
|
pszObject,
|
|
ObjType);
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS && fIsDSObj == FALSE)
|
|
{
|
|
dwErr = Nt4DrtA(pNt4AclA,
|
|
pszObject,
|
|
ObjType);
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = Nt5DrtW(pNt5AccessW,
|
|
pszObject,
|
|
ObjType);
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = Nt5DrtA(pNt5AccessA,
|
|
pszObject,
|
|
ObjType);
|
|
}
|
|
}
|
|
|
|
if(fp != NULL)
|
|
{
|
|
fclose(fp);
|
|
}
|
|
|
|
}
|
|
LocalFree(pNt4AclW);
|
|
LocalFree(pNt4AclA);
|
|
LocalFree(pNt5AccessW);
|
|
LocalFree(pNt5AccessA);
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
printf("Success\n");
|
|
}
|
|
else
|
|
{
|
|
printf("Failure: %lu\n", dwErr);
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CompareAcls
|
|
//
|
|
// Synopsis: Compares 2 acls for equality
|
|
//
|
|
// Arguments: [pAcl1] -- First ACL
|
|
// [pAcl2] -- Second ACL
|
|
//
|
|
// Returns: ERROR_SUCCESS -- They match
|
|
// ERROR_INVALID_DATA -- They don't match
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD CompAcls(PACL pAcl1,
|
|
PACL pAcl2)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
ACL_SIZE_INFORMATION AclSize1, AclSize2;
|
|
ACL_REVISION_INFORMATION AclRev1, AclRev2;
|
|
PKNOWN_ACE pAce1, pAce2;
|
|
PSID pSid1, pSid2;
|
|
DWORD iIndex;
|
|
|
|
if(pAcl1 == NULL || pAcl2 == NULL)
|
|
{
|
|
if(pAcl1 != pAcl2)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,"Acl %lu is NULL\n", pAcl1 == NULL ? 1 : 2);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(GetAclInformation(pAcl1,
|
|
&AclRev1,
|
|
sizeof(ACL_REVISION_INFORMATION),
|
|
AclRevisionInformation) == FALSE ||
|
|
GetAclInformation(pAcl2,
|
|
&AclRev2,
|
|
sizeof(ACL_REVISION_INFORMATION),
|
|
AclRevisionInformation) == FALSE)
|
|
{
|
|
return(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
if(GetAclInformation(pAcl1,
|
|
&AclSize1,
|
|
sizeof(ACL_SIZE_INFORMATION),
|
|
AclSizeInformation) == FALSE ||
|
|
GetAclInformation(pAcl2,
|
|
&AclSize2,
|
|
sizeof(ACL_SIZE_INFORMATION),
|
|
AclSizeInformation) == FALSE)
|
|
{
|
|
return(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
if(AclRev1.AclRevision != AclRev2.AclRevision)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,
|
|
"Revision mismatch: %lu %lu\n",
|
|
AclRev1.AclRevision,
|
|
AclRev2.AclRevision);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if(AclSize1.AceCount != AclSize2.AceCount)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,
|
|
"AceCount mismatch: %lu %lu\n",
|
|
AclSize1.AceCount,
|
|
AclSize2.AceCount);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if(AclSize1.AclBytesInUse != AclSize2.AclBytesInUse)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,
|
|
"BytesInUse mismatch: %lu %lu\n",
|
|
AclSize1.AclBytesInUse,
|
|
AclSize2.AclBytesInUse);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if(pAcl1->Sbz1 != pAcl2->Sbz1)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,
|
|
"Acl flags mismatch: %lu %lu\n",
|
|
pAcl1->Sbz1,
|
|
pAcl2->Sbz1);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
|
|
if(dwErr != ERROR_SUCCESS)
|
|
{
|
|
return(dwErr);
|
|
}
|
|
|
|
//
|
|
// Now, compare all of the aces
|
|
//
|
|
pAce1 = FirstAce(pAcl1);
|
|
pAce2 = FirstAce(pAcl2);
|
|
for(iIndex = 0;
|
|
iIndex < pAcl1->AceCount && dwErr == ERROR_SUCCESS;
|
|
iIndex++)
|
|
{
|
|
ACCESS_RIGHTS Rights1, Rights2;
|
|
|
|
if(fVerbose)
|
|
{
|
|
printf("Ace %lu\n", iIndex);
|
|
}
|
|
|
|
if(pAce1->Header.AceType != pAce2->Header.AceType)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,
|
|
"\tAceType mismatch: %lu %lu\n",
|
|
pAce1->Header.AceType,
|
|
pAce2->Header.AceType);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if(pAce1->Header.AceFlags != pAce2->Header.AceFlags)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,
|
|
"\tAceType mismatch: %lu %lu\n",
|
|
pAce1->Header.AceFlags,
|
|
pAce2->Header.AceFlags);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if(pAce1->Header.AceSize != pAce2->Header.AceSize)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,
|
|
"\tAceType mismatch: %lu %lu\n",
|
|
pAce1->Header.AceSize,
|
|
pAce2->Header.AceSize);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
ConvertAccessMaskToAccessRight(pAce1->Mask, &Rights1);
|
|
ConvertAccessMaskToAccessRight(pAce2->Mask, &Rights2);
|
|
if(Rights1 != Rights1)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,
|
|
"\tAccessMask mismatch: %lu %lu\n",
|
|
Rights1,
|
|
Rights2);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if(!RtlEqualSid((PSID)&(pAce1->SidStart), (PSID)&(pAce2->SidStart)))
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,
|
|
"\tSids don't match\n");
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
pAce1 = NextAce(pAce1);
|
|
pAce2 = NextAce(pAce2);
|
|
}
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CompStringsW
|
|
//
|
|
// Synopsis: Compares 2 string pointers for equality
|
|
//
|
|
// Arguments: [pwszStr1] -- First string
|
|
// [pwszStr2] -- Second string
|
|
//
|
|
// Returns: ERROR_SUCCESS -- They match
|
|
// ERROR_INVALID_DATA -- They don't match
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD
|
|
CompStringsW(PWSTR pwszStr1, PWSTR pwszStr2)
|
|
{
|
|
if(pwszStr1 != NULL && pwszStr2 != NULL)
|
|
{
|
|
if(_wcsicmp(pwszStr1, pwszStr2) == 0)
|
|
{
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pwszStr1 == NULL)
|
|
{
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
}
|
|
|
|
return(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CompStringsA
|
|
//
|
|
// Synopsis: Compares 2 string pointers for equality
|
|
//
|
|
// Arguments: [pszStr1] -- First string
|
|
// [pszStr2] -- Second string
|
|
//
|
|
// Returns: ERROR_SUCCESS -- They match
|
|
// ERROR_INVALID_DATA -- They don't match
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD
|
|
CompStringsA(PSTR pszStr1, PSTR pszStr2)
|
|
{
|
|
if(pszStr1 != NULL && pszStr2 != NULL)
|
|
{
|
|
if(_stricmp(pszStr1, pszStr2) == 0)
|
|
{
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pszStr1 == NULL)
|
|
{
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
}
|
|
|
|
|
|
return(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CompAccessW
|
|
//
|
|
// Synopsis: Compares 2 WIDE access lists for equality
|
|
//
|
|
// Arguments: [pAccess1] -- First list
|
|
// [pAccess2] -- Second list
|
|
//
|
|
// Returns: ERROR_SUCCESS -- They match
|
|
// ERROR_INVALID_DATA -- They don't match
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD CompAccessW(PACTRL_ACCESSW pAccess1,
|
|
PACTRL_ACCESSW pAccess2)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
ULONG iIndex = 0;
|
|
|
|
if(pAccess1 == NULL || pAccess2 == NULL)
|
|
{
|
|
if(pAccess1 != pAccess2)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,"Access %lu is NULL\n",
|
|
pAccess1 == NULL ? 1 : 2);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PACTRL_ACCESS_ENTRY_LISTW pAAEL1;
|
|
PACTRL_ACCESS_ENTRY_LISTW pAAEL2;
|
|
|
|
dwErr = CompStringsW((PWSTR)pAccess1->pPropertyAccessList[0].lpProperty,
|
|
(PWSTR)pAccess2->pPropertyAccessList[0].lpProperty);
|
|
if(dwErr != ERROR_SUCCESS)
|
|
{
|
|
return(dwErr);
|
|
}
|
|
|
|
pAAEL1 = pAccess1->pPropertyAccessList[0].pAccessEntryList;
|
|
pAAEL2 = pAccess2->pPropertyAccessList[0].pAccessEntryList;
|
|
if(pAAEL1->cEntries != pAAEL2->cEntries)
|
|
{
|
|
dwErr = ERROR_INVALID_DATA;
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "cEntries: %lu %lu\n",
|
|
pAAEL1->cEntries,
|
|
pAAEL2->cEntries);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Compare all of the entries
|
|
//
|
|
for(iIndex = 0; iIndex < pAAEL1->cEntries; iIndex++)
|
|
{
|
|
if(_wcsicmp(pAAEL1->pAccessList[iIndex].Trustee.ptstrName,
|
|
pAAEL1->pAccessList[iIndex].Trustee.ptstrName) != 0)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "Trustees: %ws %ws\n",
|
|
pAAEL1->pAccessList[iIndex].Trustee.ptstrName,
|
|
pAAEL2->pAccessList[iIndex].Trustee.ptstrName);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
continue;
|
|
}
|
|
|
|
if(pAAEL1->pAccessList[iIndex].fAccessFlags !=
|
|
pAAEL1->pAccessList[iIndex].fAccessFlags)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "AccessFlags: %lu %lu\n",
|
|
pAAEL1->pAccessList[iIndex].fAccessFlags,
|
|
pAAEL2->pAccessList[iIndex].fAccessFlags);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
continue;
|
|
}
|
|
|
|
if(pAAEL1->pAccessList[iIndex].Access !=
|
|
pAAEL1->pAccessList[iIndex].Access)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "Access: %lu %lu\n",
|
|
pAAEL1->pAccessList[iIndex].Access,
|
|
pAAEL2->pAccessList[iIndex].Access);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
continue;
|
|
}
|
|
|
|
if(pAAEL1->pAccessList[iIndex].ProvSpecificAccess !=
|
|
pAAEL1->pAccessList[iIndex].ProvSpecificAccess)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "ProvSpecificAccess: %lu %lu\n",
|
|
pAAEL1->pAccessList[iIndex].ProvSpecificAccess,
|
|
pAAEL2->pAccessList[iIndex].ProvSpecificAccess);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
continue;
|
|
}
|
|
|
|
if(pAAEL1->pAccessList[iIndex].Inheritance !=
|
|
pAAEL1->pAccessList[iIndex].Inheritance)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "AccessFlags: %lu %lu\n",
|
|
pAAEL1->pAccessList[iIndex].Inheritance,
|
|
pAAEL2->pAccessList[iIndex].Inheritance);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// The inheritance property
|
|
//
|
|
dwErr = CompStringsW(
|
|
(PWSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty,
|
|
(PWSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty);
|
|
|
|
if(dwErr == ERROR_SUCCESS && fVerbose)
|
|
{
|
|
printf("AccessEntry %lu\n", iIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CompAccessA
|
|
//
|
|
// Synopsis: Compares 2 ANSI access lists for equality
|
|
//
|
|
// Arguments: [pAccess1] -- First list
|
|
// [pAccess2] -- Second list
|
|
//
|
|
// Returns: ERROR_SUCCESS -- They match
|
|
// ERROR_INVALID_DATA -- They don't match
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD CompAccessA(PACTRL_ACCESSA pAccess1,
|
|
PACTRL_ACCESSA pAccess2)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
ULONG iIndex = 0;
|
|
|
|
if(pAccess1 == NULL || pAccess2 == NULL)
|
|
{
|
|
if(pAccess1 != pAccess2)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr,"Access %lu is NULL\n",
|
|
pAccess1 == NULL ? 1 : 2);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PACTRL_ACCESS_ENTRY_LISTA pAAEL1;
|
|
PACTRL_ACCESS_ENTRY_LISTA pAAEL2;
|
|
|
|
dwErr = CompStringsA((PSTR)pAccess1->pPropertyAccessList[0].lpProperty,
|
|
(PSTR)pAccess2->pPropertyAccessList[0].lpProperty);
|
|
if(dwErr != ERROR_SUCCESS)
|
|
{
|
|
return(dwErr);
|
|
}
|
|
|
|
pAAEL1 = pAccess1->pPropertyAccessList[0].pAccessEntryList;
|
|
pAAEL2 = pAccess2->pPropertyAccessList[0].pAccessEntryList;
|
|
if(pAAEL1->cEntries != pAAEL2->cEntries)
|
|
{
|
|
dwErr = ERROR_INVALID_DATA;
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "cEntries: %lu %lu\n",
|
|
pAAEL1->cEntries,
|
|
pAAEL2->cEntries);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Compare all of the entries
|
|
//
|
|
for(iIndex = 0; iIndex < pAAEL1->cEntries; iIndex++)
|
|
{
|
|
if(_stricmp(pAAEL1->pAccessList[iIndex].Trustee.ptstrName,
|
|
pAAEL1->pAccessList[iIndex].Trustee.ptstrName) != 0)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "Trustees: %ws %ws\n",
|
|
pAAEL1->pAccessList[iIndex].Trustee.ptstrName,
|
|
pAAEL2->pAccessList[iIndex].Trustee.ptstrName);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
continue;
|
|
}
|
|
|
|
if(pAAEL1->pAccessList[iIndex].fAccessFlags !=
|
|
pAAEL1->pAccessList[iIndex].fAccessFlags)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "AccessFlags: %lu %lu\n",
|
|
pAAEL1->pAccessList[iIndex].fAccessFlags,
|
|
pAAEL2->pAccessList[iIndex].fAccessFlags);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
continue;
|
|
}
|
|
|
|
if(pAAEL1->pAccessList[iIndex].Access !=
|
|
pAAEL1->pAccessList[iIndex].Access)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "Access: %lu %lu\n",
|
|
pAAEL1->pAccessList[iIndex].Access,
|
|
pAAEL2->pAccessList[iIndex].Access);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
continue;
|
|
}
|
|
|
|
if(pAAEL1->pAccessList[iIndex].ProvSpecificAccess !=
|
|
pAAEL1->pAccessList[iIndex].ProvSpecificAccess)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "ProvSpecificAccess: %lu %lu\n",
|
|
pAAEL1->pAccessList[iIndex].ProvSpecificAccess,
|
|
pAAEL2->pAccessList[iIndex].ProvSpecificAccess);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
continue;
|
|
}
|
|
|
|
if(pAAEL1->pAccessList[iIndex].Inheritance !=
|
|
pAAEL1->pAccessList[iIndex].Inheritance)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
fprintf(stderr, "AccessFlags: %lu %lu\n",
|
|
pAAEL1->pAccessList[iIndex].Inheritance,
|
|
pAAEL2->pAccessList[iIndex].Inheritance);
|
|
}
|
|
dwErr = ERROR_INVALID_DATA;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// The inheritance property
|
|
//
|
|
dwErr = CompStringsA(
|
|
(PSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty,
|
|
(PSTR)pAAEL1->pAccessList[iIndex].lpInheritProperty);
|
|
|
|
if(dwErr == ERROR_SUCCESS && fVerbose)
|
|
{
|
|
printf("AccessEntry %lu\n", iIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DumpAccessW
|
|
//
|
|
// Synopsis: Dumps an ACTRL_ACCESSW structure to the screen
|
|
//
|
|
// Arguments: [pAccess] -- Structure to dump
|
|
//
|
|
// Returns: VOID
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
DumpAccessW(PACTRL_ACCESSW pAccess)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
ULONG iProp, iEnt;
|
|
printf("\tEntries: %lu\n", pAccess->cEntries);
|
|
for(iProp = 0; iProp < pAccess->cEntries; iProp++)
|
|
{
|
|
printf("\t\tProperty: %ws\n",
|
|
pAccess->pPropertyAccessList[iProp].lpProperty == NULL ?
|
|
L"NULL" :
|
|
pAccess->pPropertyAccessList[iProp].lpProperty);
|
|
printf("\t\tFlags: %lu\n",
|
|
pAccess->pPropertyAccessList[iProp].fListFlags);
|
|
if(pAccess->pPropertyAccessList[iProp].pAccessEntryList == NULL)
|
|
{
|
|
printf("\t\tpAccessEntryList: NULL\n");
|
|
}
|
|
else
|
|
{
|
|
PACTRL_ACCESS_ENTRYW pAE= pAccess->pPropertyAccessList[iProp].
|
|
pAccessEntryList->pAccessList;
|
|
printf("\t\t\tcEntries: %lu\n",
|
|
pAccess->pPropertyAccessList[iProp].pAccessEntryList->
|
|
cEntries);
|
|
|
|
for(iEnt = 0;
|
|
iEnt < pAccess->pPropertyAccessList[iProp].
|
|
pAccessEntryList->cEntries;
|
|
iEnt++)
|
|
{
|
|
printf("\t\t\tEntry %lu:\n", iEnt);
|
|
printf("\t\t\t\tTrustee.Name: %ws\n",
|
|
pAE[iEnt].Trustee.ptstrName);
|
|
printf("\t\t\t\tfAccessFlags: %lu\n",
|
|
pAE[iEnt].fAccessFlags);
|
|
printf("\t\t\t\tAccess: 0x%lx\n", pAE[iEnt].Access);
|
|
printf("\t\t\t\tProvSpecificAccess: %lu\n",
|
|
pAE[iEnt].ProvSpecificAccess);
|
|
printf("\t\t\t\tInheritance: %lu\n", pAE[iEnt].Inheritance);
|
|
printf("\t\t\t\tlpInheritProperty: %ws\n",
|
|
pAE[iEnt].lpInheritProperty == NULL ?
|
|
L"" :
|
|
pAE[iEnt].lpInheritProperty);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#define BUILD_COUNT 5
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Nt4BuildW
|
|
//
|
|
// Synopsis: Builds an ACL using the NT4 API WIDE apis
|
|
//
|
|
// Arguments: [ppAcl] -- Acl to build
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Everything worked
|
|
// ERROR_INVALID_DATA -- One of the compares failed
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Nt4BuildW(PACL *ppAcl)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
ULONG cCount;
|
|
EXPLICIT_ACCESS_W EAW;
|
|
PEXPLICIT_ACCESS_W pEAW;
|
|
PACL pAcl = NULL, pNewAcl;
|
|
ULONG iIndex, iVer;
|
|
|
|
PWSTR rgTrustees[BUILD_COUNT] = {EVERYONE,
|
|
SYSTEM,
|
|
GUEST,
|
|
EVERYONE,
|
|
SYSTEM};
|
|
|
|
DWORD rgAccess[BUILD_COUNT] = {GENERIC_ALL | 0x8,
|
|
GENERIC_ALL,
|
|
GENERIC_ALL | 0x8,
|
|
GENERIC_ALL | 0x8,
|
|
0};
|
|
|
|
ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS,
|
|
DENY_ACCESS,
|
|
SET_ACCESS,
|
|
SET_ACCESS,
|
|
REVOKE_ACCESS};
|
|
|
|
DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE,
|
|
NO_INHERITANCE,
|
|
SUB_CONTAINERS_AND_OBJECTS_INHERIT,
|
|
NO_INHERITANCE,
|
|
SUB_CONTAINERS_AND_OBJECTS_INHERIT};
|
|
|
|
DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0},
|
|
{2, 1, 0},
|
|
{3, 1, 2, 0},
|
|
{3, 1, 3, 2},
|
|
{2, 3, 2}};
|
|
if(fVerbose)
|
|
{
|
|
printf("Nt4BuildW\n");
|
|
}
|
|
|
|
//
|
|
// We'll do this in a loop, since we have BUILD_COUNT different builds to do
|
|
//
|
|
for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++)
|
|
{
|
|
//
|
|
// Build the new entry
|
|
//
|
|
BuildExplicitAccessWithNameW(&EAW,
|
|
rgTrustees[iIndex],
|
|
rgAccess[iIndex],
|
|
rgMode[iIndex],
|
|
rgInherit[iIndex]);
|
|
|
|
dwErr = SetEntriesInAclW(1,
|
|
&EAW,
|
|
pAcl,
|
|
&pNewAcl);
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
LocalFree(pAcl);
|
|
pAcl = pNewAcl;
|
|
|
|
//
|
|
// Get the explicit entries, and we'll verify them...
|
|
//
|
|
dwErr = GetExplicitEntriesFromAclW(pAcl,
|
|
&cCount,
|
|
&pEAW);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
PDWORD pSrch = rgSrch[iIndex];
|
|
ULONG cExpected = pSrch[0];
|
|
|
|
if(cCount != cExpected)
|
|
{
|
|
dwErr = ERROR_INVALID_DATA;
|
|
if(fVerbose)
|
|
{
|
|
printf("\tCount mismatched: %lu, expected %lu\n",
|
|
cCount,
|
|
cExpected);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// verify the rest of the data
|
|
//
|
|
for(iVer = 0; iVer < cExpected; iVer++)
|
|
{
|
|
ULONG iSrch = pSrch[iVer + 1];
|
|
if(_wcsicmp(pEAW[iVer].Trustee.ptstrName,
|
|
rgTrustees[iSrch]) != 0)
|
|
{
|
|
dwErr = ERROR_INVALID_DATA;
|
|
if(fVerbose)
|
|
{
|
|
printf("\tTrustee mismatch[%lu]: %ws, expected "
|
|
"%ws\n",
|
|
iVer,
|
|
pEAW[iVer].Trustee.ptstrName,
|
|
rgTrustees[iSrch]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tCount: %lu\n", cCount);
|
|
}
|
|
}
|
|
LocalFree(pEAW);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,
|
|
"\tNt4BuildW: SetEntriesInAclW failed with %lu\n",
|
|
dwErr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,"\tNt4BuildW: SetEntriesInAclW failed with %lu\n",
|
|
dwErr);
|
|
}
|
|
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
*ppAcl = pAcl;
|
|
}
|
|
else
|
|
{
|
|
LocalFree(pAcl);
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Nt4BuildA
|
|
//
|
|
// Synopsis: Builds an ACL using the NT4 API ANSI apis
|
|
//
|
|
// Arguments: [ppAcl] -- Acl to build
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Everything worked
|
|
// ERROR_INVALID_DATA -- One of the compares failed
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Nt4BuildA(PACL *ppAcl)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
ULONG cCount;
|
|
EXPLICIT_ACCESS_A EAA;
|
|
PEXPLICIT_ACCESS_A pEAA;
|
|
PACL pAcl = NULL, pNewAcl;
|
|
ULONG iIndex, iVer;
|
|
|
|
PSTR rgTrustees[BUILD_COUNT] = {EVERYONE_A,
|
|
SYSTEM_A,
|
|
GUEST_A,
|
|
EVERYONE_A,
|
|
SYSTEM_A};
|
|
|
|
DWORD rgAccess[BUILD_COUNT] = {GENERIC_ALL | 0x8,
|
|
GENERIC_ALL,
|
|
GENERIC_ALL | 0x8,
|
|
GENERIC_ALL | 0x8,
|
|
0};
|
|
|
|
ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS,
|
|
DENY_ACCESS,
|
|
SET_ACCESS,
|
|
SET_ACCESS,
|
|
REVOKE_ACCESS};
|
|
|
|
DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE,
|
|
NO_INHERITANCE,
|
|
SUB_CONTAINERS_AND_OBJECTS_INHERIT,
|
|
NO_INHERITANCE,
|
|
SUB_CONTAINERS_AND_OBJECTS_INHERIT};
|
|
|
|
DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0},
|
|
{2, 1, 0},
|
|
{3, 1, 2, 0},
|
|
{3, 1, 3, 2},
|
|
{2, 3, 2}};
|
|
if(fVerbose)
|
|
{
|
|
printf("Nt4BuildA\n");
|
|
}
|
|
|
|
//
|
|
// We'll do this in a loop, since we have BUILD_COUNT different builds to do
|
|
//
|
|
for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++)
|
|
{
|
|
//
|
|
// Build the new entry
|
|
//
|
|
BuildExplicitAccessWithNameA(&EAA,
|
|
rgTrustees[iIndex],
|
|
rgAccess[iIndex],
|
|
rgMode[iIndex],
|
|
rgInherit[iIndex]);
|
|
|
|
dwErr = SetEntriesInAclA(1,
|
|
&EAA,
|
|
pAcl,
|
|
&pNewAcl);
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
LocalFree(pAcl);
|
|
pAcl = pNewAcl;
|
|
|
|
//
|
|
// Get the explicit entries, and we'll verify them...
|
|
//
|
|
dwErr = GetExplicitEntriesFromAclA(pAcl,
|
|
&cCount,
|
|
&pEAA);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
PDWORD pSrch = rgSrch[iIndex];
|
|
ULONG cExpected = pSrch[0];
|
|
|
|
if(cCount != cExpected)
|
|
{
|
|
dwErr = ERROR_INVALID_DATA;
|
|
if(fVerbose)
|
|
{
|
|
printf("\tCount mismatched: %lu, expected %lu\n",
|
|
cCount,
|
|
cExpected);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// verify the rest of the data
|
|
//
|
|
for(iVer = 0; iVer < cExpected; iVer++)
|
|
{
|
|
ULONG iSrch = pSrch[iVer + 1];
|
|
if(_stricmp(pEAA[iVer].Trustee.ptstrName,
|
|
rgTrustees[iSrch]) != 0)
|
|
{
|
|
dwErr = ERROR_INVALID_DATA;
|
|
if(fVerbose)
|
|
{
|
|
printf("\tTrustee mismatch[%lu]: %s, expected "
|
|
"%s\n",
|
|
iVer,
|
|
pEAA[iVer].Trustee.ptstrName,
|
|
rgTrustees[iSrch]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tCount: %lu\n", cCount);
|
|
}
|
|
}
|
|
|
|
LocalFree(pEAA);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,
|
|
"\tNt4BuildA: SetEntriesInAclA failed with %lu\n",
|
|
dwErr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,"\tNt4BuildA: SetEntriesInAclA failed with %lu\n",
|
|
dwErr);
|
|
}
|
|
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
*ppAcl = pAcl;
|
|
}
|
|
else
|
|
{
|
|
LocalFree(pAcl);
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
#undef BUILD_COUNT
|
|
#define BUILD_COUNT 6
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Nt5BuildW
|
|
//
|
|
// Synopsis: Builds an ACL using the NT5 API WIDE apis
|
|
//
|
|
// Arguments: [ppAccess] -- Access list to build
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Everything worked
|
|
// ERROR_INVALID_DATA -- One of the compares failed
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Nt5BuildW(PACTRL_ACCESSW *ppAccess)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
PACTRL_ACCESSW pAccess = NULL, pNewAccess;
|
|
ULONG iIndex, iVer;
|
|
|
|
PWSTR rgTrustees[BUILD_COUNT] = {SYSTEM, EVERYONE, SYSTEM, GUEST,
|
|
EVERYONE, SYSTEM};
|
|
|
|
DWORD rgTypes[BUILD_COUNT] = {ACTRL_ACCESS_ALLOWED,
|
|
ACTRL_ACCESS_ALLOWED,
|
|
ACTRL_ACCESS_DENIED,
|
|
ACTRL_ACCESS_ALLOWED,
|
|
ACTRL_ACCESS_ALLOWED,
|
|
ACTRL_ACCESS_DENIED};
|
|
|
|
DWORD rgAccess[BUILD_COUNT] = {ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_5,
|
|
ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_1,
|
|
ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2,
|
|
ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_3,
|
|
ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_4,
|
|
ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2};
|
|
|
|
ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS, SET_ACCESS, GRANT_ACCESS,
|
|
GRANT_ACCESS, GRANT_ACCESS,
|
|
REVOKE_ACCESS};
|
|
|
|
DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE, NO_INHERITANCE,
|
|
NO_INHERITANCE, NO_INHERITANCE,
|
|
NO_INHERITANCE, NO_INHERITANCE};
|
|
|
|
DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0},
|
|
{1, 1},
|
|
{2, 2, 1},
|
|
{3, 2, 3, 1},
|
|
{4, 2, 4, 3, 1},
|
|
{3, 4, 3, 1}};
|
|
if(fVerbose)
|
|
{
|
|
printf("Nt5BuildW\n");
|
|
}
|
|
|
|
//
|
|
// We'll do this in a loop, since we have BUILD_COUNT different builds to do
|
|
//
|
|
for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++)
|
|
{
|
|
|
|
ACTRL_ACCESS_ENTRYW AAE;
|
|
|
|
BuildTrusteeWithNameW(&(AAE.Trustee),
|
|
rgTrustees[iIndex]);
|
|
AAE.fAccessFlags = rgTypes[iIndex];
|
|
AAE.Access = rgAccess[iIndex];
|
|
AAE.ProvSpecificAccess = 0;
|
|
AAE.Inheritance = rgInherit[iIndex];
|
|
AAE.lpInheritProperty = NULL;
|
|
|
|
dwErr = SetEntriesInAccessListW(1,
|
|
&AAE,
|
|
rgMode[iIndex],
|
|
NULL,
|
|
pAccess,
|
|
&pNewAccess);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
LocalFree(pAccess);
|
|
pAccess = pNewAccess;
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Now, verify the new entries...
|
|
//
|
|
PACTRL_ACCESS_ENTRY_LISTW pAAELW =
|
|
pAccess->pPropertyAccessList[0].pAccessEntryList;
|
|
PDWORD pSrch = rgSrch[iIndex];
|
|
ULONG cExpected = pSrch[0];
|
|
|
|
if(pAAELW->cEntries != cExpected)
|
|
{
|
|
dwErr = ERROR_INVALID_DATA;
|
|
if(fVerbose)
|
|
{
|
|
printf("\tCount mismatched: %lu, expected %lu\n",
|
|
pAAELW->cEntries,
|
|
cExpected);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// verify the rest of the data
|
|
//
|
|
for(iVer = 0; iVer < pAAELW->cEntries; iVer++)
|
|
{
|
|
ULONG iSrch = pSrch[iVer + 1];
|
|
if(_wcsicmp(pAAELW->pAccessList[iVer].Trustee.ptstrName,
|
|
rgTrustees[iSrch]) != 0)
|
|
{
|
|
dwErr = ERROR_INVALID_DATA;
|
|
if(fVerbose)
|
|
{
|
|
printf("\tTrustee mismatch[%lu]: %ws, expected "
|
|
"%ws\n",
|
|
iVer,
|
|
pAAELW->pAccessList[iVer].Trustee.ptstrName,
|
|
rgTrustees[iSrch]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tCount: %lu\n", cExpected);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,"\tNt5BuildW: SetEntriesInAccessListW failed "
|
|
"with %lu\n",
|
|
dwErr);
|
|
}
|
|
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
*ppAccess = pAccess;
|
|
}
|
|
else
|
|
{
|
|
LocalFree(pAccess);
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Nt5BuildA
|
|
//
|
|
// Synopsis: Builds an ACL using the NT5 API ANSI apis
|
|
//
|
|
// Arguments: [ppAccess] -- Access list to build
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Everything worked
|
|
// ERROR_INVALID_DATA -- One of the compares failed
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Nt5BuildA(PACTRL_ACCESSA *ppAccess)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
PACTRL_ACCESSA pAccess = NULL, pNewAccess;
|
|
ULONG iIndex, iVer;
|
|
|
|
PSTR rgTrustees[BUILD_COUNT] = {SYSTEM_A, EVERYONE_A, SYSTEM_A, GUEST_A,
|
|
EVERYONE_A, SYSTEM_A};
|
|
|
|
DWORD rgTypes[BUILD_COUNT] = {ACTRL_ACCESS_ALLOWED,
|
|
ACTRL_ACCESS_ALLOWED,
|
|
ACTRL_ACCESS_DENIED,
|
|
ACTRL_ACCESS_ALLOWED,
|
|
ACTRL_ACCESS_ALLOWED,
|
|
ACTRL_ACCESS_DENIED};
|
|
|
|
DWORD rgAccess[BUILD_COUNT] = {ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_5,
|
|
ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_1,
|
|
ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2,
|
|
ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_3,
|
|
ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_4,
|
|
ACTRL_STD_RIGHTS_ALL | ACTRL_PERM_2};
|
|
|
|
ACCESS_MODE rgMode[BUILD_COUNT] = {SET_ACCESS, SET_ACCESS, GRANT_ACCESS,
|
|
GRANT_ACCESS, GRANT_ACCESS,
|
|
REVOKE_ACCESS};
|
|
|
|
DWORD rgInherit[BUILD_COUNT] = {NO_INHERITANCE, NO_INHERITANCE,
|
|
NO_INHERITANCE, NO_INHERITANCE,
|
|
NO_INHERITANCE, NO_INHERITANCE};
|
|
|
|
DWORD rgSrch[BUILD_COUNT][BUILD_COUNT + 1] = {{1, 0},
|
|
{1, 1},
|
|
{2, 2, 1},
|
|
{3, 2, 3, 1},
|
|
{4, 2, 4, 3, 1},
|
|
{3, 4, 3, 1}};
|
|
if(fVerbose)
|
|
{
|
|
printf("Nt5BuildA\n");
|
|
}
|
|
|
|
//
|
|
// We'll do this in a loop, since we have BUILD_COUNT different builds to do
|
|
//
|
|
for(iIndex = 0; iIndex < BUILD_COUNT && dwErr == ERROR_SUCCESS; iIndex++)
|
|
{
|
|
|
|
ACTRL_ACCESS_ENTRYA AAE;
|
|
|
|
BuildTrusteeWithNameA(&(AAE.Trustee),
|
|
rgTrustees[iIndex]);
|
|
AAE.fAccessFlags = rgTypes[iIndex];
|
|
AAE.Access = rgAccess[iIndex];
|
|
AAE.ProvSpecificAccess = 0;
|
|
AAE.Inheritance = rgInherit[iIndex];
|
|
AAE.lpInheritProperty = NULL;
|
|
|
|
dwErr = SetEntriesInAccessListA(1,
|
|
&AAE,
|
|
rgMode[iIndex],
|
|
NULL,
|
|
pAccess,
|
|
&pNewAccess);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
LocalFree(pAccess);
|
|
pAccess = pNewAccess;
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Now, verify the new entries...
|
|
//
|
|
PACTRL_ACCESS_ENTRY_LISTA pAAELA =
|
|
pAccess->pPropertyAccessList[0].pAccessEntryList;
|
|
PDWORD pSrch = rgSrch[iIndex];
|
|
ULONG cExpected = pSrch[0];
|
|
|
|
if(pAAELA->cEntries != cExpected)
|
|
{
|
|
dwErr = ERROR_INVALID_DATA;
|
|
if(fVerbose)
|
|
{
|
|
printf("\tCount mismatched: %lu, expected %lu\n",
|
|
pAAELA->cEntries,
|
|
cExpected);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// verify the rest of the data
|
|
//
|
|
for(iVer = 0; iVer < pAAELA->cEntries; iVer++)
|
|
{
|
|
ULONG iSrch = pSrch[iVer + 1];
|
|
if(_stricmp(pAAELA->pAccessList[iVer].Trustee.ptstrName,
|
|
rgTrustees[iSrch]) != 0)
|
|
{
|
|
dwErr = ERROR_INVALID_DATA;
|
|
if(fVerbose)
|
|
{
|
|
printf("\tTrustee mismatch[%lu]: %s, expected "
|
|
"%s\n",
|
|
iVer,
|
|
pAAELA->pAccessList[iVer].Trustee.ptstrName,
|
|
rgTrustees[iSrch]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tCount: %lu\n", cExpected);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,"\tNt5BuildA: SetEntriesInAccessListA failed "
|
|
"with %lu\n",
|
|
dwErr);
|
|
}
|
|
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
*ppAccess = pAccess;
|
|
}
|
|
else
|
|
{
|
|
LocalFree(pAccess);
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Nt4DrtW
|
|
//
|
|
// Synopsis: Does the actual API drt. This involves reading the existing
|
|
// access, writing the new one, rereading the new one and
|
|
// verifing the results, and then restores the old one. This
|
|
// uses the WIDE version of the NT4 APIs
|
|
//
|
|
// Arguments: [pAcl] -- Acl to write on the object
|
|
// [pszObject] -- The object in question
|
|
// [ObjType] -- Type of the object
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Success
|
|
// ERROR_INVALID_DATA -- One of the compares failed
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Nt4DrtW(PACL pAcl,
|
|
PSTR pszObject,
|
|
SE_OBJECT_TYPE ObjType)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR wszPath[MAX_PATH + 1];
|
|
PACL pOldAcl = NULL;
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
|
|
mbstowcs(wszPath, pszObject, strlen(pszObject) + 1);
|
|
|
|
if(fVerbose)
|
|
{
|
|
printf("Nt4DrtW: Processing %ws [%lu]\n", wszPath, ObjType);
|
|
}
|
|
|
|
//
|
|
// First, get the old acl
|
|
//
|
|
dwErr = GetNamedSecurityInfoW(wszPath,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
&pOldAcl,
|
|
NULL,
|
|
&pSD);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Set, get, and compare the new acl...
|
|
//
|
|
dwErr = SetNamedSecurityInfoW(wszPath,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
pAcl,
|
|
NULL);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
PACL pNewAcl = NULL;
|
|
PSECURITY_DESCRIPTOR pNewSD = NULL;
|
|
dwErr = GetNamedSecurityInfoW(wszPath,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
&pNewAcl,
|
|
NULL,
|
|
&pNewSD);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Compare them...
|
|
//
|
|
dwErr = CompAcls(pAcl, pNewAcl);
|
|
if(dwErr != ERROR_SUCCESS)
|
|
{
|
|
fprintf(stderr, "\tSet and old ACLs don't compare\n");
|
|
}
|
|
LocalFree(pNewSD);
|
|
}
|
|
else
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tSecond GetNamedSecurityW on %ws failed with %lu\n",
|
|
wszPath,
|
|
dwErr);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tSetNamedSecurityInfoW on %ws failed with %lu\n",
|
|
wszPath,
|
|
dwErr);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,
|
|
"\tGetNamedSecurityInfoW failed on %ws: %lu\n",
|
|
wszPath,
|
|
dwErr);
|
|
}
|
|
|
|
//
|
|
// Restore the objects security
|
|
//
|
|
if(pSD != NULL)
|
|
{
|
|
DWORD dwErr2 = SetNamedSecurityInfoW(wszPath,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
pOldAcl,
|
|
NULL);
|
|
if(dwErr2 != ERROR_SUCCESS)
|
|
{
|
|
fprintf(stderr,
|
|
"Restoring access to %ws failed with %lu\n",
|
|
wszPath,
|
|
dwErr2);
|
|
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = dwErr2;
|
|
}
|
|
|
|
}
|
|
LocalFree(pSD);
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Nt4DrtA
|
|
//
|
|
// Synopsis: Does the actual API drt. This involves reading the existing
|
|
// access, writing the new one, rereading the new one and
|
|
// verifing the results, and then restores the old one. This
|
|
// uses the ANSI version of the NT4 APIs
|
|
//
|
|
// Arguments: [pAcl] -- Acl to write on the object
|
|
// [pszObject] -- The object in question
|
|
// [ObjType] -- Type of the object
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Success
|
|
// ERROR_INVALID_DATA -- One of the compares failed
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Nt4DrtA(PACL pAcl,
|
|
PSTR pszObject,
|
|
SE_OBJECT_TYPE ObjType)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
PACL pOldAcl = NULL;
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
|
|
if(fVerbose)
|
|
{
|
|
printf("Nt4DrtA: Processing %s [%lu]\n", pszObject, ObjType);
|
|
}
|
|
|
|
//
|
|
// First, get the old acl
|
|
//
|
|
dwErr = GetNamedSecurityInfoA(pszObject,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
&pOldAcl,
|
|
NULL,
|
|
&pSD);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Set, get, and compare the new acl...
|
|
//
|
|
dwErr = SetNamedSecurityInfoA(pszObject,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
pAcl,
|
|
NULL);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
PACL pNewAcl = NULL;
|
|
PSECURITY_DESCRIPTOR pNewSD = NULL;
|
|
dwErr = GetNamedSecurityInfoA(pszObject,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
&pNewAcl,
|
|
NULL,
|
|
&pNewSD);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Compare them...
|
|
//
|
|
dwErr = CompAcls(pAcl, pNewAcl);
|
|
if(dwErr != ERROR_SUCCESS)
|
|
{
|
|
fprintf(stderr, "\tSet and old ACLs don't compare\n");
|
|
}
|
|
LocalFree(pNewSD);
|
|
}
|
|
else
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tSecond GetNamedSecurityA on %s failed with %lu\n",
|
|
pszObject,
|
|
dwErr);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tSetNamedSecurityInfoA on %s failed with %lu\n",
|
|
pszObject,
|
|
dwErr);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,
|
|
"\tGetNamedSecurityInfoA failed on %s: %lu\n",
|
|
pszObject,
|
|
dwErr);
|
|
}
|
|
|
|
//
|
|
// Restore the objects security
|
|
//
|
|
if(pSD != NULL)
|
|
{
|
|
DWORD dwErr2 = SetNamedSecurityInfoA(pszObject,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
pOldAcl,
|
|
NULL);
|
|
if(dwErr2 != ERROR_SUCCESS)
|
|
{
|
|
fprintf(stderr,
|
|
"Restoring access to %s failed with %lu\n",
|
|
pszObject,
|
|
dwErr2);
|
|
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = dwErr2;
|
|
}
|
|
|
|
}
|
|
LocalFree(pSD);
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Nt5DrtW
|
|
//
|
|
// Synopsis: Does the actual API drt. This involves reading the existing
|
|
// access, writing the new one, rereading the new one and
|
|
// verifing the results, and then restores the old one. This
|
|
// uses the WIDE version of the NT5 APIs
|
|
//
|
|
// Arguments: [pAccess] -- Access list to write on the object
|
|
// [pszObject] -- The object in question
|
|
// [ObjType] -- Type of the object
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Success
|
|
// ERROR_INVALID_DATA -- One of the compares failed
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Nt5DrtW(PACTRL_ACCESSW pAccess,
|
|
PSTR pszObject,
|
|
SE_OBJECT_TYPE ObjType)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR wszPath[MAX_PATH + 1];
|
|
PACTRL_ACCESSW pOldAccess = NULL;
|
|
|
|
mbstowcs(wszPath, pszObject, strlen(pszObject) + 1);
|
|
|
|
if(fVerbose)
|
|
{
|
|
printf("Nt5DrtW: Processing %ws [%lu]\n", wszPath, ObjType);
|
|
}
|
|
|
|
//
|
|
// First, get the old acl
|
|
//
|
|
dwErr = GetNamedSecurityInfoExW(wszPath,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
&pOldAccess,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
|
|
//
|
|
// Set, get, and compare the new value...
|
|
//
|
|
dwErr = SetNamedSecurityInfoExW(wszPath,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
pAccess,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
PACTRL_ACCESS pNewAccess = NULL;
|
|
dwErr = GetNamedSecurityInfoExW(wszPath,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
&pNewAccess,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Compare them...
|
|
//
|
|
dwErr = CompAccessW(pAccess, pNewAccess);
|
|
if(dwErr != ERROR_SUCCESS)
|
|
{
|
|
fprintf(stderr, "\tSet and old Accesses don't compare\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tSecond GetNamedSecurityExW on %ws failed "
|
|
"with %lu\n",
|
|
wszPath,
|
|
dwErr);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tSetNamedSecurityInfoExW on %ws failed with %lu\n",
|
|
wszPath,
|
|
dwErr);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,
|
|
"\tGetNamedSecurityInfoExW failed on %ws: %lu\n",
|
|
wszPath,
|
|
dwErr);
|
|
}
|
|
|
|
//
|
|
// Restore the objects security
|
|
//
|
|
if(pOldAccess != NULL)
|
|
{
|
|
DWORD dwErr2 = SetNamedSecurityInfoExW(wszPath,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
pOldAccess,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if(dwErr2 != ERROR_SUCCESS)
|
|
{
|
|
fprintf(stderr,
|
|
"Restoring access to %ws failed with %lu\n",
|
|
wszPath,
|
|
dwErr2);
|
|
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = dwErr2;
|
|
}
|
|
|
|
}
|
|
|
|
LocalFree(pOldAccess);
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Nt5DrtA
|
|
//
|
|
// Synopsis: Does the actual API drt. This involves reading the existing
|
|
// access, writing the new one, rereading the new one and
|
|
// verifing the results, and then restores the old one. This
|
|
// uses the ANSI version of the NT5 APIs
|
|
//
|
|
// Arguments: [pAccess] -- Access list to write on the object
|
|
// [pszObject] -- The object in question
|
|
// [ObjType] -- Type of the object
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Success
|
|
// ERROR_INVALID_DATA -- One of the compares failed
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD Nt5DrtA(PACTRL_ACCESSA pAccess,
|
|
PSTR pszObject,
|
|
SE_OBJECT_TYPE ObjType)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
PACTRL_ACCESSA pOldAccess = NULL;
|
|
|
|
if(fVerbose)
|
|
{
|
|
printf("Nt5DrtA: Processing %s [%lu]\n", pszObject, ObjType);
|
|
}
|
|
|
|
//
|
|
// First, get the old acl
|
|
//
|
|
dwErr = GetNamedSecurityInfoExA(pszObject,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
&pOldAccess,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Set, get, and compare the new value...
|
|
//
|
|
dwErr = SetNamedSecurityInfoExA(pszObject,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
pAccess,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
PACTRL_ACCESSA pNewAccess = NULL;
|
|
dwErr = GetNamedSecurityInfoExA(pszObject,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
&pNewAccess,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Compare them...
|
|
//
|
|
dwErr = CompAccessA(pAccess, pNewAccess);
|
|
if(dwErr != ERROR_SUCCESS)
|
|
{
|
|
fprintf(stderr, "\tSet and old Accesses don't compare\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tSecond GetNamedSecurityExA on %s failed "
|
|
"with %lu\n",
|
|
pszObject,
|
|
dwErr);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
printf("\tSetNamedSecurityInfoExA on %s failed with %lu\n",
|
|
pszObject,
|
|
dwErr);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,
|
|
"\tGetNamedSecurityInfoExA failed on %s: %lu\n",
|
|
pszObject,
|
|
dwErr);
|
|
}
|
|
|
|
//
|
|
// Restore the objects security
|
|
//
|
|
if(pOldAccess != NULL)
|
|
{
|
|
DWORD dwErr2 = SetNamedSecurityInfoExA(pszObject,
|
|
ObjType,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
pOldAccess,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if(dwErr2 != ERROR_SUCCESS)
|
|
{
|
|
fprintf(stderr,
|
|
"Restoring access to %s failed with %lu\n",
|
|
pszObject,
|
|
dwErr2);
|
|
|
|
}
|
|
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = dwErr2;
|
|
}
|
|
|
|
}
|
|
|
|
LocalFree(pOldAccess);
|
|
|
|
//
|
|
// Finally, try to convert to and from a security descriptor
|
|
//
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
PSECURITY_DESCRIPTOR pSD;
|
|
dwErr = ConvertAccessToSecurityDescriptorA(pAccess,
|
|
NULL,
|
|
"ntds\\macm",
|
|
NULL,
|
|
&pSD);
|
|
if(dwErr != ERROR_SUCCESS)
|
|
{
|
|
fprintf(stderr,
|
|
"ConvertAccessToSecurityDescriptor failed with %lu\n",
|
|
dwErr);
|
|
}
|
|
else
|
|
{
|
|
PACTRL_ACCESSA pNewAccess;
|
|
PSTR pszName;
|
|
|
|
dwErr = ConvertSecurityDescriptorToAccessA(pszObject,
|
|
ObjType,
|
|
pSD,
|
|
&pNewAccess,
|
|
NULL,
|
|
&pszName,
|
|
NULL);
|
|
if(dwErr == ERROR_SUCCESS)
|
|
{
|
|
AccFree(pszName);
|
|
AccFree(pNewAccess);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,
|
|
"ConvertSecurityDescriptorToAccessA failed with %lu\n",
|
|
dwErr);
|
|
}
|
|
|
|
LocalFree(pSD);
|
|
}
|
|
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|