/*++ 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 \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 \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 \n" L"%s -dump \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 \n" L"%s -dump \n\n", argv[0], argv[0]); } } }