Elevation Of Privileges


Most operating systems have the concept of normal users and administrators. While regular applications can run with limited privileges, installers often need full administrator privileges because they make modifications to the system that are not granted to limited users.

The required privileges depend on two factors: The operating system and the type of operations that are performed by the installer. The "Request privileges" action that is present in the "Startup" sequence of the default template for installers takes care of elevating the privileges to the required level and optionally terminating the installer with an error message if the required privileged cannot be obtained.

Due to the differences of the different operating systems, this configuration is made separately for Windows, macOS and Unix.

If the action fails, you can choose to not display an error message and switch to an installation directory in the user home directory with the "Fall back to user specific installation directory" property. Use Util.hasFullAdminRights() in condition expressions of actions that only work with elevated privileged in this case.

For the installer and the uninstaller, the privileges should be the same. This is why the default template for the uninstaller has a "Request installer privileges" action that will request the same privileges that were obtained in the installer.

If you have more complex requirements, you can have multiple "Request privileges" actions with appropriate condition expressions, each with a link in the uninstaller.

Windows privileges

On Windows, "User Account Control" (UAC) limits privileges for all users by default. An application can request full privileges, with different effects for normal users and admin users:

By default, the installer will fail if the requested privileges cannot be obtained. You can deselect the "Show failure if requested privileges cannot be obtained" property in the Windows category to continue and let the user install into the user home directory or another writable directory.

When you insert a service action and the elevation properties are not selected, you will be asked whether the necessary changes should be made automatically.

macOS privileges

Similar to Windows, macOS limits privileges for all users by default and normal users and admin users behave differently with respect to privilege elevation:

Like on Windows, the installer will fail by default if the requested privileges cannot be obtained. In the default setting this has no effect, because privileges are never requested.

Service installations require full privileges, so the "Try to obtain full privileges if admin user" and the "Try to obtain full privileges if normal user" properties in the macOS category should be selected in that case. Again, the necessary changes will be suggested when service actions are inserted into the project.

Unix privileges

install4j does not support elevation of privileges on Linux and Unix. Partly this is due to the different incompatible systems of elevation, most notably "su" and "sudo" which cannot be easily detected. If full privileges are required, the user has to elevate the installer manually, either with "su" or with "sudo" or with the corresponding GUI tools. In this case, the "Show failure if current user is not root" has to be selected, so that an error message is shown if the installer is not started as root.

Elevation mechanism

install4j does not elevate the entire process, but it starts an elevated helper process with full privileges.

Elevated actionElevated codeElevatedhelperprocessOriginalunelevatedprocessUnelevated codeUnelevated actionInstaller UIlaunchespushesdownpushesupelevatesdisplays

All actions have an "Action elevation type" property that can be set to "Inherit from parent", "Do not elevate" or "Elevate to maximum available privileges". The root element in the hierarchy or beans is always an installer application whose "Action elevation type" property is set to "Do not elevate" by default.

An action whose "Action elevation type" property results as "Elevate to maximum available privileges" will run in the elevated helper process. Such an action has full access to all installer variables as long as the contents of the variables are serializable.

Actions can have a preferred elevation type that is set automatically when you add the action. Actions that need to be elevated include

Actions that are explicitly not elevated by default include

Elevated code can only interact with the GUI in a limited way. All methods in the com.install4j.api.Util class for displaying message dialogs or option dialogs are supported. You cannot call context.getWizardContext() or directly display a GUI using the Java Swing API. Also, calling methods in the com.api.install4j.context.Context that change screens is not supported. Most importantly, because an elevated action runs in a different process, you cannot access any static state in custom code. The only means to modify state from elevated actions are installer variables.

For your own scripts or your custom code, the API offers a way to push a piece of code to the elevated helper process or to the original process if they exist. This is done by wrapping the code in a com.install4j.api.context.RemoteCallable and calling context.runElevated(...) for the elevated helper process and context.runUnelevated(...) for the original process with the RemoteCallable:

context.runElevated(new RemoteCallable() {
    public Serializable execute() {
        // do something in the elevated helper process
        return null;
    }
}, true);

context.runUnelevated(new RemoteCallable() {
    public Serializable execute() {
        // do something in the original process
        return null;
    }
});

The RemoteCallable must be serializable, so its fields can be transferred to the other process. Its execute() method that contains the code returns a Serializable so you can return a result to the calling process.