Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1066 lines
30 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
aclfuncs.c
Abstract:
This module contians the functions to process the items from the files
containing the ACL entries for registry keys and files
Author:
Bob Watson (a-robw) Dec-94
Revision History:
--*/
#ifdef TEST_MODE
#undef TEST_MODE
#endif
//#define TEST_MODE 1
#include <windows.h>
#include <stdio.h>
#include <c2inc.h>
#include <c2dll.h>
#include <c2utils.h>
#include "c2acls.h"
#include "c2aclres.h"
#include "strings.h"
#define FILE_ENTRY 1
#define DIR_ENTRY 2
// internal flag
#define FILE_PATH_SUBDIRS 8
#define NTFS_NOT_STANDARD 0x00000000
#define NTFS_FULL_CONTROL 0x00010001
#define NTFS_CHANGE 0x00010002
#define NTFS_ADD_READ 0x00010003
#define NTFS_READ 0x00010004
#define NTFS_ADD 0x00010005
#define NTFS_LIST 0x00010006
#define NTFS_NO_ACCESS 0x00010007
#define NTFS_NONE 0x00000008
#define NTFS_ALL 0x00000009
#define NTFS_FILE_ALL_ACCESS (FILE_ALL_ACCESS)
#define NTFS_FILE_CHANGE (FILE_GENERIC_READ | FILE_GENERIC_WRITE | \
FILE_GENERIC_EXECUTE | DELETE)
#define NTFS_FILE_ADD_READ (FILE_GENERIC_READ | FILE_GENERIC_WRITE | \
FILE_GENERIC_EXECUTE)
#define NTFS_FILE_READ (FILE_GENERIC_READ | FILE_GENERIC_EXECUTE)
#define NTFS_FILE_ADD (FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE)
#define NTFS_FILE_LIST (FILE_GENERIC_READ | FILE_GENERIC_EXECUTE)
#define NTFS_FILE_NO_ACCESS (FILE_ALL_ACCESS) /* access denied ace */
#define NTFS_DIR_ALL_ACCESS (GENERIC_ALL)
#define NTFS_DIR_CHANGE (GENERIC_READ | GENERIC_WRITE | \
GENERIC_EXECUTE | DELETE)
#define NTFS_DIR_ADD_READ (GENERIC_READ | GENERIC_EXECUTE)
#define NTFS_DIR_READ (GENERIC_READ | GENERIC_EXECUTE)
#define NTFS_DIR_ADD (GENERIC_WRITE | GENERIC_EXECUTE)
#define NTFS_DIR_LIST (GENERIC_READ | GENERIC_EXECUTE)
#define NTFS_DIR_NO_ACCESS (GENERIC_ALL) /* access denied ace */
#define NTFS_DIR_DIR_FLAGS (INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE)
#define NTFS_DIR_FILE_FLAGS (CONTAINER_INHERIT_ACE)
#define NTFS_FILE_FILE_FLAGS 0x00
typedef struct _ACCESS_DECODE {
LPTSTR szString;
DWORD dwMask;
} ACCESS_DECODE, *PACCESS_DECODE;
#ifdef TEST_MODE
LONG
DumpAclData (
IN LPCTSTR szFileName,
IN PSECURITY_DESCRIPTOR psdFile
);
#endif
static ACCESS_DECODE adRegistryDecodeList[] = {
// specific access
{TEXT("QV"), (DWORD)KEY_QUERY_VALUE},
{TEXT("SV"), (DWORD)KEY_SET_VALUE},
{TEXT("CS"), (DWORD)KEY_CREATE_SUB_KEY},
{TEXT("ES"), (DWORD)KEY_ENUMERATE_SUB_KEYS},
{TEXT("NT"), (DWORD)KEY_NOTIFY},
{TEXT("CL"), (DWORD)KEY_CREATE_LINK},
// standard rights
{TEXT("DE"), (DWORD)DELETE},
{TEXT("RC"), (DWORD)READ_CONTROL},
{TEXT("WD"), (DWORD)WRITE_DAC},
{TEXT("WO"), (DWORD)WRITE_OWNER},
// predefined groups
{TEXT("NONE"), (DWORD)0},
{TEXT("FULL"), (DWORD)KEY_ALL_ACCESS},
{TEXT("READ"), (DWORD)KEY_READ},
// terminating entry
{NULL, (DWORD)0}
};
static ACCESS_DECODE adNtfsDecodeList[] = {
// predefined "combination" access keywords
{TEXT("FullControl"), (DWORD)NTFS_FULL_CONTROL},
{TEXT("Change"), (DWORD)NTFS_CHANGE},
{TEXT("AddRead"), (DWORD)NTFS_ADD_READ},
{TEXT("Read"), (DWORD)NTFS_READ},
{TEXT("Add"), (DWORD)NTFS_ADD},
{TEXT("List"), (DWORD)NTFS_LIST},
{TEXT("NoAccess"), (DWORD)NTFS_NO_ACCESS},
// predefined single ACE entries
{TEXT("NONE"), (DWORD)NTFS_NONE},
{TEXT("ALL"), (DWORD)NTFS_ALL},
// terminating entry
{NULL, (DWORD)0}
};
static
BOOL
DotOrDotDotDir (
IN LPCTSTR szFileName
)
/*++
Routine Description:
examines the filename in the parameter list to see if it is one
of the default subdirectories (e.g. the . or the .. dirs). This
routine assumes that the argument is a filename only. (i.e. NO
PATH!)
Arguments:
Filename to compare
Return Value:
TRUE if filename is either the . or the .. dir
FALSE if it is any other string
--*/
{
if (szFileName != NULL) { // check for null parameter
if (lstrcmp(szFileName, cszDot) == 0) {
return TRUE; // it's the . dir
} else if (lstrcmp(szFileName, cszDotDot) == 0) {
return TRUE; // it's the .. dir
} else {
return FALSE; // it's neither
}
} else {
return FALSE; // null filename, so not a . or .. dir
}
}
static
BOOL
IsDirectory (
IN LPCTSTR szFilePath
)
{
DWORD dwAttrib;
dwAttrib = QuietGetFileAttributes (szFilePath);
if (dwAttrib != 0xFFFFFFFF) {
return ((dwAttrib & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
} else {
return FALSE;
}
}
static
ACCESS_MASK
ReadNtfsPermissionString (
IN LPCTSTR szPerms,
IN BOOL bDirectory
)
{
LPCTSTR szThisChar;
ACCESS_MASK amReturn = 0;
for (szThisChar = szPerms; *szThisChar != 0; szThisChar++) {
switch (*szThisChar) {
case TEXT('R'):
case TEXT('r'):
amReturn |= (bDirectory ? GENERIC_READ : FILE_GENERIC_READ);
break;
case TEXT('W'):
case TEXT('w'):
amReturn |= (bDirectory ? GENERIC_WRITE : FILE_GENERIC_WRITE);
break;
case TEXT('X'):
case TEXT('x'):
amReturn |= (bDirectory ? GENERIC_EXECUTE : FILE_GENERIC_EXECUTE);
break;
case TEXT('D'):
case TEXT('d'):
amReturn |= DELETE;
break;
case TEXT('P'):
case TEXT('p'):
amReturn |= WRITE_DAC;
break;
case TEXT('O'):
case TEXT('o'):
amReturn |= WRITE_OWNER;
break;
default:
// no change if unrecognized
break;
}
}
return amReturn;
}
HKEY
GetRootKey (
IN LPCTSTR szKeyPath
)
{
TCHAR szLocalPath[MAX_PATH];
LPTSTR szEndOfRoot;
lstrcpy (szLocalPath, szKeyPath);
szEndOfRoot = _tcschr(szLocalPath, cBackslash);
if (szEndOfRoot != NULL) {
*szEndOfRoot = 0; // null terminate here and use just the chars to the left
if (lstrcmpi(szLocalPath, cszLocalMachine) == 0) {
return HKEY_LOCAL_MACHINE;
} else if (lstrcmpi(szLocalPath, cszClassesRoot) == 0) {
return HKEY_CLASSES_ROOT;
} else if (lstrcmpi(szLocalPath, cszCurrentUser) == 0) {
return HKEY_CURRENT_USER;
} else if (lstrcmpi(szLocalPath, cszUsers) == 0) {
return HKEY_USERS;
} else {
return NULL;
}
} else {
return NULL;
}
}
LPCTSTR
GetKeyPath (
IN LPCTSTR szKeyPath,
OUT LPBOOL pbDoSubKeys
)
{
static TCHAR szLocalPath[MAX_PATH];
LPTSTR szEndOfRoot;
BOOL bReturn = FALSE;
szEndOfRoot = _tcschr(szKeyPath, cBackslash);
if (szEndOfRoot != NULL) {
// path found
szEndOfRoot++; // go to first char after '\'
// save in local static buffer
lstrcpy (szLocalPath, szEndOfRoot);
// now see if this is a recursive key
szEndOfRoot = _tcschr(szLocalPath, cAsterisk);
if (szEndOfRoot != NULL) {
// then this is a recursive path
bReturn = TRUE;
szEndOfRoot--; // go back to backslash
*szEndOfRoot = 0; // and terminate there
}
if (pbDoSubKeys != NULL) {
*pbDoSubKeys = bReturn;
}
return szLocalPath;
} else {
// unable to find correct syntax so just return entire string
if (pbDoSubKeys != NULL) {
*pbDoSubKeys = FALSE;
}
return szKeyPath; // or beginning of path after ROOT key
}
}
LPCTSTR
GetFilePathFromHeader (
IN LPCTSTR szHeaderPath,
OUT LPDWORD pdwFlags
)
{
static TCHAR szLocalPath[MAX_PATH];
TCHAR szLocalWorkPath[MAX_PATH];
LPTSTR szEndOfPath;
DWORD dwLastError = ERROR_SUCCESS;
DWORD dwReturn = FILE_PATH_NORMAL;
lstrcpy (szLocalWorkPath, szHeaderPath);
szEndOfPath = _tcsrchr(szLocalWorkPath, cBang);
if (szEndOfPath != NULL) {
// wild card found so remember this and truncate
szEndOfPath--; // go to first char before *
*szEndOfPath = 0; // and terminate there
dwReturn = FILE_PATH_ALL; // remember to do sub-dirs
} else {
// check for wildcard path syntax characters
szEndOfPath = _tcschr (szLocalWorkPath, cAsterisk);
if (szEndOfPath == NULL) {
// check for the other wild card char
szEndOfPath = _tcschr (szLocalWorkPath, cAsterisk);
}
if (szEndOfPath != NULL) {
// keep the path intact but set the flag
dwReturn = FILE_PATH_WILD;
}
// no wildcard, so assume the path is in the valid syntax
}
dwLastError = GetExpandedFileName(
szLocalWorkPath,
sizeof(szLocalPath)/sizeof(TCHAR),
szLocalPath,
NULL);
if (dwLastError != ERROR_SUCCESS) {
SetLastError (dwLastError); // record error
szLocalPath[0] = 0; // and clear buffer
}
if (pdwFlags != NULL) {
*pdwFlags = dwReturn; // update the sub dir flag
}
return (LPCTSTR)&szLocalPath[0];
}
static
DWORD
DecodeRegAccessEntry (
IN LPCTSTR szAccessEntry
)
{
PACCESS_DECODE pEnt;
for (pEnt = &adRegistryDecodeList[0];
pEnt->szString != NULL;
pEnt++) {
if (lstrcmpi (szAccessEntry, pEnt->szString) == 0) {
return pEnt->dwMask;
}
}
return 0; // no entry found
}
static
DWORD
DecodeNtfsAccessEntry (
IN LPCTSTR szAccessEntry
)
{
PACCESS_DECODE pEnt;
for (pEnt = &adNtfsDecodeList[0];
pEnt->szString != NULL;
pEnt++) {
if (lstrcmpi (szAccessEntry, pEnt->szString) == 0) {
return pEnt->dwMask;
}
}
return NTFS_NOT_STANDARD; // no entry found
}
static
BOOL
FillAce (
IN PACCESS_ALLOWED_ACE paaAce,
IN ACCESS_MASK amAccess,
IN BYTE Type,
IN BYTE Flags,
IN PSID pSid
)
{
paaAce->Header.AceType = Type;
paaAce->Header.AceFlags = Flags;
paaAce->Mask = amAccess;
CopySid (
(DWORD)(paaAce->Header.AceSize - (sizeof (ACCESS_ALLOWED_ACE) - sizeof(DWORD))),
(PSID)(&paaAce->SidStart),
pSid);
paaAce->Header.AceSize = (WORD)(GetLengthSid(pSid) +
(sizeof (ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
return TRUE;
}
static
BOOL
MakeAccessDeniedAce (
IN PACCESS_DENIED_ACE padAce,
IN ACCESS_MASK amAccess,
IN BYTE Flags,
IN PSID pSid
)
{
padAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
padAce->Header.AceFlags = Flags;
padAce->Mask = amAccess;
CopySid (
(DWORD)(padAce->Header.AceSize - (sizeof (ACCESS_ALLOWED_ACE) - sizeof(DWORD))),
(PSID)(&padAce->SidStart),
pSid);
padAce->Header.AceSize = (WORD)(GetLengthSid(pSid) +
(sizeof (ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
return TRUE;
}
static
LONG
MakeAceFromRegEntry (
IN LPCTSTR szAccessList,
IN PSID psidUser,
IN OUT PACCESS_ALLOWED_ACE pAce
)
/*++
Routine Description:
interprets the access string list and returns the corresponding
access mask
Arguments:
list of access strings to include:
--*/
{
DWORD dwIndex = 1;
LPCTSTR szItem;
// see if this is an "inherit" ACE or not
if (lstrcmpi ((LPTSTR)GetItemFromIniEntry(szAccessList, dwIndex),
cszInherit) == 0) {
pAce->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
dwIndex++; // go to next entry
} else {
pAce->Header.AceFlags = 0;
}
// walk down the list to set bits as they are defined.
szItem = GetItemFromIniEntry (szAccessList, dwIndex);
while (lstrlen(szItem) > 0) {
pAce->Mask |= DecodeRegAccessEntry(szItem);
dwIndex++;
szItem = (LPTSTR)GetItemFromIniEntry (szAccessList, dwIndex);
}
// now to add the sid and set the ace size
CopySid (
(DWORD)(pAce->Header.AceSize - sizeof(ACE_HEADER) - sizeof (ACCESS_MASK)),
(PSID)(&pAce->SidStart),
psidUser);
pAce->Header.AceSize = (WORD)GetLengthSid(psidUser) +
sizeof(ACE_HEADER) +
sizeof(ACCESS_MASK);
return ERROR_SUCCESS;
}
LONG
MakeAclFromRegSection (
IN LPTSTR mszSection,
OUT PACL pAcl
)
/*++
Routine Description:
interprets the section string as a list of ACE information in the form
of:
DOMAIN\ACCOUNT = Access information
and adds the ACE information to the initialized ACL passed in
Arguments:
mszSection msz Buffer of ACE information
pAcl pointer to intialized ACL buffer
Return Value:
WIN32 Error status of function
--*/
{
LPTSTR szThisEntry;
TCHAR szDomain[MAX_PATH];
DWORD dwSidBuffSize;
DWORD dwDomainSize;
SID_NAME_USE snu;
PSID psidAccount = NULL;
PACCESS_ALLOWED_ACE pAce = NULL;
LONG lStatus;
for (szThisEntry = mszSection;
*szThisEntry != 0;
szThisEntry += lstrlen(szThisEntry)+1) {
psidAccount = GLOBAL_ALLOC (SMALL_BUFFER_SIZE);
pAce = GLOBAL_ALLOC (MAX_PATH); // this should be plenty big
if ((psidAccount != NULL) && (pAce != NULL)){
dwSidBuffSize = SMALL_BUFFER_SIZE;
dwDomainSize = sizeof(szDomain) / sizeof(TCHAR);
if (LookupAccountName (
NULL, // look up on local machine
GetKeyFromIniEntry(szThisEntry),
psidAccount,
&dwSidBuffSize,
szDomain,
&dwDomainSize,
&snu)) {
// account found so make an ACE with it
pAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
pAce->Header.AceFlags = 0;
pAce->Header.AceSize = MAX_PATH; // initial buffer size
pAce->Mask = 0; // the mask will be added in the next fn.
pAce->SidStart = 0; // the sid will be added in the next fn.
lStatus = MakeAceFromRegEntry (
szThisEntry,
psidAccount,
pAce);
AddAce (
pAcl,
ACL_REVISION,
MAXDWORD, // append this ACE to the end of the list
(LPVOID)pAce,
(DWORD)pAce->Header.AceSize);
} else {
// unable to look up name
}
} else {
// unable to allocate SID buffer
}
GLOBAL_FREE_IF_ALLOC (psidAccount);
GLOBAL_FREE_IF_ALLOC (pAce);
} // end of entry loop
return ERROR_SUCCESS;
}
static
BOOL
MakeDirAce (
IN PACCESS_ALLOWED_ACE pAce,
IN PSID pSid,
IN DWORD dwAccessValue
)
{
BOOL bAddAce = TRUE;
ACCESS_MASK amAce = 0;
BYTE bType = ACCESS_ALLOWED_ACE_TYPE;
switch (dwAccessValue) {
case NTFS_FULL_CONTROL:
amAce = NTFS_DIR_ALL_ACCESS;
break;
case NTFS_CHANGE:
amAce = NTFS_DIR_CHANGE;
break;
case NTFS_ADD_READ:
amAce = NTFS_DIR_ADD_READ;
break;
case NTFS_READ:
amAce = NTFS_DIR_READ;
break;
case NTFS_ADD:
bAddAce = FALSE;
break;
case NTFS_LIST:
bAddAce = FALSE;
break;
case NTFS_NO_ACCESS:
amAce = NTFS_DIR_NO_ACCESS;
bType = ACCESS_DENIED_ACE_TYPE;
break;
default:
bAddAce = FALSE;
break;
}
if (bAddAce) {
bAddAce = FillAce (
pAce,
amAce,
bType,
NTFS_DIR_DIR_FLAGS,
pSid);
}
return bAddAce;
}
static
BOOL
MakeFileAce (
IN PACCESS_ALLOWED_ACE pAce,
IN PSID pSid,
IN DWORD dwAccessValue,
IN BOOL bDirectory
)
{
BOOL bAddAce = TRUE;
ACCESS_MASK amAce = 0;
BYTE bType = ACCESS_ALLOWED_ACE_TYPE;
switch (dwAccessValue) {
case NTFS_FULL_CONTROL:
amAce = NTFS_FILE_ALL_ACCESS;
break;
case NTFS_CHANGE:
amAce = NTFS_FILE_CHANGE;
break;
case NTFS_ADD_READ:
if (bDirectory) {
amAce = NTFS_FILE_ADD_READ;
} else {
bAddAce = FALSE; // not allowed for files
}
break;
case NTFS_READ:
amAce = NTFS_FILE_READ;
break;
case NTFS_ADD:
amAce = NTFS_FILE_ADD;
break;
case NTFS_LIST:
amAce = NTFS_FILE_LIST;
break;
case NTFS_NO_ACCESS:
amAce = NTFS_FILE_NO_ACCESS;
bType = ACCESS_DENIED_ACE_TYPE;
break;
default:
bAddAce = FALSE;
break;
}
if (bAddAce) {
bAddAce = FillAce (
pAce,
amAce,
bType,
(BYTE)(bDirectory ? NTFS_DIR_FILE_FLAGS : NTFS_FILE_FILE_FLAGS),
pSid);
}
return bAddAce;
}
static
LONG
InterpretNtfsAccessEntry (
IN LPCTSTR szThisEntry,
IN BOOL bDirectory,
IN PSID psidAccount,
OUT PACL pAcl
)
{
LONG lStatus = ERROR_SUCCESS;
LPCTSTR szAccessString;
DWORD dwAccessValue;
BOOL bCombinationEntry; // true if access string makes 2 ace's
PACCESS_ALLOWED_ACE pAce;
ACCESS_MASK amAce;
BYTE bAceType;
BYTE bAceFlags;
DWORD dwAllowedEntries;
DWORD dwThisEntry = 1;
szAccessString = GetItemFromIniEntry (szThisEntry, dwThisEntry);
dwAccessValue = DecodeNtfsAccessEntry (szAccessString);
bCombinationEntry = (BOOL)(HIWORD(dwAccessValue) == 1);
if (bCombinationEntry) {
// this is a combination entry so if this is a directory
// we'll make 2 ACE's one for dir access and one to be inherited
// for file access. If this is a file, then only the file access
// ace will be created.
if (bDirectory) {
// make the directory access ACE for the directory entry
pAce = (PACCESS_ALLOWED_ACE)GLOBAL_ALLOC(MAX_PATH);
if (pAce != NULL) {
if (MakeDirAce (pAce, psidAccount, dwAccessValue)) {
// then add ace to acl
AddAce (
pAcl,
ACL_REVISION,
MAXDWORD,
(LPVOID)pAce,
(DWORD)pAce->Header.AceSize);
}
}
GLOBAL_FREE_IF_ALLOC (pAce); // free this one
}
// create the File Access entry
pAce = (PACCESS_ALLOWED_ACE)GLOBAL_ALLOC(MAX_PATH);
if (pAce != NULL) {
if (MakeFileAce (pAce, psidAccount, dwAccessValue, bDirectory)) {
// then add ace to acl
AddAce (
pAcl,
ACL_REVISION,
MAXDWORD,
(LPVOID)pAce,
(DWORD)pAce->Header.AceSize);
}
}
GLOBAL_FREE_IF_ALLOC (pAce); // free this one
} else {
// specific permissions have been specified so process them
// this is the first entry in the list so it's either the "dir"
// entry of a directory or a File entry.
dwAllowedEntries = (bDirectory ? 2 : 1);
while (dwThisEntry <= dwAllowedEntries) {
if (lstrlen(szAccessString) > 0) {
bAceFlags = (bDirectory ? (dwThisEntry == DIR_ENTRY ?
NTFS_DIR_DIR_FLAGS : NTFS_DIR_FILE_FLAGS) : NTFS_FILE_FILE_FLAGS);
bAceType = ACCESS_ALLOWED_ACE_TYPE;
switch (dwAccessValue) {
case NTFS_NONE:
amAce = (bDirectory ? NTFS_DIR_NO_ACCESS : NTFS_FILE_NO_ACCESS);
bAceType = ACCESS_DENIED_ACE_TYPE;
break;
case NTFS_ALL:
amAce = (bDirectory ? NTFS_DIR_NO_ACCESS : NTFS_FILE_ALL_ACCESS);
break;
default:
amAce = ReadNtfsPermissionString (szAccessString, bDirectory);
break;
}
pAce = (PACCESS_ALLOWED_ACE)GLOBAL_ALLOC(MAX_PATH);
if (pAce != NULL) {
FillAce (
pAce,
amAce,
bAceType,
bAceFlags,
psidAccount);
AddAce (
pAcl,
ACL_REVISION,
MAXDWORD,
(LPVOID)pAce,
(DWORD)pAce->Header.AceSize);
}
GLOBAL_FREE_IF_ALLOC (pAce);
}
if (++dwThisEntry <= dwAllowedEntries) {
// get next entry from string
szAccessString = GetItemFromIniEntry (szThisEntry, dwThisEntry);
}
}
}
return lStatus;
}
LONG
MakeAclFromNtfsSection (
IN LPTSTR mszSection,
IN BOOL bDirectory, // true if this is for a directory
OUT PACL pAcl
)
/*++
Routine Description:
interprets the section string as a list of ACE information in the form
of:
DOMAIN\ACCOUNT = Access information
and adds the ACE information to the initialized ACL passed in
Arguments:
mszSection msz Buffer of ACE information
pAcl pointer to intialized ACL buffer
Return Value:
WIN32 Error status of function
--*/
{
LPTSTR szThisEntry;
TCHAR szDomain[MAX_PATH];
DWORD dwSidBuffSize;
DWORD dwDomainSize;
SID_NAME_USE snu;
PSID psidAccount = NULL;
LONG lStatus;
for (szThisEntry = mszSection;
*szThisEntry != 0;
szThisEntry += lstrlen(szThisEntry)+1) {
psidAccount = GLOBAL_ALLOC (SMALL_BUFFER_SIZE);
if (psidAccount != NULL) {
dwSidBuffSize = SMALL_BUFFER_SIZE;
dwDomainSize = sizeof(szDomain) / sizeof(TCHAR);
if (LookupAccountName (
NULL, // look up on local machine
GetKeyFromIniEntry(szThisEntry),
psidAccount,
&dwSidBuffSize,
szDomain,
&dwDomainSize,
&snu)) {
lStatus = InterpretNtfsAccessEntry (
szThisEntry,
bDirectory,
psidAccount,
pAcl);
} else {
// unable to look up name
}
} else {
// unable to allocate SID buffer
}
GLOBAL_FREE_IF_ALLOC (psidAccount);
} // end of entry loop
return ERROR_SUCCESS;
}
LONG
SetRegistryKeySecurity (
IN HKEY hkeyRootKey,
IN LPCTSTR szKeyPath,
IN BOOL bDoSubKeys,
IN PSECURITY_DESCRIPTOR psdSecurity
)
/*++
Routine Description:
opens the key in "KeyPath" and set's the key's security. If the
"bDoSubKeys" flag is set, then all sub keys are set to the same
security using this routine recursively.
Return Value:
WIN32 status value of function
--*/
{
LONG lStatus;
HKEY hkeyThisKey;
DWORD dwKeyIndex;
DWORD dwSubKeyLen;
TCHAR szSubKeyName[MAX_PATH];
FILETIME FileTime;
lStatus = RegOpenKeyEx (
hkeyRootKey,
szKeyPath,
0L,
KEY_ALL_ACCESS,
&hkeyThisKey);
if (lStatus == ERROR_SUCCESS) {
_tprintf (GetStringResource (GetDllInstance(), IDS_REG_DISPLAY_FORMAT),
szKeyPath);
lStatus = RegSetKeySecurity (
hkeyThisKey,
DACL_SECURITY_INFORMATION,
psdSecurity);
if (bDoSubKeys) {
dwKeyIndex = 0;
dwSubKeyLen = sizeof(szSubKeyName) / sizeof(TCHAR);
while (RegEnumKeyEx (
hkeyThisKey,
dwKeyIndex,
szSubKeyName,
&dwSubKeyLen,
NULL,
NULL, // don't care about the class
NULL, // no class buffer
&FileTime) == ERROR_SUCCESS) {
// subkey found so set subkey security
lStatus = SetRegistryKeySecurity (
hkeyThisKey,
szSubKeyName,
bDoSubKeys,
psdSecurity);
// set variables for next call
dwKeyIndex++;
dwSubKeyLen = sizeof(szSubKeyName) / sizeof(TCHAR);
}
}
RegCloseKey (hkeyThisKey);
} else {
// unable to open key so return ERROR
}
return lStatus;
}
LONG
SetNtfsFileSecurity (
IN LPCTSTR szPath,
IN DWORD dwFlags,
IN PSECURITY_DESCRIPTOR pSdDir,
IN PSECURITY_DESCRIPTOR pSdFile
)
{
LONG lReturn = ERROR_SUCCESS;
LONG lStatus = ERROR_SUCCESS;
WIN32_FIND_DATA fdThisFile;
HANDLE hFileSearch;
BOOL bFileFound = FALSE;
DWORD dwFlagsToPass;
LPTSTR szWildPath;
TCHAR szWildFilePath[MAX_PATH];
LPTSTR szWildFileName;
if ((dwFlags & FILE_PATH_NORMAL) == FILE_PATH_NORMAL) {
// then just set the security on this path
if (FileExists(szPath)) {
if (IsDirectory(szPath)) {
// then apply directory SD
#ifdef TEST_MODE
_tprintf (TEXT("\n_DIR: %s"), szPath);
DumpAclData (szPath, pSdDir);
lReturn = ERROR_SUCCESS;
#else
if (!SetFileSecurity(szPath, DACL_SECURITY_INFORMATION, pSdDir)) {
lReturn = GetLastError();
}
#endif
} else {
// it's not a dir so apply file SD
#ifdef TEST_MODE
_tprintf (TEXT("\nFILE: %s"), szPath);
DumpAclData (szPath, pSdFile);
lReturn = ERROR_SUCCESS;
#else
if (!SetFileSecurity(szPath, DACL_SECURITY_INFORMATION, pSdFile)) {
lReturn = GetLastError();
}
#endif
}
} else {
#ifdef TEST_MODE
_tprintf (TEXT("\n_ERR: %s"), szPath);
#endif
lReturn = ERROR_FILE_NOT_FOUND;
}
} else if ((dwFlags & FILE_PATH_WILD) == FILE_PATH_WILD) {
// the path is (presumably) a wild-card path spec so walk the list
// of matching files
// make a local copy of the path preceeding the wildcard chars
// to build local paths with
lstrcpy (szWildFilePath, szPath);
szWildFileName = _tcsrchr(szWildFilePath, cBackslash); // find last backslash char
if (szWildFileName == NULL) {
// no backslash found so add one to the end of the path string
lstrcat (szWildFilePath, cszBackslash);
szWildFileName = szWildFilePath + lstrlen(szWildFilePath);
} else {
// backslash found so move pointer past it.
szWildFileName++;
}
hFileSearch = FindFirstFile (szPath, &fdThisFile);
if (hFileSearch != INVALID_HANDLE_VALUE) bFileFound = TRUE;
while (bFileFound) {
if (fdThisFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (!DotOrDotDotDir (fdThisFile.cFileName)) {
// then if this is dir, do see if we should do all the sub dirs
if ((dwFlags & FILE_PATH_SUBDIRS) == FILE_PATH_SUBDIRS) {
dwFlagsToPass = FILE_PATH_ALL;
} else {
dwFlagsToPass = 0; // do not do in this case
}
} else {
// this is a . or a .. dir so ignore
dwFlagsToPass = 0;
}
} else {
// just a file so process as a normal file
dwFlagsToPass = FILE_PATH_NORMAL;
}
if (dwFlagsToPass != 0) {
// make into a full path string
lstrcpy (szWildFileName, fdThisFile.cFileName);
// set the file security of this and any other files
lStatus = SetNtfsFileSecurity (szWildFilePath, dwFlagsToPass,
pSdDir, pSdFile);
if (lStatus != ERROR_SUCCESS) {
// save last "non-success" error for return
lReturn = lStatus;
}
}
bFileFound = FindNextFile (hFileSearch, &fdThisFile);
}
FindClose (hFileSearch);
} else if ((dwFlags & FILE_PATH_ALL) == FILE_PATH_ALL) {
// set the security of this path
lStatus = SetNtfsFileSecurity (szPath, FILE_PATH_NORMAL,
pSdDir, pSdFile);
if (IsDirectory(szPath)) {
// make a wild card path an pass it do all the files and sub-dirs
// of this path
szWildPath = (LPTSTR)GLOBAL_ALLOC(MAX_PATH_BYTES);
if (szWildPath != NULL) {
lstrcpy (szWildPath, szPath);
if (szWildPath[lstrlen(szWildPath)-1] != cBackslash) {
lstrcat (szWildPath, cszBackslash);
}
lstrcat (szWildPath, cszStarDotStar); // make wild
// call this routine with both WILD and ALL flags set
// so all files and sub-dirs will get set.
lStatus = SetNtfsFileSecurity (szWildPath,
(FILE_PATH_WILD | FILE_PATH_SUBDIRS),
pSdDir, pSdFile);
lReturn = lStatus;
} else {
lReturn = ERROR_OUTOFMEMORY;
}
GLOBAL_FREE_IF_ALLOC (szWildPath);
} else {
// path not a dir so just skip the wildcard stuff
}
} else {
// unrecognized flag
lReturn = ERROR_INVALID_PARAMETER;
}
return lReturn;
}