Win32 API: creating a shared file for the current user, but for everyone else

I am testing the following C code using the Win32 API, which is designed to create a new file that is accessible to the current user, but closed (not accessible) to everyone else.

To do this, it will deny all permissions for all SIDs, and then for the current user SID. I set permissions.

The file was created successfully, and the permissions seem to be successfully configured (see screenshots below), however, when I try to open the file using notepad, it says: “Access is denied” (My file explorer works under the same session), also if I open the command line and do "type file_created.txt", the same "access denied" will appear.

I can, of course, manually restore permissions, since I'm an administrator, but the idea is to make it work programmatically.

Image with all permissions: enter image description here

Image with current user permissions: enter image description here

The code:

#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;
}

NOTE. I realized that the code has memory leaks and other problems, I just hacked quickly to test the idea.

+4
source share
1 answer

Windows Windows . "" , , . , ACL - , .

+6

Source: https://habr.com/ru/post/1657944/


All Articles