locked
Programatically removing Users Group Permissions from a folder in C# RRS feed

  • Question

  • Hi

     

    I not sure if I'm in the right forum for this as this is my first post on the msdn forum.

     

    I am having a slight problem with removing the MachineName/Users group access rights to a folder created by my web system.

     

    The system is desgined for my companys intranet and is going to be used to create folders and documents in a central network location.

     

    The system has also got the ability for letting the users restrict access to everyone in the company except for certain users who they can define.

     

    Currently the system is working fine. It creates the folders and subsequent documents, and in cases of restricting projects, it removes the "Everyone" group and adds the individual users with the appropriate access rights. 

    The problem I'm having is first I cannot seem to access the MachineName/Users group as the system keeps generating an exception everytime I try to access the group saying "Some or all identity references could not be translated." and secondly if I won't be able to access this security group is there anyway I can remove them programatically?

     

    I need to do this programatically as not all folders and files being created by my system need to be restricted. Mostly they will be open folders and files with about 5% being restricted.

     

    Any help on this would be appriciated.

     

    Tuesday, August 7, 2007 10:55 PM

Answers

  •  

    Then the code I originally suggested will not work for you.  The problem is that from machine A where you are running the code it can not validate any local users or groups on machine B.  That is simply the way Windows works.  Validation occurs when you try to translate from an NTAccount to a SecurityIdentifier.  It will try to find the account locally or in the domain from which it is running.  Local security databases on other machines will not be examined AFAIK.

     

    However you really don't care about the SID of the Users group anyway.  The default behavior you want is how NTFS works by default, sort of.  When a user (other than an administrator) creates a folder they are the only user who has explicit rights to the folder/file.  Everybody else simply inherits the security of the parent.  So in your example if you were to remove the rights of Users to the directory that is the parent of project A and B then, by default, only the creator would have the right to view it.  When you created the folder you'd still need to add in any user beyond the creator that you wanted to add but otherwise it would work.

     

    Irrelevant you still might find yourself needing to get the Users group of another machine.  This is where the WellKnownSidType comes in.  See the pre-defined groups/users in Windows happen to have the same SID.  When combined with the SID of the machine they become unique.  In theory all you would need to do is use the well-known SID of Users and, when applied on the remote machine, it would match up properly.  Theory is wonderful but if it doesn't work in practice who cares.  Well it actually does work, for well known SIDs only.

     

    Code Snippet

    DirectorySecurity sec = Directory.GetAccessControl(...);

    SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);

    sec.PurgeAccessRules(sid);

    Directory.SetAccessControl(..., sec);

     

     

    I confirmed that from one machine connected to another that the above code will remove the Users group.  It should work for any well-known SID.  However if you want to remove local users or non-standard groups then it won't.

     

    The above code will also not work for rules that are inherited.  This is an issue irrelevant of whether it is a local or remote machine.  Inherited rules are not modified by the access rule methods. Instead you have to explicitly remove the inheritance from the file/folder and then you can use the security object to remove the group.

     

    Michael Taylor - 8/8/07

    http://p3net.mvps.org

     

     

    Thursday, August 9, 2007 1:23 AM

