windows-nt/Source/XPSP1/NT/ds/security/authz/test/adl/test.cpp
2020-09-26 16:20:57 +08:00

447 lines
10 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
test.cpp
Abstract:
Utility which allows to dump a file DACL in ADL or set a file DACL from ADL
Author:
t-eugenz - August 2000
Environment:
User mode only.
Revision History:
Created - August 2000
--*/
#include "adl.h"
//
// Various file rights
// More general rights have priority
//
ADL_MASK_STRING MaskStringMap[] =
{
{ (FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | WRITE_DAC
| WRITE_OWNER | READ_CONTROL | DELETE) & ~SYNCHRONIZE , L"full control" },
{ FILE_GENERIC_READ & ~SYNCHRONIZE, L"read" },
{ FILE_GENERIC_WRITE & ~SYNCHRONIZE, L"write" },
{ FILE_GENERIC_EXECUTE & ~SYNCHRONIZE, L"execute" },
{ DELETE & ~SYNCHRONIZE, L"delete" },
{ READ_CONTROL, L"read control"},
{ WRITE_DAC, L"write dac"},
{ WRITE_OWNER, L"write owner" },
{ SYNCHRONIZE, L"synchronize" },
{ FILE_READ_DATA, L"read data" },
{ FILE_WRITE_DATA, L"write data" },
{ FILE_APPEND_DATA, L"append data" },
{ FILE_READ_EA, L"read extended attributes" },
{ FILE_WRITE_EA, L"write extended attributes" },
{ FILE_EXECUTE, L"file execute" },
{ FILE_READ_ATTRIBUTES, L"read attributes" },
{ FILE_WRITE_ATTRIBUTES, L"write attributes" },
{ 0, NULL }
};
//
// Representation of the English version of ADL
//
ADL_LANGUAGE_SPEC lEnglish =
{
TK_LANG_ENGLISH,
0,
L' ',
L'\t',
L'\n',
L'\r',
L'"',
L',',
L';',
L'(',
L')',
L'@',
L'\\',
L'.',
0,
L"and",
L"except",
L"on",
L"allowed",
L"as",
L"this file",
L"subfolders",
L"files",
L"subfolders and files",
L"noprop"
};
ADL_PARSER_CONTROL EnglishFileParser =
{
&lEnglish,
MaskStringMap,
ACCESS_SYSTEM_SECURITY | MAXIMUM_ALLOWED,
SYNCHRONIZE
};
//
// Error handler
//
void HandleError(AdlStatement::ADL_ERROR_TYPE adlErr, const AdlToken *pTok)
{
switch(adlErr)
{
//
// Errors that should not happen unless there is a problem with the
// system or the user makes a mistake
//
case AdlStatement::ERROR_FATAL_LEXER_ERROR:
case AdlStatement::ERROR_FATAL_PARSER_ERROR:
case AdlStatement::ERROR_FATAL_ACL_CONVERT_ERROR:
case AdlStatement::ERROR_OUT_OF_MEMORY:
case AdlStatement::ERROR_ACL_API_FAILED:
case AdlStatement::ERROR_NOT_INITIALIZED:
wprintf(L"\n\nFatal internal error, Errorcode %u, THIS IS BAD\n\n", adlErr);
break;
case AdlStatement::ERROR_LSA_FAILED:
wprintf(L"\n\nError: LSA failed. Unable to resolve user information\n\n");
break;
//
// Input-related grammar errors: no token supplied
//
case AdlStatement::ERROR_UNTERMINATED_STRING:
wprintf(L"\n\nError: unmatched quote in the input\n\n");
break;
case AdlStatement::ERROR_UNKNOWN_ACE_TYPE:
wprintf(L"\n\nError: Unknown ACE type encountered\n\n");
break;
case AdlStatement::ERROR_IMPERSONATION_UNSUPPORTED:
wprintf(L"\n\nError: Impersonation is currently not supported in ADL\n\n");
break;
case AdlStatement::ERROR_INVALID_PARSER_CONTROL:
wprintf(L"\n\nError: The specified laanguage type is not supported\n\n");
break;
//
// For this error, the last read token is supplied
//
case AdlStatement::ERROR_NOT_IN_LANGUAGE:
wprintf(L"\n\nError, invalid ADL statement, did not expect '%s',\n\
which was found between characters %u and %u\n\n", pTok->GetValue(),
pTok->GetStart(), pTok->GetEnd());
break;
//
// Input-related semantic errors
//
//
// For these errors, the offending token is supplied
//
case AdlStatement::ERROR_UNKNOWN_USER:
wprintf(L"\n\nError, unknown user: ");
if( pTok->GetOptValue() != NULL )
{
wprintf(L"'%s%c%s' ", pTok->GetValue(), lEnglish.CH_AT, pTok->GetOptValue());
}
else
{
wprintf(L"'%s' ", pTok->GetValue());
}
wprintf(L"found between characters %u and %u\n\n", pTok->GetStart(), pTok->GetEnd());
break;
case AdlStatement::ERROR_UNKNOWN_PERMISSION:
wprintf(L"\n\nError, unknown permission: '%s' \
found between characters %u and %u\n\n",
pTok->GetValue(), pTok->GetStart(), pTok->GetEnd());
break;
case AdlStatement::ERROR_INVALID_USERNAME:
wprintf(L"\n\nError, invalid username string: '%s' \
found between characters %u and %u\n\n",
pTok->GetValue(), pTok->GetStart(), pTok->GetEnd());
break;
case AdlStatement::ERROR_INVALID_DOMAIN:
wprintf(L"\n\nError, invalid domain name string: '%s' \
found between characters %u and %u\n\n",
pTok->GetValue(), pTok->GetStart(), pTok->GetEnd());
break;
case AdlStatement::ERROR_INVALID_OBJECT:
wprintf(L"\n\nError, invalid object specifier: '%s' \
found between characters %u and %u\n\n",
pTok->GetValue(), pTok->GetStart(), pTok->GetEnd());
break;
//
// Other errors with no token supplied
//
case AdlStatement::ERROR_UNKNOWN_SID:
wprintf(L"\n\nError: SID encountered which could not be resolved to a name\n\n");
break;
case AdlStatement::ERROR_UNKNOWN_ACCESS_MASK:
wprintf(L"\n\nError: Access mask contains unknown bit\n\n");
break;
case AdlStatement::ERROR_INEXPRESSIBLE_ACL:
wprintf(L"\n\nError: This DACL cannot be expressed in ADL\n\n");
break;
default:
wprintf(L"\n\nUNKNOWN Error code: %u, THIS IS VERY BAD\n\n", adlErr);
break;
}
}
//
// -dump Filename
//
void DumpDaclToAdl(int argc, WCHAR *argv[]) {
DWORD dwErr;
if(argc != 3)
{
wprintf(L"\nUsage:\n\n%s -dump <target>\n\n", argv[0]);
exit(1);
}
PSECURITY_DESCRIPTOR pSD;
SECURITY_INFORMATION SecInfo = DACL_SECURITY_INFORMATION;
DWORD dwLengthNeeded;
GetFileSecurity(
argv[2],
SecInfo,
NULL,
0,
&dwLengthNeeded);
pSD = (PSECURITY_DESCRIPTOR) new BYTE[dwLengthNeeded];
dwErr = GetFileSecurity(
argv[2],
SecInfo,
pSD,
dwLengthNeeded,
&dwLengthNeeded);
if( dwErr == 0)
{
dwErr = GetLastError();
wprintf(L"GetFileSecurity failed on file '%s' with error %u, 0x%x\n",
argv[2], dwErr, dwErr);
exit(5);
}
PACL pDacl;
BOOL fDaclPresent;
BOOL fDaclDefaulted;
GetSecurityDescriptorDacl(pSD, &fDaclPresent, &pDacl, &fDaclDefaulted);
if( !fDaclPresent || pDacl == NULL )
{
wprintf(L"Security descriptor of '%s' does not contain a DACL",argv[2]);
exit(6);
}
AdlStatement *stat;
try
{
stat = new AdlStatement(&EnglishFileParser);
wstring ws;
stat->ReadFromDacl(pDacl);
stat->WriteToString(&ws);
wprintf(L"%s", ws.c_str());
}
catch(AdlStatement::ADL_ERROR_TYPE adlErr)
{
HandleError(adlErr, stat->GetErrorToken());
}
if( stat != NULL )
{
delete stat;
}
delete[] (PBYTE)pSD;
}
//
// -set adlfile target
//
void WriteDaclFromAdl(int argc, WCHAR *argv[]) {
WCHAR buf[16384];
char buf3[16384];
DWORD i;
DWORD dwErr;
if(argc != 4)
{
wprintf(L"\nUsage:\n\n%s -set <adl rules file> <target>\n\n", argv[0]);
exit(1);
}
FILE *in = _wfopen(argv[2], L"rb");
if(in == NULL)
{
wprintf(L"Error: cannot open input ADL file '%s', exiting\n", argv[2]);
exit(2);
}
// skip top byte
if( fgetwc(in) != 0xFEFF)
{
fseek(in, 0, SEEK_SET);
for(i = 0; (buf3[i] = (char)fgetc(in)) != EOF && i < 16384; i++);
buf3[i] = 0;
MultiByteToWideChar(CP_ACP, 0, buf3, i+1, buf, 16384);
}
else
{
for(i = 0; (buf[i] = fgetwc(in)) != WEOF && i < 16384; i++);
buf[i] = 0;
}
AdlStatement * stat;
try
{
stat = new AdlStatement( &EnglishFileParser);
wstring ws;
stat->ReadFromString(buf);
stat->WriteToString(&ws);
wprintf(L"Setting permissions to:\n-------------\n%s\n-------------\n",
ws.c_str());
}
catch(AdlStatement::ADL_ERROR_TYPE adlErr)
{
HandleError(adlErr, stat->GetErrorToken());
if( stat != NULL )
{
delete stat;
}
exit(6);
}
//
// Initialize the security descriptor
//
SECURITY_DESCRIPTOR SD;
InitializeSecurityDescriptor(&SD, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorGroup(&SD, NULL, FALSE);
SetSecurityDescriptorOwner(&SD, NULL, FALSE);
SetSecurityDescriptorSacl(&SD, FALSE, NULL, FALSE);
PACL pDacl = NULL;
try
{
stat->WriteToDacl(&pDacl);
}
catch(AdlStatement::ADL_ERROR_TYPE adlErr)
{
HandleError(adlErr, stat->GetErrorToken());
delete stat;
exit(7);
}
SetSecurityDescriptorDacl(&SD, TRUE, pDacl, FALSE);
//
// Set the file security
//
SECURITY_INFORMATION SecInfo = DACL_SECURITY_INFORMATION;
dwErr = SetFileSecurity(argv[3], SecInfo, &SD);
if(dwErr == 0)
{
dwErr = GetLastError();
wprintf(L"SetFileSecurity on %s failed with %d, 0x%x\n",
argv[3],
dwErr,
dwErr);
}
else
{
wprintf(L"Success, permissions set.\n");
}
AdlStatement::FreeMemory(pDacl);
delete stat;
}
void __cdecl wmain(int argc, WCHAR *argv[])
{
if(argc < 2)
{
wprintf(L"\nUsage:\n\n%s -set <adl rules file> <target>\n"
L"%s -dump <target>\n\n", argv[0], argv[0]);
}
else
{
if(!_wcsicmp(argv[1], L"-dump"))
{
DumpDaclToAdl(argc, argv);
}
else if(!_wcsicmp(argv[1], L"-set"))
{
WriteDaclFromAdl(argc, argv);
}
else
{
wprintf(L"\nUsage:\n\n%s -set <adl rules file> <target>\n"
L"%s -dump <target>\n\n", argv[0], argv[0]);
}
}
}