How do you set directory permissions in NSIS? - windows

I'm trying to build a Windows installer using Nullsoft Install System that requires installation by an Administrator. The installer makes a "logs" directory. Since regular users can run this application, that directory needs to be writable by regular users. How do I specify that all users should have permission to have write access to that directory in the NSIS script language?
I admit that this sounds a like a sort of bad idea, but the application is just an internal app used by only a few people on a private network. I just need the log files saved so that I can see why the app is broken if something bad happens. The users can't be made administrator.

Use the AccessControl plugin and then add this to the script, where the "logs" directory is in the install directory.
AccessControl::GrantOnFile "$INSTDIR\logs" "(BU)" "FullAccess"
That gives full access to the folder for all users.

AccessControl::GrantOnFile "<folder>" "(BU)" "FullAccess" didn't work for me on a Windows Server 2008 machine. Instead I had to use this one:
AccessControl::GrantOnFile "<folder>" "(S-1-5-32-545)" "FullAccess"
S-1-5-32-545 is equivalent to "Users" according to Microsoft Support: Well-known security identifiers in Windows operating systems.

Instead of changing the permissions on directories under Program Files, why not put the logs in a location that is writeable by all users.
See the 4.9.7.7 SetShellVarContext section in your NSIS documentation. You can use it with $APPDATA to get the application data folder that is writeable for all users.

It's an old issue now but as suggested by Sören APPDATA directory is a nice way to do what you want, the thing is :
Don't take user's personnal APPDATA but the "All Users" APPDATA dir!
This way anyone will be able to access the log file ;-)
Also, I read somewhere that using (BU) on the GrantOnFile is not working well with some systems (Win 7 x64 if I remember well), maybe you should use the SID "(S-1-5-32-545)" instead (it's the All Users' SID, this value is a constant on each Windows OS)

One way: call the shell, and use cacls or xcacls.

Why not create a log-directory in the user's %APPDATA% directory? Do you really need to put all the logs in the install directory? Why?

Related

In Windows is any folder alternative to ProgramData?

