Fer*_*hez 4 c++ winapi sid dacl visual-c++
我正在使用Win32 API在C中测试以下代码,该API旨在创建一个新文件,该文件可供当前用户访问,但对其他人来说是私有的(不可访问).
为此,这拒绝所有人SID的权限,然后为当前的用户SID设置权限.
该文件已成功创建,并且权限显然已成功设置(请参阅下面的屏幕截图),但是当我尝试使用记事本打开文件时,它会显示"访问被拒绝"(我的文件浏览器在同一会话下运行),如果我打开命令提示符并执行"输入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(¤t_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;
}
注意:我意识到代码有内存泄漏和其他问题,我只是很快就黑客来测试这个想法.
在Windows操作系统中,显式拒绝权限优先于显式允许权限.因此,由于"Everyone"组包含您的帐户,即使您自己启用了该文件,也会拒绝访问该文件.实际上,您不需要完全拒绝规则,如果某些用户的对象ACL中没有设置访问权限,默认情况下将拒绝访问.