Focker
Focker

Reputation: 215

File\Directory Security Permissions

Have an annoying issue, and I dont essentially know where it comes from :( So, the subject is: When trying to check folders permissions from localhost (from actual filesystem) it (code attached below) works fine, but when application is launched from the network (eg: \*machinename*) it does not. When I'm requesting ANY permission I always get Approval over the network, but can't create file, for example, because I dont have sufficient permission for it!

iccFile_Security =
    class
        const
            FILE_READ_DATA        = $0001;
            FILE_WRITE_DATA       = $0002;
            FILE_APPEND_DATA      = $0004;
            FILE_READ_EA          = $0008;
            FILE_WRITE_EA         = $0010;
            FILE_EXECUTE          = $0020;
            FILE_READ_ATTRIBUTES  = $0080;
            FILE_WRITE_ATTRIBUTES = $0100;
            FILE_GENERIC_READ     = (    STANDARD_RIGHTS_READ
                                      or FILE_READ_DATA
                                      or FILE_READ_ATTRIBUTES
                                      or FILE_READ_EA
                                      or SYNCHRONIZE
                                    );
            FILE_GENERIC_WRITE    = (    STANDARD_RIGHTS_WRITE
                                      or FILE_WRITE_DATA
                                      or FILE_WRITE_ATTRIBUTES
                                      or FILE_WRITE_EA
                                      or FILE_APPEND_DATA
                                      or SYNCHRONIZE
                                    );
            FILE_GENERIC_EXECUTE  = (    STANDARD_RIGHTS_EXECUTE
                                      or FILE_READ_ATTRIBUTES
                                      or FILE_EXECUTE
                                      or SYNCHRONIZE
                                    );
            FILE_ALL_ACCESS       = (    STANDARD_RIGHTS_REQUIRED
                                      or SYNCHRONIZE
                                      or $1FF
                                    );
        strict private
        public
            class function check( _filename : String; _desiredAccess : DWORD                       ) : Boolean; overload;
            class function check( _filename : String; _desiredAccess : DWORD; out _failed : Boolean) : Boolean; overload;
    end;

implementation

{ iccFile_Security }

class function iccFile_Security.check( _filename: String; _desiredAccess: DWORD) :    Boolean;
var _failed : Boolean;
begin
    result := check( _filename, _desiredAccess, _failed) and not _failed;
end;

class function iccFile_Security.check( _filename : String; _desiredAccess : DWORD; out _failed : Boolean) : Boolean;
var Token       : DWORD;
    Status      : LongBool;
    Access      : DWORD;
    SecDescSize : DWORD;
    PrivSetSize : DWORD;
    PrivSet     : PRIVILEGE_SET;
    Mapping     : GENERIC_MAPPING;
    SecDesc     : PSECURITY_DESCRIPTOR;
begin
    Result := False;

    SecDesc     := nil;
    SecDescSize := 0;

    try
       GetFileSecurity( pchar( _filename),
                            OWNER_SECURITY_INFORMATION
                         or GROUP_SECURITY_INFORMATION
                         or DACL_SECURITY_INFORMATION,
                         nil,
                         0,
                         SecDescSize
                       );

        SecDesc := GetMemory( SecDescSize);

        if not GetFileSecurity( pchar( _filename),
                                   OWNER_SECURITY_INFORMATION
                                or GROUP_SECURITY_INFORMATION
                                or DACL_SECURITY_INFORMATION,
                                SecDesc,
                                SecDescSize,
                                SecDescSize
                              )
            then begin
                     _failed := true;
                     exit;
                 end;


        ImpersonateSelf( SecurityImpersonation);
        OpenThreadToken( GetCurrentThread, TOKEN_QUERY, False, Token);

        if Token = 0
            then begin
                     _failed := true;
                     exit;
                 end;

        Mapping.GenericRead    := FILE_GENERIC_READ;
        Mapping.GenericWrite   := FILE_GENERIC_WRITE;
        Mapping.GenericExecute := FILE_GENERIC_EXECUTE;
        Mapping.GenericAll     := FILE_ALL_ACCESS;

        MapGenericMask( Access, Mapping);
        PrivSetSize := SizeOf( PrivSet);
        AccessCheck( SecDesc, Token, _desiredAccess, Mapping, PrivSet, PrivSetSize,         Access, Status);
        CloseHandle( Token);

        if _desiredAccess = Access
            then result := Status;
    finally
        FreeMem( SecDesc, SecDescSize);
    end;
end;

WORKS Correctly:

if not iccFile_Security.check( 'C:\temp\',     iccFile_Security.FILE_ALL_ACCESS)
        then ...

DOES NOT WORK:

if not iccFile_Security.check( '\\testmachine\temp\',         iccFile_Security.FILE_ALL_ACCESS)
        then ...

Any comments\suggestions? Any help is appreciated.

Upvotes: 0

Views: 3933

Answers (1)

Erik Knowles
Erik Knowles

Reputation: 1007

Ah. I've answered this one before -- network file security is an unreliable crap-shoot. (I dumped all of my code for doing so in favor of just checking to see if I could write a file in the dir.)

C.f., http://www.ureader.com/msg/16591730.aspx

Read the discussion about AccessCheck(); specifically:

Even when performing AccessCheck(), you are doing an access check against an access token that is generated "locally", with the security descriptor associated with the object. When you directly access the object on a remote system, a network access token gets generated on the remote system. This network access token is used to perform access check on the object to determine whether access should be granted or denied. The object could be either a file or named pipe or AD object.

e.g. If the user is member of Administrators group on the remote system, when you directly access the object on a remote system, the network access token that gets generated on the remote system will have Administrators group and will allow access. Whereas, when you call AccessCheck() with a local access token, you will get different results.

Upvotes: 4

Related Questions