Storing User Settings - c#

Environment.SpecialFolder.CommonApplicationData
*returns "C:\Documents and Settings\All Users\Application Data" under XP that is
writeable for all users
*returns "C:\ProgramData[MyApp]\" under Vista and this is not writeable for regular users
Now why i want CommonFolder ?
Because, an admin will install my software database on XP (or vista) under Admin account, but when user logs back and run my software, the current account will tel my software to look at a different place the database was installed : the user directory in Documents and settings....
so AllUsers (common folder) is common to admin and regular non admin user..
This drives me crazy : where to put my database so it works under Vista and XP ?????
thanks
Jonathan

User-specific settings should be stored in the User's application data folder (Environment.SpecialFolder.ApplicationData) , so that if multiple users log in to the machine they each get their own settings. Create a default user-settings db for the program in the program's main folder at install time and copy it to a user's folder the first time that user runs the program (you'll know it's the first time because the db file won't exist yet).
If you have settings that should apply to all users on the machine, you want those settings to be set by an administrator, and you want them protected from casual change. Storing these in a place where normal users don't have write access is a good thing.

Are you using an installer to have the admin run? If so, you should be able to use the installer settings, plus a proper assembly/executable manifest to allow the application (regardless of who is running it) the proper permissions to update/modify files in the ProgramData specific to their application.
I run a similar scenario (application installs to Program Files, common data repository installs to ProgramData, user config,save files store to C:\Users) and the manifest and the settings in the WiX installer allowed this to work.

Vista is set up such that files saved from one user's account cannot
be modified from another user's
account. This enforces isolation
between one user account and another,
as well as protects settings/files
that affect the state of the entire
system.
Your program should indeed install
whatever machine-wide state it needs
in ProgramData at install time - this
folder is shared between all user
accounts; however, it is a read-only
type of shared . Administrator
privileges are needed to modify these
files if the current user did not
create them because they affect the
entire computer, not just the current
user account.
In accordance with this policy, the
security on the ProgramData folder is
as follows:
System: Full Control over files &
folders Administrators: Full Control
over files & folders Creator/Owner:
Full Control over files & folders
Users: Read Only for files, but can
create new folders and files
What this accomplishes is that it
allows any user to read and create a
folder/file anywhere inside the
ProgramData folder, but the user can
only modify the files that were
created from their user account; they
cannot modify files created from
another user account.
The only exception that I know of to
this policy is the c:\users\public
folder, which is designed to allow
users to store documents and such that
they want to be world read/writable.
From here. Looks like someone else had the same problem.

Can you make use of the IsolatedStorageFile.GetMachineStoreForApplication and IsolatedStorageFile.GetUserStoreForApplication methods?
My apologies if I have misunderstood your question.

where to put my database so it works under Vista and XP
If this database is a SQL Express data file or other shared resources it needs to be in a loocation that the server process's account can read/write.
returns "C:\ProgramData[MyApp]\" [corrected typo] under Vista and this is not writeable for regular users
Not according to a quick check at the ACL here (actually Win2k8):
PS C:\ProgramData> get-acl . | select -expand access
[...]
FileSystemRights : ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : BUILTIN\Users
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : Write
AccessControlType : Allow
IdentityReference : BUILTIN\Users
IsInherited : False
InheritanceFlags : ContainerInherit
PropagationFlags : None
Note the last to ACEs, normal users do have write access, but only to folders and the files they contain, not to files directly in C:\ProgramData.
However if a user creates a folder in C:\ProgramData then other users will not have write permissions.
Answer: Create folder under ProgramData for your database, and set the ACL on that folder to give all users read & write access to files in that folder.

Related

How can I create a protected directory that I can guarantee has only been modified by a specific user?

