Quick question if anyone happens to know. I'm working on a Worker app in dotnet6 that is intended to be made into a service and I need to store a json file somewhere. Doing some research it seems like CommonApplicationData(ex: "C:/ProgramData") is the place to go. My question is, I can't seem to write a file to that folder. I am able to create a directory just fine. But my access is denied to creating an actual file.
This service will be used on servers in the field right now and cannot answer UAC prompts. I'm unsure what else to do. I can have the file created manually and access, edit it. That seems to work fine. But I'd like to have a logs files dynamically created and more.
Heres the code("its pretty basic")
var dirPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MyServerService");
var path = dirPath + "\\service.json";
var doesDirExist = Directory.Exists(dirPath);
var doesFileExist = File.Exists(path);
if (!doesDirExist || !doesFileExist)
{
Directory.CreateDirectory(dirPath); //<- directory is created just fine
using var file = File.Create(dirPath); // <- fails here (access is denied)
//do stuff
}
This bit of code worked for me. It was indeed a permission issue with the directory being created.
public static bool CreateDirWithAccess(string fullPath, bool readOnly)
{
var dInfo = Directory.CreateDirectory(fullPath);
DirectorySecurity dSecurity = dInfo.GetAccessControl();
dSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), readOnly ? FileSystemRights.Read : FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
dInfo.SetAccessControl(dSecurity);
return true;
}
Related
I 've a Windows Service which writes somes of this parameters in registry.
I want these parameters to be common to any users, means, whatever the Windows Service "RunAs".
Where you'd you recommand to write them?
I tried to write them in SOFTWARE\MyWindowsService\Server but I've permissions issues as you can see in this code.
For example here, I try to read and write in SOFTWARE\MyWindowsService\Server\Key1 and type of Key1 is string (REG_SZ)...
//Get current user for windows Service
_windowsIdentity = WindowsIdentity.GetCurrent().Name;
MessageBox.Show("Try to change registry permissions for" + _windowsIdentity); //==> LocalSystem is my current account
//Get Main windows service registry
_WindowsServiceRegKeys = Registry.LocalMachine.CreateSubKey("SOFTWARE\\THIS_WINDOWS_SERVICE_FOLDER\\SERVER", RegistryKeyPermissionCheck.ReadWriteSubTree);
RegistrySecurity rs = new RegistrySecurity();
rs = _WindowsServiceRegKeys.GetAccessControl();
//Add new permissions
rs.AddAccessRule(new RegistryAccessRule(_windowsIdentity
, RegistryRights.FullControl
, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit
, PropagationFlags.InheritOnly, AccessControlType.Allow));
_WindowsServiceRegKeys.SetAccessControl(rs);
//Try to read a var
object objRetRegistryKeyValue = _WindowsServiceRegKeys.GetValue("Key1"); //ERROR: object is null
_WindowsServiceRegKeys.SetValue("Key1", "Test", RegistryValueKind.String);
Could you help me on this bug?
Thanks and regards,
I am trying to set program's installation folder permissions restricted only to Administrators.
There are two scenarios: the folder needs creation and folder already exists.
Here is my code:
public static void CreatePrivateFolder(string path)
{
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
DirectorySecurity securityRules = new DirectorySecurity();
FileSystemAccessRule fsRule =
new FileSystemAccessRule(sid, FileSystemRights.FullControl,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.None, AccessControlType.Allow);
securityRules.SetAccessRule(fsRule);
if (Directory.Exists(path))
{
Directory.SetAccessControl(path, securityRules);
}
else
{
Directory.CreateDirectory(path, securityRules);
}
}
When the folder needs creation, the CreateDirectory works fine, the folder's permissions restricted only to Administrators.
The strange thing is when I am re-run this code and flow to SetAccessControl - the folder's permissions being reset to regular folder with no restricted access.
What do I'm doing wrong?
Folder security results (for path c:\\folderCheck) :
Update
anrei solution answering my question.
However, it seem to be the same problem in a different way:
If the folder already exists with unrestricted permissions, anrei's code don't seem to be work.
The folder's permissions remain unrestricted.
Thanks!
Use this instead of your if (Directory.Exists(path)) block.
// what is
var existingACL = Directory.GetAccessControl(path);
// remove everything from what is
foreach (FileSystemAccessRule rule in existingACL.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
existingACL.RemoveAccessRuleAll(rule);
// add yours to what is
existingACL.AddAccessRule (fsRule);
// set again
Directory.SetAccessControl(path, existingACL);
I have an C# network application that prompts admins for network proxy authentication information. I ask the user if they want to save this information, which if they choose yes, I encrypt in a unique local file for the user. I would then like to remove all file permissions except the user that created it, but all other users to have the ability to delete the file.
Now, I found MS article below, but it's not helping if I don't know the default users that were setup on the file in the first place. Is there a remove all file permissions? I can then add the individual rights I'm wanting to setup for full access by current user and delete permissions for "All Users" or "Authenticated Users", which looks to be different depending on version of Windows.
http://msdn.microsoft.com/en-us/library/system.io.file.setaccesscontrol.aspx
I figured it out..
public void SetFileSecurity(String filePath, String domainName, String userName)
{
//get file info
FileInfo fi = new FileInfo(filePath);
//get security access
FileSecurity fs = fi.GetAccessControl();
//remove any inherited access
fs.SetAccessRuleProtection(true, false);
//get any special user access
AuthorizationRuleCollection rules = fs.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
//remove any special access
foreach (FileSystemAccessRule rule in rules)
fs.RemoveAccessRule(rule);
//add current user with full control.
fs.AddAccessRule(new FileSystemAccessRule(domainName + "\\" + userName, FileSystemRights.FullControl, AccessControlType.Allow));
//add all other users delete only permissions.
fs.AddAccessRule(new FileSystemAccessRule("Authenticated Users", FileSystemRights.Delete, AccessControlType.Allow));
//flush security access.
File.SetAccessControl(filePath, fs);
}
If you need to remove for the specific group , you can use this method ;
public static void RemoveGroupPermission(string path, string group_name)
{
long begin = Datetime.Now.Ticks;
DirectoryInfo dirInfo = new DirectoryInfo(path);
DirectorySecurity dirSecurity = dirInfo.GetAccessControl();
dirSecurity.RemoveAccessRuleAll(new FileSystemAccessRule(Environment.UserDomainName +
#"\" + group_name, 0, 0));
dirInfo.SetAccessControl(dirSecurity);
long end = DateTime.Now.Ticks;
Console.WriteLine("Tick : " + (end - begin));
}
Impersonation may be help you to solve this out.
The term "Impersonation" in a programming context refers to a technique that executes the code under another user context than the user who originally started an application, i.e. the user context is temporarily changed once or multiple times during the execution of an application.
click Here to see implimentation
I was trying to give NTFS permissions on a UNC path for a specific user, but I see different behavior depending on the UNC path. Below is the code (from MSDN) which I am using to give permissions and the result in each scenario,
static void GiveNTFSPermissions(string folderPath,
string ntAccountName,
FileSystemRights accessRights)
{
DirectorySecurity dirSecurity = Directory.GetAccessControl(folderPath);
FileSystemAccessRule newAccessRule =
new FileSystemAccessRule(
ntAccountName,
accessRights,
AccessControlType.Allow);
dirSecurity.AddAccessRule(newAccessRule);
Directory.SetAccessControl(folderPath, dirSecurity);
}
Suppose I have a share named “RootShare” on my local machine, and another folder “InsideRootShare” inside it.
Scenario1:
When I call,
GiveNTFSPermissions(#"\\sri-devpc\RootShare",
#"domain\username",
FileSystemRights.Write);
Inherited permissions were lost on the shared path,
Scenario2:
When I call,
GiveNTFSPermissions(#"\\sri-devpc\RootShare\InsideRootShare",
#"domain\username",
FileSystemRights.Write);
Inherited permissions were intact.
I have tried with different constructors of FileSystemAccessRule but no luck.
What is the reason behind this behavior, and any workaround for this?
We ran into similar issues working with file system permission while working on Dropkick's security module. The solution we came up with is as follows. This will successfully set permissions on any folder without changing the inheritance rules on the folder.
public void SetFileSystemRights(string target, string group, FileSystemRights permission)
{
if (!IsDirectory(target) && !IsFile(target))
return;
var oldSecurity = Directory.GetAccessControl(target);
var newSecurity = new DirectorySecurity();
newSecurity.SetSecurityDescriptorBinaryForm(oldSecurity.GetSecurityDescriptorBinaryForm());
var accessRule = new FileSystemAccessRule(group,
permission,
InheritanceFlags.None,
PropagationFlags.NoPropagateInherit,
AccessControlType.Allow);
bool result;
newSecurity.ModifyAccessRule(AccessControlModification.Set, accessRule, out result);
if (!result) Log.AddError("Something wrong happened");
accessRule = new FileSystemAccessRule(group,
permission,
InheritanceFlags.ContainerInherit |
InheritanceFlags.ObjectInherit,
PropagationFlags.InheritOnly,
AccessControlType.Allow);
result = false;
newSecurity.ModifyAccessRule(AccessControlModification.Add, accessRule, out result);
if (!result) Log.AddError("Something wrong happened");
Directory.SetAccessControl(target, newSecurity);
if (result) Log.AddGood("Permissions set for '{0}' on folder '{1}'", group, target);
if (!result) Log.AddError("Something wrong happened");
}
Found the link that I originally used to figure this out.
I am creating an XML file in the common application folder using C#:
%ALLUSERSPROFILE%\Application Data\
File will be created when application is installed. This file is something that is common to all the users of the local machine.(i.e it contains some setting information)
But my problem is when the file is created by an admin user(i.e application is installed by an admin user) the other users don't have write access to the file. When I checked the attributes of the file, it has given only 'read and execute' is given to other users.
I am using below code to save the file
XDocument.Save(filePath);
Is it possible to create file with write access given to all users? Any help much appreciated!
You can't pass information about ACL into XDocument.Save method, but you can modify permissions of file after saving your xml document. You can use the following code to perform it (don't forget to add reference to System.Security.dll):
using System.Security.AccessControl;
using System.Security.Principal;
using System.IO;
public class FileAccessRulesHelper
{
public void AddWriteRightsToEveryone(string filename)
{
// get sid of everyone group
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
// create rule
FileSystemAccessRule rule = new FileSystemAccessRule(sid, FileSystemRights.Write, AccessControlType.Allow);
// get ACL of file
FileSecurity fsecurity = File.GetAccessControl(filename);
// modify ACL of file
fsecurity.AddAccessRule(rule);
// apply modified ACL to file
File.SetAccessControl(filename, fsecurity);
}
}
I don't think you can pass a parameter to XDocument.Save to control the permissions but you should be able to set them after the save. Something like the following should do:
System.Security.AccessControl.FileSecurity fsec = System.IO.File.GetAccessControl(fileName);
fsec.AddAccessRule( new System.Security.AccessControl.FileSystemAccessRule("Everyone", System.Security.AccessControl.FileSystemRights.Modify, System.Security.AccessControl.AccessControlType.Allow));
System.IO.File.SetAccessControl(fileName, fsec);
I had a similar problem with a service install. You can use the following code to give a folder different permissions.
public static void CreateWithFullAccess(string targetDirectory)
{
try
{
if (!Directory.Exists(targetDirectory))
{
Directory.CreateDirectory(targetDirectory);
}
DirectoryInfo info = new DirectoryInfo(targetDirectory);
SecurityIdentifier allUsersSid =
new SecurityIdentifier(WellKnownSidType.LocalServiceSid,
null);
DirectorySecurity security = info.GetAccessControl();
security.AddAccessRule(
new FileSystemAccessRule(allUsersSid,
FileSystemRights.FullControl,
AccessControlType.Allow));
info.SetAccessControl(security);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.ToString());
}
}