0

My Program generates a file. this file should be protected, such that the User can't accidentally remove it. So, it needs to be protected in some way.

Since the file should be protected, while the application is closed FileStream.Lock is not a suitable solution for this task.

I tried to Deny FileSystemRights.Delete on the file like:

    fSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                FileSystemRights.Delete, AccessControlType.Deny));

But that does not prevent deletion, to do this i had to change it like this:

    fSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                FileSystemRights.Delete | FileSystemRights.WriteAttributes, AccessControlType.Deny));

( the user CAN open the file properties and add back the WriteAttribute permissions and can delete the file afterwards, which is fine )

The problem now is: The file should be deletable from the application. but doing:

    fSecurity.RemoveAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                FileSystemRights.Delete | FileSystemRights.WriteAttributes, AccessControlType.Deny));
    // or:
    fSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                FileSystemRights.Delete | FileSystemRights.WriteAttributes, AccessControlType.Allow));

results in an UnauthorizedAccessException. So i cannot undo what I've done. which is strange because in the file explorer its absolutely possible to do so.


So my question(s) is are - How do you grant deletion permissions again - or: what is the best way to protect a file for unintentional deletion



the file already is in %appdata% but since there are other folders the user might delete, it is absolutely mandatory that this file is not deleted accidentally

Soraphis
  • 706
  • 7
  • 26
  • 2
    You have to remove the access rule you added before, not add another one. ACLs are a list of rules, which the OS looks through to see whether there are any rules allowing a given user to perform an action, or denying them from performing that action. Deny rules have priority over Allow rules, so adding an Allow rule does not override the Deny rule you added earlier. – canton7 Oct 10 '19 at 12:16
  • What does the file contain? How is it used? Program files are already protected by the OS - that's why you can't write to anything in `Program Files`. If the application uses a proper setup program for deployment, changes will be detected by the OS – Panagiotis Kanavos Oct 10 '19 at 12:17
  • Application data should be stored in `ProgramData` or `%APPDATA%`. The user can always navigate to that folder and modify files but it's far less likely. – Panagiotis Kanavos Oct 10 '19 at 12:19

1 Answers1

1

@canton7 thanks! this was extremely helpful

okay, with much trial and error I got the solution:

  1. You have to set the file to readonly. Denying Deletion on its own does not work
  2. You have to deny Deletion + WriteAttributes - if you don't the file can be deleted in the File Explorer without asking for privileges.

  3. When unlocking the file again: first add back the Priviliges

    • you have to Remove the deny rules you added
    • and you have to add flags to allow
    • doing only one of this does not work
  4. remove the readonly flag
        private static void LockFile(string _FullPath)
        {
            File.SetAttributes(_FullPath, File.GetAttributes(_FullPath) | FileAttributes.ReadOnly);

            FileSecurity fSecurity = File.GetAccessControl(_FullPath);

            fSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                FileSystemRights.Delete | FileSystemRights.WriteAttributes, AccessControlType.Deny));

            File.SetAccessControl(_FullPath, fSecurity);
        }

        private static void UnLockFile(string _FullPath)
        {
            FileSecurity fSecurity = File.GetAccessControl(_FullPath);

            fSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                FileSystemRights.Delete | FileSystemRights.WriteAttributes, AccessControlType.Allow));

            fSecurity.RemoveAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                FileSystemRights.Delete | FileSystemRights.WriteAttributes, AccessControlType.Deny));

            File.SetAccessControl(_FullPath, fSecurity);

            File.SetAttributes(_FullPath, FileAttributes.Normal);
        }
Soraphis
  • 706
  • 7
  • 26
  • Doesn't this require that the user running the application has permission to _Change permissions_ ? Would you have to run as admin for this to work? – Chris Dunaway Oct 10 '19 at 18:12
  • I use this code to change the permissions of a file my program created. so the program has the permissions to change the permissions. it does not run with administrator privileges – Soraphis Oct 14 '19 at 08:01