I am developing a .NET Windows Service using C# that runs as the SYSTEM user so that it has permissions to install software updates etc.
I want the service to download an executable file to a protected directory and launch it. However, I want to make sure that I've considered security and that it isn't possible for another user to copy a file into the directory that the service uses and then have the file executed with SYSTEM privileges.
I've looked into creating a directory that only the SYSTEM user has access to using an ACL as follows.
var localSystemIdentifier = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
var directorySecurity = new DirectorySecurity();
directorySecurity.AddAccessRule(new FileSystemAccessRule(localSystemIdentifier, FileSystemRights.FullControl, AccessControlType.Allow));
directorySecurity.SetOwner(_localSystemIdentifier);
Directory.CreateDirectory(_pathToTempBootstrapperDirectory, directorySecurity);
Subsequent to this, I check that the owner of the directory is the SYSTEM user before I allow a cached copy of the executable file that has been downloaded to be used.
var acl = Directory.GetAccessControl(_pathToTempBootstrapperDirectory);
if (acl.GetOwner(typeof(SecurityIdentifier)) != localSystemIdentifier)
{
cache = false;
}
However, if a user with the right permissions was able to change the owner of the directory to themselves, copy in a file, and then change the owner back to the SYSTEM user, the above check would not be of any benefit.
Perhaps the only option is to always recreate the download folder with the strict ACL and redownload the file every time to prevent the possibility of the scenario above.
In short, my question is as follows; is there a way that I can create a protected directory that I can guarantee has only ever been created or modified by the SYSTEM user?
if a user with the right permissions was able to change the owner of the directory
If a user has administrative permissions he/she can just do whatever he/she wants without the help from your program. Raymond Chen calls this the "airtight hatchway", i.e. you need to protect against a user doing things he/she would not otherwise be allowed to, but there is no reason to protect against things the user already have permission to do.
I'm not an expert in windows permissions, but think that taking over ownership of a directory owned by SYSTEM requires admin permission.

Treesize can see folders and files it doesn't have access to

I have an issue with a program that I’m running on one of my work machines.
Treesize pro is a program that will scan an area (C:\, \\nasdrive\home, etc.) and give you a tree-view as well as other information on the area.
now I run this program on an account that has admin privileges and when I lunch it give the user account control pop up.
However if I search an area my admin account does not have access to (there are a few) it will work fine and show me all the info for the files, folder, size, modified and creation dates. I cannot open the files but I can see their names and go into subfolders. If I try this in explorer, I will get access denied.
I tried to do this with a script that I wrote it C# however if I try and do a Directory.getDirectories(); and Directory.GetFiles(); but even if I run my program as admin (right click run as admin) it will just give access denied command in the Catch block.
I really would like to know how Treesize is managing to list folders, sub-folders, and files that my account does not have access to.
Thanks
TreeSize reads the data through the NTFS backup API (see https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/back-up-files-and-directories ).
From the notes from treesize:
https://manuals.jam-software.de/treesize/EN/notesonntfs.html
Access Control Lists
The way users can access files and folders can be restricted. One can grant or deny other users or groups certain rights [...]. That way one can even deny administrators to access files and folders. If an administrator tries to access a folder in the Windows Explorer to which the owner denied any other users reading access, an "Access Denied" error message will be displayed. However, TreeSize is able to scan such folders, if you are logged in as administrator or as a user that has the right to perform backups (This option can be changed at "Control Panel > Administrative Tools > Local Security Policy" and with the user editor of Windows).
An in-depth look into the access rights can be found in https://learn.microsoft.com/en-us/windows/win32/fileio/file-security-and-access-rights
The SE_BACKUP_NAME and SE_RESTORE_NAME access privileges were specifically created to provide this ability to backup applications. If these privileges have been granted and enabled in the access token of the backup application process, it can then call CreateFile to open your file or directory for backup, specifying the standard READ_CONTROL access right as the value of the dwDesiredAccess parameter. However, to identify the calling process as a backup process, the call to CreateFile must include the FILE_FLAG_BACKUP_SEMANTICS flag in the dwFlagsAndAttributes parameter. This will allow the backup application process to open your file and override the standard security checking.
HANDLE hFile = CreateFile( fileName, // lpFileName
READ_CONTROL, // dwDesiredAccess
0, // dwShareMode
NULL, // lpSecurityAttributes
OPEN_EXISTING, // dwCreationDisposition
FILE_FLAG_BACKUP_SEMANTICS, // dwFlagsAndAttributes
NULL ); // hTemplateFile
You can find more information on
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-backupread
https://learn.microsoft.com/en-us/windows/win32/backup/creating-a-backup-application

Read/Write Application Settings in C#.NET project

