2016-10-17 32 views
4

我使用Win32 API在C中测试以下代码,该代码旨在创建可供当前用户访问的新文件,但是私有(不可访问)为其他人。Win32 API:为当前用户创建公共文件但为其他人私有

为此,它拒绝所有人的SID权限,然后为当前的用户SID设置权限。

该文件已成功创建并且权限显然已成功设置(请参见下面的截图),但是当我尝试用记事本打开文件时,它说“访问被拒绝”(我的文件资源管理器正在运行会话),如果我打开命令提示符并执行“输入file_created.txt”,则出现相同的“访问被拒绝”。

我当然可以手动恢复权限,因为我是管理员,但其想法是使其以编程方式工作。

图像的每个人的权限: enter image description here

图像的当前用户的权限: enter image description here

代码:

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

注:我实现了代码有内存泄漏等问题,我只是在迅速地测试这个想法。

回答

6

在Windows操作系统中,显式拒绝权限优先于显式允许权限。因此,由于“每个人”组都包含您的帐户,即使您为自己启用了该文件,对该文件的访问也会被拒绝。实际上,如果某些用户的对象ACL中没有设置访问权限,则不需要完全拒绝规则,默认情况下访问将被拒绝。

+0

你的老板是完全正确的,我删除了代码中的每个人的设置,现在按预期工作,谢谢! –