![]() |
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 07:00 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