Link to home
Start Free TrialLog in
Avatar of kontrariankid
kontrariankidFlag for United States of America

asked on

Can Create Share but Cannot Add Permissions from Target Domain

# //************************************************************************************************************
# // ***** Script Header *****
# //
# // Solution:  Coretech Share Functions
# // File:      NewShareWithPermission.ps1
# // Author:      Jakob Gottlieb Svendsen, Coretech A/S. http://blog.coretech.dk
# // Purpose:  
# // New-Share: Creates new Share on local or remote PC, with custom permissions.
# // Required Parameters: FolderPath, ShareName
# //
# // New-ACE: Creates ACE Objects, for use when running New-Share.
# // Required Parameters: Name, Domain
# //
# // New-SecurityDescriptor: used by New-Share to prepare the permissions.
# // Required Parameters: ACEs
#//
# // Usage Examples:  
# // New-Share -FolderPath "C:\Temp" -ShareName "Temp" -ACEs $ACE,$ACE2  -Description "Test Description" -Computer "localhost"
# // Sharing of folder C:\Temp, with the Name "Temp". ACE's (Permissions) are sent via the -ACEs parameter.
# // Create them with New-ACE and send one  or more, seperated by comma (or create and array and use that)
# //
# // This is the first in a couple of share-administration scripts i am planning to make and release on the blog.
# //
# // Please comment the blog post, if you have any suggestions, questions or feedback.
# // Contact me if you need us to make a custom script (or cause not for free ;-) )
# //
# // CORETECH A/S History:
# // 0.0.1     JGS 30/06/2009  Created initial version.
# //
# // Customer History:
# //
# // ***** End Header *****
# //**************************************************************************************************************
#//----------------------------------------------------------------------------
#//  Procedures
#//----------------------------------------------------------------------------

Function New-SecurityDescriptor (
$ACEs = (read-host "Missing one or more Trustees"),
[string] $ComputerName = ".")
{
      #Create SeCDesc object
      $SecDesc = ([WMIClass] "\\$ComputerName\root\cimv2:Win32_SecurityDescriptor").CreateInstance()
      #Check if input is an array or not.
      if ($ACEs -is [System.Array])
      {
            #Add Each ACE from the ACE array
            foreach ($ACE in $ACEs )
            {
                  $SecDesc.DACL += $ACE.psobject.baseobject
            }
      }
      else
      {
            #Add the ACE
            $SecDesc.DACL =  $ACEs
      }
      #Return the security Descriptor
      return $SecDesc
}

Function New-ACE (
      [string] $Name = (read-host "Please provide user/group name for trustee"),
      [string] $Domain = (read-host "Please provide Domain name for trustee"),
      [string] $Permission = "Read",
      [string] $ComputerName = ".",
      [switch] $Group = $false)
{
      #Create the Trusteee Object
      $Trustee = ([WMIClass] "\\$ComputerName\root\cimv2:Win32_Trustee").CreateInstance()
      #Search for the user or group, depending on the -Group switch
      if (!$group)
      { $account = [WMI] "\\$ComputerName\root\cimv2:Win32_Account.Name='$Name',Domain='$Domain'" }
      else
      { $account = [WMI] "\\$ComputerName\root\cimv2:Win32_Group.Name='$Name',Domain='$Domain'" }
      #Get the SID for the found account.
      $accountSID = [WMI] "\\$ComputerName\root\cimv2:Win32_SID.SID='$($account.sid)'"
      #Setup Trusteee object
      $Trustee.Domain = $Domain
      $Trustee.Name = $Name
      $Trustee.SID = $accountSID.BinaryRepresentation
      #Create ACE (Access Control List) object.
      $ACE = ([WMIClass] "\\$ComputerName\root\cimv2:Win32_ACE").CreateInstance()
      #Select the AccessMask depending on the -Permission parameter
      switch ($Permission)
      {
            "Read"              { $ACE.AccessMask = 1179817 }
            "Change"  {      $ACE.AccessMask = 1245631 }
            "Full"               { $ACE.AccessMask = 2032127 }
            default { read-host "$Permission is not a supported permission value. Possible values are 'Read','Change','Full'" }
      }
      #Setup the rest of the ACE.
      $ACE.AceFlags = 3
      $ACE.AceType = 0
      $ACE.Trustee = $Trustee
      #Return the ACE
      return $ACE
}