I need to save informations (db password) permanently in my project via an .aspx file. I found the Application Settings to store the password but other users can not access my values.
For example:
Setting db_password has the value oldPassword
Administrator (User A) changes the database password to newPassword. It is stored into the Applicatoin settings via: Properties.Settings.Default["db_password"] = tb_testSettingPassword.Text;
Saving: Properties.Settings.Default.Save();
Administrator (User A) see the changed value: lt_testSettingPassword.Text = System.Convert.ToString(Properties.Settings.Default["db_password"]);
User B (no administrator) accesses the page and want to get informations from the database. He needs to connect via the password that user A has saved but I still gets the value oldPassword.
How can I store the value for all users?
Settings stored with Properties.Settings.Default are stored in the current users own application data folder (%USERPROFILE%\AppData under Vista and above).
If you want to have a config file easily accessible to all users you should store it at System.Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData).
That line will give you the path to the common AppData folder (C:\ProgramDAta under Win7), where all users will have read and write access.
In there you should create a folder for your application and then create your config file in that folder.
If you need help creating folders and files there are multiple questions and answers on SO that should help you out.

WPF app writes files/data into "C:\ProgramData" but fails to write into other folders

We have developed WPF application which allows user to select folder path. WPF application writes files/data into this selected path. When we select "C:\ProgramData" as the path, it creates the file and write the data. But when the path is other than "C:\ProgramData", file is generated but data is not written into the file and it seems a permission issue. Can anybody help us in finding out , how we can assign the same kind of permission to selected folder same as "C:\ProgramData" so that it allows to write data into the file. In conclustion what is the extra permission does "ProgramData" has which is not their for other folders?
Note: it only works properly with ProgramData folder.
Whenever your application is launched with standard user rights, it can write to only those folders to which a standard user can write to. E.g. are:
C:\Users\USERNAME\
C:\ProgramData\
D:\
It will not be able to write to folders like:
C:\
C:\Users\SOME_OTHER_USERNAME\
c:\Windows
C:\Windows\System32 etc
For that you either need to disable UAC or launch the application with administrative permissions.
I would suggest that whenever user selects a folder from your application check if you can create a file/ folder in that location before accepting the path.
solution what i can give is let's user select the path after you get the folder path just check whether you can write data to it , see this code
bool HasAccessToWrite(string path)
{
try
{
using (FileStream fs = File.Create(Path.Combine(path, "Access.txt"), 1, FileOptions.DeleteOnClose))
{
}
return true;
}
catch
{
return false;
}
}
#Ganesh is right but you may go with one of the following options:
Run the installer with admin rights, ask user to select target folder during installation and set the permissions to everyone or required groups of users/roles.
If above is not applicable then configure your application to always run under admin account, in that way it will have access to all folder to write data. To configure run as admin user application manifest as explained here:
Turn off UAC, not a recommended approach though.
I had same issue so, I forced installer to be run under admin rights and asked user to create target folders during installation. Used a custom action to set full rights for everyone user group on the target folder. Since security was not issue for us so, it was ok to allow everyone but consider your environment before using this option.

C# Application can't read/write to files created by administrator when run in limited user account XP

I have an application that is useable by all users (admin or limited) in .NET (C# specifically).
When the application first launches - it creates a few files that it needs in the C:\Documents and Settings\All Users\Documents\ for all subsequent launches.
If the limited user in XP is the FIRST user to launch the application it creates the files fine and both the limited user and administrators can run fine.
However if the Administrator (or I am guessing a different limited user) is the first to launch the application then the limited user is NOT able to run the application.
The two files that it is NOT able to read/write to if created by an Administrator is a Log4Net log file and a SQLite db file.
The SQLite database file is being created with a straitforward .NET File.Copy(sourcepath, destinationpath). The sourcepath is a seed database file installed with the application - so on first run it copies that from the C:\Program Files\app install\seed.db
Is there a way to set the permissions on the file when I copy it? File.SetAccessControl() perhaps? I am not clear on how that works.
The other issue is that the log4Net rolling file appender will not roll the old file and create a new as the old file was created by the admin user when they ran the app.
Any ideas? Ironically this all works perfectly fine in Vista with limited/admin accounts - this is ONLY happening in XP with admin/limited accounts.
I think SetAccessControl is the way to go. Maybe something like this:
// get the existing access controls
FileSecurity fs = File.GetAccessControl(yourFilename);
// add the new rule to the existing settings
fs.AddAccessRule(new FileSystemAccessRule(
#"DOMAIN\Users", // or "BUILTIN\Users", "COMPUTER\AccountName" etc
FileSystemRights.Modify,
AccessControlType.Allow));
// set the updated access controls
File.SetAccessControl(yourFilename, fs);
Note: It's important that you get the existing access control list from the file and then add your new rule to that. If you just create a new access control list from scratch then it will overwrite the existing permissions completely.
Yeah, it's the SetAccessControl method all right, there is a good example here
(the post from satankidneypie)
Good luck

Categories