Windows Create File Access, которая позволяет только владельцу получить доступ к файлу (Win32)
Я пытаюсь изменить права доступа Windows к файлу таким образом, чтобы только владелец (даже не другие администраторы) мог получить доступ к файлу. В некоторой степени эквивалент файла unix chmod 700.
Я играл с лишением прав на общую группу (КАЖДЫЙ, АДМИНИСТРАТОРЫ) и предоставлением их текущему пользователю, но текущий пользователь всегда также теряет права.
Я пытался изменить порядок (eas[0], eas[1]) и прочее, но безуспешно.
Идеи кого-нибудь?
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);
3 ответа
В большинстве случаев запрещенные записи имеют приоритет над разрешенными записями. Поскольку доступ запрещен по умолчанию, запись запрета не требуется, однако вам необходимо отключить унаследованные разрешения. Вы можете сделать это с помощью PROTECTED_DACL_SECURITY_INFORMATION
флаг.
#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;
}
Обратите внимание, что администратор всегда может сбросить разрешения, чтобы получить доступ к файлу. Если вам действительно нужно защитить данные от других администраторов, вам придется зашифровать их. (И надеюсь, что никто не установит кейлоггер, чтобы украсть ваш пароль шифрования.)
Хотя технически это возможно, это не слишком выгодно для обеспечения безопасности объекта. Локальный администратор может не сразу получить доступ к файлу, учитывая DACL с соответствующими записями, но он всегда может стать владельцем любого объекта в системе. Это дает им полный контроль над объектом, и они могут манипулировать его DACL и SACL.
Формально вам нужен следующий код
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;
}
линия примечания
SetSecurityDescriptorControl(&sd, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
с этим кодом DACL
для файла будет иметь только одну запись - GENERIC_ALL
для текущего пользователя. а все то, что явно не разрешено в DACL - отрицается. но, конечно, если у пользователя есть SE_TAKE_OWNERSHIP_PRIVILEGE
привилегия - вы можете открыть файл с WRITE_OWNER
получить доступ и установить себя в качестве владельца. после этого вы можете открыть файл с WRITE_DAC
и поменять DACL
как было отмечено, @Harry Johnston код может быть и короче, если использовать 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;
}