# 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 privileges cannot be obtained.

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

![](../images/ui/privileges_action.png)

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.

![](../images/ui/privileges_uninstaller_action.png)

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)](https://en.wikipedia.org/wiki/User_Account_Control) limits privileges for all users by default. An application can request full privileges, with different effects for normal users and admin users:

- A **normal user** cannot be elevated to full privileges, so the user has to enter credentials for a different administrator account. A normal user is not likely to have these credentials, so by default the "Request privileges" action does not try to obtain full privileges for normal users.   Under some circumstances, for example, if you want to manage services in your installer, you absolutely require full privileges. In this case, you can select the "Try to obtain full privileges if normal user" property in the Windows category.
- An **admin user** can be elevated. A UAC prompt will be shown in this case, and the user simply has to agree to elevate privileges for the installer. Given that it is not possible to write to the program files directory without elevated privileges, this elevation is performed by default. With the "Try to obtain full privileges if admin user" property you can configure this behavior according to your own needs.

![](../images/ui/privileges_windows.png)

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:

- A **normal user** cannot be elevated to full privileges, so the user has to enter the root password. A normal user is not likely to have the root password, so the "Request privileges" action does not try to obtain full privileges for normal users by default.
- To elevate an **admin user**, an authentication dialog will be shown, and users have to enter their own password. Contrary to Windows, admin users can always write to the `/Applications ` directory, even without full privileges. That is why on macOS no elevation of privileges is requested by default.

![](../images/ui/privileges_macos.png)

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.

### Linux privileges

install4j supports elevation of privileges with `pkexec` for GUI installation if available. For console installations, `sudo` or `su` will be called. install4j does not elevate privileges for unattended installations. In this case, the installer has to be started by the root user if required.

![](../images/ui/privileges_unix.png)

### Elevation mechanism

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

![](../images/privileges_elevation.svg)

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.

![](../images/ui/privileges_elevation_type.png)

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

- the "Install files" and "Uninstall files" actions
- service actions
- actions that add rights on Windows
- actions that write files
- the "Run executable or batch file" action

Actions that are explicitly not elevated by default include

- the "Show URL" action
- the "Show file" action
- the "Execute launcher" action
- actions that should run as the original user, such as registry actions
- actions that interact with the GUI of the installer application

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.