All replies

  • So you want to remove a particular group's access rights to a folder.  Here are the steps (and it works for any group).

    Code Snippet

     

    static void RemoveUserRights ( string directory, string account )

    {

       //Get the directory security

       DirectorySecurity sec = Directory.GetAccessControl(directory);

     

       //Get the account

       NTAccount acct = new NTAccount(account);

       IdentityReference id = acct.Translate(typeof(SecurityIdentifier));

     

       //Remove write access to the directory

       FileSystemAccessRule rule = new FileSystemAccessRule(acct, 

             FileSystemRights.Write, AccessControlType.Allow);

       sec.RemoveAccessRuleAll(rule);

     

       //Apply the changes

       Directory.SetAccessControl(directory, sec);

    }

     

     

    Note that for builtin groups you can use the WellKnownSidType enumeration as well.

     

    Michael Taylor - 8/8/07

    http://p3net.mvps.org

     

    Wednesday, August 8, 2007 12:43 PM
  • Hi Michael

     

    Thank you for your reply.

     

    I am however now having an IdentityNotMappedException exception on the following line:

     

    Code Snippet

    IdentityReference idUsers = userAccount.Translate(typeof(SecurityIdentifier));

     

     

    The full exception message I am getting is:

     

    Code Snippet

    System.Security.Principal.IdentityNotMappedException was unhandled by user code
      Message="Some or all identity references could not be translated."
      Source="mscorlib"
      StackTrace:
           at System.Security.Principal.NTAccount.Translate(IdentityReferenceCollection sourceAccounts, Type targetType, Boolean forceSuccess)
           at System.Security.Principal.NTAccount.Translate(Type targetType)
           at ScopeUtil.createDirectories(String projectDirectory, ProjectDetails project) in c:\Documents and Settings\rbh3842.TRL\My Documents\Visual Studio 2005\PMOCentralApplication\App_Code\Helpers\Utils\ScopeUtil.cs:line 244
           at ScopeUtil.generateProjectDirectory(ProjectDetails project) in c:\Documents and Settings\rbh3842.TRL\My Documents\Visual Studio 2005\PMOCentralApplication\App_Code\Helpers\Utils\ScopeUtil.cs:line 188
           at ScopeUtil.createScopeDocument(ProjectDetails project) in c:\Documents and Settings\rbh3842.TRL\My Documents\Visual Studio 2005\PMOCentralApplication\App_Code\Helpers\Utils\ScopeUtil.cs:line 279
           at ScopeUtil.generateScope(Int32 projectID) in c:\Documents and Settings\rbh3842.TRL\My Documents\Visual Studio 2005\PMOCentralApplication\App_Code\Helpers\Utils\ScopeUtil.cs:line 166
           at ProjectInformation.generateScopeDocument() in c:\Documents and Settings\rbh3842.TRL\My Documents\Visual Studio 2005\PMOCentralApplication\ProjectManagement\ProjectScope\ProjectInformation.aspx.cs:line 547
           at ProjectInformation.btnModalVersionAdd_Click(Object sender, EventArgs e) in c:\Documents and Settings\rbh3842.TRL\My Documents\Visual Studio 2005\PMOCentralApplication\ProjectManagement\ProjectScope\ProjectInformation.aspx.cs:line 294
           at System.Web.UI.WebControls.Button.OnClick(EventArgs e)
           at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
           at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
           at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
           at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
           at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

     

     

    I am posting the full code to remove the "Users" group account access I am using for your convinience in understanding what I am trying to do:

     

    Code Snippet

    //Get the Directory Information Settings

    DirectoryInfo dirInfo = new DirectoryInfo(projectDirectory);

    DirectorySecurity dirSecurity = dirInfo.GetAccessControl();

     

    //Get the Machine Users Group

    string projectDirectoryMachineName = ConfigurationManager.AppSettings["ProjectDirectoryMachineName"].ToString();

    string machineUsers = projectDirectoryMachineName + "Users";

     

    //Remove the Users Group Access to this Directory

    NTAccount userAccount = new NTAccount(machineUsers);

    IdentityReference idUsers = userAccount.Translate(typeof(SecurityIdentifier));

    dirSecurity.RemoveAccessRuleAll(new FileSystemAccessRule(userAccount, FileSystemRights.ReadData, AccessControlType.Allow));

    dirInfo.SetAccessControl(dirSecurity);

     

     

     

    I tried running the code after commenting out the Identity Reference line but it then gave me the IdentityNotMappedException on the dirSecurity.RemoveAccessRuleAll line. This has led me to believe that my declaration to get the "MachineName/Users" group is incorrect (the machineUsers Variable declaration).

     

    I hope this helps.

    Wednesday, August 8, 2007 8:57 PM
  • Are you trying to remove the Users group of another machine from the folder?  For example you are running on machine A  but you want to remove the Users group of machine B.  If so then how did you get machine B's account on the folder to begin with?  Groups local to a machine are not visible outside the machine itself. 

     

    For the local machine you can actually skip the NTAccount and use SecurityIdentifier directly with the WellKnownSidType for the Users group.  This saves you a step. 

     

    If neither of the above help then do not append the machine name.  As it stands now the code can easily be broken by a bad string.  Instead use the overload of NTAccount that accepts a domain and an account name.  Note that NTAccount doesn't actually require that the account exist but when you try to convert to a security identifier it better.

     

    Michael Taylor - 8/8/07

    http://p3net.mvps.org

     

     

     

    Wednesday, August 8, 2007 9:15 PM
  •  TaylorMichaelL wrote:

    Are you trying to remove the Users group of another machine from the folder?  For example you are running on machine A  but you want to remove the Users group of machine B.  If so then how did you get machine B's account on the folder to begin with?  Groups local to a machine are not visible outside the machine itself. 

     

    For the local machine you can actually skip the NTAccount and use SecurityIdentifier directly with the WellKnownSidType for the Users group.  This saves you a step. 

     

    If neither of the above help then do not append the machine name.  As it stands now the code can easily be broken by a bad string.  Instead use the overload of NTAccount that accepts a domain and an account name.  Note that NTAccount doesn't actually require that the account exist but when you try to convert to a security identifier it better.

     

    Michael Taylor - 8/8/07

    http://p3net.mvps.org

     

     

     

     

    Hi Michael

     

    You are correct to assume that I am trying to remove the Users group on another machine.

    The reasoning behind that is that this company intranet site will sit on Machine A while these folders will be created on a company wide network share on Machine B.

     

    As I had mentioned in my original post the objective I am trying to achieve is that if a folder or document is marked by the creator as restricted then no one other than the creator or persons specified by the creator should be able to access and read the documents in that folder.

     

    For example we have 3 people person X, person Y and person Z.

    person X creates a document called project A, it is to create a folder called project A and marks it unrestricted. Then person X, Y & Z should be able to go to the network share and view the document.

    However if person Y creates a document called project B and marks it restircted with access only to himself and person Z it is to create the folder called Project B with access to only person Y and person Z. If person Y or person Z browse to the network share they should be able to view both project A and project B. However if person X browses to the  network share he should be able to see both project A and project B folders but only be able to view the documents in project A and get an access denied error if they try to view anything in the project B folder.

     

    I have got the code working to grant access to person Y and person Z in the case of a restricted access while removing the access group "Everyone" from the folder permissions.

    However the client (my company) also wants me to remove the group "MachineName\Users" from the folder.

     

    It is here where I am having the issues. Every time I try and access the "MachineName\Users" group I get the "Some or all identity references could not be translated." exception.  

     

    I hope this helps

    Wednesday, August 8, 2007 9:42 PM
  •  

    Then the code I originally suggested will not work for you.  The problem is that from machine A where you are running the code it can not validate any local users or groups on machine B.  That is simply the way Windows works.  Validation occurs when you try to translate from an NTAccount to a SecurityIdentifier.  It will try to find the account locally or in the domain from which it is running.  Local security databases on other machines will not be examined AFAIK.

     

    However you really don't care about the SID of the Users group anyway.  The default behavior you want is how NTFS works by default, sort of.  When a user (other than an administrator) creates a folder they are the only user who has explicit rights to the folder/file.  Everybody else simply inherits the security of the parent.  So in your example if you were to remove the rights of Users to the directory that is the parent of project A and B then, by default, only the creator would have the right to view it.  When you created the folder you'd still need to add in any user beyond the creator that you wanted to add but otherwise it would work.

     

    Irrelevant you still might find yourself needing to get the Users group of another machine.  This is where the WellKnownSidType comes in.  See the pre-defined groups/users in Windows happen to have the same SID.  When combined with the SID of the machine they become unique.  In theory all you would need to do is use the well-known SID of Users and, when applied on the remote machine, it would match up properly.  Theory is wonderful but if it doesn't work in practice who cares.  Well it actually does work, for well known SIDs only.

     

    Code Snippet

    DirectorySecurity sec = Directory.GetAccessControl(...);

    SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);

    sec.PurgeAccessRules(sid);

    Directory.SetAccessControl(..., sec);

     

     

    I confirmed that from one machine connected to another that the above code will remove the Users group.  It should work for any well-known SID.  However if you want to remove local users or non-standard groups then it won't.

     

    The above code will also not work for rules that are inherited.  This is an issue irrelevant of whether it is a local or remote machine.  Inherited rules are not modified by the access rule methods. Instead you have to explicitly remove the inheritance from the file/folder and then you can use the security object to remove the group.

     

    Michael Taylor - 8/8/07

    http://p3net.mvps.org

     

     

    Thursday, August 9, 2007 1:23 AM
  •  TaylorMichaelL wrote:

     

    Then the code I originally suggested will not work for you.  The problem is that from machine A where you are running the code it can not validate any local users or groups on machine B.  That is simply the way Windows works.  Validation occurs when you try to translate from an NTAccount to a SecurityIdentifier.  It will try to find the account locally or in the domain from which it is running.  Local security databases on other machines will not be examined AFAIK.

     

    However you really don't care about the SID of the Users group anyway.  The default behavior you want is how NTFS works by default, sort of.  When a user (other than an administrator) creates a folder they are the only user who has explicit rights to the folder/file.  Everybody else simply inherits the security of the parent.  So in your example if you were to remove the rights of Users to the directory that is the parent of project A and B then, by default, only the creator would have the right to view it.  When you created the folder you'd still need to add in any user beyond the creator that you wanted to add but otherwise it would work.

     

    Irrelevant you still might find yourself needing to get the Users group of another machine.  This is where the WellKnownSidType comes in.  See the pre-defined groups/users in Windows happen to have the same SID.  When combined with the SID of the machine they become unique.  In theory all you would need to do is use the well-known SID of Users and, when applied on the remote machine, it would match up properly.  Theory is wonderful but if it doesn't work in practice who cares.  Well it actually does work, for well known SIDs only.

     

    Code Snippet

    DirectorySecurity sec = Directory.GetAccessControl(...);

    SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);

    sec.PurgeAccessRules(sid);

    Directory.SetAccessControl(..., sec);

     

     

    I confirmed that from one machine connected to another that the above code will remove the Users group.  It should work for any well-known SID.  However if you want to remove local users or non-standard groups then it won't.

     

    The above code will also not work for rules that are inherited.  This is an issue irrelevant of whether it is a local or remote machine.  Inherited rules are not modified by the access rule methods. Instead you have to explicitly remove the inheritance from the file/folder and then you can use the security object to remove the group.

     

    Michael Taylor - 8/8/07

    http://p3net.mvps.org

     

     

     

    Hi Michael

     

    Thank you for this.

     

    This is exactly what I'm looking for

    Thursday, August 9, 2007 3:52 AM