TofuBug Posted December 17, 2007 Share Posted December 17, 2007 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:Add the PC to the selected OUUpdate the PC's DACL so our small Support Security Group is the only ones who can join the PC to the domainLog the results to an excel fileNow 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 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 ToolAnd after the account is created I can pull the ntSecurityDescriptor, and get its DACL, I can even add all the required ACEs to the DACLBut when I finally get back toobjComputer.Put "ntSecurityDescriptor",objSecurityDescriptorIt 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 inputCheers,Ryan StropeDistributed Services(Software package development/testing)Lockheed Martin Systems Integration Owego(Cyber City Computers)ryan.strope@lmco.comQuid quid latine dictum sit, altum videtur Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now