Reputation: 417
I'm trying to modify Windows access rights to a file in a way that only the owner (not even other Administrators) can access the file. Somewhat the equivalent of unix chmod 700 file.
I've played with denying rights to the general group (EVERYONE, ADMINISTRATORS) and granting them to the current user, but the current user always also loses the rights.
I tried to change the order (eas[0], eas[1]) and stuff, but without success.
Ideas anyone?
EXPLICIT_ACCESSA ea= { 0, }, eas[5]= { { 0, }, };
PACL pacl= 0;
ea.grfAccessPermissions = GENERIC_ALL;
ea.grfAccessMode = DENY_ACCESS ;
ea.grfInheritance = NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea.Trustee.ptstrName = "EVERYONE";
eas[0]= ea;
ea.grfAccessPermissions = GENERIC_ALL;
ea.grfAccessMode = GRANT_ACCESS ;
ea.grfInheritance = NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
ea.Trustee.ptstrName = "CURRENT_USER";
eas[1]= ea;
rc= SetEntriesInAcl(2, &eas[0], NULL, &pacl);
rc= SetNamedSecurityInfoA((LPSTR)filename, SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL, NULL, pacl, NULL);
Upvotes: 1
Views: 2662
Reputation: 33706
formally you need next code
DWORD demo(PCWSTR filename)
{
EXPLICIT_ACCESS ea= {
GENERIC_ALL,
GRANT_ACCESS,
NO_INHERITANCE,
{ 0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_NAME, TRUSTEE_IS_USER, L"CURRENT_USER"}
};
PACL pacl;
DWORD err = SetEntriesInAcl(1, &ea, NULL, &pacl);
if (!err)
{
err = ERROR_GEN_FAILURE;
if (pacl->AceCount == 1)
{
union {
PVOID pvAce;
PACE_HEADER Header;
PACCESS_ALLOWED_ACE pAce;
};
if (GetAce(pacl, 0, &pvAce) && Header->AceType == ACCESS_ALLOWED_ACE_TYPE)
{
HANDLE hFile = CreateFile(filename, WRITE_DAC|WRITE_OWNER, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE);
SetSecurityDescriptorOwner(&sd, &pAce->SidStart, FALSE);
SetSecurityDescriptorControl(&sd, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
err = SetKernelObjectSecurity(hFile, DACL_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION, &sd)
? NOERROR : GetLastError();
CloseHandle(hFile);
}
else
{
err = GetLastError();
}
}
}
LocalFree(pacl);
}
return err;
}
note line
SetSecurityDescriptorControl(&sd, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
with this code DACL
for file will be have only one entry - GENERIC_ALL
for current user. and all what explicitly not allowed in DACL - denied. but of course if user have SE_TAKE_OWNERSHIP_PRIVILEGE
privilege - you can open file with WRITE_OWNER
access and set self as owner. after this you can open file with WRITE_DAC
and change DACL
as noted @Harry Johnston code can be and shorter if use SetNamedSecurityInfo
DWORD demo(PCWSTR filename)
{
EXPLICIT_ACCESS ea= {
GENERIC_ALL,
GRANT_ACCESS,
NO_INHERITANCE,
{ 0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_NAME, TRUSTEE_IS_USER, L"CURRENT_USER"}
};
PACL pacl;
DWORD err = SetEntriesInAcl(1, &ea, NULL, &pacl);
if (!err)
{
err = ERROR_GEN_FAILURE;
if (pacl->AceCount == 1)
{
union {
PVOID pvAce;
PACE_HEADER Header;
PACCESS_ALLOWED_ACE pAce;
};
if (GetAce(pacl, 0, &pvAce) && Header->AceType == ACCESS_ALLOWED_ACE_TYPE)
{
err = SetNamedSecurityInfo((PWSTR)filename, SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION |PROTECTED_DACL_SECURITY_INFORMATION,
&pAce->SidStart, NULL, pacl, NULL);
}
}
LocalFree(pacl);
}
return err;
}
Upvotes: 1
Reputation: 36308
In most cases, deny entries take precedent over allow entries. Since access is denied by default, you don't need the deny entry, however you will need to disable inherited permissions. You can do this by using the PROTECTED_DACL_SECURITY_INFORMATION
flag.
#include <Windows.h>
#include <Aclapi.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
EXPLICIT_ACCESS eas[1];
PACL pacl = 0;
DWORD rc;
eas[0].grfAccessPermissions = GENERIC_ALL;
eas[0].grfAccessMode = GRANT_ACCESS;
eas[0].grfInheritance = NO_INHERITANCE;
eas[0].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
eas[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
eas[0].Trustee.ptstrName = L"CURRENT_USER";
rc = SetEntriesInAcl(1, &eas[0], NULL, &pacl);
if (rc != ERROR_SUCCESS)
{
printf("SetEntriesInAcl: %u\n", rc);
return 1;
}
rc = SetNamedSecurityInfo(L"C:\\working\\test.txt", SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
NULL, NULL, pacl, NULL);
if (rc != ERROR_SUCCESS)
{
printf("SetNamedSecurityInfo: %u\n", rc);
return 1;
}
printf("OK!\n");
return 0;
}
Note that an administrator can always reset the permissions in order to gain access to the file. If you really need to protect the data against other administrators you'll have to encrypt it. (And hope nobody installs a keylogger to steal your encryption password.)
Upvotes: 4
Reputation: 51345
While technically possible, it doesn't buy you much in the way of securing an object. A local administrator may not immediately be able to access a file, given a DACL with appropriate entries, but they can always take ownership of any object in the system. This grants them full control over the object, and they can manipulate its DACL and SACL.
Upvotes: 1