Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1338 lines
43 KiB

//+------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation.
//
// File: t2.cxx
//
// Contents:
//
// Classes:
//
// History: Nov-93 DaveMont Created.
// Oct-96 Modified BrunoSc
// Aug-01 Modified Wipro Technologies
//
//-------------------------------------------------------------------
#include "pch.h"
#include "t2.hxx"
#include "filesec.hxx"
#include "fileenum.hxx"
#include "dumpsec.hxx"
#include "caclsmsg.h"
#include "locale.h"
#include "winnlsp.h"
#if DBG
ULONG Debug = 1;
#endif
//+----------------------------------------------------------------------------
//
// local prototypes
//
//+----------------------------------------------------------------------------
BOOL OpenToken(PHANDLE ph);
void printfsid(SID *psid, ULONG *outputoffset);
void printface(ACE_HEADER *paceh, BOOL fdir, ULONG outputoffset);
void printfmask(ULONG mask, WCHAR acetype, BOOL fdir, ULONG outputoffset);
LPWSTR mbstowcs(LPCWSTR aname );
BOOL GetUserAndAccess(LPCWSTR arg, LPWSTR *user, ULONG *access, ULONG *dirmask, BOOL *filespec);
#if DBG
ULONG DebugEnumerate(LPCWSTR filename, ULONG option);
#endif
ULONG DisplayAces(LPCWSTR filename, ULONG option);
ULONG ModifyAces(LPCWSTR filename,
MODE emode,
ULONG option,
LPCWSTR argv[],
LONG astart[], LONG aend[] );
ULONG GetCmdLineArgs(DWORD argc, LPCWSTR argv[],
ULONG *option,
LONG astart[], LONG aend[],
MODE *emode
#if DBG
,ULONG *debug
#endif
);
ULONG printmessage (FILE* fp, DWORD messageID, ...);
//+----------------------------------------------------------------------------
//
// Function: Usage
//
// Synopsis: prints usage functionality
//
// Arguments: none
//
//----------------------------------------------------------------------------
VOID usage()
{
printmessage(stdout, MSG_CACLS_USAGE, NULL);
#if DBG
if (Debug)
{
printf("\n /B deBug <[#]>\n");
printf(" default is display error returned\n");
printf(" in /B '#' is a mask: 1 display SIDS values\n");
printf(" 2 display access masks\n");
printf(" 4 display error returned\n");
printf(" 8 display error location\n");
printf(" 0x10 verbose\n");
printf(" 0x20 verboser\n");
printf(" 0x40 enumerate names\n");
printf(" 0x80 enumerate failures\n");
printf(" 0x100 enumerate starts and returns\n");
printf(" 0x200 enumerate extra data\n");
printf(" 0x400 size allocation data\n");
printf(" 0x800 display enumeration of files\n");
}
#endif
}
//+----------------------------------------------------------------------------
//
// Function: Main, Public
//
// Synopsis: main!!
//
// Arguments: IN [argc] - cmdline arguement count
// IN [argv] - input cmdline arguements
//
//----------------------------------------------------------------------------
VOID __cdecl wmain(DWORD argc, LPCWSTR argv[])
{
//
// Set the local to system OEM code page.
//
setlocale(LC_ALL, ".OCP" );
SetThreadUILanguage(0);
LONG astart[MAX_OPTIONS], aend[MAX_OPTIONS];
MODE emode;
ULONG ret;
ULONG option;
if (ERROR_SUCCESS != (ret = GetCmdLineArgs(argc, argv,
&option,
astart, aend,
&emode
#if DBG
,&Debug
#endif
)))
{
usage();
exit(ret);
}
switch (emode)
{
case MODE_DISPLAY:
ret = DisplayAces(argv[1], option);
break;
case MODE_REPLACE:
case MODE_MODIFY:
case MODE_MODIFY_EXCLUSIVE:
ret = ModifyAces(argv[1], emode, option, argv, astart, aend );
break;
#if DBG
case MODE_DEBUG_ENUMERATE:
ret = DebugEnumerate(argv[1], option);
break;
#endif
default:
{
usage();
exit(1);
}
}
if (ERROR_SUCCESS != ret)
{
LAST_ERROR((stderr, L"Cacls failed, %ld\n",ret))
fwprintf ( stderr, L"ERROR: ");
printmessage(stderr, ret, NULL);
}
exit(ret);
}
//---------------------------------------------------------------------------
//
// Function: GetCmdLineArgs
//
// Synopsis: gets and parses command line arguments into commands
// recognized by this program
//
// Arguments: IN [argc] - cmdline arguement count
// IN [argv] - input cmdline arguements
// OUT [option] - requested option
// OUT [astart] - start of arguments for each option
// OUT [aend] - end of arguments for each option
// OUT [emode] - mode of operation
// OUT [debug] - debug mask
//
//
//----------------------------------------------------------------------------
ULONG GetCmdLineArgs(DWORD argc, LPCWSTR argv[],
ULONG *option,
LONG astart[], LONG aend[],
MODE *emode
#if DBG
,ULONG *debug
#endif
)
{
ARG_MODE_INDEX am = ARG_MODE_INDEX_NEED_OPTION;
#if DBG
*debug = 0;
#endif
*emode = MODE_DISPLAY;
*option = 0;
LPWSTR pszBuffer = NULL;
for (DWORD j=0; j < MAX_OPTIONS ;j++ )
{
astart[j] = 0;
aend[j] = 0;
}
if ( (argc < 2) || (argv[1][0] == L'/') )
{
#if DBG
// do this so debug args are printed out
if (argc >= 2)
{
if ( (0 == _wcsicmp(&argv[1][1], L"deBug")) ||
(0 == _wcsicmp(&argv[1][1], L"b")) )
{
*debug = DEBUG_LAST_ERROR;
}
}
#endif
return(ERROR_BAD_ARGUMENTS);
}
for (DWORD k = 2; k < argc ; k++ )
{
//wprintf (L"%s", &argv[k][0] );
if (argv[k][0] == L'/')
{
switch (am)
{
case ARG_MODE_INDEX_NEED_OPTION:
#if DBG
case ARG_MODE_INDEX_DEBUG:
#endif
break;
case ARG_MODE_INDEX_DENY:
case ARG_MODE_INDEX_REVOKE:
case ARG_MODE_INDEX_GRANT:
case ARG_MODE_INDEX_REPLACE:
if (astart[am] == k)
return(ERROR_BAD_ARGUMENTS);
break;
default:
return(ERROR_BAD_ARGUMENTS);
}
if ( (0 == _wcsicmp(&argv[k][1], L"Tree")) ||
(0 == _wcsicmp(&argv[k][1], L"t")) )
{
if (*option & OPTION_TREE)
return(ERROR_BAD_ARGUMENTS);
*option |= OPTION_TREE;
am = ARG_MODE_INDEX_NEED_OPTION;
continue;
}
if ( (0 == _wcsicmp(&argv[k][1], L"Continue")) ||
(0 == _wcsicmp(&argv[k][1], L"c")) )
{
if (*option & OPTION_CONTINUE_ON_ERROR)
return(ERROR_BAD_ARGUMENTS);
*option |= OPTION_CONTINUE_ON_ERROR;
am = ARG_MODE_INDEX_NEED_OPTION;
continue;
}
if ( (0 == _wcsicmp(&argv[k][1], L"Edit")) ||
(0 == _wcsicmp(&argv[k][1], L"E")) )
{
if (*emode != MODE_DISPLAY)
return(ERROR_BAD_ARGUMENTS);
*emode = MODE_MODIFY;
am = ARG_MODE_INDEX_NEED_OPTION;
continue;
}
//a-henry
if ( (0 == _wcsicmp(&argv[k][1], L"EditX")) ||
(0 == _wcsicmp(&argv[k][1], L"X")) )
{
if (*emode != MODE_DISPLAY)
return(ERROR_BAD_ARGUMENTS);
*emode = MODE_MODIFY_EXCLUSIVE;
am = ARG_MODE_INDEX_NEED_OPTION;
continue;
}
//a-henry
if ( (0 == _wcsicmp(&argv[k][1], L"Yes")) ||
(0 == _wcsicmp(&argv[k][1], L"Y")) )
{
if (*emode & OPTION_CONTINUE_ON_REPLACE)
return(ERROR_BAD_ARGUMENTS);
*option |= OPTION_CONTINUE_ON_REPLACE;
am = ARG_MODE_INDEX_NEED_OPTION;
continue;
}
#if DBG
if ( (0 == _wcsicmp(&argv[k][1], L"deBug")) ||
(0 == _wcsicmp(&argv[k][1], L"b")) )
{
if (*debug)
return(ERROR_BAD_ARGUMENTS);
am = ARG_MODE_INDEX_DEBUG;
*debug = DEBUG_LAST_ERROR;
continue;
}
#endif
if ( (0 == _wcsicmp(&argv[k][1], L"Deny")) ||
(0 == _wcsicmp(&argv[k][1], L"D")) )
{
am = ARG_MODE_INDEX_DENY;
*option |= OPTION_DENY;
} else if ( (0 == _wcsicmp(&argv[k][1], L"Revoke")) ||
(0 == _wcsicmp(&argv[k][1], L"R")) )
{
am = ARG_MODE_INDEX_REVOKE;
*option |= OPTION_REVOKE;
} else if ( (0 == _wcsicmp(&argv[k][1], L"Grant")) ||
(0 == _wcsicmp(&argv[k][1], L"G")) )
{
am = ARG_MODE_INDEX_GRANT;
*option |= OPTION_GRANT;
} else if ( (0 == _wcsicmp(&argv[k][1], L"rePlace")) ||
(0 == _wcsicmp(&argv[k][1], L"P")) )
{
*option |= OPTION_REPLACE;
am = ARG_MODE_INDEX_REPLACE;
} else
return(ERROR_BAD_ARGUMENTS);
if (astart[am] != 0)
return(ERROR_BAD_ARGUMENTS);
astart[am] = k+1;
} else
{
switch (am)
{
case ARG_MODE_INDEX_NEED_OPTION:
return(ERROR_BAD_ARGUMENTS);
#if DBG
case ARG_MODE_INDEX_DEBUG:
*debug = wcstol(argv[k], &pszBuffer, 10 );
if ( wcslen (pszBuffer) )
{
return(ERROR_BAD_ARGUMENTS);
}
if (*debug & DEBUG_ENUMERATE)
if (*emode == MODE_DISPLAY)
*emode = MODE_DEBUG_ENUMERATE;
else
return(ERROR_BAD_ARGUMENTS);
am = ARG_MODE_INDEX_NEED_OPTION;
break;
#endif
case ARG_MODE_INDEX_DENY:
case ARG_MODE_INDEX_REVOKE:
case ARG_MODE_INDEX_GRANT:
case ARG_MODE_INDEX_REPLACE:
aend[am] = k+1;
break;
default:
return(ERROR_BAD_ARGUMENTS);
}
}
}
if ( ( (*option & OPTION_DENY) && (aend[ARG_MODE_INDEX_DENY] == 0) ) ||
( (*option & OPTION_REVOKE) && (aend[ARG_MODE_INDEX_REVOKE] == 0) ) ||
( (*option & OPTION_GRANT) && (aend[ARG_MODE_INDEX_GRANT] == 0) ) ||
( (*option & OPTION_REPLACE) && (aend[ARG_MODE_INDEX_REPLACE] == 0) ) )
{
return(ERROR_BAD_ARGUMENTS);
} else if ( (*option & OPTION_DENY) ||
(*option & OPTION_REVOKE) ||
(*option & OPTION_GRANT) ||
(*option & OPTION_REPLACE) )
{
if (*emode == MODE_DISPLAY)
*emode = MODE_REPLACE;
}
return(ERROR_SUCCESS);
}
//---------------------------------------------------------------------------
//
// Function: DisplayAces
//
// Synopsis: displays ACL from specified file
//
// Arguments: IN [filename] - file name
// IN [option] - display option
//
//----------------------------------------------------------------------------
ULONG DisplayAces(LPCWSTR filename, ULONG option)
{
CFileEnumerate cfe(option & OPTION_TREE);
LPWSTR pwfilename = NULL;
BOOL fdir;
ULONG ret;
if (NO_ERROR == (ret = cfe.Init(filename, &pwfilename, &fdir)))
{
while ( (NO_ERROR == ret) ||
( (ERROR_ACCESS_DENIED == ret ) &&
(option & OPTION_CONTINUE_ON_ERROR) ) )
{
#if DBG
if (fdir)
DISPLAY((stderr, L"processing file: "))
else
DISPLAY((stderr, L"processing dir: "))
#endif
fwprintf(stdout, L"%ws",pwfilename);
if (ERROR_ACCESS_DENIED == ret)
{
printmessage(stdout,MSG_CACLS_ACCESS_DENIED, NULL);
} else
{
DISPLAY((stderr, L"\n"))
VERBOSE((stderr, L"\n"))
CDumpSecurity cds(pwfilename);
if (NO_ERROR == (ret = cds.Init()))
{
#if DBG
if (Debug & DEBUG_VERBOSE)
{
SID *psid;
ULONG oo;
if (NO_ERROR == (ret = cds.GetSDOwner(&psid)))
{
wprintf(L" Owner = ");
printfsid(psid, &oo);
if (NO_ERROR == (ret = cds.GetSDGroup(&psid)))
{
wprintf(L" Group = ");
printfsid(psid, &oo);
}
else
ERRORS((stderr, L"GetSDGroup failed, %d\n",ret))
}
else
ERRORS((stderr, L"GetSDOwner failed, %d\n",ret))
}
#endif
if(cds.IsDaclNull())
{
printmessage(stdout,MSG_NULL_DACL, NULL);
}
else
{
ACE_HEADER *paceh;
LONG retace;
if (NO_ERROR == ret)
for (retace = cds.GetNextAce(&paceh); retace >= 0; )
{
printface(paceh, fdir, wcslen(pwfilename));
retace = cds.GetNextAce(&paceh);
if (retace >= 0)
wprintf(L"%*s",wcslen(pwfilename),L" ");
}
}
}
#if DBG
else
ERRORS((stderr, L"cds.init failed, %d\n",ret))
#endif
}
fwprintf(stdout, L"\n");
if ( (NO_ERROR == ret) ||
( (ERROR_ACCESS_DENIED == ret ) &&
(option & OPTION_CONTINUE_ON_ERROR) ) )
ret = cfe.Next(&pwfilename, &fdir);
}
switch (ret)
{
case ERROR_NO_MORE_FILES:
ret = ERROR_SUCCESS;
break;
case ERROR_ACCESS_DENIED:
break;
case ERROR_SUCCESS:
break;
default:
break;
}
} else
{
ERRORS((stderr, L"cfe.init failed, %d\n",ret))
}
return(ret);
}
/*
BOOL FindExistingUser(ACL* poldacl, CDaclWrop* cdw)
{
for (ULONG cace = 0; cace < poldacl->AceCount;
cace++, pah = (ACE_HEADER *)Add2Ptr(pah, pah->AceSize))
{
if (ERROR_SUCCESS == (ret = _aaa[j].pcaa->Sid(&psid)))
{
if (EqualSid(psid,
(SID *)&((ACCESS_ALLOWED_ACE *)pah)->SidStart) )
return TRUE;
}
}
return FALSE;
}
*/
//---------------------------------------------------------------------------
//
// Function: ModifyAces
//
// Synopsis: modifies the aces for the specified file(s)
//
// Arguments: IN [filename] - name of file(s) to modify the aces on
// IN [emode] - mode of operation
// IN [option] - requested option
// IN [astart] - start of arguments for each option
// IN [aend] - end of arguments for each option
//
//----------------------------------------------------------------------------
ULONG ModifyAces(LPCWSTR filename,
MODE emode,
ULONG option,
LPCWSTR argv[],
LONG astart[], LONG aend[])
{
CDaclWrap cdw;
CFileEnumerate cfe(option & OPTION_TREE);
LPWSTR user = NULL;
ULONG access;
ULONG dirmask;
BOOL filespec;
ULONG ret = ERROR_SUCCESS;
LPWSTR pwfilename;
ULONG curoption;
VERBOSER((stderr, L"user:permission pairs\n"))
// first proces the command line args to build up the new ace
cdw._EditMode = emode;
for (ULONG j = 0, k = 1;j < MAX_OPTIONS ; k <<= 1, j++ )
{
curoption = k;
if (option & k)
{
for (LONG q = astart[j];
q < aend[j] ; q++ )
{
VERBOSER((stderr, L" %s\n",argv[q]))
if ((k & OPTION_GRANT) || (k & OPTION_REPLACE))
{
filespec = FALSE;
if (!GetUserAndAccess(argv[q], &user, &access, &dirmask, &filespec))
{
//if (user)
// LocalFree(user);
return(ERROR_BAD_ARGUMENTS);
}
if (GENERIC_NONE == access)
{
if (k & OPTION_REPLACE)
{
curoption = OPTION_DENY;
} else
{
//if (user)
//LocalFree(user);
return(ERROR_BAD_ARGUMENTS);
}
}
} else
{
user = (LPWSTR ) (argv[q]);
access = GENERIC_NONE;
}
VERBOSER((stderr, L"OPTION = %d, USER = %ws, ACCESS = %lx, DIR = %lx\n",
option,
user,
access,
dirmask ))
if (ERROR_SUCCESS != (ret = cdw.SetAccess(curoption,
user,
NULL,
access,
dirmask,
filespec )))
{
ERRORS((stderr, L"SetAccess for %ws:%lx;%lx failed, %d\n",
user,
access,
dirmask,
ret))
//LocalFree(user);
return(ret);
}
//LocalFree(user);
user = NULL;
}
}
}
BOOL fdir;
if (emode == MODE_REPLACE)
{ if (!(option & OPTION_CONTINUE_ON_REPLACE))
{
WCHAR well[MAX_PATH] = L"";
WCHAR msgbuf[MAX_PATH] = L"";
WCHAR tmpmsgbuf[MAX_PATH] = L"";
printmessage(stdout,MSG_CACLS_ARE_YOU_SURE, NULL);
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, MSG_CACLS_Y, NULL,
msgbuf, MAX_PATH, NULL);
ZeroMemory ( well, MAX_PATH );
if(!fgetws(well,MAX_PATH,stdin))
{
int err = 0;
if((err = ferror(stdin)))
return err;
return ERROR_INVALID_PARAMETER;
}
if ( L'\n' == well[ wcslen (well) - 1] )
well[ wcslen (well) - 1] = L'\0';
if (0 != _wcsicmp(well, msgbuf))
{
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, MSG_CACLS_YES, 0,
msgbuf, MAX_PATH, NULL);
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, MSG_CACLS_NO, 0,
tmpmsgbuf, MAX_PATH, NULL);
if (0 == _wcsicmp(well, tmpmsgbuf))
{
printmessage(stdout, MSG_OPERATION_CANCEL, NULL);
return(ERROR_SUCCESS);
}
else if (0 != _wcsicmp(well, msgbuf))
{
return(MSG_WRONG_INPUT);
}
}
}
}
if (NO_ERROR == (ret = cfe.Init(filename, &pwfilename, &fdir)))
{
while ( (NO_ERROR == ret) ||
( (ERROR_ACCESS_DENIED == ret ) &&
(option & OPTION_CONTINUE_ON_ERROR) ) )
{
CFileSecurity cfs(pwfilename);
if (NO_ERROR == (ret = cfs.Init()))
{
if (NO_ERROR != (ret = cfs.SetFS(emode == MODE_REPLACE ? FALSE : TRUE, &cdw, fdir)))
{
ERRORS((stderr, L"SetFS on %ws failed %ld\n",pwfilename, ret))
// return(ret);
}
} else
{ // continue modifying ACLs only if we receive an access denied error
if ((ret != ERROR_SHARING_VIOLATION) && (ret != ERROR_ACCESS_DENIED) && (option & OPTION_CONTINUE_ON_ERROR))
{ ERRORS((stderr, L"init failed, %d\n",ret))
// return(ret);
}
}
if (fdir)
{
LPTSTR sFilename = NULL;
/*WideCharToMultiByte( CP_UTF8,
0,
pwfilename,
-1,
(LPTSTR) sFilename,
MAX_PATH,
NULL,
NULL ); */
printmessage(stdout, MSG_CACLS_PROCESSED_DIR, NULL);
fwprintf(stdout, L"%s\n", pwfilename);
}
else
{
switch (ret)
{ case ERROR_SHARING_VIOLATION:
printmessage(stdout, MSG_SHARING_VIOLATION, NULL);
ret = ERROR_ACCESS_DENIED;
break;
case ERROR_ACCESS_DENIED:
printmessage(stdout, MSG_ACCESS_DENIED, pwfilename);
ret = ERROR_ACCESS_DENIED;
break;
default:
printmessage(stdout, MSG_CACLS_PROCESSED_FILE, NULL);
break;
}
// now convert the string two times again to ensure proper display of
// german umlaute. (probably another more elegant way??)
LPTSTR sFilename = NULL;
LPCTSTR szFile = NULL;
/*WideCharToMultiByte( CP_UTF8,
0,
pwfilename,
-1,
(LPSTR) sFilename,
MAX_PATH,
szFile,
TRUE ); */
fwprintf(stdout, L" %s\n", pwfilename);
}
if ( (NO_ERROR == ret) ||
( (ERROR_ACCESS_DENIED == ret ) &&
(option & OPTION_CONTINUE_ON_ERROR) ) )
ret = cfe.Next(&pwfilename, &fdir);
}
switch (ret)
{
case ERROR_NO_MORE_FILES:
ret = ERROR_SUCCESS;
break;
case ERROR_ACCESS_DENIED:
break;
case ERROR_SUCCESS:
break;
default:
DISPLAY((stderr, L"%ws failed: %d\n", pwfilename, ret))
break;
}
} else
ERRORS((stderr, L"file enumeration failed to initialize %ws, %ld\n",pwfilename, ret))
if (ret == ERROR_NO_MORE_FILES)
{
ret = ERROR_SUCCESS;
}
if (ret != ERROR_SUCCESS)
{
ERRORS((stderr, L"Enumeration failed, %d\n",ret))
}
return(ret);
}
#if DBG
//---------------------------------------------------------------------------
//
// Function: DebugEnumerate
//
// Synopsis: debug function
//
// Arguments: IN [filename] - file name
// IN [option] - option
//
//----------------------------------------------------------------------------
ULONG DebugEnumerate(LPCWSTR filename, ULONG option)
{
CFileEnumerate cfe(option & OPTION_TREE);
LPWSTR pwfilename = NULL;
BOOL fdir;
ULONG ret;
ret = cfe.Init(filename, &pwfilename, &fdir);
while ( (ERROR_SUCCESS == ret) ||
( (ERROR_ACCESS_DENIED == ret ) &&
(option & OPTION_CONTINUE_ON_ERROR) ) )
{
if (fdir)
wprintf(L"dir name = %ws%ws\n",pwfilename,
ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
else
wprintf(L"file name = %ws%ws\n",pwfilename,
ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
ret = cfe.Next(&pwfilename, &fdir);
}
if (ret == ERROR_ACCESS_DENIED)
{
if (fdir)
wprintf(L"dir name = %ws%ws\n",pwfilename,
ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
else
wprintf(L"file name = %ws%ws\n",pwfilename,
ERROR_ACCESS_DENIED == ret ? L"ACCESS DENIED" : L"");
}
if (ret != ERROR_NO_MORE_FILES)
wprintf(L"Enumeration failed, %d\n",ret);
return(ret);
}
#endif
//---------------------------------------------------------------------------
//
// Function: GetUserAccess
//
// Synopsis: parses an input string for user:access
//
// Arguments: IN [arg] - input string to parse
// OUT [user] - user if found
// OUT [access] - access if found
// OUT [dirmask] - access for directory if found
// else set to [access]
// OUT [filespec]- if TRUE, only dir ACE will be written, no
// file inheritence ACE (necessary for LIST etc.)
//
//----------------------------------------------------------------------------
BOOL GetUserAndAccess(LPCWSTR arg, LPWSTR *user, ULONG *access, ULONG *dirmask, BOOL *filespec)
{ ULONG *mask;
BOOL bChanged;
LPWSTR saccess = wcschr(arg, L':');
if (saccess)
{
*saccess = NULL;
bChanged = FALSE;
mask = access;
*mask = 0;
saccess++;
if (wcschr(saccess, L':'))
return(FALSE);
*user = (LPWSTR) arg;
// Enter the loop for access rights
while ( (*saccess == L'N') ||
(*saccess == L'n') ||
(*saccess == L'R') ||
(*saccess == L'r') ||
(*saccess == L'C') ||
(*saccess == L'c') ||
(*saccess == L'F') ||
(*saccess == L'f') ||
(*saccess == L'P') ||
(*saccess == L'p') ||
(*saccess == L'O') ||
(*saccess == L'o') ||
(*saccess == L'X') ||
(*saccess == L'x') ||
(*saccess == L'E') ||
(*saccess == L'e') ||
(*saccess == L'W') ||
(*saccess == L'w') ||
(*saccess == L'D') ||
(*saccess == L'd') ||
(*saccess == L'T') ||
(*saccess == L't') ||
(*saccess == L';'))
{ if ((*saccess == L'F') || (*saccess == L'f'))
{
*mask |= ( STANDARD_RIGHTS_ALL |
FILE_READ_DATA |
FILE_WRITE_DATA |
FILE_APPEND_DATA |
FILE_READ_EA |
FILE_WRITE_EA |
FILE_EXECUTE |
FILE_DELETE_CHILD |
FILE_READ_ATTRIBUTES |
FILE_WRITE_ATTRIBUTES );
}
else if ((*saccess == L'R') || (*saccess == L'r'))
{
if (bChanged)
*mask |= READ_CONTROL | SYNCHRONIZE | FILE_GENERIC_READ | FILE_GENERIC_EXECUTE | FILE_READ_DATA | FILE_EXECUTE | FILE_READ_EA | FILE_READ_ATTRIBUTES;
else
*mask |= FILE_GENERIC_READ | FILE_EXECUTE;
}
else if ((*saccess == L'C') || (*saccess == L'c'))
{
*mask |= FILE_GENERIC_WRITE | FILE_GENERIC_READ | FILE_EXECUTE | DELETE;
}
else if ((*saccess == L'N') || (*saccess == L'n'))
{
*mask |= GENERIC_NONE;
}
else if ((*saccess == L'P') || (*saccess == L'p'))
{
*mask |= WRITE_DAC;
}
else if ((*saccess == L'O') || (*saccess == L'o'))
{
*mask |= WRITE_OWNER;
}
else if ((*saccess == L'X') || (*saccess == L'x'))
{
if (bChanged)
*mask |= READ_CONTROL | SYNCHRONIZE | FILE_GENERIC_EXECUTE | FILE_EXECUTE | FILE_READ_ATTRIBUTES;
else
*mask |= GENERIC_EXECUTE;
}
else if ((*saccess == L'E') || (*saccess == L'e'))
{ if (bChanged)
*mask |= READ_CONTROL | SYNCHRONIZE | FILE_GENERIC_READ | FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES;
else
*mask |= FILE_GENERIC_READ;
}
else if ((*saccess == L'W') || (*saccess == L'w'))
{
if (bChanged)
*mask |= READ_CONTROL | SYNCHRONIZE | FILE_GENERIC_WRITE | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES;
else
*mask |= FILE_GENERIC_WRITE;
}
else if ((*saccess == L'D') || (*saccess == L'd'))
{
*mask |= DELETE;
}
else if ((*saccess == L'T') || (*saccess == L't'))
{
if (!bChanged)
return (FALSE);
else
{ *filespec = TRUE;
*mask = 0;
// at least one option has to follow
if ((*(saccess+1) == ' ') || (*(saccess+1) == 0) || (*(saccess+1) == '/'))
return (FALSE);
}
}
else if (*saccess == ';')
{
mask = dirmask;
bChanged = TRUE;
*mask = 0;
} else
return(FALSE);
saccess++;
}
if (!bChanged)
*dirmask = *access;
if ((*saccess == L' ') || (*saccess == 0) || (*saccess == L'/'))
return(TRUE);
}
return(FALSE);
}
//---------------------------------------------------------------------------
//
// Function: mbstowcs
//
// Synopsis: converts char to wchar, allocates space for wchar
//
// Arguments: IN [aname] - char string
//
//----------------------------------------------------------------------------
LPWSTR mbstowcs(LPCWSTR aname )
{
if (aname)
{
LPCWSTR pwname = NULL;
pwname = (LPCWSTR) LocalAlloc(LMEM_FIXED, sizeof(WCHAR) * (wcslen(aname)+1));
if (NULL == pwname)
return(NULL);
LPWSTR prwname = (LPWSTR) pwname;
for (; prwname = (LPWSTR) aname; prwname++,aname++ );
return((LPWSTR)pwname);
} else
return(NULL);
}
//----------------------------------------------------------------------------
//
// Function:
//
// Synopsis:
//
// Arguments:
//
//----------------------------------------------------------------------------
BOOL OpenToken(PHANDLE ph)
{
HANDLE hprocess;
hprocess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
if (hprocess == NULL)
return(FALSE);
if (OpenProcessToken(hprocess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ph))
{
CloseHandle(hprocess);
return(TRUE);
}
CloseHandle(hprocess);
return(FALSE);
}
//----------------------------------------------------------------------------
//
// Function: printfsid
//
// Synopsis: prints a NT SID
//
// Arguments: IN [psid] - pointer to the sid to print
//
//----------------------------------------------------------------------------
void printfsid(SID *psid, ULONG *outputoffset)
{
#if DBG
if ((Debug & DEBUG_VERBOSE) || (Debug & DEBUG_DISPLAY_SIDS))
{
wprintf(L"S-%lx",psid->Revision);
if ( (psid->IdentifierAuthority.Value[0] != 0) ||
(psid->IdentifierAuthority.Value[1] != 0) )
{
wprintf(L"0x%02hx%02hx%02hx%02hx%02hx%02hx",
(USHORT)psid->IdentifierAuthority.Value[0],
(USHORT)psid->IdentifierAuthority.Value[1],
(USHORT)psid->IdentifierAuthority.Value[2],
(USHORT)psid->IdentifierAuthority.Value[3],
(USHORT)psid->IdentifierAuthority.Value[4],
(USHORT)psid->IdentifierAuthority.Value[5] );
} else
{
wprintf(L"-%lu",
(ULONG)psid->IdentifierAuthority.Value[5] +
(ULONG)(psid->IdentifierAuthority.Value[4] << 8) +
(ULONG)(psid->IdentifierAuthority.Value[3] << 16) +
(ULONG)(psid->IdentifierAuthority.Value[2] << 24) );
}
if ( 0 < psid->SubAuthorityCount )
{
for (int k = 0; k < psid->SubAuthorityCount; k++ )
{
wprintf(L"-%d",psid->SubAuthority[k]);
}
}
}
#endif
ULONG ret;
CAccount ca(psid, NULL);
LPWSTR domain = NULL;
LPWSTR user = NULL;
if (NO_ERROR == ( ret = ca.GetAccountDomain(&domain) ) )
{
if ( (NULL == domain) || (0 == wcslen(domain)) )
{
fwprintf(stdout, L" ");
*outputoffset +=1;
}
else
{
fwprintf(stdout, L" %ws\\",domain);
*outputoffset +=2 + wcslen(domain);
}
if (NO_ERROR == ( ret = ca.GetAccountName(&user) ) )
{
fwprintf(stdout, L"%ws:",user);
*outputoffset += 1 + wcslen(user);
} else
{
*outputoffset += printmessage(stdout, MSG_CACLS_NAME_NOT_FOUND, NULL);
ERRORS((stderr, L"(%lx)",ret))
}
} else
{
*outputoffset+= printmessage(stdout, MSG_CACLS_DOMAIN_NOT_FOUND, NULL);
ERRORS((stderr, L"(%lx)",ret))
}
VERBOSE((stderr, L"\n"))
}
//----------------------------------------------------------------------------
//
// Function: printface
//
// Synopsis: prints the specifed ace
//
// Arguments: IN [paceh] - input ace (header)
// IN [fdir] - TRUE = directory (different display options)
//
//----------------------------------------------------------------------------
void printface(ACE_HEADER *paceh, BOOL fdir, ULONG outputoffset)
{
VERBOSE((stderr, L" "))
VERBOSER((stderr, L"\npaceh->AceType = %x\n",paceh->AceType ))
VERBOSER((stderr, L"paceh->AceFlags = %x\n",paceh->AceFlags ))
VERBOSER((stderr, L"paceh->AceSize = %x\n",paceh->AceSize ))
ACCESS_ALLOWED_ACE *paaa = (ACCESS_ALLOWED_ACE *)paceh;
printfsid((SID *)&(paaa->SidStart),&outputoffset);
if (paceh->AceFlags & OBJECT_INHERIT_ACE )
{
outputoffset+= printmessage(stdout, MSG_CACLS_OBJECT_INHERIT, NULL);
}
if (paceh->AceFlags & CONTAINER_INHERIT_ACE )
{
outputoffset+= printmessage(stdout, MSG_CACLS_CONTAINER_INHERIT, NULL);
}
if (paceh->AceFlags & NO_PROPAGATE_INHERIT_ACE)
{
outputoffset+= printmessage(stdout, MSG_CACLS_NO_PROPAGATE_INHERIT, NULL);
}
if (paceh->AceFlags & INHERIT_ONLY_ACE )
{
outputoffset+= printmessage(stdout, MSG_CACLS_INHERIT_ONLY, NULL);
}
if (paceh->AceType == ACCESS_DENIED_ACE_TYPE)
{
DISPLAY_MASK((stderr, L"(DENIED)"))
VERBOSE((stderr, L"(DENIED)"))
}
printfmask(paaa->Mask, paceh->AceType, fdir, outputoffset);
fwprintf(stdout, L"\n");
}
//----------------------------------------------------------------------------
//
// Function: printfmask
//
// Synopsis: prints the access mask
//
// Arguments: IN [mask] - the access mask
// IN [acetype] - allowed/denied
// IN [fdir] - TRUE = directory
//
//----------------------------------------------------------------------------
LPWSTR aRightsStr[] = { L"STANDARD_RIGHTS_ALL",
L"DELETE",
L"READ_CONTROL",
L"WRITE_DAC",
L"WRITE_OWNER",
L"SYNCHRONIZE",
L"STANDARD_RIGHTS_REQUIRED",
L"SPECIFIC_RIGHTS_ALL",
L"ACCESS_SYSTEM_SECURITY",
L"MAXIMUM_ALLOWED",
L"GENERIC_READ",
L"GENERIC_WRITE",
L"GENERIC_EXECUTE",
L"GENERIC_ALL",
L"FILE_GENERIC_READ",
L"FILE_GENERIC_WRITE",
L"FILE_GENERIC_EXECUTE",
L"FILE_READ_DATA",
//FILE_LIST_DIRECTORY
L"FILE_WRITE_DATA",
//FILE_ADD_FILE
L"FILE_APPEND_DATA",
//FILE_ADD_SUBDIRECTORY
L"FILE_READ_EA",
L"FILE_WRITE_EA",
L"FILE_EXECUTE",
//FILE_TRAVERSE
L"FILE_DELETE_CHILD",
L"FILE_READ_ATTRIBUTES",
L"FILE_WRITE_ATTRIBUTES" };
#define NUMRIGHTS 26
ULONG aRights[NUMRIGHTS] = { STANDARD_RIGHTS_ALL ,
DELETE ,
READ_CONTROL ,
WRITE_DAC ,
WRITE_OWNER ,
SYNCHRONIZE ,
STANDARD_RIGHTS_REQUIRED ,
SPECIFIC_RIGHTS_ALL ,
ACCESS_SYSTEM_SECURITY ,
MAXIMUM_ALLOWED ,
GENERIC_READ ,
GENERIC_WRITE ,
GENERIC_EXECUTE ,
GENERIC_ALL ,
FILE_GENERIC_READ ,
FILE_GENERIC_WRITE ,
FILE_GENERIC_EXECUTE ,
FILE_READ_DATA ,
//FILE_LIST_DIRECTORY ,
FILE_WRITE_DATA ,
//FILE_ADD_FILE ,
FILE_APPEND_DATA ,
//FILE_ADD_SUBDIRECTORY ,
FILE_READ_EA ,
FILE_WRITE_EA ,
FILE_EXECUTE ,
//FILE_TRAVERSE ,
FILE_DELETE_CHILD ,
FILE_READ_ATTRIBUTES ,
FILE_WRITE_ATTRIBUTES };
void printfmask(ULONG mask, WCHAR acetype, BOOL fdir, ULONG outputoffset)
{
ULONG savmask = mask;
VERBOSER((stderr, L"mask = %08lx ", mask))
DISPLAY_MASK((stderr, L"mask = %08lx\n", mask))
VERBOSE((stderr, L" "))
#if DBG
if (!(Debug & (DEBUG_VERBOSE | DEBUG_DISPLAY_MASK)))
{
#endif
if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
(mask == (FILE_GENERIC_READ | FILE_EXECUTE)))
{
printmessage(stdout, MSG_CACLS_READ, NULL);
} else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
(mask == (FILE_GENERIC_WRITE | FILE_GENERIC_READ | FILE_EXECUTE | DELETE)))
{
printmessage(stdout, MSG_CACLS_CHANGE, NULL);
} else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
(mask == (GENERIC_WRITE | GENERIC_READ | GENERIC_EXECUTE | DELETE)))
{
printmessage(stdout, MSG_CACLS_CHANGE, NULL);
} else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
(mask == ( STANDARD_RIGHTS_ALL |
FILE_READ_DATA |
FILE_WRITE_DATA |
FILE_APPEND_DATA |
FILE_READ_EA |
FILE_WRITE_EA |
FILE_EXECUTE |
FILE_DELETE_CHILD |
FILE_READ_ATTRIBUTES |
FILE_WRITE_ATTRIBUTES )) )
{
printmessage(stdout, MSG_CACLS_FULL_CONTROL, NULL);
} else if ((acetype == ACCESS_ALLOWED_ACE_TYPE) &&
(mask == GENERIC_ALL))
{
printmessage(stdout, MSG_CACLS_FULL_CONTROL, NULL);
} else if ((acetype == ACCESS_DENIED_ACE_TYPE) &&
(mask == GENERIC_ALL))
{
printmessage(stdout, MSG_CACLS_NONE, NULL);
} else if ((acetype == ACCESS_DENIED_ACE_TYPE) &&
(mask == ( STANDARD_RIGHTS_ALL |
FILE_READ_DATA |
FILE_WRITE_DATA |
FILE_APPEND_DATA |
FILE_READ_EA |
FILE_WRITE_EA |
FILE_EXECUTE |
FILE_DELETE_CHILD |
FILE_READ_ATTRIBUTES |
FILE_WRITE_ATTRIBUTES )) )
{
printmessage(stdout, MSG_CACLS_NONE, NULL);
} else
{
if (acetype == ACCESS_DENIED_ACE_TYPE)
printmessage(stdout, MSG_CACLS_DENY, NULL);
printmessage(stdout, MSG_CACLS_SPECIAL_ACCESS, NULL);
for (int k = 0; k<NUMRIGHTS ; k++ )
{
if ((mask & aRights[k]) == aRights[k])
{
fwprintf(stdout, L"%*s%s\n",outputoffset, L" ", aRightsStr[k]);
}
if (mask == 0)
break;
}
}
#if DBG
} else
{
if (Debug & (DEBUG_DISPLAY_MASK | DEBUG_VERBOSE))
{
for (int k = 0; k<NUMRIGHTS ; k++ )
{
if ((mask & aRights[k]) == aRights[k])
{
if (mask != savmask) wprintf(L" |\n");
wprintf(L" %s",aRightsStr[k]);
mask &= ~aRights[k];
}
if (mask == 0)
break;
}
}
VERBOSE((stderr, L"=%x",mask))
if (mask != 0)
DISPLAY((stderr, L"=%x/%x",mask,savmask))
}
#endif
fwprintf(stdout, L" ");
}
//----------------------------------------------------------------------------
//
// Function: printmessage
//
// Synopsis: prints a message, either from the local message file, or from the system
//
// Arguments: IN [fp] - stderr, stdio, etc.
// IN [messageID] - variable argument list
//
// Returns: length of the output buffer
//
//----------------------------------------------------------------------------
/*ULONG printmessage (FILE* fp, DWORD messageID, ...)
{
WCHAR messagebuffer[4096];
va_list ap;
va_start(ap, messageID);
if (!FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, messageID, 0,
(LPTSTR)messagebuffer, 4095, &ap))
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, messageID, 0,
(LPTSTR)messagebuffer, 4095, &ap);
fwprintf(fp, messagebuffer);
va_end(ap);
return(wcslen(messagebuffer));
}*/