Anachronism
Anachronism

Reputation: 417

Windows Create File Access that only allows Owner to access the file (Win32)

I'm trying to modify Windows access rights to a file in a way that only the owner (not even other Administrators) can access the file. Somewhat the equivalent of unix chmod 700 file.

I've played with denying rights to the general group (EVERYONE, ADMINISTRATORS) and granting them to the current user, but the current user always also loses the rights.

I tried to change the order (eas[0], eas[1]) and stuff, but without success.

Ideas anyone?

    EXPLICIT_ACCESSA ea= { 0, }, eas[5]= { { 0, }, };
    PACL pacl= 0;

    ea.grfAccessPermissions = GENERIC_ALL;
    ea.grfAccessMode = DENY_ACCESS ;
    ea.grfInheritance = NO_INHERITANCE;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
    ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea.Trustee.ptstrName = "EVERYONE";
    eas[0]= ea;


    ea.grfAccessPermissions = GENERIC_ALL;
    ea.grfAccessMode = GRANT_ACCESS ;
    ea.grfInheritance = NO_INHERITANCE;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
    ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
    ea.Trustee.ptstrName = "CURRENT_USER";
    eas[1]= ea;

    rc= SetEntriesInAcl(2, &eas[0], NULL, &pacl);

    rc= SetNamedSecurityInfoA((LPSTR)filename, SE_FILE_OBJECT,
                                    DACL_SECURITY_INFORMATION,
                                    NULL, NULL, pacl, NULL);

Upvotes: 1

Views: 2662

Answers (3)

RbMm
RbMm

Reputation: 33706

formally you need next code

DWORD demo(PCWSTR filename)
{
    EXPLICIT_ACCESS ea= { 
        GENERIC_ALL, 
        GRANT_ACCESS, 
        NO_INHERITANCE, 
        { 0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_NAME, TRUSTEE_IS_USER, L"CURRENT_USER"}
    };
    PACL pacl;

    DWORD err = SetEntriesInAcl(1, &ea, NULL, &pacl);

    if (!err)
    {
        err = ERROR_GEN_FAILURE;

        if (pacl->AceCount == 1)
        {
            union {
                PVOID pvAce;
                PACE_HEADER Header;
                PACCESS_ALLOWED_ACE pAce;
            };

            if (GetAce(pacl, 0, &pvAce) && Header->AceType == ACCESS_ALLOWED_ACE_TYPE)
            {
                HANDLE hFile = CreateFile(filename, WRITE_DAC|WRITE_OWNER, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);

                if (hFile != INVALID_HANDLE_VALUE)
                {
                    SECURITY_DESCRIPTOR sd;
                    InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
                    SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE);
                    SetSecurityDescriptorOwner(&sd, &pAce->SidStart, FALSE);
                    SetSecurityDescriptorControl(&sd, SE_DACL_PROTECTED, SE_DACL_PROTECTED);

                    err = SetKernelObjectSecurity(hFile, DACL_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION, &sd)
                        ? NOERROR : GetLastError();

                    CloseHandle(hFile);
                }
                else
                {
                    err = GetLastError();
                }
            }
        }

        LocalFree(pacl);
    }

    return err;
}

note line

SetSecurityDescriptorControl(&sd, SE_DACL_PROTECTED, SE_DACL_PROTECTED);

with this code DACL for file will be have only one entry - GENERIC_ALL for current user. and all what explicitly not allowed in DACL - denied. but of course if user have SE_TAKE_OWNERSHIP_PRIVILEGE privilege - you can open file with WRITE_OWNER access and set self as owner. after this you can open file with WRITE_DAC and change DACL


as noted @Harry Johnston code can be and shorter if use SetNamedSecurityInfo

DWORD demo(PCWSTR filename)
{
    EXPLICIT_ACCESS ea= { 
        GENERIC_ALL, 
        GRANT_ACCESS, 
        NO_INHERITANCE, 
        { 0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_NAME, TRUSTEE_IS_USER, L"CURRENT_USER"}
    };
    PACL pacl;

    DWORD err = SetEntriesInAcl(1, &ea, NULL, &pacl);

    if (!err)
    {
        err = ERROR_GEN_FAILURE;

        if (pacl->AceCount == 1)
        {
            union {
                PVOID pvAce;
                PACE_HEADER Header;
                PACCESS_ALLOWED_ACE pAce;
            };

            if (GetAce(pacl, 0, &pvAce) && Header->AceType == ACCESS_ALLOWED_ACE_TYPE)
            {
                err = SetNamedSecurityInfo((PWSTR)filename, SE_FILE_OBJECT, 
                    DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION |PROTECTED_DACL_SECURITY_INFORMATION, 
                    &pAce->SidStart, NULL, pacl, NULL);
            }
        }

        LocalFree(pacl);
    }

    return err;
}

Upvotes: 1

Harry Johnston
Harry Johnston

Reputation: 36308

In most cases, deny entries take precedent over allow entries. Since access is denied by default, you don't need the deny entry, however you will need to disable inherited permissions. You can do this by using the PROTECTED_DACL_SECURITY_INFORMATION flag.

#include <Windows.h>
#include <Aclapi.h>

#include <stdio.h>

int main(int argc, char ** argv)
{
    EXPLICIT_ACCESS eas[1];
    PACL pacl = 0;
    DWORD rc;

    eas[0].grfAccessPermissions = GENERIC_ALL;
    eas[0].grfAccessMode = GRANT_ACCESS;
    eas[0].grfInheritance = NO_INHERITANCE;
    eas[0].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
    eas[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    eas[0].Trustee.ptstrName = L"CURRENT_USER";

    rc = SetEntriesInAcl(1, &eas[0], NULL, &pacl);
    if (rc != ERROR_SUCCESS)
    {
        printf("SetEntriesInAcl: %u\n", rc);
        return 1;
    }

    rc = SetNamedSecurityInfo(L"C:\\working\\test.txt", SE_FILE_OBJECT, 
             DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, 
             NULL, NULL, pacl, NULL);
    if (rc != ERROR_SUCCESS)
    {
        printf("SetNamedSecurityInfo: %u\n", rc);
        return 1;
    }

    printf("OK!\n");
    return 0;
}

Note that an administrator can always reset the permissions in order to gain access to the file. If you really need to protect the data against other administrators you'll have to encrypt it. (And hope nobody installs a keylogger to steal your encryption password.)

Upvotes: 4

IInspectable
IInspectable

Reputation: 51345

While technically possible, it doesn't buy you much in the way of securing an object. A local administrator may not immediately be able to access a file, given a DACL with appropriate entries, but they can always take ownership of any object in the system. This grants them full control over the object, and they can manipulate its DACL and SACL.

Upvotes: 1

Related Questions