123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- unit Setup.SecurityFunc;
- {
- Inno Setup
- Copyright (C) 1997-2024 Jordan Russell
- Portions by Martijn Laan
- For conditions of distribution and use, see LICENSE.TXT.
- Functions for altering ACLs on files & registry keys
- }
- interface
- uses
- Windows, SysUtils, Shared.CommonFunc, Shared.Struct;
- function GrantPermissionOnFile(const DisableFsRedir: Boolean; Filename: String;
- const Entries: TGrantPermissionEntry; const EntryCount: Integer): Boolean;
- function GrantPermissionOnKey(const RegView: TRegView; const RootKey: HKEY;
- const Subkey: String; const Entries: TGrantPermissionEntry;
- const EntryCount: Integer): Boolean;
- implementation
- uses
- PathFunc, SetupLdrAndSetup.Messages, SetupLdrAndSetup.InstFunc, Setup.LoggingFunc,
- SetupLdrAndSetup.RedirFunc, Setup.Helper;
- function InternalGrantPermission(const ObjectType: DWORD; const ObjectName: String;
- const Entries: TGrantPermissionEntry; const EntryCount: Integer;
- const Inheritance: DWORD): DWORD;
- { Grants the specified access to the specified object. Returns ERROR_SUCCESS if
- successful. }
- type
- PPSID = ^PSID;
- PPACL = ^PACL;
- PTrusteeW = ^TTrusteeW;
- TTrusteeW = record
- pMultipleTrustee: PTrusteeW;
- MultipleTrusteeOperation: DWORD; { MULTIPLE_TRUSTEE_OPERATION }
- TrusteeForm: DWORD; { TRUSTEE_FORM }
- TrusteeType: DWORD; { TRUSTEE_TYPE }
- ptstrName: PWideChar;
- end;
- TExplicitAccessW = record
- grfAccessPermissions: DWORD;
- grfAccessMode: DWORD; { ACCESS_MODE }
- grfInheritance: DWORD;
- Trustee: TTrusteeW;
- end;
- PArrayOfExplicitAccessW = ^TArrayOfExplicitAccessW;
- TArrayOfExplicitAccessW = array[0..999999] of TExplicitAccessW;
- const
- GRANT_ACCESS = 1;
- TRUSTEE_IS_SID = 0;
- TRUSTEE_IS_UNKNOWN = 0;
- var
- AdvApiHandle: HMODULE;
- GetNamedSecurityInfoW: function(pObjectName: PWideChar; ObjectType: DWORD;
- SecurityInfo: SECURITY_INFORMATION; ppsidOwner, ppsidGroup: PPSID;
- ppDacl, ppSacl: PPACL; var ppSecurityDescriptor: PSECURITY_DESCRIPTOR): DWORD;
- stdcall;
- SetNamedSecurityInfoW: function(pObjectName: PWideChar; ObjectType: DWORD;
- SecurityInfo: SECURITY_INFORMATION; ppsidOwner, ppsidGroup: PSID;
- ppDacl, ppSacl: PACL): DWORD; stdcall;
- SetEntriesInAclW: function(cCountOfExplicitEntries: ULONG;
- const pListOfExplicitEntries: TExplicitAccessW; OldAcl: PACL;
- var NewAcl: PACL): DWORD; stdcall;
- SD: PSECURITY_DESCRIPTOR;
- Dacl, NewDacl: PACL;
- ExplicitAccess: PArrayOfExplicitAccessW;
- E: ^TGrantPermissionEntry;
- I: Integer;
- Sid: PSID;
- begin
- AdvApiHandle := GetModuleHandle(advapi32);
- GetNamedSecurityInfoW := GetProcAddress(AdvApiHandle, PAnsiChar('GetNamedSecurityInfoW'));
- SetNamedSecurityInfoW := GetProcAddress(AdvApiHandle, PAnsiChar('SetNamedSecurityInfoW'));
- SetEntriesInAclW := GetProcAddress(AdvApiHandle, PAnsiChar('SetEntriesInAclW'));
- if (@GetNamedSecurityInfoW = nil) or (@SetNamedSecurityInfoW = nil) or
- (@SetEntriesInAclW = nil) then begin
- Result := ERROR_PROC_NOT_FOUND;
- Exit;
- end;
- ExplicitAccess := nil;
- Result := GetNamedSecurityInfoW(PChar(ObjectName), ObjectType,
- DACL_SECURITY_INFORMATION, nil, nil, @Dacl, nil, SD);
- if Result <> ERROR_SUCCESS then
- Exit;
- try
- { Note: Dacl will be nil if GetNamedSecurityInfo is called on a FAT partition.
- Be careful not to dereference a nil pointer. }
- ExplicitAccess := AllocMem(EntryCount * SizeOf(ExplicitAccess[0]));
- E := @Entries;
- for I := 0 to EntryCount-1 do begin
- if not AllocateAndInitializeSid(E.Sid.Authority, E.Sid.SubAuthCount,
- E.Sid.SubAuth[0], E.Sid.SubAuth[1], 0, 0, 0, 0, 0, 0, Sid) then begin
- Result := GetLastError;
- if Result = ERROR_SUCCESS then { just in case... }
- Result := ERROR_INVALID_PARAMETER;
- Exit;
- end;
- ExplicitAccess[I].grfAccessPermissions := E.AccessMask;
- ExplicitAccess[I].grfAccessMode := GRANT_ACCESS;
- ExplicitAccess[I].grfInheritance := Inheritance;
- ExplicitAccess[I].Trustee.TrusteeForm := TRUSTEE_IS_SID;
- ExplicitAccess[I].Trustee.TrusteeType := TRUSTEE_IS_UNKNOWN;
- PSID(ExplicitAccess[I].Trustee.ptstrName) := Sid;
- Inc(E);
- end;
- Result := SetEntriesInAclW(EntryCount, ExplicitAccess[0], Dacl, NewDacl);
- if Result <> ERROR_SUCCESS then
- Exit;
- try
- Result := SetNamedSecurityInfoW(PChar(ObjectName), ObjectType,
- DACL_SECURITY_INFORMATION, nil, nil, NewDacl, nil);
- finally
- LocalFree(HLOCAL(NewDacl));
- end;
- finally
- if Assigned(ExplicitAccess) then begin
- for I := EntryCount-1 downto 0 do begin
- Sid := PSID(ExplicitAccess[I].Trustee.ptstrName);
- if Assigned(Sid) then
- FreeSid(Sid);
- end;
- FreeMem(ExplicitAccess);
- end;
- LocalFree(HLOCAL(SD));
- end;
- end;
- function GrantPermission(const Use64BitHelper: Boolean; const ObjectType: DWORD;
- const ObjectName: String; const Entries: TGrantPermissionEntry;
- const EntryCount: Integer; const Inheritance: DWORD): DWORD;
- { Invokes either the internal GrantPermission function or the one inside the
- 64-bit helper, depending on the setting of Use64BitHelper }
- begin
- try
- if Use64BitHelper then
- Result := HelperGrantPermission(ObjectType, ObjectName, Entries,
- EntryCount, Inheritance)
- else
- Result := InternalGrantPermission(ObjectType, ObjectName, Entries,
- EntryCount, Inheritance);
- except
- { If the helper interface (or even InternalGrantPermission) raises an
- exception, don't propagate it. Just log it and return an error code, as
- that's what the caller is expecting on failure. }
- Log('Exception while setting permissions:' + SNewLine + GetExceptMessage);
- Result := ERROR_GEN_FAILURE;
- end;
- end;
- const
- OBJECT_INHERIT_ACE = 1;
- CONTAINER_INHERIT_ACE = 2;
- function GrantPermissionOnFile(const DisableFsRedir: Boolean; Filename: String;
- const Entries: TGrantPermissionEntry; const EntryCount: Integer): Boolean;
- { Grants the specified access to the specified file/directory. Returns True if
- successful. On failure, the thread's last error code is set. }
- const
- SE_FILE_OBJECT = 1;
- var
- Attr, Inheritance, ErrorCode: DWORD;
- begin
- { Expand filename if needed because the 64-bit helper may not have the same
- current directory as us }
- Filename := PathExpand(Filename);
- Attr := GetFileAttributesRedir(DisableFsRedir, Filename);
- if Attr = INVALID_FILE_ATTRIBUTES then begin
- Result := False;
- Exit;
- end;
- if Attr and FILE_ATTRIBUTE_DIRECTORY <> 0 then
- Inheritance := OBJECT_INHERIT_ACE or CONTAINER_INHERIT_ACE
- else
- Inheritance := 0;
- ErrorCode := GrantPermission(DisableFsRedir, SE_FILE_OBJECT, Filename, Entries,
- EntryCount, Inheritance);
- SetLastError(ErrorCode);
- Result := (ErrorCode = ERROR_SUCCESS);
- end;
- function GrantPermissionOnKey(const RegView: TRegView; const RootKey: HKEY;
- const Subkey: String; const Entries: TGrantPermissionEntry;
- const EntryCount: Integer): Boolean;
- { Grants the specified access to the specified registry key. Returns True if
- successful. On failure, the thread's last error code is set. }
- const
- SE_REGISTRY_KEY = 4;
- var
- ObjName: String;
- ErrorCode: DWORD;
- begin
- case RootKey of
- HKEY_CLASSES_ROOT: ObjName := 'CLASSES_ROOT';
- HKEY_CURRENT_USER: ObjName := 'CURRENT_USER';
- HKEY_LOCAL_MACHINE: ObjName := 'MACHINE';
- HKEY_USERS: ObjName := 'USERS';
- else
- { Other root keys are not supported by Get/SetNamedSecurityInfo }
- SetLastError(ERROR_INVALID_PARAMETER);
- Result := False;
- Exit;
- end;
- ObjName := ObjName + '\' + Subkey;
- ErrorCode := GrantPermission(RegView = rv64Bit, SE_REGISTRY_KEY, ObjName,
- Entries, EntryCount, CONTAINER_INHERIT_ACE);
- SetLastError(ErrorCode);
- Result := (ErrorCode = ERROR_SUCCESS);
- end;
- end.
|