2

The Wix source code that I feed to the Wix compiler to build an MSI package for my application, contains the following PermissionEx directive, part of a file component which Windows Installer should install with additional (to those that should be inherited by default) permissions:

<PermissionEx Sddl="D:AR(A;;FW;;;BU)" />

As you can surmise, I intend to install the file with inherited permissions ("AR") included in its ACL and on top of that allow members of the Built-in Users group ("BU") to be allowed ("A") to write to the file ("FW").

The code above does not have the desired effect -- the file is installed, but only that single explicit ACE is listed, none of the ACEs that are supposed to be inherited from parent folder.

In contrast, if I subsequently remove all permissions from the file and run cacls file /S:D:AR(A;;FW;;;BU), i.e. specify exactly the same SDDL string, it does work as intended -- the permissions from parent are inherited and form part of the ACL, together with the explicit non-inherited ACE.

I am using Wix 3.11.1.2318 and the Windows Installer version is 5.0.16299.611, all running on Windows 10 Enterprise 64-bit. Orca tells me the MsiLockPermissionsEx table embedded in my built MSI file is populated with the intended SDDL record. So why is the file created without inheriting permissions from its containing folder?

I tried to use "AI" in place of "AR", and both strings together, but none of it had any effect either.

Is this some known limitation or a quirk with Windows Installer? I know that people were talking a while back how the old LockPermissions table (the one specified for Windows Installer versions earlier than 5) was inadequate in this specific regard -- inherited permissions, namely -- but they also said Microsoft was out to address this very issue with the new table feature.

Otherwise what am I doing wrong?

