mirror of
https://github.com/reactos/reactos.git
synced 2024-09-10 21:04:26 +00:00
![Amine Khaldi](/assets/img/avatar_default.png)
* Create a branch for some evul shell experiments. svn path=/branches/shell-experiments/; revision=61927
605 lines
20 KiB
C
605 lines
20 KiB
C
/*
|
|
* ReactOS Control ACLs Program
|
|
* Copyright (C) 2006 Thomas Weidenmueller
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
static GENERIC_MAPPING FileGenericMapping =
|
|
{
|
|
FILE_GENERIC_READ,
|
|
FILE_GENERIC_WRITE,
|
|
FILE_GENERIC_EXECUTE,
|
|
FILE_ALL_ACCESS
|
|
};
|
|
|
|
|
|
static
|
|
INT
|
|
LengthOfStrResource(IN HINSTANCE hInst,
|
|
IN UINT uID)
|
|
{
|
|
HRSRC hrSrc;
|
|
HGLOBAL hRes;
|
|
LPWSTR lpName, lpStr;
|
|
|
|
if (hInst == NULL)
|
|
{
|
|
hInst = GetModuleHandle(NULL);
|
|
}
|
|
|
|
/* There are always blocks of 16 strings */
|
|
lpName = (LPWSTR)MAKEINTRESOURCE((uID >> 4) + 1);
|
|
|
|
/* Find the string table block */
|
|
hrSrc = FindResourceW(hInst, lpName, (LPWSTR)RT_STRING);
|
|
if (hrSrc)
|
|
{
|
|
hRes = LoadResource(hInst, hrSrc);
|
|
if (hRes)
|
|
{
|
|
lpStr = LockResource(hRes);
|
|
if (lpStr)
|
|
{
|
|
UINT x;
|
|
|
|
/* Find the string we're looking for */
|
|
uID &= 0xF; /* position in the block, same as % 16 */
|
|
for (x = 0; x < uID; x++)
|
|
{
|
|
lpStr += (*lpStr) + 1;
|
|
}
|
|
|
|
/* Found the string */
|
|
return (int)(*lpStr);
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
static
|
|
INT
|
|
AllocAndLoadString(OUT LPTSTR *lpTarget,
|
|
IN HINSTANCE hInst,
|
|
IN UINT uID)
|
|
{
|
|
INT ln;
|
|
|
|
ln = LengthOfStrResource(hInst,
|
|
uID);
|
|
if (ln++ > 0)
|
|
{
|
|
(*lpTarget) = (LPTSTR)HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
ln * sizeof(TCHAR));
|
|
if ((*lpTarget) != NULL)
|
|
{
|
|
INT Ret;
|
|
Ret = LoadString(hInst,
|
|
uID,
|
|
*lpTarget,
|
|
ln);
|
|
if (!Ret)
|
|
{
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
*lpTarget);
|
|
}
|
|
return Ret;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static
|
|
VOID
|
|
PrintHelp(VOID)
|
|
{
|
|
LPTSTR szHelp;
|
|
|
|
if (AllocAndLoadString(&szHelp,
|
|
NULL,
|
|
IDS_HELP) != 0)
|
|
{
|
|
_tprintf(_T("%s"),
|
|
szHelp);
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
szHelp);
|
|
}
|
|
}
|
|
|
|
|
|
static
|
|
VOID
|
|
PrintErrorMessage(IN DWORD dwError)
|
|
{
|
|
LPTSTR szError;
|
|
|
|
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS |
|
|
FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
dwError,
|
|
MAKELANGID(LANG_NEUTRAL,
|
|
SUBLANG_DEFAULT),
|
|
(LPTSTR)&szError,
|
|
0,
|
|
NULL) != 0)
|
|
{
|
|
_tprintf(_T("%s"),
|
|
szError);
|
|
LocalFree((HLOCAL)szError);
|
|
}
|
|
}
|
|
|
|
|
|
static
|
|
DWORD
|
|
LoadAndPrintString(IN HINSTANCE hInst,
|
|
IN UINT uID)
|
|
{
|
|
TCHAR szTemp[255];
|
|
DWORD Len;
|
|
|
|
Len = (DWORD)LoadString(hInst,
|
|
uID,
|
|
szTemp,
|
|
sizeof(szTemp) / sizeof(szTemp[0]));
|
|
|
|
if (Len != 0)
|
|
{
|
|
_tprintf(_T("%s"),
|
|
szTemp);
|
|
}
|
|
|
|
return Len;
|
|
}
|
|
|
|
|
|
static
|
|
BOOL
|
|
PrintFileDacl(IN LPTSTR FilePath,
|
|
IN LPTSTR FileName)
|
|
{
|
|
SIZE_T Length;
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
|
DWORD SDSize = 0;
|
|
TCHAR FullFileName[MAX_PATH + 1];
|
|
BOOL Error = FALSE, Ret = FALSE;
|
|
|
|
Length = _tcslen(FilePath) + _tcslen(FileName);
|
|
if (Length > MAX_PATH)
|
|
{
|
|
/* file name too long */
|
|
SetLastError(ERROR_FILE_NOT_FOUND);
|
|
return FALSE;
|
|
}
|
|
|
|
_tcscpy(FullFileName,
|
|
FilePath);
|
|
_tcscat(FullFileName,
|
|
FileName);
|
|
|
|
/* find out how much memory we need */
|
|
if (!GetFileSecurity(FullFileName,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
0,
|
|
&SDSize) &&
|
|
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
SecurityDescriptor = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
SDSize);
|
|
if (SecurityDescriptor != NULL)
|
|
{
|
|
if (GetFileSecurity(FullFileName,
|
|
DACL_SECURITY_INFORMATION,
|
|
SecurityDescriptor,
|
|
SDSize,
|
|
&SDSize))
|
|
{
|
|
PACL Dacl;
|
|
BOOL DaclPresent;
|
|
BOOL DaclDefaulted;
|
|
|
|
if (GetSecurityDescriptorDacl(SecurityDescriptor,
|
|
&DaclPresent,
|
|
&Dacl,
|
|
&DaclDefaulted))
|
|
{
|
|
if (DaclPresent)
|
|
{
|
|
PACCESS_ALLOWED_ACE Ace;
|
|
DWORD AceIndex = 0;
|
|
|
|
/* dump the ACL */
|
|
while (GetAce(Dacl,
|
|
AceIndex,
|
|
(PVOID*)&Ace))
|
|
{
|
|
SID_NAME_USE Use;
|
|
DWORD NameSize = 0;
|
|
DWORD DomainSize = 0;
|
|
LPTSTR Name = NULL;
|
|
LPTSTR Domain = NULL;
|
|
LPTSTR SidString = NULL;
|
|
DWORD IndentAccess;
|
|
DWORD AccessMask = Ace->Mask;
|
|
PSID Sid = (PSID)&Ace->SidStart;
|
|
|
|
/* attempt to translate the SID into a readable string */
|
|
if (!LookupAccountSid(NULL,
|
|
Sid,
|
|
Name,
|
|
&NameSize,
|
|
Domain,
|
|
&DomainSize,
|
|
&Use))
|
|
{
|
|
if (GetLastError() == ERROR_NONE_MAPPED || NameSize == 0)
|
|
{
|
|
goto BuildSidString;
|
|
}
|
|
else
|
|
{
|
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
Error = TRUE;
|
|
break;
|
|
}
|
|
|
|
Name = (LPTSTR)HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
(NameSize + DomainSize) * sizeof(TCHAR));
|
|
if (Name == NULL)
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
Error = TRUE;
|
|
break;
|
|
}
|
|
|
|
Domain = Name + NameSize;
|
|
Name[0] = _T('\0');
|
|
if (DomainSize != 0)
|
|
Domain[0] = _T('\0');
|
|
if (!LookupAccountSid(NULL,
|
|
Sid,
|
|
Name,
|
|
&NameSize,
|
|
Domain,
|
|
&DomainSize,
|
|
&Use))
|
|
{
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
Name);
|
|
Name = NULL;
|
|
goto BuildSidString;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BuildSidString:
|
|
if (!ConvertSidToStringSid(Sid,
|
|
&SidString))
|
|
{
|
|
Error = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* print the file name or space */
|
|
_tprintf(_T("%s "),
|
|
FullFileName);
|
|
|
|
/* attempt to map the SID to a user name */
|
|
if (AceIndex == 0)
|
|
{
|
|
DWORD i = 0;
|
|
|
|
/* overwrite the full file name with spaces so we
|
|
only print the file name once */
|
|
while (FullFileName[i] != _T('\0'))
|
|
FullFileName[i++] = _T(' ');
|
|
}
|
|
|
|
/* print the domain and/or user if possible, or the SID string */
|
|
if (Name != NULL && Domain[0] != _T('\0'))
|
|
{
|
|
_tprintf(_T("%s\\%s:"),
|
|
Domain,
|
|
Name);
|
|
IndentAccess = (DWORD)_tcslen(Domain) + _tcslen(Name);
|
|
}
|
|
else
|
|
{
|
|
LPTSTR DisplayString = (Name != NULL ? Name : SidString);
|
|
|
|
_tprintf(_T("%s:"),
|
|
DisplayString);
|
|
IndentAccess = (DWORD)_tcslen(DisplayString);
|
|
}
|
|
|
|
/* print the ACE Flags */
|
|
if (Ace->Header.AceFlags & CONTAINER_INHERIT_ACE)
|
|
{
|
|
IndentAccess += LoadAndPrintString(NULL,
|
|
IDS_ABBR_CI);
|
|
}
|
|
if (Ace->Header.AceFlags & OBJECT_INHERIT_ACE)
|
|
{
|
|
IndentAccess += LoadAndPrintString(NULL,
|
|
IDS_ABBR_OI);
|
|
}
|
|
if (Ace->Header.AceFlags & INHERIT_ONLY_ACE)
|
|
{
|
|
IndentAccess += LoadAndPrintString(NULL,
|
|
IDS_ABBR_IO);
|
|
}
|
|
|
|
IndentAccess += 2;
|
|
|
|
/* print the access rights */
|
|
MapGenericMask(&AccessMask,
|
|
&FileGenericMapping);
|
|
if (Ace->Header.AceType & ACCESS_DENIED_ACE_TYPE)
|
|
{
|
|
if (AccessMask == FILE_ALL_ACCESS)
|
|
{
|
|
LoadAndPrintString(NULL,
|
|
IDS_ABBR_NONE);
|
|
}
|
|
else
|
|
{
|
|
LoadAndPrintString(NULL,
|
|
IDS_DENY);
|
|
goto PrintSpecialAccess;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (AccessMask == FILE_ALL_ACCESS)
|
|
{
|
|
LoadAndPrintString(NULL,
|
|
IDS_ABBR_FULL);
|
|
}
|
|
else if (!(Ace->Mask & (GENERIC_READ | GENERIC_EXECUTE)) &&
|
|
AccessMask == (FILE_GENERIC_READ | FILE_EXECUTE))
|
|
{
|
|
LoadAndPrintString(NULL,
|
|
IDS_ABBR_READ);
|
|
}
|
|
else if (AccessMask == (FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_EXECUTE | DELETE))
|
|
{
|
|
LoadAndPrintString(NULL,
|
|
IDS_ABBR_CHANGE);
|
|
}
|
|
else if (AccessMask == FILE_GENERIC_WRITE)
|
|
{
|
|
LoadAndPrintString(NULL,
|
|
IDS_ABBR_WRITE);
|
|
}
|
|
else
|
|
{
|
|
DWORD x, x2;
|
|
static const struct
|
|
{
|
|
DWORD Access;
|
|
UINT uID;
|
|
}
|
|
AccessRights[] =
|
|
{
|
|
{FILE_WRITE_ATTRIBUTES, IDS_FILE_WRITE_ATTRIBUTES},
|
|
{FILE_READ_ATTRIBUTES, IDS_FILE_READ_ATTRIBUTES},
|
|
{FILE_DELETE_CHILD, IDS_FILE_DELETE_CHILD},
|
|
{FILE_EXECUTE, IDS_FILE_EXECUTE},
|
|
{FILE_WRITE_EA, IDS_FILE_WRITE_EA},
|
|
{FILE_READ_EA, IDS_FILE_READ_EA},
|
|
{FILE_APPEND_DATA, IDS_FILE_APPEND_DATA},
|
|
{FILE_WRITE_DATA, IDS_FILE_WRITE_DATA},
|
|
{FILE_READ_DATA, IDS_FILE_READ_DATA},
|
|
{FILE_GENERIC_EXECUTE, IDS_FILE_GENERIC_EXECUTE},
|
|
{FILE_GENERIC_WRITE, IDS_FILE_GENERIC_WRITE},
|
|
{FILE_GENERIC_READ, IDS_FILE_GENERIC_READ},
|
|
{GENERIC_ALL, IDS_GENERIC_ALL},
|
|
{GENERIC_EXECUTE, IDS_GENERIC_EXECUTE},
|
|
{GENERIC_WRITE, IDS_GENERIC_WRITE},
|
|
{GENERIC_READ, IDS_GENERIC_READ},
|
|
{MAXIMUM_ALLOWED, IDS_MAXIMUM_ALLOWED},
|
|
{ACCESS_SYSTEM_SECURITY, IDS_ACCESS_SYSTEM_SECURITY},
|
|
{SPECIFIC_RIGHTS_ALL, IDS_SPECIFIC_RIGHTS_ALL},
|
|
{STANDARD_RIGHTS_REQUIRED, IDS_STANDARD_RIGHTS_REQUIRED},
|
|
{SYNCHRONIZE, IDS_SYNCHRONIZE},
|
|
{WRITE_OWNER, IDS_WRITE_OWNER},
|
|
{WRITE_DAC, IDS_WRITE_DAC},
|
|
{READ_CONTROL, IDS_READ_CONTROL},
|
|
{DELETE, IDS_DELETE},
|
|
{STANDARD_RIGHTS_ALL, IDS_STANDARD_RIGHTS_ALL},
|
|
};
|
|
|
|
LoadAndPrintString(NULL,
|
|
IDS_ALLOW);
|
|
|
|
PrintSpecialAccess:
|
|
LoadAndPrintString(NULL,
|
|
IDS_SPECIAL_ACCESS);
|
|
|
|
/* print the special access rights */
|
|
x = sizeof(AccessRights) / sizeof(AccessRights[0]);
|
|
while (x-- != 0)
|
|
{
|
|
if ((Ace->Mask & AccessRights[x].Access) == AccessRights[x].Access)
|
|
{
|
|
_tprintf(_T("\n%s "),
|
|
FullFileName);
|
|
for (x2 = 0;
|
|
x2 < IndentAccess;
|
|
x2++)
|
|
{
|
|
_tprintf(_T(" "));
|
|
}
|
|
|
|
LoadAndPrintString(NULL,
|
|
AccessRights[x].uID);
|
|
}
|
|
}
|
|
|
|
_tprintf(_T("\n"));
|
|
}
|
|
}
|
|
|
|
_tprintf(_T("\n"));
|
|
|
|
/* free up all resources */
|
|
if (Name != NULL)
|
|
{
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
Name);
|
|
}
|
|
|
|
if (SidString != NULL)
|
|
{
|
|
LocalFree((HLOCAL)SidString);
|
|
}
|
|
|
|
AceIndex++;
|
|
}
|
|
|
|
if (!Error)
|
|
Ret = TRUE;
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_NO_SECURITY_ON_OBJECT);
|
|
}
|
|
}
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
SecurityDescriptor);
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
|
|
int
|
|
__cdecl
|
|
_tmain(int argc, const TCHAR *argv[])
|
|
{
|
|
if (argc < 2)
|
|
{
|
|
PrintHelp();
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
TCHAR FullPath[MAX_PATH + 1];
|
|
TCHAR *FilePart = NULL;
|
|
WIN32_FIND_DATA FindData;
|
|
HANDLE hFind;
|
|
DWORD LastError;
|
|
|
|
if (argc > 2)
|
|
{
|
|
/* FIXME - parse arguments */
|
|
}
|
|
|
|
/* get the full path of where we're searching in */
|
|
if (GetFullPathName(argv[1],
|
|
sizeof(FullPath) / sizeof(FullPath[0]),
|
|
FullPath,
|
|
&FilePart) != 0)
|
|
{
|
|
if (FilePart != NULL)
|
|
*FilePart = _T('\0');
|
|
}
|
|
else
|
|
goto Error;
|
|
|
|
/* find the file(s) */
|
|
hFind = FindFirstFile(argv[1],
|
|
&FindData);
|
|
if (hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
do
|
|
{
|
|
if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
|
|
(_tcscmp(FindData.cFileName,
|
|
_T(".")) &&
|
|
_tcscmp(FindData.cFileName,
|
|
_T(".."))))
|
|
{
|
|
if (argc > 2)
|
|
{
|
|
/* FIXME - edit or replace the descriptor */
|
|
}
|
|
else
|
|
{
|
|
if (!PrintFileDacl(FullPath,
|
|
FindData.cFileName))
|
|
{
|
|
LastError = GetLastError();
|
|
|
|
if (LastError == ERROR_ACCESS_DENIED)
|
|
{
|
|
PrintErrorMessage(LastError);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
else
|
|
_tprintf(_T("\n"));
|
|
}
|
|
}
|
|
} while (FindNextFile(hFind,
|
|
&FindData));
|
|
|
|
FindClose(hFind);
|
|
|
|
if (GetLastError() != ERROR_NO_MORE_FILES)
|
|
{
|
|
goto Error;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Error:
|
|
PrintErrorMessage(GetLastError());
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|