2016-10-17 51 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

你的老闆是完全正確的,我刪除了代碼中的每個人的設置,現在按預期工作,謝謝! –