I'm writing a desktop app and need a folder which...
Exists in Windows 7 and Vista
Is common to all users (for store config data).
Application can save data on it, without Admin privileges (not like "ProgramData").
is standard (I don't want to create another app specific folder in "C:", the Desktop or other place alike.)
"Program Files" is not an option, of course.
Can you suggest an appropriate folder, or better use the Registry?
The recommended way to do this is to create a folder at install time, dedicated to your application, underneath "ProgramData" (i.e. CSIDL_COMMON_APPDATA/FOLDERID_ProgramData).
As you already know, the CSIDL_COMMON_APPDATA folder is read only for standard users. So your install program needs to give the folder that it creates an ACL that permits the access that you require.
This is the solution that meets all the criteria laid out in your bullet points.
You mention the registry. There is no area of the registry that is shared between all users and yet writeable by standard users. Whilst you can use ACLs to grant more permissive access rights to the registry, it is really not the done thing. Please forget that I even mentioned this possibility!
IF your app is .NET then use CommonApplicationData - you can get the real location by calling GetFolderPath.
EDIT - as per comments:
You need to setup ACL correctly - for sample source code on how to do this see http://www.codeproject.com/Tips/61987/Allow-write-modify-access-to-CommonApplicationData
What about Public User directories? For Example: C:\Users\Public\Libraries or C:\Users\Public\Documents
I've noticed these folder on several of my Windows 7 machines. I'm not sure if it is always there, but might be an option. I was hoping for something like an %appdata% for the Public User, but the closest thing I found was Public\Libraries.
(As a side note, it appears C:\Users\Public\Desktop does require admin to write to.)
what about using %APPDATA%/Company/Product for the directory?

Do applications installed to Program Files have permissions to modify their folder?

If I install my app to program files, will it always be able to create and write files within its install directory? It seems to work in a lot of different versions of windows, but are there situations where this wouldn't work?
Mainly I'm using this approach for logging. If this is not the correct approach, is there a better place to log?
Note: My installer requires Admin privileges to run and it grants Full Access to all users in the install directory.
Apps don't run as users, users run as users. If you install an app into Program Files, and let's assume you needed elevated permissions to do so, when your standard user then runs that app, that is the user that needs permissions.
App is installed with elevated permissions (user: Admin, for example)
All permissions on the AppName folder might well be "Admin:Full, Users:Read"
User runs app, so cannot change any files
At install-time, your installer will need to know which of it's own files need to be made writable to standard users, and set permissions accordingly. Of course, user-data should not be in Program Files anyway. That's what %appdata% and the user profile are for, usually.
If your app has a globalsettings.ini or whatever, that lives in "Program Files\YourApp", then while you have admin permissions (i.e. at install time) you need to grant write permission to all users to that globalsettings.ini file. Or Power Users. Or a group. Or whatever is correct for your app.
In summary, no, users do not have default write-access to ProgFiles, nor should they.
Yes, there are definitely situations where this won't work, such as when your app is running on Windows 7, or if your user account is a limited user.
We always put our log files in a temp directory or a special folder such as AppData.

Is there a shared folder in Windows to which non-elevated users have write access?

I know that commonappdata (All Users) can hold system-wide application settings, but under Vista/7 non-elevated users can't write to that directory.
Is there a folder which is shared among users and any non-admin user can write to it?
Here is why I need this:
My app is installed in PF directory by an Inno Setup installer with elevated rights. Then when the actual non-admin user runs the program, it copies its settings to the user's AppData directory using another non-elevated Inno Setup installer. Upon deinstalling the program (initiated by the system-wide installer with admin rights) I want to uninstall the program's files from each users' AppData directory.
I can think of two solutions:
1. Getting a list of Windows users and iterating through their AppData dirs (seems way too complicated)
2. Storing the paths to the uninstallers in the above mentioned common user data directory.
Any ideas?
Thanks!
"Shared Documents" Directory in Windows XP
C:\Documents and Settings\All Users\Documents
Or,
%ALLUSERSPROFILE%\Documents
Corresponding directory in Vista/7
C:\Users\Public
Or,
%PUBLIC%\Documents
But what you are really looking for, is the KNOWNFOLDERID value of FOLDERID_PublicDocuments (legacy CSIDL_COMMON_DOCUMENTS). The SHGetFolderPath function can then get you the path.
Or an easier VBScript alternative, but I'm not sure how reliable this is across OS versions:
Const CSIDL_COMMON_DOCUMENTS = &h2e
Set oShell = CreateObject("Shell.Application")
Wscript.Echo oShell.Namespace(CSIDL_COMMON_DOCUMENTS).Self.Path
I think NameSpace doesn't accept that particular constant. So you might be able to take COMMONAPPDATA = &H23 and then use its parent. But that's not very clean or internationalized:
Wscript.Echo oShell.NameSpace(&h23).ParentFolder.Self.Path & "\Documents"
But since you are using Inno Setup, you should really be using the {commondocs} Shell Folder Constant and make it easy for yourself.
The user owns the document folder. Expect files to be copied, moved, deleted or edited with another program if you put something there, because of the visibility to the user.
I suggest you to create a folder under the common application data (CSIDL_COMMON_APPDATA or FOLDERID_ProgramData) in your installer with a security descriptor that allows everyone access.
E.g.
[Dirs]
Name: "{commonappdata}\productname";Permissions:everyone-modify;
Would stuff under C:\Users\Public\ qualify for what you need?
Solution 1 looks quite reasonable to me. So every user control their and only their installation, and you control the central shared installation.
For solution 2 you can create a write-allowed folder in a well-defined location so that your installer knows about it, or use a registry key for the same purpose. But keep in mind that this may create a security hole because anyone could tamper with uninstall paths of other users.

Visual Studio Setup Project folder permission

I have a setup project that installs my app to the typical program files directly.
My app periodically saves some temporary images to the apps installation folder. It seems on Vista, the permissions are not setup for write permissions. I can change it manually in windows explorer and it works, but I would rather have the setup project do that automatically.
How can I do this?
Is there a better/more normal place to put temp images that won't have permissions issues?
It is not Vista specific, this will happen with any kind of user account that doesn't have admin privileges. Your program just can't write to folders like c:\program files\blah. That UAC disables admin privileges has been publicized for a long time now. Use Environment.GetFolderPath() to get the path to an ApplicationData folder that you can write to.
See http://msdn.microsoft.com/en-us/library/bb756940.aspx for details on UAC issues for vista. These problems can also occur in other versions of windows when running applications from non-admin accounts. You should only write data to app data or temp directories and not program files.

How to pass security issues in Vista?

I have a vb6 application. I am unable to carry out the following on a Windows Vista machine:
Register a .DLL from the Users directory
Start another .EXE
Write to a file in the Users directory.
How can I overcome these issues?
This is by design. Software is supposed to require admin rights for installation (including update/upgrades). You got away with it in XP because so many people ran as administrator. If you're registering a dll after installation, you're doing something wrong.
You should be able to do this without issue, but only with the same rights as the user that the current app is running under. What is this exe trying to do, and would a standard user normally have those permissions?
What specific folder in the user's directory? Again: a user should have write access to most of the their own profile, but not necessarily as much outside of that as you think.
You have access to write to the c:\users\ directory. Going to another users directory is a bit of a security problem that you're not going to work around.
As far as registering an assembly from a users directory... There is a directory under c:\users\\AppData\Local\assembly which you should have access to for temporary assemblies
Starting another exe is trivial... As long as it's installed in the normal \program files.. path.
It really sounds like maybe you need to reevaluate how your application works.
Some suggestions:
Move to Reg-Free COM where it can handle things (i.e. not for ActiveX EXEs, DCOM).
We'd need more information. This should be no problem unless there are permissions issues.
Users are not supposed to be creating files outside of their own profiles, CommonAppData, and application-defined locations (often on non-system drives). More information is required to give any really useful answer.

Resources