Immediate Custom Actions Always Impersonate
Windows Installer is a client/server application. When you install a package using msiexec.exe – which is executed by default in response to shell verbs such as Install – or APIs like MsiInstallProduct the package is initially processed under the user’s credentials. This means, of course, that in over-the-shoulder elevation when administrative credentials are provided it’s the administrator’s credentials that are used. The package is opened and certain properties are read to determine if the product is already installed, what the product language is, and other stateful information. If any user interface is authored and is to be displayed, the client processes the UI to collect install locations, feature selection, and other properties from the user. If the install is to run in silent mode the client does very little as shown in a verbose log.
Any custom actions executed during this time, of course, run under the invoking user’s credentials. This isn’t impersonation, true, but the title of this post is really in regard to what happens next.
When the execution sequence tables like InstallExecuteSequence are processed, the client process passes data through the command line to msiexec.exe running as a Windows service (on Winodws NT-based platforms). In a verbose log you’ll see something like the following:
MSI (c) (A8:78) [13:33:28:352]: Switching to server: TARGETDIR="C:" CURRENTDIRECTORY="C:UsersheathsDownloads" CLIENTUILEVEL="0" CLIENTPROCESSID="1704" USERNAME="heaths" COMPANYNAME="Microsoft Corporation" SOURCEDIR="C:UsersheathsDownloads" ROOTDRIVE="C:" EXECUTEACTION="INSTALL" ACTION="INSTALL" INSTALLLEVEL="1" SECONDSEQUENCE="1" ADDLOCAL=Complete
If the package’s Word Count summary property doesn’t specify that elevated privileges are not required, Windows Installer will then prompt to elevate the installation as shown below from a verbose log.
MSI (s) (BC:70) [13:34:10:669]: MSI_LUA: Elevation required to install product, will prompt for credentials
MSI (s) (BC:70) [13:34:59:528]: MSI_LUA: Credential Request return = 0x0
MSI (s) (BC:70) [13:34:59:528]: MSI_LUA: Elevated credential consent provided. Install will run elevated
Any immediate custom actions impersonate the invoking user. Before Windows Vista this wasn’t a problem since at this point the installing administrative user had a privileged token. With the introduction of UAC in Windows Vista the default administrative token with UAC enabled is a filtered token and does not hold all privileges. Since immediate custom actions are not supposed to modify machine state – only to gather state data and schedule custom actions to run deferred – this still shouldn’t be a problem. After all, at this point the generation of the installation and rollback scripts is all that should be going on.
It’s when InstallExecute, InstallExecuteAgain, or InstallFinalize are run that the installation script is executed in a deferred context. Custom actions will, by default, consistently impersonate the user unless they are attributed with msidbCustomActionTypeNoImpersonate (2048), more colloquially called the NoImpersonate bit. Since in Vista and newer the impersonated token is filtered, many machine state-changing operations will fail since full privileges are not held. Robert Flaming, a Program Manager on the Windows Installer team, has a great diagram explaining this in his series regarding UAC and Windows Installer.
Deferred custom actions, including rollback and commit custom actions, should typically be attributed with the NoImpersonate bit. These are the only custom actions that can run outside of the user’s security context and, on Vista, must if the user’s filtered token does not hold the necessary privileges.
Since immediate custom actions are always impersonated in the server, it doesn’t make sense to attribute them with the NoImpersonate bit and ICE68 will actually warn against this.