GetAce() 返回无法识别的受托者 (SID)

GetAce() returning unrecognizable Trustee (SID)

我正在继续寻找圣杯 - 或者,实际上,只是编写一些 C++ 代码,对文件进行一些非常基本的 ACL 修改。而且,我继续用各种挑战来撞墙。最近的一个是 GetAce() 函数返回的“受托人”似乎不是可识别的受托人,即使我确切地知道它应该是什么。

在较高级别上,我目前正在尝试删除特定文件上的显式 ACE,该文件拒绝访问众所周知的 Everyone 组。有趣的是,如果我使用 GetExplicitEntriesFromAcl() 而不是 GetAce(),我将能够获得可识别的 SID,并且它可以与使用 EqualSid() 的 Everyone SID 进行正确比较;但是,我不知道如何从 GetExplicitEntriesFromAcl() 获取信息,然后使用它从 ACL 中完全删除 ACE,因为那时我没有获得 ACE 的绝对索引,并且没有似乎不是 RemoveExplicitEntriesFromAcl() 类型的函数。

下面是使用 GetAce() 的当前代码,但我愿意听取有关如何可靠地定位和删除 Everyone 组的 DENY ACE 的其他建议。

BOOL removeAce(LPTSTR filePath) {

    PACL existingAcl;
    PSECURITY_DESCRIPTOR securityDescriptor;
    
    PSID everyoneSid;
    
    // Get PSID for well-known "Everyone" group
    SID_IDENTIFIER_AUTHORITY sidAuthority = SECURITY_WORLD_SID_AUTHORITY;
    if (!AllocateAndInitializeSid(&sidAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSid))
        return false;
    
    // Make sure we really have a file path
    if (filePath == NULL || wcscmp(filePath, L"") == 0)
        return false;
        
    // Retrieve the ACL for the file, or bail out.
    if (GetNamedSecurityInfo(filePath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &existingAcl, NULL, &securityDescriptor) != ERROR_SUCCESS)
        return false;

    EXPLICIT_ACCESS* aclEntries;
    ULONG numEntries = existingAcl->AceCount;
    
    // Loop through all ACEs
    for (DWORD i = 0; i < numEntries; i++) {
    
        // Going to cast as a ACCESS_DENIED_ACE entry.
        ACCESS_DENIED_ACE* entry;
        
        // Try to get the ACE at current index, or continue to next one.
        if (!GetAce(existingAcl, i, (LPVOID*) &entry))
            continue;
            
        // We're only interested in DENY entries.
        if (entry->Header.AceType != ACCESS_DENIED_ACE_TYPE)
            continue;
        
        // Cast a couple of things to make it easier below
        PSID thisSid = (PSID)entry->SidStart;
        EXPLICIT_ACCESS* eaEntry = (EXPLICIT_ACCESS*)entry;
        
        /* This is where I start to have problems - I put this code
         * in strictly for debug purposes, and it always hits the 
         * default case, indicating that the TrusteeForm is either
         * some unknown type, or I'm doing something insanely
         * wrong and pointing to the wrong block of memory
         * somewhere.
         */
        switch (thisEntry->Trustee.TrusteeForm) {
            case TRUSTEE_IS_SID:
                OutputDebugString(L"We have a SID.\n");
                break;
                
            case TRUSTEE_IS_NAME:
                OutputDebugString(L"We have a name.\n");
                break;
                
            case TRUSTEE_IS_OBJECTS_AND_SID:
                OutputDebugString(L"We have objects and a SID.\n");
                break;
                
            case TRUSTEE_IS_OBJECTS_AND_NAME:
                OutputDebugString(L"We have objects and a name.\n");
                break;
            
            default:
                OutputDebugString(L"We have an alien Trustee type.\n");
        }
        
        /* This is the ultimate goal - being able to match the Trustee
         * of the current ACE being evaluated with the Everyone SID, but
         * this if statement never evaluates to True, and, so far, it
         * seems to be because the TrusteeForm isn't recognized as a SID
         * - or anything else for that matter.
         */
        if (eaEntry->Trustee.TrusteeForm == TRUSTEE_IS_SID
            && EqualSid((PSID)entry->SidStart, everyoneSid))
            OutputDebugString(L"This is our EVERYONE entry.\n");
    }

    return true;

}

SidStart 不是指向 SID 的指针;它是 SID 的前 4 个字节。您需要像这样访问它:

PSID thisSid = (PSID)&(entry->SidStart);