none
Changing file ownership using PowerShell natives alone RRS feed

  • General discussion

  • All,

    I wish to give ownership of a file programmatically to another user (let's call him "server\test" with UID 1008). I'm running with elevated permissions (right click, run as administrator) on Windows 8. My script will eventually be ran as part of our automated testing environment using snapshotted virtual machines across multiple different Windows versions, from Server 2003 to Server 2012, and everything in between. Therefore, it is undesirable to install dependencies such as Subinacl.exe. I know my answer is to use Get-Acl and Set-Acl, but that's not what I'm after here.

    Why does giving ownership to a file to another user fail silently? What's REALLY going on here? Assuming I have a file owned by Administrator, "C:\run_123\case_chown\src\1f.txt", with normal default security attributes, I use the following script with no warnings nor errors (forgiving typos):

    $SID = [System.Security.Principal.SecurityIdentifier]
    $NTA = [System.Security.Principal.NTAccount]
    
    $user = New-Object $NTA 'test'
    $uid = $user.Translate($SID)
    $path = "C:\run_123\case_chown\src\1f.txt"
    $i = gi -force $path
    
    $ac = $i.GetAccessControl()
    $ac.SetOwner($user)
    $i.SetAccessControl($ac) # gives no error
    
    # all of these checks pass:
    $expected = $uid
    $actual = $i.GetAccessControl().GetOwner($SID)
    Assert($expected.Value -eq $actual.Value)
    
    $expected = $uid.Translate($NTA) # domain-qualify the username
    $actual = $i.GetAccessControl().GetOwner($NTA)
    Assert($expected.Value -eq $actual.Value)
    
    $expected = [int]$uid.Value.Substring($uid.Value.LastIndexOf('-')+1)
    $actual = 1008
    Assert($expected -eq $actual)

    However, when I close powershell and examine the file's security using Explorer, it shows the owner was never changed.

    1. Why does this fail, and more importantly, why does this fail silently?
    2. How is it possible that PowerShell and Explorer see the same file differently?
    3. Would enabling SeTakeOwnershipPrivilege fix this problem for me?
    4. What does Set-Acl do, exactly, that results in this working?

    I'm interested in these questions, rather than "how do I change a file's ownership?".

    I'm aware of the following statement from "Hey, Scripting Guy!":

    "although you can take ownership of a file using Windows PowerShell, we don’t believe that you can give ownership of a file to someone else." (source)

    Why is this the case?


    Monday, March 24, 2014 6:41 PM

All replies

  • By nature Windows only allows use to "Take OwnerShip"  By design it is not set up to allow us to force ownership on anyone.

    There is an API function which can SetOwner on an object.

    Read this: http://forum.sysinternals.com/tool-to-change-ownership-of-files_topic10608.html


    ¯\_(ツ)_/¯

    Monday, March 24, 2014 6:59 PM
  • Well for starters, you're trying to pass in an instance of NTAccount to SetAccessControl(), instead of the security descriptor object:

    $i.SetAccessControl($user)
    
    # Should be: $i.SetAccessControl($ac)

    I have no idea why you're not getting a bunch of errors there.  Have you set $ErrorActionPreference to 'SilentlyContinue'?

    Edit:  Also, you may run into issues due to the "Take ownership" privilege not being enabled by default in your process token.  I don't think PowerShell performs this step for you, so you'd need to use some P/Invoke code to do that yourself. There are examples of this online, for instance: http://channel9.msdn.com/Forums/Coffeehouse/Powershell-subinacl-ownership-of-directories  (which happens to be about this exact topic, taking ownership of files / folders.)

    Monday, March 24, 2014 7:31 PM
  • The link I posted has all of the PowerShell code to do all of the required bits.  It has a CmdLet for Set-Owner.


    ¯\_(ツ)_/¯

    Monday, March 24, 2014 7:48 PM
  • Well for starters, you're trying to pass in an instance of NTAccount to SetAccessControl(), instead of the security descriptor object:

    $i.SetAccessControl($user)
    
    # Should be: $i.SetAccessControl($ac)

    I have no idea why you're not getting a bunch of errors there.  Have you set $ErrorActionPreference to 'SilentlyContinue'?

    Edit:  Also, you may run into issues due to the "Take ownership" privilege not being enabled by default in your process token.  I don't think PowerShell performs this step for you, so you'd need to use some P/Invoke code to do that yourself. There are examples of this online, for instance: http://channel9.msdn.com/Forums/Coffeehouse/Powershell-subinacl-ownership-of-directories  (which happens to be about this exact topic, taking ownership of files / folders.)

    Typo. I apologize. I wrote up the script quickly as a testcase, as the actual script I'm using is far more complicated, and I wanted something simpler. I just wrote it to demonstrate my issue; I didn't actually run it.
    Monday, March 24, 2014 8:03 PM