We help IT Professionals succeed at work.

Re-apply ACL to share/folder

I'm performing a file scan and collecting information from all of a server's shares into a report file.
Running into trouble when something is amiss with permissions, requiring me to often take ownership and re-push the permissions down the tree (nothing's changing, just re-applying the inheritance).
Is there a way to automate this, so that my code can accomodate those scenarios, rather than announcing them so I have to perform the cleanup manually and rerun the report?  Servers are all Windows 2003
I'm not opposed to command-line tools in a shell process, but would prefer they be native.
Comment
Watch Question

Commented:
My copy pasting got mixed up.
The attached file contains instructions on a registry key change for your server so when files are copied they carry the permissions with them.
It came in really handy when I had to create a backup server and had to copy many files where many different users had different permissions to different folders/files.
Top Expert 2007

Author

Commented:
Not sure that's what I'm attempting to do here.
I'm simply performing a recursive scan of a local server volume, and collecting file details (date, size, etc.).
Every so often a folder comes up with an Access Denied.  If I manually claim ownership, and re-push the permissions, I can re-run the code and get the results back as expected.  
So, I'm not copying between servers.  Just curious if there was an easy way to take ownership and reaapply perms down the tree...

Commented:
Oh. I see. Are you running your program with elevated permissions, using run as administrator?
Top Expert 2007

Author

Commented:
Win2k3, not 2k8.  Running under domain admin credentials.
Chris DentPowerShell Developer
Top Expert 2010

Commented:
Hey SirBounty,

Catch the access denied exception then perhaps attempt to call the SetOwner method from System.Security.AccessControl.FileSystemSecurity? Or did you try that already?

If that works you may either disable AccessRuleProtection or load a couple of access control entries to finish things off?

Chris
Top Expert 2007

Author

Commented:
No, I haven't tried it. I'll give it a shot.  Thanks.

Commented:
'I'm performing a file scan and collecting information from all of a server's shares into a report file'
How are you doing that? Take a look at this:
http://www.vbdotnetforums.com/vb-net-general-discussion/21011-my-computer-filesystem-findinfiles-unauthorizedaccessexception-directorysecurity.html

Top Expert 2007

Author

Commented:
Chris-Dent - would you have an example?

This is a slimmed down version of the code snippet:
Try
  For Each fi As FileInfo In aDir.GetFiles()  'Access denied flags here (5)
    Try
      Dim ShortName As String = ResolveToShortPath(fi.FullName)
      Dim RO As Boolean = False
      Dim Owner As String = GetOwner(fi)
      Dim ext As String = fi.Extension.ToLower
      If (File.GetAttributes(fi.FullName) And FileAttributes.ReadOnly) = FileAttributes.ReadOnly Then RO = True
 '...
    Catch ex As Exception
      IsInError = True
      console.writeline ex.message  
    End Try

Open in new window

Top Expert 2007

Author

Commented:
I've maxed out the points - would really like a working solution on this, if you have any examples?
I appreciate your help! :^)
Chris DentPowerShell Developer
Top Expert 2010

Commented:
Damn I'm sorry I completely forgot. Let me throw something together.

Chris
PowerShell Developer
Top Expert 2010
Commented:

Okay, this is a start, it may still fail with SetOwner, it's quite hard to call it reliably, I need to have more of a look.

Chris
Imports System.IO
Imports System.Security.AccessControl
Imports System.Security.Principal

Module Module1
    Sub Main()
        Dim Dir As New DirectoryInfo("C:\Temp")

        For Each SubDirectory As DirectoryInfo In Dir.GetDirectories()
            Try
                SubDirectory.GetFiles()
            Catch ex As UnauthorizedAccessException

                Dim Identity As NTAccount = New NTAccount("administrators")

                Dim DirSecurity As DirectorySecurity = SubDirectory.GetAccessControl()
                ' Take ownership
                DirSecurity.SetOwner(Identity)
                ' Enable inheritance again
                DirSecurity.SetAccessRuleProtection(False, False)
                ' Apply modified ACL
                SubDirectory.SetAccessControl(DirSecurity)

            End Try
        Next
    End Sub
End Module

Open in new window

Top Expert 2007

Author

Commented:
No errors against a test folder on my local drive, but the owner doesn't seem to change either - still shows me as the owner, rather than admins.

I think the other part of my issue is that it throws an exception in my for/each block, and I've no clue how to pick up from where it left off.  I tried passing the folder/file item to a sub, but it generally burps at the 'collection' piece.
Top Expert 2007

Author

Commented:
Oops - my mistake, it actually 'did' work - I was looking at the parent owner - it changed the child object.
However, if I change it to a domain account, Domain Admins, for example, it fails with:
The security identifier is not allowed to be the owner of this object

Any ideas?
Chris DentPowerShell Developer
Top Expert 2010

Commented:

Yeah, the constraints on SetOwner are extreme. It must be the current user or token of the current user. Essentailly either the user, or a group like Administrators. Discussed here:

https://connect.microsoft.com/VisualStudio/feedback/details/96556/setowner-method-in-namespace-system-security-accesscontrol-does-not-work

If you want to set to a different security principal I'm afraid you're a bit out of luck with .NET. A frustration I've bumped into before when trying to do much the same thing in PowerShell.

I can spend a bit more time with this and make it more robust and useful if you're happy enough with the limitations?

Chris
Top Expert 2007

Author

Commented:
Tried it also with the SID of Domain Admins, but it gives me the same error. : \
Chris DentPowerShell Developer
Top Expert 2010

Commented:

Yeah, limited is a bit of a tame description :)

Chris
Top Expert 2007

Author

Commented:
(oops - didn't refresh)

Oh, so you're saying I'd have to take ownership with my specific account? Hmm... I'm not sure about that....

What I do (manually) now is, right-click, security, advanced, owner, and then assign Administrators to all sub folders.  Then I have to go back to the security tab, advanced, and replace permissions on all child objects.
That's the bit I'm trying to automate.

If you're saying that it's not possible, unless I claim ownership for 'my' account, then I'll need to think about that.  Didn't really want to take specific user ownership...
Chris DentPowerShell Developer
Top Expert 2010

Commented:

No, you should be able to set Administrators as owner (hopefully as in the example above), provided the current identity (the caller) has the Administrators group listed in their token (which they should if they're a member of that).

Chris
Top Expert 2007

Author

Commented:
I'm a bit confused then?  But I'll try a live test and get back to you.
Thanks again for the help!
Chris DentPowerShell Developer
Top Expert 2010

Commented:

Okay, let me know how it goes :)

Chris
Top Expert 2007

Author

Commented:
Having too many .Net related issues, so I switched to vbscript... : \
Thanks.