none
VBS: Running my ADSI modify script from a non-domain controller?

    Question

  • Hello Scripting Guys Forum :)

    Firstly, let me say how great this resource is, how much I enjoyed getting started many months ago with the 'Sesame Script' series of articles and how much it has furthered my career (I am now the resident AD SME and a good deal of this is due to my ability to write code for use on my client's directories). I haven't invested much time in PowerShell yet, I decided to still focus on vbs as its got 100% compatibility in all current Windows environments, while in some older environments Powershell requires plugins to be installed. Even in just scripting for AD against 2008 DCs, my vbs can just do what it needs to while the equivalent in PowerShell code requires the PowerShell commandlets to be installed on the DCs (from what I understand).

    However with Server 2012, I’m sure I’ll be working with PS a lot more. Good to know many of the core principals I’ve learned about the directory and its functions will be unchanged, it’s just getting my head around syntax.

    Anyways, the reason I am here is because I want to know about the details of remote execution of vbs code, specifically vbs code that modifies the directory. I know with PS there are ‘remote execution’ permissions that need to be enabled on the DC, but I don’t know how that applies to vbs.

    The problem is:

    1. I’ve written a script that modifies some user attributes in the directory.
    2. When I run this script from a Domain Controller, it works fine. Every time I run one of my own scripts I do it from a DC, because that’s the access I have. I’ve never had any problems (beyond my own misunderstandings ;)).
    3. This particular script is to go to the Service Desk, and they will be using it on their Jumphosts, which are just MS Terminal Servers that enable many Service Desk operators to do work on the domain, they’ve got the RSAT tools installed and they do simple things like reset passwords and create user accounts.
    4. The script does not work on the Jumphost. The Jumphost obviously has ‘rights’ to modify the directory (ADUC can be run from there and modify operations performed) but I didn’t think that was computer specific anyway. It’s the user’s rights on the domain that allow the modify operation, assuming the tools are installed on the local machine. So I’m logging into the Jumphost as a Domain Administrator and the script still does not function under my login.

    Additional Notes:

    I’ve seen use of the impersonate method to try and get around this, where I impersonate a domain controller and perhaps the script works because the directory believes it’s being executed from there? Is that possible? If it is possible, is there a less ‘hacky’ way to do it?

    Here is the code I’m using to modify the attribs, its really boiler-plate stuff and shouldn’t be the cause of the problem:

    objCommand.CommandText = "<LDAP://THEDC/THEDOMAIN>;(&(objectCategory=user)(samaccountname=" & username & "));distinguishedname;subTree"

                                                    Set objRecordSet = objCommand.Execute

                                                    objRecordSet.MoveFirst

                                                    strUserDN = objRecordSet.Fields("distinguishedname").Value

                                                    Set objUser = GetObject("LDAP://" & strUserDN)

                                                    objUser.put "msExchOmaAdminWirelessEnable", 7

                                                    objUser.Setinfo

    Any help would be appreciated! :)

     


    Thursday, February 28, 2013 6:50 AM

Answers

  • You do not need to use credentials in a domain.  Just run from an account that can run the AD tools.  VBScript uses the same authentication method.

    You cannot remote into an AD domain to  AD unless AD has been modified to allow non-Kerberos authentication.

    There is no impersonate in LDAP/ADSI.  You are thinking of WMI

    he server the script is running on must be connected to the domain.  If it is then you can run the VBScript query with no problems.

    If you have RSAT tools installed why use VBScript?

    You say the scrip doesn't work.  What doesn't work?  What error messages?

    You need to be clear and post a complete script and not just a few bits.


    ¯\_(ツ)_/¯

    Thursday, February 28, 2013 7:07 AM
  • Your script can be run on any computer joined to the domain. In fact, it is recommended that scripts not be run on a domain controller.

    I found two example scripts where the number in the Put statement is quoted:

    objUser.Put "msExchOmaAdminWirelessEnable", "7"
    
    As in this article:

    http://support.microsoft.com/kb/830188

    Otherwise, please indicate any error message, including the statement that raises the error. There is a slight chance that an error can be raised on your "Set objUser" statement, but it should be very rare (when the common name of the user includes the "/" character).


    Richard Mueller - MVP Directory Services

    Thursday, February 28, 2013 11:23 AM

