NSIS Access Control problem with built-in users group

I was dealing with a subtle issue recently involving setting access permissions using NSIS (Nullsoft Scriptable Install System). In the end, it turned out that the problem was not with NSIS at all. Rather, it was a misunderstanding on our part regarding an unexpected quirk in Windows. However, hopefully this post will help anybody who encounters a similar issue.

Our installer was supposed to enable read/write permissions for all users on certain important files and registry keys. However, some users were finding these files/keys were not accessible, and it was preventing the software from working correctly.

Language barrier

We eventually realised that the affected users were all running Windows 7 systems which had been setup in a language other than English. The file permissions were being set like this:

AccessControl::GrantOnFile "$INSTDIRfile.foo" "BUILTINUSERS" "GenericRead + GenericWrite"

Older versions of our installer had previously specified user group “(BU)” instead of “BUILTINUSERS”. However, the “(BU)” only works on Windows XP. As such, it had been changed to “BUILTINUSERS”, which seemed to work on Windows XP, Vista, 7, and 8.

Unfortunately, it turns out that “BUILTINUSERS” is a localised string, meaning it’s in whatever language was used when Windows was originally installed on the system. That means that specifying it in English in the installer script will fail on non-English systems. In retrospect, that’s probably very obvious to anybody who administers Microsoft systems on a daily basis, but it took us by surprise.

Security Identifiers

The correct approach is to use the newer security identifiers (SID’s), which are not localised; i.e. they are the same no matter what the original system language is. According to Microsoft’s documentation, the equivalent SID for the built-in users group is: “(S-1-5-32-545)”.

The reason we didn’t originally use that was because it’s not supported by Windows XP, which is still being used by several of our long-standing customers. Our assumption was that trying to set a file permission using an unsupported security identifier could cause installation problems.

As it happens, that’s not the case. Based on our testing, the worst that seems to happen is that the individual file permission command silently fails, and the installer moves on without any problem.

The Solution

The simplest (and frankly the most obvious) way to support Windows XP and Vista onwards in a single installer is to use both types of language-independent user group identifier. For example, instead of the “BUILTINUSERS” line shown earlier, we now have these two lines:

AccessControl::GrantOnFile "$INSTDIRfile.foo" "(BU)" "GenericRead + GenericWrite"
AccessControl::GrantOnFile "$INSTDIRfile.foo" "(S-1-5-32-545)" "GenericRead + GenericWrite"

So far, that appears to work correctly, supporting users on Windows XP and on Windows Vista etc.. We haven’t observed any side effects from setting the permissions twice, or from either one failing on other OS versions.

One comment on “NSIS Access Control problem with built-in users group

  1. Using a SID like “(S-1-5-32-545)” should work on all NT systems but they are a bit hard to remember. Support for SDDL strings like “(BU)” really started in Win2000 and each version of Windows have added more of them.

    AccessControl v1.0.8.0 and later should support AN, AU, BA, BU, IU, SY and WD all the way back to NT4 because it has a internal mapping for those now.

Leave a Reply

Your email address will not be published. Required fields are marked *