Zitat von
nicodex:
Zitat von
0xF30FC7:
Ich hab die Funktion nur kurz überflogen, aber sicher das AccessCheck ebenfalls die Integrity Level überprüft? Eigentlich checkt es ja nur die
ACL. Wenn nicht sollte man in Hinsicht auf Vista die Funktion entsprechend erweitern.
Da gibt es nichts zu erweitern. Entweder der ausführende Thread/Prozess hat mit seinem/n aktuellen Token die entsprechende Rechte, oder nicht. Man kann einen Prozess nicht nachträglich im Level anheben (deswegen braucht man dafür Out-of-Process-Server).
Mir ist das schon klar. Ich sagte ja auch man soll den Test erweitern um eine explizite Überprüfung der Integrity Level, weil diese meiner Ansicht nach von AccessCheck nicht berücksichtigt werden. Ich hab das Ganze auch mal getestet.
C:\TEST.TXT hat den Integrity Level High. Meine Applikation hat den Integrity Level Medium. Das Testprogramm:
Delphi-Quellcode:
program Project1;
{$APPTYPE CONSOLE}
uses
windows;
// stuff Delphi might not know...
const
FILE_READ_DATA = $0001; // file & pipe
FILE_LIST_DIRECTORY = $0001; // directory
FILE_WRITE_DATA = $0002; // file & pipe
FILE_ADD_FILE = $0002; // directory
FILE_APPEND_DATA = $0004; // file
FILE_ADD_SUBDIRECTORY = $0004; // directory
FILE_CREATE_PIPE_INSTANCE = $0004; // named pipe
FILE_READ_EA = $0008; // file & directory
FILE_WRITE_EA = $0010; // file & directory
FILE_EXECUTE = $0020; // file
FILE_TRAVERSE = $0020; // directory
FILE_DELETE_CHILD = $0040; // directory
FILE_READ_ATTRIBUTES = $0080; // all
FILE_WRITE_ATTRIBUTES = $0100; // all
FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $1FF;
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;
(**)
function CheckAccessToFile(DesiredAccess: DWORD; const FileName: WideString): Boolean;
const
GenericFileMapping : TGenericMapping = (
GenericRead: FILE_GENERIC_READ;
GenericWrite: FILE_GENERIC_WRITE;
GenericExecute: FILE_GENERIC_EXECUTE;
GenericAll: FILE_ALL_ACCESS
);
var
LastError : DWORD;
LengthNeeded : DWORD;
SecurityDescriptor : PSecurityDescriptor;
ClientToken : THandle;
AccessMask : DWORD;
PrivilegeSet : TPrivilegeSet;
PrivilegeSetLength : DWORD;
GrantedAccess : DWORD;
AccessStatus : BOOL;
begin
Result := False;
LastError := GetLastError;
if not GetFileSecurityW(PWideChar(FileName), OWNER_SECURITY_INFORMATION or
GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION, nil, 0,
LengthNeeded) and (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then
Exit;
SetLastError(LastError);
Inc(LengthNeeded, $1000);
SecurityDescriptor := PSecurityDescriptor(LocalAlloc(LPTR, LengthNeeded));
if not Assigned(SecurityDescriptor) then
Exit;
try
if not GetFileSecurityW(PWideChar(FileName), OWNER_SECURITY_INFORMATION or
GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION,
SecurityDescriptor, LengthNeeded, LengthNeeded) then
Exit;
if not ImpersonateSelf(SecurityImpersonation) then
Exit;
try
if not OpenThreadToken(GetCurrentThread, TOKEN_QUERY or
TOKEN_IMPERSONATE or TOKEN_DUPLICATE, False, ClientToken) then
Exit;
try
AccessMask := DesiredAccess;
MapGenericMask(AccessMask, GenericFileMapping);
PrivilegeSetLength := SizeOf(TPrivilegeSet);
if AccessCheck(SecurityDescriptor, ClientToken, AccessMask,
GenericFileMapping, PrivilegeSet, PrivilegeSetLength, GrantedAccess,
AccessStatus) then
Result := AccessStatus;
finally
CloseHandle(ClientToken);
end;
finally
RevertToSelf;
end;
finally
LocalFree(HLOCAL(SecurityDescriptor));
end;
end;
function IsFileWritable(FileName : WideString) : Boolean;
var
FileHandle : THandle;
begin
FileHandle := CreateFileW(PWideChar(FileName), GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, nil, OPEN_ALWAYS, 0, 0);
Result := FileHandle <> INVALID_HANDLE_VALUE;
if Result then
CloseHandle(FileHandle);
end;
const
Filename : widestring = 'c:\test.txt';
begin
writeln('CheckAccessToFile: ', CheckAccessToFile(GENERIC_WRITE, Filename));
writeln('IsFileWritable: ', IsFileWritable(Filename));
readln;
end.
Das Ergebnis:
http://img520.imageshack.us/img520/3...eaccessxa7.png
Das bestärkt um ehrlich zu sein meinen Verdacht, daß AccessCheck Integrity Level nicht berücksichtigt und die von Luckie gepostete Funktion um einen Integrity Level Check erweitert werden sollte. Falls Integrity Level Checks doch durchgeführt werden sollten bei AccessCheck wie Du sagst, frag ich mich, wie es zu dem Ergebnis kommt.
EDIT: Sobald der Integrity Level von C:\TEST.TXT wieder auf Medium gesetzt ist, geben beide Funktionen übrigens wieder identische Ergebnisse aus.