|Tutorial: How to Use the MsiLockPermissionsEx Table (and CSI_GetSDDLFromObject Helper Script)|
Windows Installer 5.0 (Windows 7) introduced several new capabilities for setting permissions. However, it is difficult to find samples of how to configure the new table and even more difficult to learn the permissions syntax (SDDLText) required to configure permissions. The information in this article and a new CSI toolkit utility make this challenging chore into an easy one.
MsiLockPermissionsEx was introduced in the MSI 5.0 release which was the release for Windows 7. Previous versions of MSI simply ignore this new table.
The detection and use of the MsiLockPermissionsEx table is automatic if it exists – there is no need to add a Standard Action or for the .MSI file database version to be set as “5.0”
Converting to MsiLockPermissionsEx & One Package for XP and Win7
If, however, a package that runs on Windows 7 has BOTH the legacy table (LockPermissions) and the new one (MsiLockPermissionsEx), an error is generated and the package has a hard failure. Conditions cannot be used to avoid this behavior as the check does not happen ONLY IF the MsiLockPermissionsEx table needs to be used – even a blank MsiLockPermissionsEx table causes the error.
This is an unfortunate design as it creates significant problems for designing a single package (that sets permissions) to run on Windows XP through Windows 7. I think it would have been a much more flexible approach to simply have Windows 7 ignore the legacy table when both are present and note this fact in the log when it occurs. Another approach would have been to only generate the error if rows in MsiLockPermissionsEx targeted objects that were also targeted by LockPermissions – that may have allowed both tables to be processed when just a few new capabilities (like setting service permissions) were needed by a package that is otherwise working fine with its legacy LockPermissions table.
As it is, converting an existing LockPermissions table to an MsILockPermissionsEx implementation could be costly since it involves converting all existing rows and, if the package needs to target XP as well.
There are two primary approaches for supporting both LockPermissions and MsiLockPermissionsEx in one package.
Here are some notes about the MsiLockPermissionsEx table and how each column should be used:
What is SDDLText ?
SDDL stands for “Security Descriptor Definition Language”. It is a method for specifying permissions on the Windows OS. Instead of using permissions bitmasks (like the LockPermissions table and most of the Win32 API) it uses a text string with a specific syntax to indicate what permissions to apply to objects. Although it is a big improvement over calculating permission bitmasks, it ends up being a fairly complex “language” in order to support the many permissions available on Windows.
SDDLText vs. Windows Installer FormattedSDDLText
MSI “enhances” the standard SDDLText strings so that they can use the similar types of variable references available in LockPermissions (with the exception of using a property). Any substitutions must be surrounded by angle brackets “<>”.
Any references to a user or group can use:
Standard SDDL Support:
MSI SDDLFormattedText Support:
With Windows security, anywhere a “Domain” can be used, a workstation name can be used for referencing local groups and anywhere a “UserID” can be used, a group name can be used as well.
If the domain is not the local machine, then when Windows Installer requests the permissions to be set by the Windows Operating System, the OS will need to be able to contact a domain controller for the domain during the install or else the install will fail.
CSI_GetSDDLFromObject.vbs Features and Benefits
As of this writing, your authoring tool may not yet support a GUI for setting permissions in this new table. I had to ask myself “Why can’t I just use my familiar old tools to set the permissions?” That question led to CSI_GetSDDLFromObject.vbs. This script simply exacts the existing permissions and formats them as an SDDLText string for easy copying of it (or portions of it) to the MsiLockPermissionsEx table.
Here is a feature overview:
Converting From Secedit Security Templates
Some packagers use Secedit security templates to apply permissions to their packages. These templates actually use SDDL – so conversion from these solutions should be fairly easy. Obviously you lose the advantage of being able to run audit reports and reapply permissions with secedit.exe long after a package has been installed.
Cautions and Tips
What Can Go Wrong?
Here are some of the most common errors and resolutions relating the new permissions support in MSI 5.
Log file: Error 1941. Both LockPermissions and MsiLockPermissionsEx tables were found in the package. Only one of them should be present. This is a problem with the package.
This error only shows up on MSI 5 (currently Windows 7) and later – so it is possible some package authors working primarily on XP could create the new table to support Windows 7 and forget to remove the old one.
Log file: Error 1943. SDDL string 'O:SYG:SYD:AI(A;CI;KA;;;<NonExistentUser>)(A;;KR;;;BU)(A;CIIO;GR;;;BU)(A;;KA;;;BA)(A;CIIO;GA;;;BA)(A;;KA;;;SY)(A;CIIO;GA;;;SY)(A;CIIO;GA;;;CO)' for object Software\DesktopEngineer.com(in table Registry) could not be resolved into a valid Security Descriptor.
If you are using CSI_GetSDDLFromObject, the most likely cause of this message is that the username is specified incorrectly. Another possibility is that the object you copied the SDDL from contains permissions from local users or groups that do not exist on the machine where the permissions is attempting to be applied.
Logging of Successful Permission Application
To audit the successful application of permissions from MsiLockPermissionsEx, search the log for the keyword “SDDLText” The SDDLText= will be appended to the “Executing op” log line of the respective operation depending on what resource the permissions are set on. File permissions have a new Op called “FileCopySDDL”.
Folder Permissions Success Logged
File Permissions Success Logged
MSI (s) (10:94) [12:39:34:772]: Executing op: FileCopySDDL(SourceName=Sample1.txt,SourceCabKey=Sample1.txt, DestName=Sample1.txt,Attributes=0, FileSize=36,PerTick=65536,, VerifyMedia=1,,,,SDDLText=O:SYG:SYD:AI(A;;FA;;;SY)(A;;FA;;;BO)(A;;FA;;;AU)(A;;FA;;;BA)(A;;0x1200a9;;;BU) ,CheckCRC=0,,, InstallMode=58982400,HashOptions=0, HashPart1=-1871278063,HashPart2=123487348, HashPart3=-1882229098,HashPart4=197033840,,)
Registry Key Permissions Success Logged
MSI (s) (10:94) [12:39:34:927]: Executing op: RegOpenKey(Root=-1,Key=Software\DesktopEngineer.com,,BinaryType=0,,SDDLText=O:SYG:SYD:AI(A;;KA;;;SY)(A;CIOI;KA;;;AU)(A;;KR;;;BU)(A;CIIO;GR;;;BU)(A;;KA;;;BA)(A;CIIO;GA;;;BA)(A;CIIO;GA;;;SY)(A;CIIO;GA;;;CO))
Tutorial: How to Add MsiLockPermissionsEx Support to a Package
This tutorial uses Orca. Your authoring tool may not yet (or ever) have a GUI for setting these permissions – so you will need to use it’s table editor which will be very similar to Orca. Even if your authoring tool does not yet support this MSI 5 table, it should allow you to create this table as a custom table in your project file (.WSI for Wise and .ISM for InstallShield).
ATTENTION: You must use Orca version 5 which ships with the latest SDK so that the schema will include the description of the MsiLockPermissionsEx table.
Step 1 – Remove Legacy LockPermissions Table.
If both LockPermissions and MsiLockPermissionsEx are in the same package – the package will fail with an error when run on Windows 7 or later.
Step 2 – Add the MsiLockPermissionsEx Table.
From the main menu bar select Table and then Add Table. Select MsiLockPermissionsEx and click OK. (MsiLockPermissionsEx will only appear in this list for Orca 5 and later.)
Step 3 – Install the Software.
In order to use the standard Windows tools to set permissions on application objects, the application must be installed.
Step 4 – Use Regedit to Set Registry Permissions.
Select the desired application key and edit the permissions. By default the permissions you apply will apply to the registry key and and will be inherited by sub-keys created by Windows Installer during the install.
Step 4 – Granting Authenticated Users Full Control.
In this example we will simply give Authenticated Users full permissions.
Step 5 – Copy the Key name Before Leaving Regedit.
Step 6 – From An Elevated CMD Prompt Run CSI_GetSDDLFromObject.vbs
Step 7 – At The Prompt, Paste in the Registry Key Name and Click OK.
Step 8 – When the SDDL Displays, Press CTRL-C to Copy It.
Leave the script display window up as you may need to copy the SDDL again.
Step 6 – In Orca Click the Registry Table and Locate a Reference To the Key.
For the located row, write down the value in the "Registry” column. IMPORTANT: This value is case sensitive.
If there are a lot of registry keys, select Edit > Find and type in the name of the key WITHOUT the hive (first part). If there is more than one value being set in that key, there will be more than one reference to it in the Registry table. You can pick any of them, however, be careful to reference the SAME Registry table row in future updates.
Step 7 – Click the MsiLockPermissionsEx Table and from the Main Menu Bar Select Table > Add Row.
Step 8 – Using Windows Explorer to Set Permissions on the Program Files Folder for Authenticated Users to Have Full control
Step 9 – Run CSI_GetSDDLFromObject.vbs (elevated) and Specify the Folder Name.
Step 10 – Use CTRL-C to Copy The SDDL Permissions String
STEP 11 – Find the Directory Table Key of A Component That has Files That Will Be Copied to The Program Files Folder
Step 12 – Add a Row to the CreateFolder Table
Step 13 – Ensure CreateFolders Standard Action is In the InstallExecuteSequence Table.
Step 14 – Add a MsiLockPermissionsEx Table Row
By default the permissions you apply will apply to the folder and all files within it and will be inherited by all files and folders created by Windows Installer during the install.