A few weeks ago I had the need to customize DCOM launch & activation permissions for a COM component. I came up with this hack, er script, that I thought I would share “as-is”. If anybody wants to take this and run with it – go for it.
function New-DComAccessControlEntry {
param(
[Parameter(Mandatory=$true, Position=0)]
[string]
$Domain,
[Parameter(Mandatory=$true, Position=1)]
[string]
$Name,
[string]
$ComputerName = ".",
[switch]
$Group
)
#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()
# COM Access Mask
# Execute = 1,
# Execute_Local = 2,
# Execute_Remote = 4,
# Activate_Local = 8,
# Activate_Remote = 16
#Setup the rest of the ACE.
$ACE.AccessMask = 11 # Execute | Execute_Local | Activate_Local
$ACE.AceFlags = 0
$ACE.AceType = 0 # Access allowed
$ACE.Trustee = $Trustee
$ACE
}
$Name = 'IUsr'
$ComComponentName = 'foo'
# Configure the DComConfg settings for the component so it can be activated & launched locally
$dcom = Get-WMIObject Win32_DCOMApplicationSetting `
-Filter "Description='$ComComponentName'" -EnableAllPrivileges
$sd = $dcom.GetLaunchSecurityDescriptor().Descriptor
$nsAce = $sd.Dacl | Where {$_.Trustee.Name -eq $Name}
if ($nsAce) {
$nsAce.AccessMask = 11
}
else {
$newAce = New-DComAccessControlEntry $env:COMPUTERNAME -Name $Name
$sd.Dacl += $newAce
}
$dcom.SetLaunchSecurityDescriptor($sd)
Have fun!
Pingback: Microsoft Most Valuable Professional (MVP) – Best Posts of the Week around Windows Server, Exchange, SystemCenter and more – #39 - Flo's Datacenter Report
Pingback: Dell Community
Pingback: Microsoft Most Valuable Professional (MVP) – Best Posts of the Week around Windows Server, Exchange, SystemCenter and more – #39 - Dell TechCenter - TechCenter - Dell Community
Thanks Keith, this script is very useful, Thanks again!
Any example using CIM available?
In theory, CIM should work. I had gone around and around on this enough that I was desperate to just get something to work. 🙂
I wrote a script based off of your example. The changes work, but they aren’t persisting. When I get the appropriate Win32_DCOMApplicationSetting object, I enable all privileges. Also, when setting properties on this object explicitly, like
$WMIObject.AuthenticationLevel = 1
I have to call the Put() method afterwards on the object for the setting to persist.
Is there something similar I have to do to make the SetLaunchSecurityDescriptor() method call persist? It works, because if I output the DACL I modified directly afterwards, it shows the correct AccessMask I modified. However, that change does not persist.
Here’s my script:
****************************************************
$WMIObject = Get-WMIObject -Class Win32_DCOMApplicationSetting -Filter “Caption=’$AppToGet'” -EnableAllPrivileges
$WMIObject.AuthenticationLevel = 1 # Sets to “None”
$WMIObject.Put() # Saves property set
$serviceDescriptor = $WMIObject.GetLaunchSecurityDescriptor().Descriptor
$accessControl = $serviceDescriptor.DACL | Where {$_.Trustee.Name -eq ‘ANONYMOUS LOGON’}
$accessControl.AccessMask = 31
$WMIObject.SetLaunchSecurityDescriptor($serviceDescriptor)
****************************************************
The access mask change does not persist. Any thoughts? And thank you for your script.
I don’t know off the top of my head. Run the $WMIObject through Get-Member to see if there are any other Set methods.
Thanks for this script. I found that I would needed to cast the $newAce object to a System.Management.ManagementBaseObject before adding it to the DACL list, otherwise I got an invalid cast error from PSObject to ManagementBaseObject. Solution found here: http://measureofchaos.wordpress.com/2012/03/09/modifying-embedded-properties-in-wmi-using-powershell/
Like so:
In the Else statement:
$newAce = New-DComAccessControlEntry $env:COMPUTERNAME -Name $Name
#cast to a ManagementBaseObject
$newAce = [System.Management.ManagementBaseObject] $newAce
$sd.Dacl += $newAce