Armen Michaeli
  • 8,625
  • 8
  • 58
  • 95
  • 1
    [Maybe have a quick skim here for context](https://stackoverflow.com/a/55124447/129130). Will have a further look soon. – Stein Åsmul Mar 13 '19 at 18:36

2 Answers2

4

Given your knowledge in this field, you probably have already tried this. It would also be much better to eliminate the need for permissioning, but two snippets for you - notice the Append attribute:


Create a WiX project in Visual Studio. Add the Util namespace to the WiX element:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
     xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">

In Visual Studio project, right click References and add reference to "%ProgramFiles(x86)%\WiX Toolset v3.11\bin\WixUtilExtension.dll".


Permission Folder:

<Component Feature="ProductFeature" Id="Test.exe" Guid="PUT-GUID-HERE">
   <File Source="C:\Test.exe" />
   <CreateFolder>
     <util:PermissionEx User="Power Users" GenericWrite="yes"  />
   </CreateFolder>
</Component>

Permission File:

<Component>
   <File Source="C:\Test2.exe">
      <util:PermissionEx Append="yes" User="Users" GenericWrite="yes" />
    </File>
</Component>
Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
2

Take a look at WiX's custom PermissionEx in the Util extension.

http://wixtoolset.org/documentation/manual/v3/xsd/util/permissionex.html

Christopher Painter
  • 54,556
  • 6
  • 63
  • 100
  • Did they write that extension because `MSILockPermissionsEx` is buggy? – Armen Michaeli Mar 14 '19 at 11:28
  • 1
    I believe they wrote it before MSILockPermissionsEx because LockPermissions was buggy. Also MSILockPermissions was an MSI 5.0 only thing and wasn't available on downlevel systems. It's hard for me to remember some of the history / trivia over the past 20 years so I'd have to go search the archives to give an official answer. But there are certainly certain MSI features that just aren't used anymore because of buggy issues such as Concurrent/nested installs, third party merge modules, COM tables vs registry table, chained installs, delta patches, LockPermissions and so on. – Christopher Painter Mar 14 '19 at 11:34
  • 1
    Great list Chris. I wish one of those elements would be called PermissionEx2 or something like that (like some Win32 APIs). Problematic MSI constructs? I would add per-user setups, install from source, and also GUI for being so clunky that people replace it. I don't like this content (very ad-hoc), but [here is my list of common MSI pitfalls](https://stackoverflow.com/q/45840086/129130). And [some borderline anti-patterns](https://stackoverflow.com/a/1055861/129130) (towards bottom). Please avoid permissioning if you can. [Some alternatives](https://stackoverflow.com/a/50588465/129130). – Stein Åsmul Mar 14 '19 at 12:32
  • 1
    I found an [article](https://support.microsoft.com/en-us/help/266461/how-to-use-adsi-to-set-automatic-inheritance-of-file-folder-permission) that hinted at different behavior when security information is set on an object with the now obsolete `SetFileSecurity` procedure vs using its intended replacement (as per Microsoft doc.), `SetNamedSecurityInfo`, where the former does not result in inherited ACEs being included. I wrote a program as an attempt to see if there is truth to it, which it seems there is -- https://gist.github.com/amn/e0553d80f93620909247ea91d94f9f83 – Armen Michaeli Mar 14 '19 at 12:42
  • What I have found suggests to me that Windows Installer uses at least one obsolete security procedure, which is why, despite their own documentation (deferred with the link to SDDL format), the SDDL string that goes through the Wix compiler does not result in inherited ACEs. Basically, WI has a bug. Everything else can be seen as an attempt to circumvent that issue. – Armen Michaeli Mar 14 '19 at 12:44
  • That wouldn't surprise me. Are you up for a design review of why you need to do this? When you say that you want users to be able to write to a file being installed I wonder why? What kind of file is it? What happens when you upgrade? Do you want to keep the file, replace the file, merge the file? I try to keep my installer files/folders and user files/folder apart from each other. For example I might create a [CommonAppData\Company\Product\Logs directory and open the permissions on that folder if needed. But I don't like users writing anything to [ProgramFilesFolder]. – Christopher Painter Mar 14 '19 at 12:51
  • @ChristopherPainter Yes, the WI issue aside, I should consider a better location for the log file (right now in `%ProgramData%\foobar`) where I won't have to set permissions explicitly. Wait, doesn't `CommonAppData` refer to the same folder as `%ProgramData%`? I _am_ keeping my software runtime and it's data/artefacts separate. – Armen Michaeli Mar 14 '19 at 13:02
  • Windows Installer [CommonAppDataFolder] is Environment.SpecialFolder.CommonApplicationData which is %ProgramData% which is C:\ProgramData on most modern OS. It used to be something like C:\Documents and Settings\All Users\Program Data\ but my memory fades as the decades go by. – Christopher Painter Mar 14 '19 at 13:39
  • `[CommonAppData]` is a great choice for this sort of thing. And you are on the right track, you just need to get the SDDL correct or use util:PermissionEx Christopher Painter's memory is also correct that util:PermissionEx came before MsiLockPermissionsEx and we debated what to do with the names when Windows Installer added MsiLockPermissionsEx. We ended up where we ended up. – Rob Mensching Mar 14 '19 at 13:49
  • @RobMensching Thank you for your input and thank you for the effort with Wix toolkit. I see now that the default permissions in Windows 10 for %ProgramData% only allow creator of a file undernearth to write file's data. Meaning that I can't get away with just creating a multi-user log file there without adding an explicit ACE to the file, in addition to inherited ACEs. All of which I am unable to do. Seems like regardless history and software faults, my practical options are dwindling. I'll have to use Wix extension features or custom actions or somehow wriggle out of this one another way. – Armen Michaeli Mar 14 '19 at 14:01
  • 1
    @amn It should be possible to set the ACL on the new folder to allow writes to the folder with inheritance using util:PermissionEx (IIRC, it always respects inheritance). I expect there is a way to do it with SDDL as well but my SDDL-fu is quite rusty at this time. Best of luck. – Rob Mensching Mar 14 '19 at 22:29
  • I did use `util:PermissionEx` in the end, as the preferred method did not work -- this is simply an artefact of how WI 5.0 is implemented and nothing was done since. With MSIX already having made an entrance, we can only hope WI will continue to develop but I am not holding my hopes up. Also, there is nothing wrong with the original SDDL string -- it works exactly as intended with `cacls` and directly through the use of `SetNamedSecurityInfo` as demonstrated with the program I shared the source code of with the link in a previous comment. Just wanted to share my conclusions with this comment. – Armen Michaeli Apr 08 '19 at 19:03
  • MSIX isn't replacing MSI. MSI needs improvements... they aren't happening. Hence which you have extensions such as util:*. – Christopher Painter Apr 08 '19 at 19:41