Win32 API: создание файла общедоступным для текущего пользователя, но приватным для всех остальных

Я тестирую следующий код на C, используя Win32 API, который предназначен для создания нового файла, который доступен для текущего пользователя, но закрыт (не доступен) для всех остальных.

Для этого это запрещает все разрешения для каждого SID, затем для текущего SID пользователя я установил разрешения.

Файл успешно создан, и разрешения, по-видимому, настроены успешно (см. Скриншоты ниже), однако, когда я пытаюсь открыть файл с помощью блокнота, он говорит: «Доступ запрещен» (Мой файловый менеджер работает в том же сеансе), также если я открою командную строку и введу «type file_created.txt», появится тот же «доступ запрещен».

Конечно, я могу восстановить разрешения вручную, так как я администратор, но идея состоит в том, чтобы заставить его работать программно.

Изображение со всеми разрешениями:
введите описание изображения здесь

Изображение с текущими правами пользователя:
введите описание изображения здесь

Код:

#include <windows.h>
#include <AccCtrl.h>
#include <aclapi.h>

#include <stdio.h>
#include <stdexcept>
#include <string>

#undef UNICODE

int GetCurrentUserSid(PSID* pSID)
{
const int MAX_NAME = 256;
DWORD i, dwSize = 0;
HANDLE hToken;
PTOKEN_USER user;
TOKEN_INFORMATION_CLASS TokenClass = TokenUser;

if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ | TOKEN_QUERY, &hToken))
return GetLastError();
else
wprintf(L"OpenProcessToken() - got the handle to the access token!\n");

if (!GetTokenInformation(hToken, TokenClass, NULL, 0, &dwSize))
{
DWORD dwResult = GetLastError();
if (dwResult != ERROR_INSUFFICIENT_BUFFER)
{
wprintf(L"GetTokenInformation() failed, error %u\n", dwResult);
return FALSE;
}
else
wprintf(L"GetTokenInformation() - have an ample buffer...\n");
}
else
wprintf(L"GetTokenInformation() - buffer for Token group is OK\n");

user = (PTOKEN_USER)LocalAlloc(GPTR, dwSize);
if (!GetTokenInformation(hToken, TokenClass, user, dwSize, &dwSize))
{
wprintf(L"GetTokenInformation() failed, error %u\n", GetLastError());
return FALSE;
}
else
wprintf(L"GetTokenInformation() for getting the TokenGroups is OK\n");

DWORD dw_sid_len = GetLengthSid(user->User.Sid);
*pSID = (SID*)LocalAlloc(GPTR, dw_sid_len);
CopySid(dw_sid_len, *pSID, user->User.Sid);
return 0;
}

DWORD set_file_security(LPSTR filename)
{
PACL pNewDACL = NULL;
PSID current_user = NULL;
DWORD sid_size = SECURITY_MAX_SID_SIZE;
SID everyone_sid;
DWORD dwRes;
if (CreateWellKnownSid(WinWorldSid, NULL, &everyone_sid, &sid_size) ==
FALSE) {
throw std::runtime_error("CreateWellKnownSid() failed: " +
std::to_string(GetLastError()));
}

GetCurrentUserSid(&current_user);

EXPLICIT_ACCESSA ea[2];
ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESSA));

ea[0].grfAccessPermissions = ACCESS_SYSTEM_SECURITY | READ_CONTROL | WRITE_DAC | GENERIC_ALL;
ea[0].grfAccessMode = GRANT_ACCESS;
ea[0].grfInheritance = NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.ptstrName = reinterpret_cast<char*>(current_user);

ea[1].grfAccessPermissions = ACCESS_SYSTEM_SECURITY | READ_CONTROL | WRITE_DAC | GENERIC_ALL;
ea[1].grfAccessMode = DENY_ACCESS;
ea[1].grfInheritance = NO_INHERITANCE;
ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[1].Trustee.ptstrName = reinterpret_cast<char*>(&everyone_sid);

dwRes = SetEntriesInAclA(2, ea, NULL, &pNewDACL);
if (ERROR_SUCCESS != dwRes) {
printf("SetEntriesInAcl Error %u\n", dwRes);
//TODO: goto Cleanup;
}

PSECURITY_DESCRIPTOR pSD = NULL;

// Initialize a security descriptor.
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,
SECURITY_DESCRIPTOR_MIN_LENGTH);
if (NULL == pSD)
{
_tprintf(_T("LocalAlloc Error %u\n"), GetLastError());
goto Cleanup;
}

if (!InitializeSecurityDescriptor(pSD,
SECURITY_DESCRIPTOR_REVISION))
{
_tprintf(_T("InitializeSecurityDescriptor Error %u\n"),
GetLastError());
goto Cleanup;
}

// Add the ACL to the security descriptor.
if (!SetSecurityDescriptorDacl(pSD,
TRUE,     // bDaclPresent flag
pNewDACL,
FALSE))   // not a default DACL
{
_tprintf(_T("SetSecurityDescriptorDacl Error %u\n"),
GetLastError());
goto Cleanup;
}
SECURITY_ATTRIBUTES sa;
// Initialize a security attributes structure.
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = FALSE;

HANDLE hFile = CreateFileA(filename, GENERIC_ALL, 0, &sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
CloseHandle(hFile);

//dwRes = SetNamedSecurityInfoA(filename, SE_FILE_OBJECT,
//  DACL_SECURITY_INFORMATION, NULL, NULL, pNewDACL, NULL);
//if (ERROR_SUCCESS != dwRes) {
//  printf("SetNamedSecurityInfo Error %u\n", dwRes);
//  //goto Cleanup;
//}

Cleanup:

if (pNewDACL != NULL)
LocalFree((HLOCAL)pNewDACL);

return dwRes;
}

int main()
{
//return 0;

// Create Everyone SID.
DWORD sid_size = SECURITY_MAX_SID_SIZE;
SID everyone_sid;
if (CreateWellKnownSid(WinWorldSid, NULL, &everyone_sid, &sid_size) ==
FALSE) {
throw std::runtime_error("CreateWellKnownSid() failed: " +
std::to_string(GetLastError()));
}

LPSTR filename = "created_file.txt";

set_file_security(filename);

return 0;
}

ПРИМЕЧАНИЕ: я понял, что у кода есть утечки памяти и другие проблемы, я просто быстро взломал, чтобы проверить идею.

4

Решение

В ОС Windows разрешения на явное запрещение имеют приоритет над разрешениями на явное разрешение. Так как в группу «Все» входит ваша учетная запись, доступ к файлу запрещен, даже если вы включили его для себя. Фактически вам не нужно полностью запрещать правило, если права доступа не установлены в ACL объекта для какого-либо пользователя, доступ по умолчанию будет запрещен.

6

Другие решения

Других решений пока нет …