Make file not moveable, copyable or deleteable? [closed] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I here from CodeProject, but they don't seem to have an answer to my question. I just want a desktop file to have security permission(make the file not moveable, copyable or deletable). This is possible to do manually in the file's "properties!. I am using C#, your help is much appreciated - thanks!
As a helper said below, if it is not possible to make a readable file uncopyable...is it possible to make it not moveable and deletable?

All these things are possible EXCEPT being uncopyable. Readable files can always be copied unless you restrict ALL copying on the system (which is a formidable task). However you can certainly prevent it from being moved or deleted.
From a file permissions perspective, you need to set the owner to an administator, then grant read-only permissions to the user in question. This will allow them to read the file but not delete or move it.
Doing so is quite simple using the FileInfo.SetAccessControl method in System.IO; here's the documentation to help out.
Edit to add example, credit to MS for the example:
using System;
using System.IO;
using System.Security.AccessControl;
namespace FileSystemExample
{
class FileExample
{
public static void Main()
{
try
{
string FileName = "c:/test.txt";
Console.WriteLine("Adding access control entry for " + FileName);
// Add the access control entry to the file.
// Before compiling this snippet, change MyDomain to your
// domain name and MyAccessAccount to the name
// you use to access your domain.
AddFileSecurity(FileName, #"MyDomain\MyAccessAccount", FileSystemRights.ReadData, AccessControlType.Allow);
Console.WriteLine("Removing access control entry from " + FileName);
// Remove the access control entry from the file.
// Before compiling this snippet, change MyDomain to your
// domain name and MyAccessAccount to the name
// you use to access your domain.
RemoveFileSecurity(FileName, #"MyDomain\MyAccessAccount", FileSystemRights.ReadData, AccessControlType.Allow);
Console.WriteLine("Done.");
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
// Adds an ACL entry on the specified file for the specified account.
public static void AddFileSecurity(string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
{
// Create a new FileInfo object.
FileInfo fInfo = new FileInfo(FileName);
// Get a FileSecurity object that represents the
// current security settings.
FileSecurity fSecurity = fInfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
fSecurity.AddAccessRule(new FileSystemAccessRule(Account,
Rights,
ControlType));
// Set the new access settings.
fInfo.SetAccessControl(fSecurity);
}
// Removes an ACL entry on the specified file for the specified account.
public static void RemoveFileSecurity(string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
{
// Create a new FileInfo object.
FileInfo fInfo = new FileInfo(FileName);
// Get a FileSecurity object that represents the
// current security settings.
FileSecurity fSecurity = fInfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
fSecurity.RemoveAccessRule(new FileSystemAccessRule(Account,
Rights,
ControlType));
// Set the new access settings.
fInfo.SetAccessControl(fSecurity);
}
}
}

Related

Remove all default file permissions

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

%AllUsersProfile%(%PROGRAMDATA%) gives a repetitive file path

I have an application written in C#, and I am seeking to write some information to the hidden ProgramData in order to access the same connection string from both the application's front end and back end.
I am accessing the directory using path variables as follows:
private bool ProgramDataWriteFile(string contentToWrite)
{
try
{
string strProgramDataPath = "%PROGRAMDATA%";
string directoryPath = Environment.ExpandEnvironmentVariables(strProgramDataPath) + "\\MyApp\\";
string path = Environment.ExpandEnvironmentVariables(strProgramDataPath)+"\\MyApp\\ConnectionInfo.txt";
if (Directory.Exists(directoryPath))
{
System.IO.StreamWriter file = new System.IO.StreamWriter(path);
file.Write(contentToWrite);
file.Close();
}
else
{
Directory.CreateDirectory(directoryPath);
System.IO.StreamWriter file = new System.IO.StreamWriter(path);
file.Write(contentToWrite);
file.Close();
}
return true;
}
catch (Exception e)
{
}
return false;
}
This seems to work correctly. However, my question is, when I used this path variable: %AllUsersProfile%(%PROGRAMDATA%)
instead, it expanded into an illegal(and redundant) file path : C:\ProgramData(C:\ProgramData)\
However, I thought that the latter path variable was the correct full name. Was I just using it incorrectly? I need to ensure that this connection info will be accessible to all users, will just using %PROGRAMDATA% allow that? I am using Windows 7 in case that is relevant.
From here:
FOLDERID_ProgramData / System.Environment.SpecialFolder.CommonApplicationData
The user would never want to browse here in Explorer, and settings changed here should affect every user on the machine. The default location is %systemdrive%\ProgramData, which is a hidden folder, on an installation of Windows Vista. You'll want to create your directory and set the ACLs you need at install time.
So, just use %PROGRAMDATA%, or better still:
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)

Creating XML file with write access given to all the windows account users

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());
}
}

How to copy ntfs permissions

I found a method for copying ntfs permissions information from one existing folder to a newly created one - I'm not sure if it's doing the work it should do. Maybe one can have a look at the method and give some comments:
private static void CopySecurityInformation(String source, String dest)
{
FileSecurity fileSecurity = File.GetAccessControl(
source,
AccessControlSections.All);
FileAttributes fileAttributes = File.GetAttributes(source);
File.SetAccessControl(dest, fileSecurity);
File.SetAttributes(dest, fileAttributes);
}
Thanks for your help,
Daniel
I tried following the OP suggested pattern for copying a file's ACLs and attributes and found a few issues in our application. Hopefully this information helps others.
According to MSDN, using the File.SetAccessControl() method as shown above will not work.
The SetAccessControl method persists only FileSecurity objects that
have been modified after object creation. If a FileSecurity object
has not been modified, it will not be persisted to a file. Therefore,
it is not possible to retrieve a FileSecurity object from one file and
reapply the same object to another file.
It is necessary to make a new FileSecurity object for the destination file and assign to this a copy of the source FileSecurity object.
Here is an example of a pattern that works from our app.
public static void CopyFile(string source, string destination)
{
// Copy the file
File.Copy(source, destination, true);
// Get the source file's ACLs
FileSecurity fileSecuritySource = File.GetAccessControl(source, AccessControlSections.All);
string sddlSource = fileSecuritySource.GetSecurityDescriptorSddlForm(AccessControlSections.All);
// Create the destination file's ACLs
FileSecurity fileSecurityDestination = new FileSecurity();
fileSecurityDestination.SetSecurityDescriptorSddlForm(sddlSource);
// Set the destination file's ACLs
File.SetAccessControl(destination, fileSecurityDestination);
// copy the file attributes now
FileAttributes fileAttributes = File.GetAttributes(source);
File.SetAttributes(destination, fileAttributes);
}
After fixing the first issue, then we found the owner attribute was not being copied. Instead, the destination file was owned by Administrator in our case. To get around that the process needs to enable the SE_RESTORE_NAME privilege. Check out AdjustTokenPrivileges on pinvoke.net for a complete Privileges class that makes setting privileges easy.
The last thing that we had to deal with was UAC. We needed to restart our app with administrative rights if the user is running under UAC. Here is another example from our app that deals with relaunching the app with elevated privileges.
private static void RelaunchWithAdministratorRights(string[] args)
{
// Launch as administrator
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.UseShellExecute = true;
processStartInfo.WorkingDirectory = Environment.CurrentDirectory;
string executablePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
processStartInfo.FileName = executablePath;
processStartInfo.Verb = "runas";
if (args != null && args.Count() > 0)
{
string arguments = args[0];
for (int i = 1; i < args.Count(); i++)
arguments += " " + args[i];
processStartInfo.Arguments = arguments;
}
try
{
using (Process exeProcess = Process.Start(processStartInfo))
{
exeProcess.WaitForExit();
}
}
catch
{
// The user refused to allow privileges elevation. Do nothing and return directly ...
}
Environment.Exit(0);
}
Ours was a console app so we need to pass the args parameter from the Main method to the RelaunchWithAdministratorRights(args). Non-console apps could pass null instead. We call RelaunchWithAdministratorRights from within catch blocks as in:
try
{
...
}
catch (SecurityException)
{
RelaunchWithAdministratorRights(args);
return;
}
In our app we just return after the call to RelaunchWithAdministratorRights to exit the instance of the app that lacked privileges. Depending on your app, you may prefer to throw your way out. Regardless, after returning from RelaunchWithAdministratorRights you don't want this instance to continue processing.
Enjoy!
It does slightly more than just copying the NTFS permissions. It also copies the attributes of the file. I'm not quite certain whether it copies inherited permissions, though, but run it once and you should be able to find out.
Note that copying permissions on and of itself requires special permissions (administrators have these, of course), be sure the process running this method has the required permissions to query, view and set permissions on those objects.

i have problem with sharing a folder through programming using c#?

here is my code it shares the folder but that does not work correctly when i want to access it , it shows access denied help required,
private static void ShareFolder(string FolderPath, string ShareName, string Description)
{
try
{
// Create a ManagementClass object
ManagementClass managementClass = new ManagementClass("Win32_Share");
// Create ManagementBaseObjects for in and out parameters
ManagementBaseObject inParams = managementClass.GetMethodParameters("Create");
ManagementBaseObject outParams;
// Set the input parameters
inParams["Description"] = Description;
inParams["Name"] = ShareName;
inParams["Path"] = FolderPath;
inParams["Type"] = 0x0; // Disk Drive
//Another Type:
//DISK_DRIVE = 0x0;
//PRINT_QUEUE = 0x1;
//DEVICE = 0x2;
//IPC = 0x3;
//DISK_DRIVE_ADMIN = 0x80000000;
//PRINT_QUEUE_ADMIN = 0x80000001;
//DEVICE_ADMIN = 0x80000002;
//IPC_ADMIN = 0x8000003;
//inParams["MaximumAllowed"] = int maxConnectionsNum;
// Invoke the method on the ManagementClass object
outParams = managementClass.InvokeMethod("Create", inParams, null);
// Check to see if the method invocation was successful
if ((uint)(outParams.Properties["ReturnValue"].Value) != 0)
{
throw new Exception("Unable to share directory. Because Directory is already shared or directory not exist");
}//end if
}//end try
catch (Exception ex)
{
MessageBox.Show(ex.Message, "error!");
}//end catch
}//End Method
You have to add permissions to the shared folders. This post Adding Permissions to a shared folder using WMI and Microsoft .Net explains the steps in detail.
Excerpt from the post
To assign permission to the user, the
following needs to be done
Get hold of the Shared folder object’s setting and extract its
security descriptor.
Extract Access Control List (ACL) from the security descriptor.
Get hold of the user account object and extract its security
descriptor.
Create a Windows Trustee object for the user using its security
descriptor.
Create an Access Control Entry (ACE) using the Trustee object.
Add Access Control Entry to Access Control List.
Assign List back to Security Descriptor for the folder
Reassign security descriptor to the shared folder.
Return Values
Returns one of the values in the following table or any other value to indicate an error.
0 – Success
2 – Access denied
8 – Unknown failure
9 – Invalid name
10 – Invalid level
21 – Invalid parameter
22 – Duplicate share
23 – Redirected path
24 – Unknown device or directory
25 – Net name not found
Where are you accessing the shared folder from? If from another computer, make sure you have given read privileges on that folder to the computer that you are accessing it from.. Hope this helps...
Thanks,
Ram

Categories

Resources