![]() |
WinAPI Problem mit Rechten setzen in der Registry
Hallo,
ich habe mir diesen ![]() Der Code ist folgender :
Delphi-Quellcode:
Was ist jetzt falsch an dem Code ? Ich möchte ja lediglich nur einen Registrykey öffnen um dort einen Schlüssel oder Key zu erstellen oder zu ändern mit ganz normalen Hauptbenutzerrechten. Es kann auch sein, dass ich das ganze bis jetzt falsch verstanden habe. Wenn dieses der Fall ist, da bitte ich um eine Erklärung.
type
TAccessMode = ( NOT_USED_ACCESS, GRANT_ACCESS, SET_ACCESS, DENY_ACCESS, REVOKE_ACCESS, SET_AUDIT_SUCCESS, SET_AUDIT_FAILURE ); type PObjectsAndSid = ^TObjectsAndSid; TObjectsAndSid = record ObjectsPresent: DWORD; ObjectTypeGuid: TGUID; InheritedObjectTypeGuid: TGUID; pSid: PSID; end; type TSeObjectType = ( SE_UNKNOWN_OBJECT_TYPE, SE_FILE_OBJECT, SE_SERVICE, SE_PRINTER, SE_REGISTRY_KEY, SE_LMSHARE, SE_KERNEL_OBJECT, SE_WINDOW_OBJECT, SE_DS_OBJECT, SE_DS_OBJECT_ALL, SE_PROVIDER_DEFINED_OBJECT, SE_WMIGUID_OBJECT ); PObjectsAndNameA = ^TObjectsAndNameA; TObjectsAndNameA = record ObjectsPresent: DWORD; ObjectType: TSeObjectType; ObjectTypeName: PAnsiChar; InheritedObjectTypeName: PAnsiChar; ptstrName: PAnsiChar; end; PObjectsAndNameW = ^TObjectsAndNameW; TObjectsAndNameW = record ObjectsPresent: DWORD; ObjectType: TSeObjectType; ObjectTypeName: PWideChar; InheritedObjectTypeName: PWideChar; ptstrName: PWideChar; end; PObjectsAndName = ^TObjectsAndName; TObjectsAndName = TObjectsAndNameA; type TMultipleTrusteeOperation = ( NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_IMPERSONATE ); TTrusteeForm = ( TRUSTEE_IS_SID, TRUSTEE_IS_NAME, TRUSTEE_BAD_FORM, TRUSTEE_IS_OBJECTS_AND_SID, TRUSTEE_IS_OBJECTS_AND_NAME ); TTrusteeType = ( TRUSTEE_IS_UNKNOWN, TRUSTEE_IS_USER, TRUSTEE_IS_GROUP, TRUSTEE_IS_DOMAIN, TRUSTEE_IS_ALIAS, TRUSTEE_IS_WELL_KNOWN_GROUP, TRUSTEE_IS_DELETED, TRUSTEE_IS_INVALID, TRUSTEE_IS_COMPUTER ); PTrusteeA = ^TTrusteeA; TTrusteeA = packed record pMultipleTrustee: PTrusteeA; MultipleTrusteeOperation: TMultipleTrusteeOperation; TrusteeForm: TTrusteeForm; TrusteeType: TTrusteeType; case TTrusteeForm of TRUSTEE_IS_SID: ( pSid: PSID); TRUSTEE_IS_OBJECTS_AND_SID: ( pObjectsAndSid: PObjectsAndSid); TRUSTEE_IS_OBJECTS_AND_NAME: ( pObjectsAndName: PObjectsAndNameA); { else } TRUSTEE_IS_NAME, TRUSTEE_BAD_FORM: ( ptstrName: PAnsiChar); { end; } end; PTrusteeW = ^TTrusteeW; TTrusteeW = packed record pMultipleTrustee: PTrusteeW; MultipleTrusteeOperation: TMultipleTrusteeOperation; TrusteeForm: TTrusteeForm; TrusteeType: TTrusteeType; case TTrusteeForm of TRUSTEE_IS_SID: ( pSid: PSID); TRUSTEE_IS_OBJECTS_AND_SID: ( pObjectsAndSid: PObjectsAndSid); TRUSTEE_IS_OBJECTS_AND_NAME: ( pObjectsAndName: PObjectsAndNameW); { else } TRUSTEE_IS_NAME, TRUSTEE_BAD_FORM: ( ptstrName: PWideChar); { end; } end; PTrustee = ^TTrustee; TTrustee = TTrusteeA; type PExplicitAccessA = ^TExplicitAccessA; TExplicitAccessA = packed record grfAccessPermissions: DWORD; grfAccessMode: TAccessMode; grfInheritance: DWORD; Trustee: TTrusteeA; end; PExplicitAccessW = ^TExplicitAccessW; TExplicitAccessW = packed record grfAccessPermissions: DWORD; grfAccessMode: TAccessMode; grfInheritance: DWORD; Trustee: TTrusteeW; end; PExplicitAccess = ^TExplicitAccess; TExplicitAccess = TExplicitAccessA; function SetEntriesInAclA(cCountOfExplicitEntries: ULONG; pListOfExplicitEntries: PExplicitAccessA; OldAcl: PACL; var NewAcl: ACL): DWORD; stdcall; {use localfree to release NewAcl} external advapi32 name 'SetEntriesInAclA'; function SetEntriesInAclW(cCountOfExplicitEntries: ULONG; pListOfExplicitEntries: PExplicitAccessW; OldAcl: PACL; var NewAcl: ACL): DWORD; stdcall; {use localfree to release NewAcl} external advapi32 name 'SetEntriesInAclW'; function SetEntriesInAcl(cCountOfExplicitEntries: ULONG; pListOfExplicitEntries: PExplicitAccess; OldAcl: PACL; var NewAcl: ACL): DWORD; stdcall; {use localfree to release NewAcl} external advapi32 name 'SetEntriesInAclA'; {------------------------------------------------------------------------------} const SECURITY_WORLD_SID_AUTHORITY: TSIDIdentifierAuthority = ( Value: (0, 0, 0, 0, 0, 1); ); SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = ( Value: (0, 0, 0, 0, 0, 5); ); SECURITY_WORLD_RID = $00000000; SECURITY_BUILTIN_DOMAIN_RID = $00000020; DOMAIN_ALIAS_RID_ADMINS = $00000220; DOMAIN_ALIAS_RID_POWER_USERS = $00000223; NO_INHERITANCE = $0; function RegKeyWithFullAccess(Key: HKEY; SubKey: PChar): LongBool; stdcall; var EveryoneSID: PSID; AdminSID: PSID; PowerUserSID: PSID; ExplicitAccesses: array [0..2] of TExplicitAccess; Acl: PACL; SecurityDescriptor: PSecurityDescriptor; SecurityAttributes: TSecurityAttributes; Disposition: DWORD; KeyHandle: HKEY; begin Result := False; EveryoneSID := nil; AdminSID := nil; PowerUserSID := nil; ACL := nil; SecurityDescriptor := nil; KeyHandle := 0; { Bekannte SID fr die "Jeder"-Gruppe erzeugen. } if AllocateAndInitializeSid(SECURITY_WORLD_SID_AUTHORITY, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, EveryoneSID) then begin { Der ACE wird "Jeder" Vollzugriff erlauben. } FillChar(ExplicitAccesses, 2 * SizeOf(TExplicitAccess), 0); ExplicitAccesses[0].grfAccessPermissions := KEY_ALL_ACCESS; ExplicitAccesses[0].grfAccessMode := SET_ACCESS; ExplicitAccesses[0].grfInheritance := NO_INHERITANCE; ExplicitAccesses[0].Trustee.TrusteeForm := TRUSTEE_IS_SID; ExplicitAccesses[0].Trustee.TrusteeType := TRUSTEE_IS_WELL_KNOWN_GROUP; ExplicitAccesses[0].Trustee.pSid := EveryoneSID; end; { Bekannte SID für die "Administratoren"-Gruppe erzeugen. } if AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, AdminSID) then begin { Der ACE wird "Administratoren" Vollzugriff erlauben. } ExplicitAccesses[1].grfAccessPermissions := KEY_ALL_ACCESS; ExplicitAccesses[1].grfAccessMode := SET_ACCESS; ExplicitAccesses[1].grfInheritance := NO_INHERITANCE; ExplicitAccesses[1].Trustee.TrusteeForm := TRUSTEE_IS_SID; ExplicitAccesses[1].Trustee.TrusteeType := TRUSTEE_IS_GROUP; ExplicitAccesses[1].Trustee.pSid := AdminSID; end; { Bekannte SID für die "Hauptbenutzer"-Gruppe erzeugen. } if AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0, 0, PowerUserSID) then begin { Der ACE wird "Hauptbenutzern" Vollzugriff erlauben. } ExplicitAccesses[2].grfAccessPermissions := KEY_ALL_ACCESS; ExplicitAccesses[2].grfAccessMode := SET_ACCESS; ExplicitAccesses[2].grfInheritance := NO_INHERITANCE; ExplicitAccesses[2].Trustee.TrusteeForm := TRUSTEE_IS_SID; ExplicitAccesses[2].Trustee.TrusteeType := TRUSTEE_IS_GROUP; ExplicitAccesses[2].Trustee.pSid := PowerUserSID; end; try { Neue ACL erzeugen, die den neuen ACE enthlt. } if SetEntriesInAcl(3, @ExplicitAccesses, nil, PACL(@Acl)^) = ERROR_SUCCESS then begin { Security Descriptor initialisieren. } SecurityDescriptor := PSecurityDescriptor(LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH)); if Assigned(SecurityDescriptor) then if InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION) then { Die ACL zum Security Descriptor hinzufgen. } if SetSecurityDescriptorDacl(SecurityDescriptor, True, ACL, False) then begin { Eine Sicherheits-Attribute-Struktur initialisieren. } SecurityAttributes.nLength := SizeOf(TSecurityAttributes); SecurityAttributes.lpSecurityDescriptor := SecurityDescriptor; SecurityAttributes.bInheritHandle := False; { Die Sicherheits-Attribute benutzen um den Schlssel anzulegen. } // RegCreateKeyEx(Key, SubKey, 0, '', 0, KEY_READ or KEY_WRITE or WRITE_DAC, @SecurityAttributes, KeyHandle, @Disposition); RegOpenKeyEx(Key, SubKey, 0, KEY_READ or KEY_WRITE or WRITE_DAC, KeyHandle); if RegSetKeySecurity(KeyHandle, DACL_SECURITY_INFORMATION, SecurityDescriptor) = ERROR_SUCCESS then if RegSetValue(key, SubKey, REG_SZ, 'Test', 0 ) = ERROR_SUCCESS then begin RegDeleteValue(Key, 'Test'); RegCloseKey(Key); end; if KeyHandle <> 0 then Result := RegSetKeySecurity(KeyHandle, DACL_SECURITY_INFORMATION, SecurityDescriptor) = ERROR_SUCCESS; end; end; finally if Assigned(EveryoneSID) then FreeSid(EveryoneSID); if Assigned(AdminSID) then FreeSid(AdminSID); if Assigned(PowerUserSID) then FreeSid(PowerUserSID); if Assigned(Acl) then LocalFree(HLOCAL(Acl)); if Assigned(SecurityDescriptor) then LocalFree(HLOCAL(SecurityDescriptor)); if KeyHandle <> 0 then RegCloseKey(KeyHandle); end; end; |
Re: WinAPI Problem
Wenn ein Benutzer nur Leserechte hat wird er den Schlüssel eben nicht löschen können. Er hat ja wohl nicht umsonst nur Leserechte in dem Schlüssel. Und wenn er sich selbst (als nicht Admin) dort auch Schreibrechte verschaffen könnte per Programmcode, wäre wohl die gesamte Benutzerverwaltung von Windows für den Pop.
|
Re: WinAPI Problem
Könntest du bitte deinem Beitrag einen aussagekräftigen Titel geben? :-D
|
Re: WinAPI Problem
Zitat:
Zitat:
Edit : Zitat:
|
Re: WinAPI Problem mit Rechten setzen in der Registry
Moin Rolf,
die Softwareverteilungen, die ich kenne, lösen das Problem dadurch, dass sie mit einem Dienst arbeiten. Dieser wird mit einem speziell berechtigten Installationsaccount, oder dem Local System Account gestartet, der dann mit den notwendigen Berechtigungen für Installationen ausgestattet ist. |
Re: WinAPI Problem mit Rechten setzen in der Registry
Ja, so ist das auch. Ich benutze hier in der Firma Novell Zenworks for Desktop. Nur leider gibt es immer wieder die Situation, das im HKLM\System verschiedenste Werte nicht geändert werden können, trotz das diese Werte im Paket der Softwareverteilung stehen.
|
Re: WinAPI Problem mit Rechten setzen in der Registry
Hi Leute
Ich habe mal den Code ausprobiert unter Vista und bekomme nach Ausführen der Funktion SetEntriesInACL den Rückgabewert 87 (INVALID_PARAMETER). Weiss jemand einen Rat ?? |
Re: WinAPI Problem mit Rechten setzen in der Registry
wo genau?
|
Re: WinAPI Problem mit Rechten setzen in der Registry
Hi
Der Rückgabewert der Funktion
Delphi-Quellcode:
ist nicht ERROR_SUCCESS, sondern ERROR_INVALID_PARAMETER{ Neue ACL erzeugen, die den neuen ACE enthlt. } if SetEntriesInAcl(3, @ExplicitAccesses, nil, PACL(@Acl)^) = ERROR_SUCCESS then begin |
Re: WinAPI Problem mit Rechten setzen in der Registry
Ja das kommt davon, wenn die Leute nur abkupfern und nicht die
![]() ![]() Die ganze Geschichte oben funktioniert nur, wenn die Aufzählungstypen eine bestimmte Größe haben. Das muss man setzen mit :
Delphi-Quellcode:
{$MINENUMSIZE 4}
Hier ein Beispiel mit den WinNT Apis von Assarbad und Co.
Delphi-Quellcode:
program Project1;
{$APPTYPE CONSOLE} uses //jwa... download from [url]http://jedi-apilib.sourceforge.net[/url] jwaACLApi, jwaAccCtrl, jwaWinBase, jwaWindows, jwaNative, SysUtils; var AdminSID: PSID; ExplicitAccesses: TExplicitAccess; Acl: PACL; dwRes : DWORD; begin { TODO -oUser -cConsole Main : Hier Code einfügen } if AllocateAndInitializeSid(@SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, AdminSID) then begin FillChar(ExplicitAccesses,sizeof(ExplicitAccesses),0); ExplicitAccesses.grfAccessPermissions := KEY_READ;//KEY_ALL_ACCESS; ExplicitAccesses.grfAccessMode := SET_ACCESS; ExplicitAccesses.grfInheritance := NO_INHERITANCE; ExplicitAccesses.Trustee.TrusteeForm := TRUSTEE_IS_SID; ExplicitAccesses.Trustee.TrusteeType := TRUSTEE_IS_GROUP; ExplicitAccesses.Trustee.ptstrName := PAnsiChar(AdminSID); end; dwRes := SetEntriesInAcl(1, @ExplicitAccesses, 0, ACL); if (dwRes = 0) then begin LocalFree(ACL); end; end. |
Re: WinAPI Problem mit Rechten setzen in der Registry
Hi Leute
Danke für den Tip. Das SetEntriesInACL funktioniert nun. Leider habe ich nun ein weiteres Problem. Ich habe versucht, mit RegOpenKeyEx den Schlüssel "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib" zu öffnen. Leider hat die Funktion immer ACCESS_DENIED zurückgegeben. Grund all meiner Versuche ist die Abfrage der aktuellen CPU Auslastung und die Anzahl der Prozessoren unter Windows Vista. Unter allen anderen OS funkts einwandfrei. Aber unter VISTA wurde der Zugriff auf HKEY_PERFORMANCE_DATA eingeschränkt. Habe nun in der KnowledgeBase folgenden Artikel gefunden:
Code:
Den habe ich nun versucht in Delphi zu übersetzen und damit den Zugriff auch für Hauptbenutzer wieder freizugeben. Leider habe ich dabei ein paar Problemchen. Oder gibt es noch eine andere Möglichkeit (mglw. mit Manifest ??).
/*
This sample illustrates how to regulate access to the performance data provided by the registry key HKEY_PERFORMANCE_DATA. The security on the following registry key dictates which users or groups can gain access to the performance data: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib This sample opens the registry key for WRITE_DAC access, which allows for a new Dacl to be applied to the registry key. A Dacl is then built, which grants the following users access: Administrators are granted full control to allow for future updates to the security on the key and to allow for querying performance data. Interactively logged on users, through the well-known Interactive Sid, are granted KEY_READ access, which allows for querying performance data. The new Dacl is then applied to the registry key using the RegSetKeySecurity() Win32 API. This sample relies on the import library Advapi32.lib. Note that not all errors will cause an information message to be displayed. */ #include <windows.h> #include <stdio.h> #define RTN_OK 0 #define RTN_USAGE 1 #define RTN_ERROR 13 int __cdecl main( void ) { SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY; PSID pInteractiveSid = NULL; PSID pAdministratorsSid = NULL; SECURITY_DESCRIPTOR sd; PACL pDacl = NULL; DWORD dwAclSize; HKEY hKey; LONG lRetCode; BOOL bSuccess = FALSE; // assume this function fails // // open the performance key for WRITE_DAC access // lRetCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"), 0, WRITE_DAC, &hKey ); if(lRetCode != ERROR_SUCCESS) { fprintf(stderr, "RegOpenKeyEx error! (rc=%lu)\n", lRetCode); return RTN_ERROR; } // // prepare a Sid representing any Interactively logged-on user // if(!AllocateAndInitializeSid( &sia, 1, SECURITY_INTERACTIVE_RID, 0, 0, 0, 0, 0, 0, 0, &pInteractiveSid )) goto cleanup; // // prepare a Sid representing the well-known admin group // if(!AllocateAndInitializeSid( &sia, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdministratorsSid )) goto cleanup; // // compute size of new acl // dwAclSize = sizeof(ACL) + 2 * ( sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) ) + GetLengthSid(pInteractiveSid) + GetLengthSid(pAdministratorsSid) ; // // allocate storage for Acl // pDacl = (PACL)HeapAlloc(GetProcessHeap(), 0, dwAclSize); if(pDacl == NULL) goto cleanup; if(!InitializeAcl(pDacl, dwAclSize, ACL_REVISION)) goto cleanup; // // grant the Interactive Sid KEY_READ access to the perf key // if(!AddAccessAllowedAce( pDacl, ACL_REVISION, KEY_READ, pInteractiveSid )) goto cleanup; // // grant the Administrators Sid GENERIC_ALL access to the perf key // if(!AddAccessAllowedAce( pDacl, ACL_REVISION, KEY_ALL_ACCESS, pAdministratorsSid )) goto cleanup; if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) goto cleanup; if(!SetSecurityDescriptorDacl(&sd, TRUE, pDacl, FALSE)) { fprintf(stderr, "SetSecurityDescriptorDacl error! (rc=%lu)\n", GetLastError()); goto cleanup; } // // apply the security descriptor to the registry key // lRetCode = RegSetKeySecurity( hKey, (SECURITY_INFORMATION)DACL_SECURITY_INFORMATION, &sd ); if(lRetCode != ERROR_SUCCESS) { fprintf(stderr, "RegSetKeySecurity error! (rc=%lu)\n", lRetCode); goto cleanup; } bSuccess = TRUE; // indicate success cleanup: RegCloseKey(hKey); RegCloseKey(HKEY_LOCAL_MACHINE); // // free allocated resources // if(pDacl != NULL) HeapFree(GetProcessHeap(), 0, pDacl); if(pInteractiveSid != NULL) FreeSid(pInteractiveSid); if(pAdministratorsSid != NULL) FreeSid(pAdministratorsSid); if(!bSuccess) return RTN_ERROR; return RTN_OK; } Kann mir einer beim Übersetzen helfen ?? |
Re: WinAPI Problem mit Rechten setzen in der Registry
Wenn du die Rechte ändern willst, brauchst du natürlich das Rechte das Recht zu ändern.
Also z.B. Admin- oder Besitzerrechte. D.h. der Benutzer muss dein Programm zumindest mit Adminrechten gestartet haben. Wenn der Administrator selbst nicht in der ACL (Access Control List)vorkommt, oder sogar den Zugriff verwehrt bekommt, dann muss er ersteinmal der Besitzer werden, und die ACL korrigieren. |
Re: WinAPI Problem mit Rechten setzen in der Registry
Hallo,
ich hatte ein ähnliches Problem (alle Rechte eines Registry Schlüssels bzw. Datei wurden gelöscht, wie setze ich die Rechte) und dieser Thread hat mir sehr geholfen. Die Antwort von Dezipaitor sollte man sich zweimal durchlesen. Für alle die ein ähnliches Problem haben und auf diesen Thread stoßen, will ich hier meinen Source posten. Problem: Ich erhalte bei Registry oder Dateizugriff ERROR_ACCESS_DENIED obwohl ich Owner oder Admin bin (siehe auch ![]()
Delphi-Quellcode:
SetRegPermission setzt die Zugriffsrechte des aktuellen Benutzers (bzw. Account meines Delphiprogramms).
if RegOpenKeyEx(HKEY_LOCAL_MACHINE, '...', 0, KEY_READ, Key)=ERROR_ACCESS_DENIED then begin
SetRegPermission(HKEY_LOCAL_MACHINE,'...', OldResetAccess); RegOpenKeyExW(HKEY_LOCAL_MACHINE, '...', 0, KEY_READ, Key); end;
Delphi-Quellcode:
Für Dateirechte sieht es so aus (SetNamedSecurityInfo kann man auch für Registry nutzen)
function SetRegPermission(Key:HKey; SubKeyName:WideString; var ResetAccess:string):boolean;
const SDDL_REVISION_1 = 1; SECURITY_DESCRIPTOR_REVISION = 1; var dwSize,RegResult:DWORD; pNewSD,pSD:Windows.PSECURITY_DESCRIPTOR; pSdStr:PChar; SvcKey:HKey; dwLength: DWORD; Token:THandle; pTokenUser:PTOKEN_USER; sNewSD:string; begin result:=false; sErr:=''; //*** Start Set Owner **** (see [url]http://support.microsoft.com/kb/111546[/url]) SetPrivilege('SeTakeOwnershipPrivilege', True); // SE_TAKE_OWNERSHIP_NAME try RegResult:=RegOpenKeyExW(Key, PWideChar(SubKeyName), 0, WRITE_OWNER, SvcKey); //TODO reset Owner? if RegResult=ERROR_SUCCESS then begin dwLength:=0; pTokenUser := nil; OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, Token); if not GetTokenInformation(Token, TokenUser, pTokenUser, 0, dwLength) then begin if GetLastError=ERROR_INSUFFICIENT_BUFFER then begin pTokenUser:=HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwLength); if pTokenUser<>nil then begin if GetTokenInformation(Token, TokenUser, pTokenUser, dwLength, dwLength) then begin GetMem(pSD,SECURITY_DESCRIPTOR_MIN_LENGTH); InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(pSD, True, Nil, False); // No ACL - all access granted SetSecurityDescriptorOwner(pSD, pTokenUser^.User.Sid, FALSE); SysErrorMessage( RegSetKeySecurity(SvcKey,OWNER_SECURITY_INFORMATION, pSD) ); FreeMem(pSD); end; HeapFree(GetProcessHeap, 0, pTokenUser); end; end; end; CloseHandle(Token); RegCloseKey(SvcKey); end; finally SetPrivilege('SeTakeOwnershipPrivilege', false); end; //*** End Set Owner **** RegResult:=RegOpenKeyExW(Key, PWideChar(SubKeyName), 0, READ_CONTROL or WRITE_DAC, SvcKey); if RegResult<>ERROR_SUCCESS then raise Exception.Create(SysErrorMessage(RegResult)); try pSD:=nil; dwSize:=0; RegResult:=RegGetKeySecurity(SvcKey,DACL_SECURITY_INFORMATION, pSD, dwSize); if RegResult<>ERROR_SUCCESS then raise Exception.Create(SysErrorMessage(RegResult)); GetMem(pSD,dwSize); InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); RegResult:=RegGetKeySecurity(SvcKey, DACL_SECURITY_INFORMATION, pSD, dwSize); if RegResult<>ERROR_SUCCESS then raise Exception.Create(SysErrorMessage(RegResult)); if ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, pSdStr, nil) then begin pNewSD:=nil; if ResetAccess<>'' then sNewSD:=ResetAccess else sNewSD:=StrPas(pSdStr)+'(A;OICI;GA;;;'+GetCurrentUserSIDString('BA')+')'; //AdminAccess='(A;OICI;GA;;;BA)'; //see "Security Descriptor String Format": [url]http://msdn2.microsoft.com/en-us/library/aa379570.aspx[/url] + "SID Strings" [url]http://msdn2.microsoft.com/en-us/library/aa379602.aspx[/url] + [url]http://msdn.microsoft.com/en-us/magazine/cc982153.aspx[/url] if ConvertStringSecurityDescriptorToSecurityDescriptor(PChar(sNewSD), SDDL_REVISION_1, pNewSD, nil) then if IsValidSecurityDescriptor(pNewSD) then begin RegResult:=RegSetKeySecurity(SvcKey, DACL_SECURITY_INFORMATION, pNewSD); if RegResult=ERROR_SUCCESS then begin ResetAccess:=StrPas(pSdStr); result:=true; end; end; if pNewSD<>nil then LocalFree(HLOCAL(pNewSD)); LocalFree(HLOCAL(pSdStr)); end; finally if pSD<>nil then FreeMem(pSD); RegCloseKey(SvcKey); end; end;
Delphi-Quellcode:
Hier noch die Hilfsfunktionen:
{SetFileAccessForAll: Set File Access for the current user}
procedure SetFileAccessForAll(FileName:string); var pSD:PSECURITY_DESCRIPTOR; Token:THandle; pTokenUser:PTOKEN_USER; r,dwLength: DWORD; sErr:string; pOldDACL,pDACL: PACL; EA: TExplicitAccess; begin sErr:=''; SetPrivilege('SeTakeOwnershipPrivilege', True); // SE_TAKE_OWNERSHIP_NAME try dwLength:=0; pTokenUser := nil; OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, Token); if not GetTokenInformation(Token, TokenUser, pTokenUser, 0, dwLength) then begin if GetLastError=ERROR_INSUFFICIENT_BUFFER then begin pTokenUser:=HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwLength); if pTokenUser<>nil then begin if GetTokenInformation(Token, TokenUser, pTokenUser, dwLength, dwLength) then begin SetNamedSecurityInfo(PChar(FileName), SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, pTokenUser^.User.Sid, nil, nil, nil); // **** Start: grant all access to current User *** pSD:=nil; pOldDACL:=nil; GetNamedSecurityInfo(PChar(FileName), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, @pOldDACL, nil, pSD); ZeroMemory(@EA, SizeOf(EA)); BuildTrusteeWithSid(@EA.Trustee, pTokenUser^.User.Sid); EA.grfAccessPermissions := GENERIC_ALL; EA.grfAccessMode := SET_ACCESS; EA.grfInheritance := SUB_CONTAINERS_AND_OBJECTS_INHERIT; EA.Trustee.TrusteeForm := TRUSTEE_IS_SID; EA.Trustee.TrusteeType := TRUSTEE_IS_USER; r := SetEntriesInAcl(1, @EA, pOldDACL, pDACL); // Merges EA + pOldDACL = pDACL if r = ERROR_SUCCESS then begin SetNamedSecurityInfo(PAnsiChar(FileName), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, pDACL, nil); if pDACL<>nil then LocalFree(Cardinal(pDACL)); end; if pOldDACL<>nil then LocalFree(Cardinal(pOldDACL)); // **** Ende: *** end; HeapFree(GetProcessHeap, 0, pTokenUser); end; end; CloseHandle(Token); end; finally SetPrivilege('SeTakeOwnershipPrivilege', false); end; end;
Delphi-Quellcode:
Als Anregung auch mal hier angucken:
function ConvertSidToStringSid(Sid: PSID; var StringSid: LPSTR): BOOL; stdcall; external advapi32 name 'ConvertSidToStringSidA';
//function ConvertStringSidToSid(StringSid: LPCSTR; var Sid: PSID): BOOL; stdcall; external advapi32 name 'ConvertStringSidToSidA'; function GetCurrentUserSIDString(sDefault:string):string; //für SvcHostDlls var dwLength: DWORD; Token:THandle; pTokenUser:PTOKEN_USER; StringSid:PChar; begin result:=sDefault; dwLength:=0; pTokenUser := nil; OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, Token); if not GetTokenInformation(Token, TokenUser, pTokenUser, 0, dwLength) then begin if GetLastError=ERROR_INSUFFICIENT_BUFFER then begin pTokenUser:=HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwLength); if pTokenUser<>nil then begin if GetTokenInformation(Token, TokenUser, pTokenUser, dwLength, dwLength) then begin ConvertSidToStringSid(pTokenUser^.User.Sid, StringSid); result:=StrPas(StringSid); LocalFree(HLOCAL(StringSid)); end; HeapFree(GetProcessHeap, 0, pTokenUser); end; end; end; CloseHandle(Token); end; function ConvertSecurityDescriptorToStringSecurityDescriptor( SecurityDescriptor: PSECURITY_DESCRIPTOR; RequestedStringSDRevision: DWORD; SecurityInformation: SECURITY_INFORMATION; var StringSecurityDescriptor: LPSTR; StringSecurityDescriptorLen: PULONG): BOOL; stdcall; external advapi32 name 'ConvertSecurityDescriptorToStringSecurityDescriptorA'; function ConvertStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor: LPCSTR; StringSDRevision: DWORD; var SecurityDescriptor: Windows.PSECURITY_DESCRIPTOR; SecurityDescriptorSize: PULONG): BOOL; stdcall; external advapi32 name 'ConvertStringSecurityDescriptorToSecurityDescriptorA'; ![]() (Bitte nicht meckern, dass ich einen alten Thread ausgegraben habe - für die Delphiprogrammierer die nach Hilfe googeln ist doch nur wichtig, ob sie Hilfe finden oder nicht) |
Re: WinAPI Problem mit Rechten setzen in der Registry
Zitat:
![]() Beispiel für Registry Key Security.
Delphi-Quellcode:
program RegKeySecurity;
{.$APPTYPE CONSOLE} uses SysUtils, Registry, JwaWindows, JwsclToken, JwsclSecureObjects, JwsclPrivileges, JwsclAcl, JwsclDescriptor, JwsclTypes, JwsclConstants, JwsclKnownSid, JwsclUtils, JwsclStrings; procedure SetRegKeySecurity(KeyRoot : HKEY; KeyName : String); var Privs : IJwPrivilegeScope; Key : HKEY; KeySec : TJwSecureRegistryKey; DACL : TJwDAccessControlList; begin JwInitWellKnownSIDs; //inits JwSecurityProcessUserSID if RegOpenKeyEx(KeyRoot, PChar(KeyName), 0, KEY_ALL_ACCESS, Key) = ERROR_ACCESS_DENIED then begin //not necessary since KeySec.TakeOwnerShip(); does it on its own //But just show the power of interfaces //The privilege will be restored to inactive state when the procedure exists Privs := JwGetPrivilegeScope([SE_TAKE_OWNERSHIP_NAME], pst_Enable); //First open key for write owner if RegOpenKeyEx(KeyRoot, PChar(KeyName), 0, WRITE_OWNER, Key) <> 0 then RaiseLastOSError; try //take ownership - can fail with exception TJwSecureRegistryKey.TakeOwnerShip(Key); //we need to reopen the handle for further access if RegOpenKeyEx(KeyRoot, PChar(KeyName), 0, WRITE_DAC, Key) <> 0 then RaiseLastOSError; //because access is granted on handle creation we need to //recreate the object KeySec := TJwSecureRegistryKey.Create(Key); try DACL := KeySec.DACL; //returns a cached DACL so we must not free it! //add process user with full access //and also set inheritance DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil, [afContainerInheritAce], KEY_ALL_ACCESS, JwSecurityProcessUserSID)); //set DACL - may fail with exception KeySec.SetDACL(DACL); finally KeySec.Free; end; finally RegCloseKey(Key) end; end; end; begin SetRegKeySecurity(HKEY_CURRENT_USER, 'test'); end. |
Re: WinAPI Problem mit Rechten setzen in der Registry
Hi Dezipaitor,
Danke für Deine elegante Lösung (auch wenn ich ein Fan vom reinen Win32API bin). Danke besonders für den Link zum genialen ![]() Noch ein Nachtrag/Frage: Am 04.05.2007 schriebst Du: Zitat:
D.h. der Benutzer muss dein Programm zumindest mit Adminrechten gestartet haben oder der Benutzer ist Besitzer des Objektes. (Genauer gesagt: das Programm läuft im Account des Owners des Objektes; Objekt ist hier der Registry-Key oder die Datei). Das hast Du ja auch gestern geschrieben: Zitat:
|
Re: WinAPI Problem mit Rechten setzen in der Registry
Ich habe mich ungeschickt ausgedrückt.
Wenn der Benutzer nicht der Besitzer ist, dann muss er Admin sein, um der Besitzer werden zu können. Das gilt jedoch nicht, wenn die DACL ihm WRITE_OWNER gewährt. Wenn er jedoch Besitzer schon ist, kann er mit dem Objekt machen was er will, auch wenn er erstmal noch die DACL anpassen muss. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:01 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