All replies

  • You do not need to use credentials in a domain.  Just run from an account that can run the AD tools.  VBScript uses the same authentication method.

    You cannot remote into an AD domain to  AD unless AD has been modified to allow non-Kerberos authentication.

    There is no impersonate in LDAP/ADSI.  You are thinking of WMI

    he server the script is running on must be connected to the domain.  If it is then you can run the VBScript query with no problems.

    If you have RSAT tools installed why use VBScript?

    You say the scrip doesn't work.  What doesn't work?  What error messages?

    You need to be clear and post a complete script and not just a few bits.


    ¯\_(ツ)_/¯

    Thursday, February 28, 2013 7:07 AM
  • Here is a good place to start:

    http://support.microsoft.com/kb/830188


    ¯\_(ツ)_/¯

    Thursday, February 28, 2013 7:17 AM
  • Your script can be run on any computer joined to the domain. In fact, it is recommended that scripts not be run on a domain controller.

    I found two example scripts where the number in the Put statement is quoted:

    objUser.Put "msExchOmaAdminWirelessEnable", "7"
    
    As in this article:

    http://support.microsoft.com/kb/830188

    Otherwise, please indicate any error message, including the statement that raises the error. There is a slight chance that an error can be raised on your "Set objUser" statement, but it should be very rare (when the common name of the user includes the "/" character).


    Richard Mueller - MVP Directory Services

    Thursday, February 28, 2013 11:23 AM
  • Thanks for the responses, guys :)

    Took me a little while to get back, but I took what you said and went back and tested again.. and it worked. Let me respond to some of the logic involved here, I'll explain what I believe has happened and I'd be interested to hear if you agree. I'll also post my whole script incase someone else wants to use it.

    You do not need to use credentials in a domain.  Just run from an account that can run the AD tools.  VBScript uses the same authentication method.

    Yep, this is what was confusing me as I knew this.

    You cannot remote into an AD domain to  AD unless AD has been modified to allow non-Kerberos authentication.

    I was thinking the 'remote code execution' permission as used by PowerShell. vbs does not need this from what I know.

    If you have RSAT tools installed why use VBScript?

    The intention was to automate part of the dsa.msc GUI to allow service desk to bulk process these kind of requests. Actually looking up the user in dsa.msc and navitgating the tabs takes longer than a simple script that asks for the username and sets the attribute. Keep this in context of a very large Service Desk servicing multiple large corporate networks.

    Your script can be run on any computer joined to the domain. In fact, it is recommended that scripts not be run on a domain controller.

    I found two example scripts where the number in the Put statement is quoted

    Oh, I know the mechanics of how the attribute works is sound, because I could manually manipulate it (through ADSIedit or there is a tab in dsa.msc if you don't use the 'Find' feature) and get the behaviour I wanted. It was then automating it that wasn't working.

    I will now post the script, please understand I only modified this and did not write it from scratch. This is not the way I would have done it, but my task was just to add some functionality and I've done that. For instance I'd use RootDSE rather than define a domain controller..

    'Title: ActiveSync and OCS User configuration
    'Contributor: Marco
    'Author: Unknown
    'Date: 26/2/2013
    'Version: 1.1
    '
    'Set locale to Australia for date formatting and other values
    SetLocale(3081)
    
    'Active Directory Connection Parameters
    Const Ads_Scope_SubTree = 2
    Set objConnection = CreateObject("ADODB.Connection")
    Set objCommand = CreateObject("ADODB.Command")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Open "Active Directory Provider"
    Set objCommand.ActiveConnection = objConnection
    objCommand.Properties("Page Size") = 1000
    objCommand.Properties("Searchscope") = Ads_Scope_SubTree 
    
    If Msgbox ("Do you want to remove ActiveSync rights for bulk users?"  & chr(13) & chr(13) & "Pressing NO will allow you to add or remove OCS and ActiveSync for a single user.",vbYesNo,"OCS and ActiveSync Configuration") = vbyes then
    		If Msgbox ("You need to place the usernames in a text file called OCSUsers.txt, one at the start of each new line and nothing else on each line. Then place this text file in c:\GSD\ directory on the Domain Controller this script is run from. Putting this script in there as well is probably smart to keep it neat. A log file will also be generated in that directory showing you the progress of the process."  & chr(13) & chr(13) & "Have you done this and are ready for me to process?",vbYesNo,"OCS and ActiveSync Configuration") = vbyes then
    			'Read computer list from txt file and write progress to a log
    			Const ForReading = 1
    			dt = Replace(Date,"/","-")
    			strFileName = "C:\GSD\" & dt & "-OCSandActiveSyncLog.txt"
    			Set objFSO = CreateObject("Scripting.FileSystemObject")
    			Set objFile = objFSO.CreateTextFile(strFileName)
    			'Users.txt requires the usernames of the computers to be listed one on each new line
    			Set objFile2 = objFSO.OpenTextFile("C:\GSD\OCSUsers.txt", ForReading)
    			'Set up log
    			objFile.WriteLine ("Active Sync Removal Log")
    			objFile.WriteLine ("-----------------------")
    			objFile.WriteLine ()
    			'Loop through the user list and and configure parameters for each
    			Do Until objFile2.AtEndOfStream
    				user = objFile2.ReadLine
    				objCommand.CommandText = "<LDAP://DC/DOMAINFQDN>;(&(objectCategory=user)(samaccountname=" & user & "));distinguishedname;subTree"
    				Set objRecordSet = objCommand.Execute
    				objRecordSet.MoveFirst
    				strUserDN = objRecordSet.Fields("distinguishedname").Value
    				Set objUser = GetObject("LDAP://" & strUserDN)
    				objUser.put "msExchOmaAdminWirelessEnable", 7
    				objUser.Setinfo
    				objFile.WriteLine (Time & ": " & "ActiveSync rights removed for " & user & "!")
    			Loop
    			objFile.WriteLine (Time & ": " & "Bulk processing complete!")
    			Msgbox "Processing is complete",vbinformation,"OCS and ActiveSync Configuration"
    			wscript.quit
    		Else
    		Msgbox "Get the resources set up and then run this script again!", vbcritical, "OCS and ActiveSync Configuration"
    		End If
    		wscript.quit	
    Else 
    	user = InputBox("Please Enter User Name", "OCS and ActiveSync Configuration")
    	if user = "" then
    		Msgbox "No username entered", vbcritical
    		wscript.quit
    	end if	
    	objCommand.CommandText = "<LDAP://DC/DOMAINFQDN>;(&(objectCategory=user)(samaccountname=" & user & "));distinguishedname;subTree"
    	Set objRecordSet = objCommand.Execute
    	objRecordSet.MoveFirst
    	strUserDN = objRecordSet.Fields("distinguishedname").Value
    	Set objUser = GetObject("LDAP://" & strUserDN)
    	on error resume next
    	objUser.GetInfo
    	mail = objuser.Get("mail")
    	gn = objUser.Get("givenName")
    	sn = objUser.Get("sn")
    	moc = objUser.Get("msRTCSIP-UserEnabled")
    	mocsip = objUser.Get("msRTCSIP-PrimaryUserAddress")
    	on error goto 0
    	Select Case mail
    		Case ""
    		Msgbox gn & " doesn't have an email address setup yet. Configure Exchange mailbox for this user before running this script again", vbcritical
    		wscript.quit
    	End Select
    	Select Case moc
    	Case "True"
    		If Msgbox (gn & " already has Office Communicator enabled with SIP address " & right (mocsip, len(mocsip) - 4) & vbcrlf & "Remove the access and ActiveSync?", vbYesNo + vbquestion, "OCS and ActiveSync Configuration") = vbyes then
    			objUser.put "msRTCSIP-UserEnabled", false
    			objUser.put "msExchOmaAdminWirelessEnable", 7
    			objUser.Setinfo
    			msgbox "OCS and ActiveSync rights removed", vbinformation, "OCS and ActiveSync Configuration"
    			wscript.quit
    		else
    			Msgbox "Process Aborted", vbcritical, "OCS and ActiveSync Configuration"
    		end if
    		wscript.quit
    	Case "False"
    		If Msgbox ("Add Office Communicator for " & gn & " " & sn & vbcrlf & "with SIP address " & mail & " and remove ActiveSync?", vbYesNo + vbquestion, "OCS and ActiveSync Configuration") = vbyes then
    			objUser.put "msRTCSIP-OptionFlags", 256         ' set this value to a bitmask representing which OCS features you want to enable/disable
    			objuser.Put "msRTCSIP-PrimaryHomeServer", "FQDNOFSERVER"
    			Objuser.Put "msRTCSIP-PrimaryUserAddress", "sip:" & mail
    			objUser.put "msRTCSIP-UserEnabled", true
    			objUser.put "msExchOmaAdminWirelessEnable", 7
    			objUser.Setinfo
    			Msgbox "OCS and ActiveSync rights added",vbinformation,"OCS and ActiveSync Configuration"
    		Else
    			Msgbox "User OCS setup aborted", vbcritical, "OCS and ActiveSync Configuration"
    		End If
    	End Select
    End If
    wscript.quit

    What I believe was happening, and causing me to think it wasn't working, is that the query in here to fetch the FQDN of the user is pointed to a DC. However, the put and SetInfo statements do not necessarily set the attribute on that same DC, it's just the first DC that responds to the request. So I was checking on the defined DC, not seeing the attribute set and not understanding why it wasn't working. Only it was working, just a faster, better specced DC on a better connection was answering first and I didn't wait for the replication interval to see the change on the specified DC. 

    Do you agree this sounds likely?


    Thursday, March 07, 2013 6:10 AM
  • You cannot authenticate on AD from outside of a trust with VBScript or any other tools.  AD must be  set to allow this or it will not work.


    ¯\_(ツ)_/¯

    Thursday, March 07, 2013 6:12 AM
  • You cannot authenticate on AD from outside of a trust with VBScript or any other tools.  AD must be  set to allow this or it will not work.


    ¯\_(ツ)_/¯


    I'm not. I'm within the domain. With PowerShell you need to enable Remote Code Execution to run AD Cmdlets against DCs from another source. That's how I understand it anyway.
    Thursday, March 07, 2013 6:25 AM