none
How to retrieve user rights for shared folder using WMI - user in groups RRS feed

  • Question

  • Hi,

    I need to get the user rights of selected user (login) for specified share. Currently I'm using this method

    public AccessMask GetUserRightsDetailed(string login)
            {
                try
                {
                    ManagementBaseObject[] ACL = SecurityDescriptor.Properties["DACL"].Value as ManagementBaseObject[];
                    AccessControlList accessControlList = new AccessControlList(ACL);
                    int index = accessControlList.GetTrusteeIndex(login);
                    if (index == -1)
                        return AccessMask.None;
    
                    AccessMask mask = (AccessMask)ACL[index].Properties["AccessMask"].Value;
    
                   return mask;
    
                }
                catch (Exception ex)
                {
                    throw new Exception(String.Format("Unable to get user rights for user '{0}'.", login), ex);
                }
            }

    But the problem occures if the user is not listed directly but he is 'only' member of some user group. Currently I'm testing following code to retrieve the usergroups where the user is member, but it's very very slow ...

            public static string GetGroupsForUser(string login)
            {
                string[] loginParts = login.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
                string domain = loginParts[0];
                string user = loginParts[1];
    
                StringBuilder strGroups = new StringBuilder();
    
                using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_GroupUser where PartComponent=\"Win32_UserAccount.Domain='" + domain + "',Name='" + user + "'\""))
                {
    
                    foreach (ManagementObject mObject in searcher.Get())
                    {
                        ManagementPath path = new ManagementPath(mObject["GroupComponent"].ToString());
    
                        if (path.ClassName == "Win32_Group")
                        {
                            String[] names = path.RelativePath.Split(',');
                            strGroups.Append(names[1].Substring(names[1].IndexOf("=") + 1).Replace('"', ' ').Trim() + ", ");
                        }
                    }
                }
    
               
                return strGroups.ToString();
            }

    And what about it the user is member of more groups with different rights ? 

    What is the easiest and mainly fastest way how to get the highest rights of user?

    Thanks a lot

    Filip

    Monday, October 21, 2013 8:56 AM

All replies

  • Hi Filip,

    Did you want to check if user belongs to AD group? If so, please refer to  http://stackoverflow.com/questions/12029378/checking-if-user-belongs-to-ad-group to see more information.


    Tuesday, October 22, 2013 12:19 PM
  • HI,

    no I didn't want to know if user belongs to AD group. So what I need at the end:

    1) I have shared folders on the server

    2) every shared folder serves as datastore for a so called "project site" which is a Sharepoint site dedicated to one project in our company

    3) when project site administrator change rights for some sharepoint site users I  change the relevant access rights for this user also on the shared folder

    4) I developed a tool for data sync between the local computer and this datastore, however before the sync is run I have to check the current user rights on datastore

    5)  in my existing code it worked if the user was listed (at share permissions) as mydomain\myusername. The I could check the user rights directly. The problem was when user was not listed individually but was only part of group like mydomain\mydepartentworkers. In that case I have to

    a) get all groups in which user is included

    b) check share access rights of these groups

    c) select highest right and return it

    Finally I've already found some solution, however it's still quite slow. There is a method http://msdn.microsoft.com/en-us/library/aa390438(v=vs.85).aspx which maybe could be faster, but I don't know how to call it "on behalf" of some specified user, since I don't need to know it only for currently loged user - the reason is, that the user rights check is done in the webservice, which is run under one account but should return rights for login, which has been sent into its method as a parameter.

    I hope I¨ve explained it better now

    regards

    F.




    Tuesday, October 22, 2013 12:31 PM
  • Hi Filip,

    I have heard the news about the WMI is very slow. I have tried the same kind of behavior in an application that does WMI queries. I also find some queries on the same machine behave differently than other queries on the same machine simply because a different class is queries.

    EnumerationOptions options = new EnumerationOptions();

                options.ReturnImmediately = false;

    You could try the above code and see if it helps. But the most obvious optimization is to run the entire thing in Parallel. Please refer to http://msdn.microsoft.com/en-us/library/dd460693.aspx to find a solution to get around this issue.

    Best Regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, October 23, 2013 5:42 AM
    Moderator
  • Hmm, my current solution is

            public AccessMask GetUserRightsDetailed(string login)
            {
                try
                {
                    ManagementBaseObject[] ACL = SecurityDescriptor.Properties["DACL"].Value as ManagementBaseObject[];
                    AccessControlList accessControlList = new AccessControlList(ACL);
    
                    AccessMask mask = AccessMask.None;
    
                    //check user if exists (index !=-1)
                    int index = accessControlList.GetTrusteeIndex(login);
                    if (index != -1)
                        mask = (AccessMask)ACL[index].Properties["AccessMask"].Value;
    
                    if (mask == AccessMask.FullControl)
                        return mask; //if user has full control no need to check the groups
    
                    //check groups of user
                    var groups = GetGroupsForUser(login);//returns logins of all groups in which current user is included
                    var groupIndeces = accessControlList.GetTrusteeIndeces(groups);
                    foreach (var gLogin in groupIndeces)
                    {
                        index = gLogin.Value;
                        if (index != -1)
                        {
                            var m = (AccessMask)ACL[index].Properties["AccessMask"].Value;
                            if (m > mask) mask = m;//check if the rights of group are higher then stored rights
                            if (mask == AccessMask.FullControl)//if full control rights are reached, no need to continue
                                break;
                        }
                    }
    
                    return mask;
    
                }
                catch (Exception ex)
                {
                    throw new Exception(String.Format("Unable to get user rights for user '{0}'.", login), ex);
                }
            }
    
            public List<string> GetGroupsForUser(string login)
            {
                string[] loginParts = login.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
                string domain = loginParts[0];
                string username = loginParts[1];
                UserPrincipal user = UserPrincipal.FindByIdentity(new PrincipalContext(ContextType.Domain, domain), IdentityType.SamAccountName, username);
    
                return user.GetGroups().Select(g => g.Sid.Translate(typeof(NTAccount)).ToString()).ToList(); // g.Context.Name + "\\" + g.Name).ToList ();
            }
    
    
    public class AccessControlList : List<ManagementBaseObject>
        {
            public AccessControlList() { }
    
            public AccessControlList(ManagementBaseObject[] items) : base(items) { }
    
            public int GetTrusteeIndex(string login)
            {
                //look if current user already exists
                for (int i = 0; i < this.Count; i++)
                {
                    ManagementBaseObject trustee = (ManagementBaseObject)this[i].Properties["Trustee"].Value;
                    string trusteeLogin = string.Format(@"{0}\{1}", trustee.Properties["Domain"].Value, trustee.Properties["Name"].Value);
    
                    if (string.Compare(trusteeLogin, login, true) == 0)
                        return i;
                }
                return -1;
            }
    
            public Dictionary<string,int> GetTrusteeIndeces(List<string> logins)
            {
                Dictionary<string, int> result = new Dictionary<string, int>();
    
                for (int i = 0; i < this.Count; i++)
                {
                    ManagementBaseObject trustee = (ManagementBaseObject)this[i].Properties["Trustee"].Value;
                    string trusteeLogin = string.Format(@"{0}\{1}", trustee.Properties["Domain"].Value, trustee.Properties["Name"].Value);
                    string removeLogin=string.Empty ;
    
                    foreach (var searchedLogin in logins)
                    {
                        if (string.Compare(trusteeLogin, searchedLogin, true) == 0)
                        {
                            result.Add(searchedLogin, i);
                            removeLogin = searchedLogin;
                            break;
                        }
                    }
    
                    if(!string.IsNullOrEmpty (removeLogin ))
                        logins.Remove(removeLogin);
                    
                }
                return result;
            }
    }

    It still take something about 3 - 6 s per one call, however I havent found any faster way. Maybe it could hep somebody. However, I don't see any chance to use parallel processing in it.

    If anybody found a better solution, I'd be very happy. 

    F.

    • Marked as answer by Filip Mateasko Wednesday, October 23, 2013 7:44 AM
    • Unmarked as answer by Filip Mateasko Thursday, October 24, 2013 11:12 AM
    Wednesday, October 23, 2013 7:41 AM
  • Unfortunatelly, my previous post is not the aswer. The problem is that the user could be member of groups which could be members of another groups and they could be member of another groups and so on.  and only some of the group in this 'tree' could be listed in a Share with defined rights. in such a case using the previous method I should 

    1) check user himself

    2) check groups in which the user is a member

    3) for every group G of these groups

    a) check the group itself

    b) check groups in which the group G is a member

    c) for every group of groups from point b)

    do points a-c

    this could take a quite a long time. However, the system itself know your rights immediatelly when you try to write or read from share. So isn't there really any other much more simple way ? Nobody knows??

    Thanks

    Filip

     

    Thursday, October 24, 2013 11:22 AM