How to Elevate Privileges Only When Required

How to elevate privileges only when required?

I don't believe that it is possible to elevate the currently running process. It is built into Windows Vista that administrator privileges are given to a process upon startup, as I understand. If you look at various programs that utilise UAC, you should see that they actually launch a separate process each time an administrative action needs to be performed (Task Manager is one, Paint.NET is another, the latter being a .NET application in fact).

The typical solution to this problem is to specify command line arguments when launching an elevated process (abatishchev's suggestion is one way to do this), so that the launched process knows only to display a certain dialog box, and then quit after this action has been completed. Thus it should hardly be noticeable to the user that a new process has been launched and then exited, and would rather appear as if a new dialog box within the same app has been opened (especially if you some hackery to make the main window of the elevated process a child of the parent process). If you don't need UI for the elevated access, even better.

For a full discussion of UAC on Vista, I recommend you see this very through article on the subject (code examples are in C++, but I suspect you'll need to use the WinAPI and P/Invoke to do most of the things in C# anyway). Hopefully you now at least see the right approach to take, though designing a UAC compliant program is far from trivial...

how to elevate administrator pirivileges only when required vb.net

Processes must be given an administrator token when they start or they never will get one at all. The only way to make it work "on demand" is you must make a 2nd program that requires administrator privlages that does the download and nothing else, you then have your program launch the 2nd program and wait for it to finish.

However, the better solution is choose a better save location that does not require administrator privileges to write to, for example you can use Environment.GetFolderPath to find the user's LocalApplicationData folder (for example for you that would point to somthing like C:\Users\Ntohing_Trolll\AppData\Local) and save and run the exe from a subfolder in there. That is what programs like Chrome do for their updating so you don't require administrative privileges to update.

How can I request elevated permissions in a bash script's begin and let it go at the end?

If your main concern is code clarity, using wrapper functions can do a lot of good.

# call any named bash function under sudo with arbitrary arguments
run_escalated_function() {
local function_name args_q
function_name=$1; shift || return
printf -v args_q '%q ' "$@"
sudo bash -c "$(declare -f "$function_name"); $function_name $args_q"
}

privileged_bits() {
command1_which_needs_sudo
echo "hello2"
command2_which_needs_sudo
}

echo "hello"
run_escalated_function privileged_bits
echo "hello3"

How to elevate account on start / install with standard user?

If you don't want to prompt the UAC in the moment of the administrative operation (using runas), or on every program start (via manifest), you need to create a Service or a Scheduled Task once, at first program setup. A lot of programs use this technique such as Chrome for updates, which normally don't require elevated privileges but for few occasional operations.

Choosing the service method means that you must implement an IPC mechanism for example via named pipe so the low privilege program can talk to the service and ask to execute the desired operation. Keep in mind that the service will always run in background and you shouldn't expose too much permissive operations otherwise other malicious programs could use your service to elevate themselves, or you'll need also an authentication method.

For the scheduled task you could use the same executable with a command line argument like /disabletouch. You only need to manually trigger the task from the low privilege instance. There are the TaskScheduler COM interface (some open-source wrappers exists around it) and the schtasks tool that allow task creation and manual triggers. The task can be created for running as Administrator or SYSTEM account. As for the service allow only strict and harmless elevated operations to prevent misuse.

Make Inno Setup installer request privileges elevation only when needed

Inno Setup 6 has a built-in support for non-administrative install mode.

Basically, you can simply set PrivilegesRequiredOverridesAllowed:

[Setup]
PrivilegesRequiredOverridesAllowed=commandline dialog

Sample Image

Additionally, you will likely want to use the auto* variants of the constants. Notably the {autopf} for the DefaultDirName.

[Setup]
DefaultDirName={pf}\My Program

The following is my (now obsolete) solution for Inno Setup 5, based on @TLama's answer.

When the setup is started non-elevated, it will request elevation, with some exceptions:

  • Only on Windows Vista and newer (though it should work on Windows XP too)
  • When upgrading, the setup will check if the current user has a write access to the previous installation location. If the user has the write access, the setup won't request the elevation. So if the user has previously installed the application to user folder, the elevation won't be requested on upgrade.

If the user rejects the elevation on a new install, the installer will automatically fall back to "local application data" folder. I.e. C:\Users\standard\AppData\Local\AppName.

Other improvements:

  • the elevated instance won't ask for language again
  • by using PrivilegesRequired=none, the installer will write uninstall information to HKLM, when elevated, not to HKCU.
#define AppId "myapp"
#define AppName "MyApp"

#define InnoSetupReg \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + AppId + "_is1"
#define InnoSetupAppPathReg "Inno Setup: App Path"

[Setup]
AppId={#AppId}
PrivilegesRequired=none
...

[Code]

function IsWinVista: Boolean;
begin
Result := (GetWindowsVersion >= $06000000);
end;

function HaveWriteAccessToApp: Boolean;
var
FileName: string;
begin
FileName := AddBackslash(WizardDirValue) + 'writetest.tmp';
Result := SaveStringToFile(FileName, 'test', False);
if Result then
begin
Log(Format(
'Have write access to the last installation path [%s]', [WizardDirValue]));
DeleteFile(FileName);
end
else
begin
Log(Format('Does not have write access to the last installation path [%s]', [
WizardDirValue]));
end;
end;

procedure ExitProcess(uExitCode: UINT);
external 'ExitProcess@kernel32.dll stdcall';
function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
lpParameters: string; lpDirectory: string; nShowCmd: Integer): THandle;
external 'ShellExecuteW@shell32.dll stdcall';

function Elevate: Boolean;
var
I: Integer;
RetVal: Integer;
Params: string;
S: string;
begin
{ Collect current instance parameters }
for I := 1 to ParamCount do
begin
S := ParamStr(I);
{ Unique log file name for the elevated instance }
if CompareText(Copy(S, 1, 5), '/LOG=') = 0 then
begin
S := S + '-elevated';
end;
{ Do not pass our /SL5 switch }
if CompareText(Copy(S, 1, 5), '/SL5=') <> 0 then
begin
Params := Params + AddQuotes(S) + ' ';
end;
end;

{ ... and add selected language }
Params := Params + '/LANG=' + ActiveLanguage;

Log(Format('Elevating setup with parameters [%s]', [Params]));
RetVal :=
ShellExecute(0, 'runas', ExpandConstant('{srcexe}'), Params, '', SW_SHOW);
Log(Format('Running elevated setup returned [%d]', [RetVal]));
Result := (RetVal > 32);
{ if elevated executing of this setup succeeded, then... }
if Result then
begin
Log('Elevation succeeded');
{ exit this non-elevated setup instance }
ExitProcess(0);
end
else
begin
Log(Format('Elevation failed [%s]', [SysErrorMessage(RetVal)]));
end;
end;

procedure InitializeWizard;
var
S: string;
Upgrade: Boolean;
begin
Upgrade :=
RegQueryStringValue(HKLM, '{#InnoSetupReg}', '{#InnoSetupAppPathReg}', S) or
RegQueryStringValue(HKCU, '{#InnoSetupReg}', '{#InnoSetupAppPathReg}', S);

{ elevate }

if not IsWinVista then
begin
Log(Format('This version of Windows [%x] does not support elevation', [
GetWindowsVersion]));
end
else
if IsAdminLoggedOn then
begin
Log('Running elevated');
end
else
begin
Log('Running non-elevated');
if Upgrade then
begin
if not HaveWriteAccessToApp then
begin
Elevate;
end;
end
else
begin
if not Elevate then
begin
WizardForm.DirEdit.Text := ExpandConstant('{localappdata}\{#AppName}');
Log(Format('Falling back to local application user folder [%s]', [
WizardForm.DirEdit.Text]));
end;
end;
end;
end;

Disable Vista UAC per-application, or elevate privileges without prompt?

Generally this problem solved by installing a Windows Service which runs as SYSTEM or an admin account. Then your application can request the privileged action from this service.

Obviously to not pose a security threat ensure that your service can't run arbitrary code or something which might leave the all users vulnerable to privilege escalation attacks.

Winpcap and most of the other sniffing applications use a similar design to give sniffing access to unprivileged users.



Related Topics



Leave a reply



Submit