![]() |
Re: Named Pipes zwischen Service und eingeschränktem Program
Delphi-Quellcode:
Ist ein kleiner Pipe Server, der eine Pipe mit einer DACL die Jedem im System explizit Lese und Schreibrechte erlaubt erstellt.
program pipeserver;
{$APPTYPE CONSOLE} uses jwawinbase, jwawintype, jwawinnt, jwaaccctrl, jwaaclapi, jwawinerror, sysutils; function InstanceThread(PipeHandle : dword) : dword; stdcall; var Value : dword; tmp : dword; begin result := 0; ReadFile(PipeHandle, @Value, 4, @tmp, nil); WriteFile(PipeHandle, @Value, 4, @tmp, nil); FlushFileBuffers(PipeHandle); DisconnectNamedPipe(PipeHandle); CloseHandle(PipeHandle); end; function ServerThread(unused : dword) : dword; stdcall; const BUFSIZE = 4; var PipeHandle : dword; Connected : boolean; SA : LPSECURITY_ATTRIBUTES; ACL : PACL; Group : TRUSTEE; EA : PEXPLICIT_ACCESS; SD : PSECURITY_DESCRIPTOR; ACL_SIZE : ACL_SIZE_INFORMATION; tmp : dword; begin Group.MultipleTrusteeOperation := NO_MULTIPLE_TRUSTEE; Group.pMultipleTrustee := nil; Group.ptstrName := 'Jeder'; Group.TrusteeForm := TRUSTEE_IS_NAME; Group.TrusteeType := TRUSTEE_IS_GROUP; new(EA); EA^.grfAccessMode := GRANT_ACCESS; EA^.grfAccessPermissions := GENERIC_READ or GENERIC_WRITE; EA^.grfInheritance := NO_INHERITANCE; EA^.Trustee := group; SetEntriesInAcl(1, EA, nil, ACL); GetAclInformation(ACL, @ACL_SIZE, sizeof(ACL_SIZE), AclSizeInformation); getmem(SD, SECURITY_DESCRIPTOR_MIN_LENGTH + ACL_SIZE.AclBytesFree + ACL_SIZE.AclBytesInUse); InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(sd, TRUE, ACL, FALSE); new(SA); sa^.bInheritHandle := FALSE; sa^.lpSecurityDescriptor := sd; sa^.nLength := sizeof(sa); while true do begin PipeHandle := CreateNamedPipeW('\\.\pipe\demopipe', PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, INFINITE, SA); if PipeHandle = INVALID_HANDLE_VALUE then begin sleep(100); continue; end; Connected := ConnectNamedPipe(PipeHandle, nil) or (GetLastError = ERROR_PIPE_CONNECTED); if Connected then begin tmp := CreateThread(nil, 0, @InstanceThread, Pointer(PipeHandle), 0, nil); if tmp = 0 then begin DisconnectNamedPipe(PipeHandle); CloseHandle(PipeHandle); continue; end else CloseHandle(tmp); end else CloseHandle(PipeHandle); end; LocalFree(cardinal(ACL)); freemem(SD); dispose(EA); end; var tmp : dword; begin write('Starting ServerThread: '); tmp := CreateThread(nil, 0, @ServerThread, nil, 0, nil); writeln(tmp <> 0); CloseHandle(tmp); readln; end. |
Re: Named Pipes zwischen Service und eingeschränktem Program
Danke!
Sieht recht kompliziert aus. Ich habe parallel hier im Forum noch nach dem Stichwort gesucht und ![]() Tun es die paar Zeilen, um FSA zu bestimmen, auch? Oder gibt es irgendwelche Bedenken?
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var FSA : SECURITY_ATTRIBUTES; FSD : SECURITY_DESCRIPTOR; pch1: shortstring; begin InitializeSecurityDescriptor(@FSD, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(@FSD, True, nil, False); FSA.lpSecurityDescriptor := @FSD; FSA.nLength := sizeof(SECURITY_ATTRIBUTES); FSA.bInheritHandle := True; Pipe:= CreateNamedPipe(PChar('\\.\pipe\<test>'), PIPE_ACCESS_DUPLEX or FILE_FLAG_WRITE_THROUGH, PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, 50, @FSA); end; |
Re: Named Pipes zwischen Service und eingeschränktem Program
Funktioniert genauso. Allerdings solltest Du Dir bewusst sein, das alles und jeder dann auf die Pipe zugreifen kann - auch übers Netzwerk und ohne Authentifizierung!
|
Re: Named Pipes zwischen Service und eingeschränktem Program
Hm, also mein Service prüft den Sender der Nachricht auf seine Signatur und agiert nur dann, wenn es sich um meine Signatur handelt.
Dennoch wäre es wahrscheinlich nicht verkehrt, die beiden Punkte Netzwerk und Authentifizierung in den Code einzubeziehen. Ich habe Deinen Code nun genauer angeschaut. Ich verstehe zwar nicht alles davon, aber die Zeile Group.ptstrName := 'Jeder'; macht mich stutzig. Die starre Angabe, würde dann doch nur auf deutschen Betriebssystemen funktionieren, oder? Ich nehme an, dass es nicht einfach einen Flag-Wert gibt, der nur lokal angemeldete Benutzer zulässt? :gruebel: |
Re: Named Pipes zwischen Service und eingeschränktem Program
Mit der TRUSTEE-Struktur kann man Gruppen oder Benutzer nicht nur per Name, sondern auch per SID angeben.
![]() |
Re: Named Pipes zwischen Service und eingeschränktem Program
Nunja, das war Code aus einem kleinen Beispiel von mir, wie man eine Pipe erstellt auf die nur Mitglieder einer bestimmten Gruppe Zugriff haben. Für Deine Zwecke wäre es wahrscheinlich besser den Zugriff an einen Well Known SID zu koppeln. Der Code würde dann so aussehen:
Delphi-Quellcode:
Eine Liste der Well Known SIDs gibts hier: http://msdn.microsoft.com/en-us/library/aa379650(VS.85).aspx
program pipeserver;
{$APPTYPE CONSOLE} uses jwawinbase, jwawintype, jwawinnt, jwaaccctrl, jwaaclapi, jwawinerror, sysutils; function InstanceThread(PipeHandle : dword) : dword; stdcall; var Value : dword; tmp : dword; begin result := 0; ReadFile(PipeHandle, @Value, 4, @tmp, nil); WriteFile(PipeHandle, @Value, 4, @tmp, nil); FlushFileBuffers(PipeHandle); DisconnectNamedPipe(PipeHandle); CloseHandle(PipeHandle); end; function ServerThread(unused : dword) : dword; stdcall; const BUFSIZE = 4; var PipeHandle : dword; Connected : boolean; SA : LPSECURITY_ATTRIBUTES; ACL : PACL; Group : TRUSTEE; EA : PEXPLICIT_ACCESS; SD : PSECURITY_DESCRIPTOR; ACL_SIZE : ACL_SIZE_INFORMATION; WellKnownSID : PSID; tmp : dword; begin tmp := SECURITY_MAX_SID_SIZE; GetMem(WellKnownSID, tmp); CreateWellKnownSid(WinWorldSid, nil, WellKnownSID, tmp); Group.MultipleTrusteeOperation := NO_MULTIPLE_TRUSTEE; Group.pMultipleTrustee := nil; Group.ptstrName := Pointer(WellKnownSID); Group.TrusteeForm := TRUSTEE_IS_SID; Group.TrusteeType := TRUSTEE_IS_WELL_KNOWN_GROUP; new(EA); EA^.grfAccessMode := GRANT_ACCESS; EA^.grfAccessPermissions := GENERIC_READ or GENERIC_WRITE; EA^.grfInheritance := NO_INHERITANCE; EA^.Trustee := group; SetEntriesInAcl(1, EA, nil, ACL); GetAclInformation(ACL, @ACL_SIZE, sizeof(ACL_SIZE), AclSizeInformation); getmem(SD, SECURITY_DESCRIPTOR_MIN_LENGTH + ACL_SIZE.AclBytesFree + ACL_SIZE.AclBytesInUse); InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(sd, TRUE, ACL, FALSE); new(SA); sa^.bInheritHandle := FALSE; sa^.lpSecurityDescriptor := sd; sa^.nLength := sizeof(sa); while true do begin PipeHandle := CreateNamedPipeW('\\.\pipe\demopipe', PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, INFINITE, SA); if PipeHandle = INVALID_HANDLE_VALUE then begin sleep(100); continue; end; Connected := ConnectNamedPipe(PipeHandle, nil) or (GetLastError = ERROR_PIPE_CONNECTED); if Connected then begin tmp := CreateThread(nil, 0, @InstanceThread, Pointer(PipeHandle), 0, nil); if tmp = 0 then begin DisconnectNamedPipe(PipeHandle); CloseHandle(PipeHandle); continue; end else CloseHandle(tmp); end else CloseHandle(PipeHandle); end; LocalFree(cardinal(ACL)); freemem(SD); freemem(WellKnownSID); dispose(EA); end; var tmp : dword; begin write('Starting ServerThread: '); tmp := CreateThread(nil, 0, @ServerThread, nil, 0, nil); writeln(tmp <> 0); CloseHandle(tmp); readln; end. In Deinem Falle wäre wohl WinLocalSid nützlich. Man kann den Code übrigens noch stark vereinfachen indem man die JWSCL benutzt. Allerdings ist mir die JWSCL für meinen Geschmack zu viel Overhead. |
Re: Named Pipes zwischen Service und eingeschränktem Program
Wäre es hier nicht klüger, den Speicher für WellKnownSID auf dem Stack zu reservieren?
|
Re: Named Pipes zwischen Service und eingeschränktem Program
Welchen Vorteil erhoffst Du Dir dadurch?
|
Re: Named Pipes zwischen Service und eingeschränktem Program
Zitat:
Da ich die JWSCL so oder so bereits eingebunden habe, würd ich auch gern den vereinfachten Code nehmen. Zitat:
|
Re: Named Pipes zwischen Service und eingeschränktem Program
@0xF30FC7: Ich finde einfach, dass man den Memory Manager nicht bemühen sollte, wenn der Stack es genauso tut, denn er ist in jedem Fall langsamer und hat einen nicht zu vernachlässigenden Speicher-Overhead.
Das gleiche gilt für EA. Bei SD würde ich allerdings auch den MM nehmen, da du die Größe nicht im Voraus weißt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:33 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz