Link to home
Start Free TrialLog in
Avatar of mjgardne
mjgardne

asked on

Cannot Take Ownership of Directory with owner = "Unable to display current owner"

Hello,

Basically, I have a program that copies all the files in a descending directory tree.  Sometimes, there are directories and/or files that have messed up security, so I want my application to take ownership (recursively on all child objects)  of them with read access so it can continue along and complete the copy.  The application is being run by Administrator, who is part of the Adminstrators security group.  If running on Vista, the application is run elevated.  Right now, this application is being run on a computer on a workgroup, but the same issue should be present on a domain.

I have tried to take ownership of a folder programmatically trying two separate paths: (1) using System.Security and (2) WMI's TakeOwnerShip.  WMI reports "Access is denied" and .NET reports "Attemped to perform an unauthorized operation" after calling Directory.GetAccessControl().  I can manually take ownership using Explorer, but that doesn't help my application! :)   I've included the code that I am using and also a screenshot of the security on this directory.

Anyway, I am at a loss and would appreciate your help.

Thanks,

Mike
protected void AddSelfToAcl(string theFullPath)
{
    if (theFullPath == null || theFullPath == "")
    {
        throw new Exception("Path cannot be null or empty");
     }
 
  // Trailing backslash is not supported.
  string fullPath = theFullPath.TrimEnd('\\');
            
  // create a rule for self
  WindowsIdentity self = System.Security.Principal.WindowsIdentity.GetCurrent();
 
  FileSystemAccessRule rule = new FileSystemAccessRule(
    self.Name, 
    FileSystemRights.FullControl,
    AccessControlType.Allow);
 
  // add the rule to the file's existing ACL list
  DirectorySecurity security = Directory.GetAccessControl(fullPath);
 
  AuthorizationRuleCollection acl = security.GetAccessRules(
    true, 
    true,
    typeof(System.Security.Principal.NTAccount));
 
  security.AddAccessRule(rule);
 
  // persist changes and update view
  Directory.SetAccessControl(fullPath, security);
 
/////////////////////////////////////////////////////////////////////
// WMI VERSION... 
//string dirObject = String.Format("win32_Directory.Name='{0}'", fullFileName);
//using(ManagementObject dir = new ManagementObject(dirObject))
//{
//    dir.Get();
//    ManagementBaseObject outParams = dir.InvokeMethod("TakeOwnerShip", null, null);
//    // ReturnValue should be 0, else failure
//    int result = Convert.ToInt32(outParams.Properties["ReturnValue"].Value);
//}
            
}

Open in new window

Permissions.jpg
Avatar of graye
graye
Flag of United States of America image

Hang on.... set the Permissions to allow  you Full Control is not the same thing as changing the Ownership.
So, the first thing you need to do is seize ownership of the directory, and then change the DACLs to whatever you want.   (I'm not sure if you have to persist the owner first... you might try it)

            if (theFullPath == null || theFullPath == "")
            {
            throw new Exception("Path cannot be null or empty");
            }
         
            // Trailing backslash is not supported.
            string fullPath = theFullPath.TrimEnd('\\');
                        
            // create a rule for self
            WindowsIdentity self = System.Security.Principal.WindowsIdentity.GetCurrent();
             
            FileSystemAccessRule rule = new FileSystemAccessRule(self.Name, FileSystemRights.FullControl, AccessControlType.Allow);
             
            // add the rule to the file's existing ACL list
            DirectorySecurity security = System.IO.Directory.GetAccessControl(fullPath);
            security.SetOwner(new System.Security.Principal.NTAccount(self.Name));
 
            security.AddAccessRule(rule);
             
            // persist changes and update view
            System.IO.Directory.SetAccessControl(fullPath, security);

Open in new window

Avatar of mjgardne
mjgardne

ASKER

Hi Grave,

Thank you for the quick response...  I see what you mean by taking ownership and then full control.  In fact, that is what I would do using Explorer...  But, there seems to be a "chicken before the egg" in this case.  In you suggested code, you use security.SetOwner to take ownership (by the way, is that recursive to the folder and its children?), but in order to call this method, security=Directory.GetAccessControl must work.  In my case, when I call Directory.GetAccessControl, I am getting an "attempt to perform an unauthorized operation".  Is there another way to invoke SetOwner?

Thanks for your help!

MIke
OK... then let's make a small change...
// get only the Owner section of the Security Descriptor            
DirectorySecurity security = System.IO.Directory.GetAccessControl(fullPath, AccessControlSections.Owner);
// set yourself as the new onwer
security.SetOwner(new System.Security.Principal.NTAccount(self.Name));
// save the changes
System.IO.Directory.SetAccessControl(fullPath, security);

Open in new window

Hi Grave,

I wonder if taking ownership first would work...  I will try it and report back to you.

-----------------------------------------------
DirectorySecurity ds = new DirectorySecurity();
 ds.SetOwner(new SecurityIdentifier(WellKnownSidType.AccountAdministratorSid.ToString()));
.
.
.
 dir.SetAccessControl(ds);
--------------------------

... We just cross posted! :)  I will try your suggestion too!  Thank you!  More to follow...  

