![]() |
Berechtigungen einer Datei setzen (jwscl)
Hallo
Ich habe das 'kleine' Problem nach einem 'Zwischenfall' Dateien wiederherstellen zu müssen. Ausgangslage: Die Dateien und Verzeichnisse befinden sich alle in einem Verzeichnis(ca. 15600 Dateien und ca. 1500 Verzeichnisse mit weiteren Dateien von ca. 300 Usern). Die Berechtigungen sind alle vorhanden, nur die Namen sind geändert(kein Problem). Lösungsansatz: Quell- und Zielverzeichnis festlegen. Mittels FindFirst/FindNext alle Dateien und Verzeichnisse aus dem Quellverzeichnis in eine Liste eintragen und dabei die Berechtigungen(AccessControlEntry) erfassen. Im Zielverzeichnis entsprechend des dem User zu gewiesenen Wertes ein Verzeichnis erstellen und die Berechtigungen zuweisen(Problem). Dateien und Verzeichnisse in das Zielverzeichnis kopieren. Damit man auch etwas sieht gibt es dafür eine Form und die Informationen werden in einer ListView dargestellt. Um das ganze praktisch zu umzusetzen, habe ich zum Zwischenspeichern der Informationen eine Klasse erstellt:
Delphi-Quellcode:
Zu Testzwecken besteht die Möglichkeit einzelne Dateien einzulesen und zu kopieren.
type
PFileEntry = ^TFileEntry; TFileEntry = class(TObject) private FFilePath : WideString; FFileName : WideString; FOwnerName : WideString; FType : WideString; FAttr : Integer; FAccessControlEntry : TJwSecurityAccessControlEntry; FSecurityDescriptor : TJwSecurityDescriptor; function GetFullFileName : WideString; procedure SetOwnerName(Value : WideString); procedure SetAccessControlEntry(Value : TJwSecurityAccessControlEntry); procedure SetSecurityDescriptor(Value : TJwSecurityDescriptor); protected procedure CheckFile; public constructor Create(FullFileName : WideString); function HasSecurityData : Boolean; property FullFileName : WideString read GetFullFileName; property FilePath : WideString read FFilePath; property FileName : WideString read FFileName; property FileTyp : WideString read FType; property FileAttr : Integer read FAttr; property OwnerName : WideString read FOwnerName write SetOwnerName; property AccessControlEntry : TJwSecurityAccessControlEntry read FAccessControlEntry write SetAccessControlEntry; property SecurityDescriptor : TJwSecurityDescriptor read FSecurityDescriptor write SetSecurityDescriptor; end;
Delphi-Quellcode:
Die Ermittlung der Berechtigungen erfolgt auf diese Art(habe ich mir aus den Beispielen der jwcsl zusammen 'gebastelt')
procedure TMainForm.aSingleFileExecute(Sender: TObject);
var LI : TListItem; FEntry : TFileEntry; begin OpenDlg.InitialDir := FSourceDir; if OpenDlg.Execute then begin FEntry := TFileEntry.Create(OpenDlg.FileName); lvData.Items.BeginUpdate; lvData.Items.Clear; LI := lvData.Items.Add; LI.Caption := FEntry.FileName; LI.SubItems.Add(FEntry.FileTyp); GetAccessRights(FEntry); LI.SubItems.Add(FEntry.OwnerName); LI.Data := FEntry; lvData.Items.EndUpdate; end; end;
Delphi-Quellcode:
Das mit dem 'mapping' habe ich nicht verstanden, da letztlich nur der 'SecurityDescriptor'
procedure TMainForm.GetSelectedPermissions(out mapping : TJwSecurityGenericMappingClass;
out bAuditAccess : Boolean; var FileEntry : TFileEntry); var Flags : TJwSecurityInformationFlagSet; cExDesiredAccessMask : TJwAccessMask; FileObject : TJwSecureFileObject; begin bAuditAccess := JwIsPrivilegeSet(SE_SECURITY_NAME, pqt_Available); cExDesiredAccessMask := 0; Flags := [siDaclSecurityInformation, siOwnerSecurityInformation]; if bAuditAccess then begin Include(Flags, siSaclSecurityInformation); JwEnablePrivilege(SE_SECURITY_NAME,pst_Enable); //enable access to SACL generally cExDesiredAccessMask := ACCESS_SYSTEM_SECURITY; //add SACL access to handle end; if (FileEntry.FileAttr and faDirectory) = faDirectory then mapping := TJwSecurityFileFolderMapping else mapping := TJwSecurityFileMapping; try FileObject := TJwSecureFileObject.Create(FileEntry.FullFileName); try FileEntry.SecurityDescriptor := FileObject.GetSecurityDescriptor(Flags); finally FreeAndNil(FileObject); end; finally if bAuditAccess then JwEnablePrivilege(SE_SECURITY_NAME, pst_Disable); end; end; gebraucht wird, sollte auch dies reichen(ungetestet)
Delphi-Quellcode:
Das eigentliche auslesen der Berechtigungen erfolgt so
procedure TMainForm.GetSelectedPermissions(var FileEntry : TFileEntry);
var FileObject : TJwSecureFileObject; begin FileObject := TJwSecureFileObject.Create(FileEntry.FullFileName); try FileEntry.SecurityDescriptor := FileObject.GetSecurityDescriptor(Flags); finally FreeAndNil(FileObject); end; end;
Delphi-Quellcode:
Nachdem auswählen des Eintrages im ListView kann und soll
procedure TMainPESForm.GetAccessRights(var FileEntry : TFileEntry);
var SD : TJwSecurityDescriptor; mapping : TJwSecurityGenericMappingClass; ACLEntry : TJwSecurityAccessControlEntry; bAuditAccess : Boolean; sText : String; I : Integer; begin GetSelectedPermissions(mapping, bAuditAccess, FileEntry); if Assigned(FileEntry.SecurityDescriptor) then try if Assigned(FileEntry.SecurityDescriptor.Owner) then begin if Assigned(FileEntry.SecurityDescriptor.DACL) then begin for I := 0 to FileEntry.SecurityDescriptor.DACL.Count -1 do begin ACLEntry := FileEntry.SecurityDescriptor.DACL.Items[I]; sText := ACLEntry.SID.GetText(true); if (POS('@', sText) = 4) then begin sText := Trim(Copy(sText, POS('@', sText) +1, POS('(', sText)-(POS('@', sText) +1))); if IsValue(sText) then begin FileEntry.OwnerName := sText; FileEntry.AccessControlEntry := ACLEntry; Break; end else sText := ''; end; end; end; end; finally FreeAndNil(SD); end; end; 1. Das Zielverzeichnis anlegt und die Berechtigungen hinzufügt werden
Delphi-Quellcode:
2. Kopieren der Dateien mittels CopyFile
procedure TMainForm.aCopyUserExecute(Sender: TObject);
begin if lvData.Selected = nil then Exit else begin if CreateFolder(FDestDir, TFileEntry(lvData.Selected.Data)) then CopyFile(FDestDir, TFileEntry(lvData.Selected.Data)); end; end; function CreateFolder(DestPath : WideString; FileEntry : TFileEntry) : Boolean; var FileObject : TJwSecureFileObject; Flags : TJwSecurityInformationFlagSet; ODACL : TJwDAccessControlList; begin Result := false; if FileEntry.HasSecurityData then begin if not DirectoryExists(DestPath + FileEntry.OwnerName) then ForceDirectories(DestPath + FileEntry.OwnerName); FileObject := TJwSecureFileObject.Create(DestPath + FileEntry.OwnerName); try ODACL := FileObject.GetDACL; if ODACL <> nil then begin try if ODACL.IndexOf(FileEntry.AccessControlEntry) = -1 then begin ODACL.Add(FileEntry.AccessControlEntry); FileObject.SetDACL(ODACL); end; except end; end; finally FileObject.Free; FreeAndNil(ODACL); end; Result := true; end; end; Damit die einfache Zuweisung von
Delphi-Quellcode:
funktioniert sieht TFileEntry.SetAccessControlEntry so aus
ODACL.Add(FileEntry.AccessControlEntry);
Delphi-Quellcode:
Das Problem:
procedure TFileEntry.SetAccessControlEntry(Value : TJwSecurityAccessControlEntry);
begin if FAccessControlEntry <> Value then FAccessControlEntry := TJwDiscretionaryAccessControlEntryAllow.Create(nil, Value.Flags, Value.AccessMask, Value.SID); end; Die Routinen laufen alle ohne Fehler durch, nur werden die Berechtigungen des Zielverzeichnisses nicht gesetzt. Liegt es an der falsch verstandenen Umsetzung von TFileEntry.SetAccessControlEntry, oder ist der Fehler in CreateFolder, oder ganz wo anders? Für Tipps und Anregungen wie immer Dankbar Alter Mann |
Re: Berechtigungen einer Datei setzen (jwscl)
Nur ein Schuss ins Blaue:
In SetAccessControlEntry kopierst du die Flags der anderen ACE. Meiner Meinung nach wird da das Flag afInheritedAce, welches definiert, dass ein ACE vererbt ist, angegeben und dann von Windows ignoriert, da es ungültig ist. Ein Mapping ist nur notwendig, wenn du generische Rechte verwendest (GENERIC_ALL, GENERIC_READ, usw). Dann wird, wenn ein solches Recht irgendwo in den ACEs gefunden wird, in die explizite Rechte umgewandelt. z.B. GenericRead -> STANDARD_RIGHTS_READ or READ_CONTROL or SYNCHRONIZE or FILE_READ_EA or FILE_READ_DATA or FILE_READ_EA |
Re: Berechtigungen einer Datei setzen (jwscl)
Hallo Alter Mann,
Zitat:
Da ich (zu meiner Schande) nicht ganz durch Deinen Code durchsteige, erteile ich Dir den (wohl überflüssigen) Rat eine Musterberechtigung für ein Verzeichnis zu erstellen, die einmalig beim Erstellen des Verzeichnisses vergeben wird. Gruß K-H |
Re: Berechtigungen einer Datei setzen (jwscl)
Hi
die Standardberechtigungen werden auf dem Root des Laufwerkes gesetzt, sodass diese auch für das Zielverzeichnis gelten. Hinzugefügt werden soll nur die Berechtigung für den User. Die Berechtigungen für die Dateien und den weiteren Verzeichnissen im Zielverzeichnis ergeben sich dadurch automatisch, da sie ohne weitere Berechtigungen kopiert werden. Gruß |
Re: Berechtigungen einer Datei setzen (jwscl)
Wenn du einen neuen User in die ACL einfügst, dann muss dessen ACE angepasst werden. Und wenn Unterordner und -dateien diese Berechtigung auch bekommen sollen, muss einfach nur noch das Container (afContainerInheritAce) und Objekte (afObjectInheritAce) gesetzt werden, denn dann haben alle es andere.
|
Re: Berechtigungen einer Datei setzen (jwscl)
Hi
@Dezipaitor Das ist schon klar, das Problem ist, dass die Berechtigungen des hinzugefügten Users überhaupt nicht gesetzt werden. |
Re: Berechtigungen einer Datei setzen (jwscl)
Wie sind denn die Flags?D.h. sind sie so wie gedacht?
Was ich gerade bemerkt habe ist, dass du SID einfach übergibst. Da Create jedoch keine Kopie anlegt und du keinen 5 Parameter (ownSid = true) verwendest, könnte es zu Problemem kommen (doppelt freigegebenes Objekt). Nutze den Kopierkonstruktor:
Delphi-Quellcode:
Versuch das einfach mal.
procedure TFileEntry.SetAccessControlEntry(Value : TJwSecurityAccessControlEntry);
begin if FAccessControlEntry <> Value then begin FAccessControlEntry := TJwDiscretionaryAccessControlEntryAllow.Create(Value); FAccessControlEntry.Flags := [afObjectInheritAce, afContainerInheritAce]; //dieses ACE ist in keiner Liste! end; end; |
Re: Berechtigungen einer Datei setzen (jwscl)
Hi,
Habe die Ausführung übernommen und folgende Meldung erhalten: "Es gibt keine Überladene Version von 'Create', die man mit diesen Argumenten aufrufen kann." Komisch, in der 'jwsclAcl' steht:
Delphi-Quellcode:
es sollte also gehen :gruebel:
TJwDiscretionaryAccessControlEntry = class(TJwSecurityAccessControlEntry);
TJwDiscretionaryAccessControlEntryAllow = class(TJwDiscretionaryAccessControlEntry); Gruß |
Re: Berechtigungen einer Datei setzen (jwscl)
Ja der Parametertype muss auch TJwDiscretionaryAccessControlEntryAllow sein.
|
Re: Berechtigungen einer Datei setzen (jwscl)
Hi,
Ich habe es hin bekommen. SetAccessControlEntry sieht jetzt so aus:
Delphi-Quellcode:
procedure TFileEntry.SetAccessControlEntry(Value : TJwSecurityAccessControlEntry);
begin if FAccessControlEntry <> Value then begin FAccessControlEntry := TJwDiscretionaryAccessControlEntryAllow.Create(nil, [afObjectInheritAce, afContainerInheritAce], Value.AccessMask, Value.SID, false); end; end; @Dezipaitor Das mit den Flags hat den erwünschten Effekt gehabt. Danke!!! Gruß |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:52 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