How to get SeBackupPrivilege in a deferred custom action EXE?
I have encountered a privilege difference in Windows Installer between XP and Vista RC1 which makes our installation fail. I have searched for an explanation and workaround but haven't found anything so far. This is NOT a UAC issue: the difference in privileges is there even when UAC is off.
The Problem:
In Vista RC1, a custom action of type 3074 runs WITHOUT having the SeBackupPrivilege privilege. The privilege is not there so it is not possible to enable it using AdjustTokenPrivileges. (Type 3074 custom action is an EXE that runs from a temp file using deferred execution in the Local
System context.)
In XP SP2 and earlier versions of Windows, this custom action has the SeBackupPrivilege privilege so it is possible to enable it using AdjustTokenPrivileges.
Our custom action needs to enable SeBackupPrivilege and SeRestorePrivilege in order to use RegLoadKey.
Questions:
1. Is this an intentional difference between XP (msiexec.exe 3.1.4000.1823) and Vista RC1 (msiexec.exe 4.0.5600.16384)?
2. How can I run an EXE as a custom action so that it can enable SeBackupPrivilege and SeRestorePrivilege and then call RegLoadKey?
3. If there is no way to do the above (question 2), is it possible to run some kind of custom action that could enable SeBackupPrivilege and SeRestorePrivilege and then call RegLoadKey?
Thanks in advance!
Antti
> Privileges are associated with tokens not with custom actions AFAIK.
Yes, I understand this.
> If your custom action runs under Local System (which it will with that action type), the privilege is there
This is what I thought, too. But it seems it is not that simple in reality.
For example, I think Windows Installer could have called CreateRestrictedToken to create a token which represents LocalSystem but has some privileges deleted (i.e. removed, not just disabled). This token could then have been used in a call to CreateProcessAsUser when launching a new process for my custom action (the custom action uses an EXE file in this case).
I'm not saying that Windows Installer is doing exactly that, but something like that seems to be happening. It did not happen in XP, but is now happening in Vista RC1.
> How do you check whether your token has the privilege?
I checked this by modifying the custom action EXE program so that it opens the process token using OpenProcessToken and then gets all privileges using GetTokenInformation. I show the privilege names in a message box and SeBackupPrivilege is not there when the custom action runs under Windows Installer in Vista RC1. It is there when the custom action runs under Windows Installer in XP SP2.
Additionally, I have tried to enable the SeBackupPrivilege privilege anyway using AdjustTokenPrivileges. It returns a nonzero value and GetLastError returns ERROR_NOT_ALL_ASSIGNED, which according to MSDN means that "the token does not have one or more of the privileges specified in the NewState parameter".
So, I really think that the process that Windows Installer started to execute my custom action of type 3074 does not have the SeBackupPrivilege in Vista RC1 although it has it in XP SP2 and in earlier versions of Windows. This takes me back to my original questions about whether this is an intentional difference between XP and Vista or perhaps a bug which will cause installers such as ours fail on Vista. And if the difference is intentional, is there any way to execute an EXE custom action so that the SeBackupPrivilege privilege is there?
Antti
Maarten,
Christopher Painter seems to have found the exact cause of the problem. This is indeed a change in how MSI 4.0 works in Vista as compared to MSI 3.x on XP. See Cristopher's blog:
http://chrpai.blogspot.com/2006/10/vista-deferred-ca-consideration.html
Christopher writes "I'm suspecting that this is a defect in the MSI 4.0 in Vista" and "Microsoft should either document why this priv was taked away or fix it in Vista". My opinion on the issue is exactly the same. How can I take this issue further? What is the proper way of reporting this as a defect in MSI 4.0 in Vista and request Microsoft to fix it?
I'm sure there are others out there who are calling RegLoadKey in a deferred custom action in their installer (e.g. in order to manipulate other users' HKCU registry settings). RegLoadKey requires SeBackupPrivilege. I believe this issue should be fixed, otherwise some installers will be failing in Vista.
If this issue is not fixed, is there any way to use RegLoadKey in a deferred custom action in MSI 4.0 in Vista?
Antti
I haven't tried RegLoadAppKey in practice but based on its documentation, I got the impression that I cannot use it to load a complete hive of another user. For example, RegLoadAppKey requires that all keys have the same security descriptor, which I don't think would be true for another user's HKEY_USERS hive in a general case.
Do you think we would be able to use RegLoadAppKey to load each user's hive and modify it?
Antti
RegLoadAppKey probably can’t be used to load user hives because a user hive certainly won’t have identical security descriptors on all keys. This API is meant for application specific data hives.
RegLoadKey() is the API and you must have backup/restore priviledges, as documented. And you will also need to have permission to make changes to the keys after it is loaded.
You could change the problem.
If this is application specific changes, then you could change the application to “pull” changes from a central location (like a HKLM registry location) the next time it runs in a specific users context. For example, Office does this. Every time you run Office, it checks a central location (I’m not sure where) for changes that need to be applied to the current user.
If these are changes to an application that you can’t control (like Windows itself), then you can put an application in HKLM\...\Run that applies the changes when the user logs in. It will need to always be there and be written so that it knows that its applied the changes already, but that’s just a development project.
If these are changes that must be applied before the user logs in, then a domain script might be appropriate.
But if that isn’t possible, then loading the registry hive is indeed the last resort and requires these privs.
Thanks for your suggestions. They would work in some other application, but are not directly helpful in what we are trying to achieve (or actually, in preserving the tried-and-true functionality we've been using in our installer for a couple of years on Windows 2000 and XP).
We need to migrate user-specific settings in each user's hive from a previous version's key to the new version's key before the previous version gets uninstalled. Additionally, it is desirable to delete the user-specific settings of the previous version from each user's hive during uninstallation. And more, we need to change certain 3rd-party settings (e.g. AutoCAD's registry settings) in user-specific hives. All of this was possible in Windows XP but is now much more difficult in Vista. Of course there are ways to do it, but I do not understand why this has been made so difficult in Vista. I would understand if it increased security, but as far as I understand, it does not really improve security. It just requires an additional step from the installer.
As suggested in another newsgroup, we plan to create a service EXE that includes the code that we previously had in the custom action. Our installer can install this helper service EXE, configure it to use the Local System, and start this service. This service can now enable the SeBackupPrivilege privilege and use RegLoadKey as we did previously.
I guess this also means that anyone who wants full privileges in a Vista MSI installer can do the same -- it is just more work compared to how it was possible in XP. Why make it more difficult if there is no real security benefit anyway, that is what I do not understand. My view is that this change in Windows Installer in Vista will create more harm in the form of installer compatibility problems that it can do good.
Antti
I agree wholeheartedly! Our application needs to perform certain actions on uninstall for each user based on their registry settings, such as deleting a sometimes-large cache directory. On Vista, it will leave these directories and registry settings behind because Windows Installer has removed the privileges from the MSI service (this is a bad installation change). A simple remedy would be to have such settings written to a central registry location, but then we can't write to HKLM when running in the user's context due to UAC (this is a good security change).
Has anyone found any kind of decent workaround for this on the uninstall side? I think it's ironic that the Windows Installer now doesn't provide enough privileges to actually perform clean uninstallations, and I'd expect to see some migration to a different installation engine for products that want to behave well for multiple users. The proper solution is to fix Windows Installer so that it still works as a general-purpose installation platform (give us back SeBackupName/SeRestoreName!), and custom actions can do what they need to do. The general consensus on the web, that I've seen, is that this is tough luck - deal with it - and Windows Installer is broken for multi-user apps for the foreseeable future.
Antti Nivala wrote: |
As suggested in another newsgroup, we plan to create a service EXE that includes the code that we previously had in the custom action. Our installer can install this helper service EXE, configure it to use the Local System, and start this service. This service can now enable the SeBackupPrivilege privilege and use RegLoadKey as we did previously. |
|
This seems a rather heavyweight solution. Wouldn't it be better to just check if it is the first time an individual user has run the application and migrate the necessary registry settings then? This also has the distinct advantage that you won't get a broken end-user experience in situations where you can't consistantly load a user's profile - consider for example a roaming profile where a roamed user is logged on elsewhere.