Function New-Share (
      [string] $FolderPath = (read-host "Please provide the share folder path (FolderPath)"),
      [string] $ShareName = (read-host "Please provide the Share Name"),
      $ACEs,
      [string] $Description = "",
      [string] $ComputerName=".")
{
      #Start the Text for the message.
      $text = "$ShareName ($FolderPath): "
      #Package the SecurityDescriptor via the New-SecurityDescriptor Function.
      $SecDesc = New-SecurityDescriptor $ACEs
      #Create the share via WMI, get the return code and create the return message.
      $Share = [WMICLASS] "\\$ComputerName\Root\Cimv2:Win32_Share"
      $result = $Share.Create($FolderPath, $ShareName, 0, $false , $Description, $false  , $SecDesc)
      switch ($result.ReturnValue)
      {
            0 {$text += "has been successfully created" }
            2 {$text += "Error 2: Access Denied" }
            8 {$text += "Error 8: Unknown Failure" }
            9 {$text += "Error 9: Invalid Name"}
            10 {$text += "Error 10: Invalid Level" }
            21 {$text += "Error 21: Invalid Parameter" }
            22 {$text += "Error 22 : Duplicate Share"}
            23 {$text += "Error 23: Redirected Path" }
            24 {$text += "Error 24: Unknown Device or Directory" }
            25 {$text += "Error 25: Net Name Not Found" }
      }
      #Create Custom return object and Add results
      $return = New-Object System.Object
      $return | Add-Member -type NoteProperty -name ReturnCode -value $result.ReturnValue
      $return | Add-Member -type NoteProperty -name Message -value $text      
      #Return result object
      $return
}

#//----------------------------------------------------------------------------
#//  Main routines
#//----------------------------------------------------------------------------

#Create ACE's for the securitydescriptor for the share:
#a group ACE, containing Group info, please notice the -Group switch

$ACE = New-ACE -Name "001UniqueUser" -Domain "TargetDomain" -Permission "Change"

$result = New-Share -FolderPath "d:\users\001UniqueUser" -ShareName "001UniqueUser" -ACEs $ACE -Description "Hidden Home Share for UniqueUser, 001" -Computer "ServerinLegacyDomain"



#Output result message from new-share
Write-Output $result.Message

#Check if the share was succesfully created
If ($result.ReturnCode -eq 0)
{
      #Creation was succesfull, put your next code here.
}

#//----------------------------------------------------------------------------
#//  End Script
#//----------------------------------------------------------------------------
Avatar of kontrariankid
kontrariankid
Flag of United States of America image

ASKER

Above script works great when adding permissions from the same domain of which the server (containing the shares) is a member. But I need to create shares on a server in legacy domain (which the script does well), but I also need to add "change" permissions onto those shares such as TargetDomain\userid. If nothing else, I could just add "Everyone" to each share because of course the NTFS permissions are locked down.

The target domain is trusted by the legacy domain. I am able to add permissions  to the shares manually when logging into the server in legacy domain.

This is the resulting message from my output. The share(s) are created but permissions are empty:

Cannot convert value "\\.\root\cimv2:Win32_Account.Name='001UniqeUser',Domain='TargetDomain'" to type "System.Managem
ent.ManagementObject". Error: "Not found "
At C:\Users\dmvbjt\Desktop\NewShareWithPermissions_Test.ps1:73 char:20
+     { $account = [WMI] <<<<  "\\$ComputerName\root\cimv2:Win32_Account.Name='$Name',Domain='$Domain'"
}
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException
 
001UniqueUser$ (d:\users\001UniqueUser): has been successfully created
Also, if it's not asking too much :) I need some help to understand a better way to add multiple permissions. I have discovered that this works well by changing ACE to ACE1 and incrementing from there so the value is not overwritten (again only when adding permissions and server are related to the same domain). How could I replace this below process by an import-csv? Is that feasible in this situation or would I need a new script altogether?

$ACE = New-ACE001 -Name "001UniqeUser" -Domain "TargetDomain" -Permission "Change"
$ACE = New-ACE002 -Name "002UniqeUser" -Domain "TargetDomain" -Permission "Change"
$ACE = New-ACE003 -Name "003UniqeUser" -Domain "TargetDomain" -Permission "Change"

$result = New-Share -FolderPath "d:\users\001UniqeUser" -ShareName "001UniqeUser" -ACEs $ACE001 -Description "Hidden Home Share for UniqeUser, 001" -Computer "ServerinLegacyDomain"
$result = New-Share -FolderPath "d:\users\002UniqeUser" -ShareName "002UniqeUser" -ACEs $ACE002 -Description "Hidden Home Share for UniqeUser, 002" -Computer "ServerinLegacyDomain"
$result = New-Share -FolderPath "d:\users\003UniqeUser" -ShareName "003UniqeUser" -ACEs $ACE003 -Description "Hidden Home Share for UniqeUser, 003" -Computer "ServerinLegacyDomain"
ASKER CERTIFIED SOLUTION
Avatar of kontrariankid
kontrariankid
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