Mike
Bummer!  I still get the same error when I called GetAccessControl with AccessControlSections.Owner.  Argggg!  :)  I will try the other alternative next...  
Arggg!  I had the same results with the following code...  Geez, this should not be this difficult! :P

            DirectorySecurity ds = new DirectorySecurity();
            ds.SetOwner(new System.Security.Principal.NTAccount(self.Name));
            Directory.SetAccessControl(fullPath, ds);
ASKER CERTIFIED SOLUTION
Avatar of graye
graye
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of bbao
running on vista?? are you sure your UAC is disabled or the privilege has been raised?
YOU DID IT GRAYE!!!  THANK YOU!

I cannot believe that I did not find any documentation on MSDN about having to SetPriv before I can take ownership of a folder!  Geeeeez!!!  I think that my issues are about 98% resolved, now.  Here are the final variation on our work... I think! :)

1) When I take ownership of a folder, I become owner of it, but ownership does not automatically propagate down to its child folders.  Is that expected, Graye?  My real application recursively decends the directory tree, so "touching" each folder's ownership is not a big issue, but I wonder whether there is a way to simply set the parent's ownership and have it inherited by the children.  I think that the issue here, is that the troublesome folder was an orphan... That is, his inheritance was purposefully severed by someone from its parent.

(2) When I look at the troublesome folder's permissions after taking ownership and setting Full Control on it, I was surprised to find that I did not have the usual Full Control bits set, but rather I was assigned special permissions.  I have attached a picture of the permissions so you can see them.  When I created a new document inside of the troublesome folder, I own it and it does have the usual Full Control bits set.  Is this what is expected?  It seems strange that I told the troublesome folder that I wanted full control, and it didn't simply set my access as full control on it.  Naturally, since I do not own the child folders in the troublesome directory, they are still untouchable by me until I do more work...  

So, it appears that my program will have to take ownership on all of the child folders, one by one.  Does that make sense to you or is there another step that I can take to ensure that child folder inheritance is reestablish after I take ownership of the containing/parent folder and grant myself full control on the parent?  

I've attached the most current code that I use to change permissions after taking ownership of the troublesome directory so you can see what I am doing.  When we are done, I think that I will publish the code here since there is nothing that really works out on the Internet.  Hopefully it will help others...

Thanks again for your help!

Mike

WindowsIdentity self = System.Security.Principal.WindowsIdentity.GetCurrent();
 
// Take ownership of the folder.
ChangeOwner.ChangeOwnerOnFolder(ref fullPath, self.Name);
 
// Grant full control and persist
FileSystemAccessRule rule = new FileSystemAccessRule(
                self.Name,
                FileSystemRights.FullControl,
                InheritanceFlags.ContainerInherit |  
                InheritanceFlags.ObjectInherit,
                PropagationFlags.InheritOnly,
                AccessControlType.Allow);
 
DirectorySecurity ds = new DirectorySecurity();
ds.AddAccessRule(rule);
 
// persist changes
Directory.SetAccessControl(fullPath, ds);

Open in new window

FolderPermissions.jpg
Thanks for the help!!!
what was the solution for the ownership not propagating to child objects?