Jump to content

Problem updating ntSecurityDescriptor when adding computer to domain f


Recommended Posts

Hello Everybody.

Not entirely sure if this is the right forum for this question but it's as close as I can get right now so I’ll give it a shot.

I have a script that I cannot get a specific part to work and I am lost as to what I should do.

Here's the scenario I have been over the last year developing/fixing exiting and new ADSI management scripts our Imaging Department uses Add/Remove/Update/Move Computer accounts in AD My predecessor left us with several I’ll call them "legacy" scripts for lack of a better term that doesn't sound vile. This basically contained only slightly modified blindly copy and pasted Microsoft TechNet examples or scripting guy’s examples. To make a long frustrating story short I'm trying deal with updating a poorly written set of AD management scripts that are about as cohesive and adaptive as water and Cesium (and half the time they have about the same affect on our OU)

One of the first scripts I rewrote was a long drawn out vbscript file with 15+ input boxes to add a computer to one of our OU's and add an account as having the permissions to join the pc to the domain, rename it etc.

I created a set of HTA files to manage the process the vbscript file did effectively putting all the separate linear choices in the original vbscript file into a GUI with general predefined settings and logging. We only run the Tool on a system which is authenticated to the domain (the GUI has a login function bouncing off of ADSI's GetDSObject method to facilitate temporarily running the Tool on a system that is not currently logged in with our domain administrative account) it basically does the following:

  1. Add the PC to the selected OU
  2. Update the PC's DACL so our small Support Security Group is the only ones who can join the PC to the domain
  3. Log the results to an excel file

Now there are a small sub group of PC's that either due to AD timeout or special circumstances we do not add to the domain using our tool.

To facilitate that we have another :thumbdown Beautifully written legacy script that lets us run it on a computer that is still in a workgroup essentially add itself to the domain using WMI. the problem is doing this voids all of the security descriptor settings we need to set and our Support Security Group does not have access to join the pc to the domain, etc.

To try and correct the problem I basically replicated the core function of the HTA I had described early.

To facilitate joining the domain from a workgroup I updated the OpenDSObject's parameters to include an explicit server bind to our domain controller.

Now the part of the HTA that adds the computer to the Domain works just as it does in the normal Tool

And after the account is created I can pull the ntSecurityDescriptor, and get its DACL, I can even add all the required ACEs to the DACL

But when I finally get back to

objComputer.Put "ntSecurityDescriptor",objSecurityDescriptor

It Errors out saying "The security ID structure is invalid"

I can go out to AD and see the computer has been added so I know that's working.

And I really haven't changed the coding that adds the ACE's and updates the DACL from the original tool.

I'm really lost and I can't seem to find anything that's not disambiguous to Exchange server in my searches.

Here's the entire code block of the HTA if anyone can find the problem I would really appreciate it (mind you the exact same core functions have not been modified with the exception of the Domain Controller Server Bind from the original HTA tool which does everything as it should when run on a PC already a member of AD)

<html>
<!--
The purpose of this script to allow DS bench personnel to join a PC to the acct05\domain

'Author: Ryan Strope
'Date: 12/13/07;
'Version: 1.0
-->
<head>
<hta:Application
id="JD"
Applicationname="JD"
border="thin"
borderstyle="raised"
caption="yes"
icon=""
maximizebutton="No"
minimizebutton="No"
showintaskbar="NO"
singleinstance="yes"
scroll="no"
sysmenu="yes"
contextmenu="yes"
selection="yes"
version="1.0"
windowstate="normal"
/>
</head>
<body>
<script language="vbscript" type="text/vbscript">
On Error Resume Next

'----------------------Component Constants----------------------
Const ADMIN = 1
Const USER = 2
Const OTHER = 1
Const UNKNOWN = 2
Const DESKTOP = 3
Const LOW_PROFILE_DESKTOP = 4
Const PIZZA_BOX = 5
Const MINI_TOWER = 6
Const TOWER = 7
Const PORTABLE = 8
Const LAPTOP = 9
Const NOTEBOOK = 10
Const HANDHELD = 11
Const DOCKING_STATION = 12
Const ALL_IN_ONE = 13
Const SUB_NOTEBOOK = 14
Const SPACE_SAVING = 15
Const LUNCH_BOX = 16
Const MAIN_SYSTEM_CHASSIS = 17
Const EXPANSION_CHASSIS = 18
Const SUB_CHASSIS = 19
Const BUS_EXPANSION_CHASSIS = 20
Const PERIPHERAL_CHASSIS = 21
Const STORAGE_CHASSIS = 22
Const RACK_MOUNT_CHASSIS = 23
Const SEALED_CASE_PC = 24

'Global Functions
Function PopulateACES(Trustee, AccessMask, AceFlags, AceType, Flags, ObjectType)
Dim LocalACE
Set LocalACE = CreateObject("AccessControlEntry")
LocalACE.Trustee = Trustee
LocalACE.AccessMask = AccessMask
LocalACE.AceFlags = AceFlags
LocalACE.AceType = AceType
If Not IsEmpty(Flags) Then LocalACE.Flags = Flags
If Not IsEmpty(ObjectType) Then LocalACE.ObjectType = ObjectType
Set PopulateACES = LocalACE
End Function

Function addUser(byVal Computer, byVal AdminGroup, byVal LDAPPath)
Dim objRootDSE
Dim objContainer
Dim objComputer
Dim objSecurityDescriptor
Dim objDACL
Const ADS_OPTION_SECURITY_MASK = 3
Const ADS_SECURITY_INFO_DACL = &H4
Const ADS_UF_PASSWD_NOTREQD = &h0020
Const ADS_UF_WORKSTATION_TRUST_ACCOUNT = &h1000
Const ADS_ACETYPE_ACCESS_ALLOWED = &h0
Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = &h5
Const ADS_FLAG_OBJECT_TYPE_PRESENT = &h1
Const ADS_RIGHT_GENERIC_READ = &h80000000
Const ADS_RIGHT_DS_SELF = &h8
Const ADS_RIGHT_DS_WRITE_PROP = &h20
Const ADS_RIGHT_DS_CONTROL_ACCESS = &h100
Const ALLOWED_TO_AUTHENTICATE = "{68B1D179-0D15-4d4f-AB71-46152E79A7BC}"
Const RECEIVE_AS = "{AB721A56-1E2f-11D0-9819-00AA0040529B}"
Const SEND_AS = "{AB721A54-1E2f-11D0-9819-00AA0040529B}"
Const USER_CHANGE_PASSWORD = "{AB721A53-1E2f-11D0-9819-00AA0040529b}"
Const USER_FORCE_CHANGE_PASSWORD = "{00299570-246D-11D0-A768-00AA006E0529}"
Const USER_ACCOUNT_RESTRICTIONS = "{4C164200-20C0-11D0-A768-00AA006E0529}"
Const VALIDATED_DNS_HOST_NAME = "{72E39547-7B18-11D1-ADEF-00C04FD8D5CD}"
Const VALIDATED_SPN = "{F3A64788-5306-11D1-A9C5-0000F80367C1}"
Const ADS_SECURE_AUTHENTICATION = 1

Set objContainer = GetObject("LDAP:").OpenDSObject(LDAPPath,"acct05\" + UserNameHidden.value,PasswordHidden.value,1 + 512)
Set objComputer = objContainer.Create("Computer", "cn=" & Computer)
objComputer.Put "sAMAccountName", Computer & "$"
objComputer.Put "userAccountControl", ADS_UF_PASSWD_NOTREQD Or ADS_UF_WORKSTATION_TRUST_ACCOUNT
'On Error Resume Next
objComputer.SetInfo
If(Err <> 0) Then
addUser = "Possible Duplicate Not Created"
Else
Set objComputer = GetObject("LDAP:").OpenDSObject(replace(LDAPPath,"A05DC21/","A05DC21/CN=" + Computer + ",",1,-1,1),"acct05\" + UserNameHidden.value, PasswordHidden.value,1 + 512)
Set objSecurityDescriptor = objComputer.Get("ntSecurityDescriptor")
Set objDACL = objSecurityDescriptor.DiscretionaryAcl
objDACL.AddAce PopulateACES(AdminGroup, ADS_RIGHT_GENERIC_READ, 0, ADS_ACETYPE_ACCESS_ALLOWED,Empty,Empty)
' objACE2 through objACE6: Extended Rights
objDACL.AddAce PopulateACES(AdminGroup, ADS_RIGHT_DS_CONTROL_ACCESS, 0, ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, ADS_FLAG_OBJECT_TYPE_PRESENT, ALLOWED_TO_AUTHENTICATE)
objDACL.AddAce PopulateACES(AdminGroup, ADS_RIGHT_DS_CONTROL_ACCESS, 0, ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, ADS_FLAG_OBJECT_TYPE_PRESENT, RECEIVE_AS)
objDACL.AddAce PopulateACES(AdminGroup, ADS_RIGHT_DS_CONTROL_ACCESS, 0, ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, ADS_FLAG_OBJECT_TYPE_PRESENT, SEND_AS)
objDACL.AddAce PopulateACES(AdminGroup, ADS_RIGHT_DS_CONTROL_ACCESS, 0, ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, ADS_FLAG_OBJECT_TYPE_PRESENT, USER_CHANGE_PASSWORD)
objDACL.AddAce PopulateACES(AdminGroup, ADS_RIGHT_DS_CONTROL_ACCESS, 0, ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, ADS_FLAG_OBJECT_TYPE_PRESENT, USER_FORCE_CHANGE_PASSWORD)
' objACE7: Property Sets
objDACL.AddAce PopulateACES(AdminGroup, ADS_RIGHT_DS_WRITE_PROP, 0, ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, ADS_FLAG_OBJECT_TYPE_PRESENT, USER_ACCOUNT_RESTRICTIONS)
' objACE8 and objACE9: Validated Rights
objDACL.AddAce PopulateACES(AdminGroup, ADS_RIGHT_DS_SELF, 0, ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, ADS_FLAG_OBJECT_TYPE_PRESENT, VALIDATED_DNS_HOST_NAME)
objDACL.AddAce PopulateACES(AdminGroup, ADS_RIGHT_DS_SELF, 0, ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, ADS_FLAG_OBJECT_TYPE_PRESENT, VALIDATED_SPN)
objSecurityDescriptor.DiscretionaryAcl = objDACL
objComputer.Put "ntSecurityDescriptor", objSecurityDescriptor
msgbox err.description & "12 "& err.number & " " & err.Source
err.Clear()
objComputer.SetOption ADS_OPTION_SECURITY_MASK, ADS_SECURITY_INFO_DACL
objComputer.SetInfo
msgbox err.description & "13 "& err.number
err.Clear()
msgbox "Test"
addUser = "Success"
End If
Set objRootDSE = Nothing
Set objContainer = Nothing
Set objComputer = Nothing
Set objSecurityDescriptor = Nothing
On Error GoTo 0
End Function

Function ValidLogin()
On Error Resume Next
Set ADTestLoginObject = GetObject("LDAP:").OpenDSObject("LDAP://A05DC21/DC=ACCT05,DC=us,DC=lmco,DC=com","acct05\" + UserNameHidden.value,PasswordHidden.value,1 + 512)
ValidLogin = (Err.Number = 0)
End Function

Function GetComputerName() : For Each BIOS In GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2").ExecQuery("Select SerialNumber from Win32_BIOS"): GetComputerName = ucase(BIOS.SerialNumber) : Next : End Function

Function JoinTheDomain()
If Not ValidLogin() Then
Window.alert("Invalid User ID or Password." + vbcrlf + vbcrlf + "Please try again or contact your network administrator.")
UserNameHidden.value = "owgpcset"
PasswordHidden.value = ""
PasswordHidden.select()
Else
if GetChassis() = "Laptop" then LDAPHidden.value = replace(LDAPHidden.value,"Workstations","Laptops",1,-1,1)
AddComputers()
End If
End Function

Function Is_System_Supported(Supported_Chassis_Types)
If IsEmpty(Supported_Chassis_Types) Then Is_System_Supported = True : Exit Function
For Each Chassis In GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2").ExecQuery("Select ChassisTypes from Win32_SystemEnclosure") : For Each SupportedChassis In Supported_Chassis_Types : If SupportedChassis = Chassis.ChassisTypes(0) Then Is_System_Supported = True : Exit Function : End If : Next : Next
Is_System_Supported = False
End Function 'Is_System_Supported(Supported_Chassis_Types)

Function GetChassis()
GetChassis = "Desktop"
If Is_System_Supported(Array(PORTABLE,LAPTOP,NOTEBOOK,DOCKING_STATION,SUB_NOTEBOOK,PERIPHERAL_CHASSIS)) Then GetChassis = "Laptop"
End Function

'Global Subs
Sub AddComputers()
If (addUser(GetComputerName(),UserGroupHidden.value,LDAPHidden.value) = "Success") Then
If window.confirm("This " + GetChassis() + " has been successfully joined to the " + GetChassis() + " domain, Would you like to reboot now?") Then Reboot()
window.close()
Else
window.alert("This " + GetChassis() + " could not join the " + GetChassis() + " domain. A duplicate name already exits" + vbCrLf + "Please attempt to join the domain manually, or contact your system administrator...")
window.close()
End If
End Sub 'InstallSelectedComputerlications(ComputersNames, ComputersPaths)

Sub Reboot : For Each OS in GetObject("winmgmts:{(Shutdown)}").ExecQuery("Select * from Win32_OperatingSystem") : OS.Reboot : Next : End Sub

'Event Handlers
Sub Window_onload()
window.moveTo 300,100
window.resizeTo 300,120
JoinButton.value = "Join this " + GetChassis() + " to the ACCT05 domain"
PasswordHidden.select()
document.title="Join " + UCase(GetComputerName()) + " to the ACCT05 Domain"
End Sub 'Window_onload()

Sub CheckKey() If window.event.keyCode = 13 Then JoinTheDomain() : End If : End Sub

</script>
<textarea id="Title" style="font-weight: bold; font-size: 10pt; left: 5px; overflow: hidden; width: 280px; border-top-style: none; font-family: verdana; border-right-style: none; border-left-style: none; position: absolute; top: 2px; height: 18px; border-bottom-style: none">Enter your ACCT05 Logon.</textarea>
<input id="PasswordHidden" onkeypress="CheckKey()" type="password" value="" style="font-size: 10pt; left: 83px; border-top-style: none; border-bottom: blue thin solid; font-family: verdana; border-right-style: none; border-left-style: none; position: absolute; top: 40px; width: 201px;" />
<input id="UserNameHidden" type="Text" value="owgpcset" style="border-right: blue thin; border-top: blue thin; font-size: 10pt; left: 83px; border-left: blue thin; border-bottom: blue thin solid; font-family: verdana; position: absolute; top: 19px; width: 201px;" />
<input id="UserIDText" type="text" value="User ID:" style="font-size: 10pt; left: 5px; border-top-style: none; font-family: verdana; border-right-style: none; border-left-style: none; position: absolute; top: 20px; border-bottom-style: none; vertical-align: middle; text-align: right; width: 72px;" />
<input id="PasswordText" type="text" value="Password:" style="font-size: 10pt; left: 5px; border-top-style: none; font-family: verdana; border-right-style: none; border-left-style: none; position: absolute; top: 41px; border-bottom-style: none; vertical-align: middle; text-align: right; width: 72px;" />
<input id="LDAPHidden" type="hidden" value="LDAP://A05DC21/OU=Workstations,OU=Production,OU=Owego,OU=EPI,DC=ACCT05,DC=us,DC=lmco,DC=com" style="left: 13px; position: absolute; top: 113px" />
<input id="UserGroupHidden" type="hidden" value="owg.irm.Desktop.Admin" style="left: 175px; position: absolute; top: 113px" />
<input type="button" value="Join Domain" name="JoinButton" onClick="JoinTheDomain()" style="font-size: 10pt; left: 5px; font-family: verdana; position: absolute; top: 63px; width: 280px;" />
</body>
</html>

Thanks for the help and future input

Cheers,

Ryan Strope

Distributed Services

(Software package development/testing)

Lockheed Martin Systems Integration Owego

(Cyber City Computers)

ryan.strope@lmco.com

Quid quid latine dictum sit, altum videtur

Link to comment
Share on other sites


Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...