Script that queries cross-forest group memberships

I have a script that login script:
1) figures out your username and DN
2) verifies if you are part of a certain group
3) creates a desktop icon if you are.
This works great in a local domain.  But I need it to work across trusted forests.
So basically user A whose account is in domainA.forestA.root will login into a terminal server in domainB.forestB.root, and the script needs to check the groups in domainA.forestA.root that the user is a member of.  what in the script needs to be changed?

I know "set objRootDSE = getobject("LDAP://RootDSE")" needs to be changed to "set objRootDSE = getobject("LDAP://domainA.forestA.com")

what else?
Set objShell = CreateObject("Wscript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objSysInfo = CreateObject("ADSystemInfo")
Set objNetwork = CreateObject("WScript.Network")
set objGroupList = CreateObject("Scripting.Dictionary")

objGroupList.CompareMode = vbTextCompare
strDesktopPath = objShell.SpecialFolders("Desktop")

set objUser1 = getobject("LDAP://" & objSysInfo.UserName)

On Error Resume Next
strGroup = "Test Group"

if isMember(objUser1,strGroup) then

Set objShortcutLnk = objShell.CreateShortcut(strDesktopPath & "\Notepad.lnk")
objShortcutLnk.TargetPath = "notepad"
objShortcutLnk.Save

End if			
			                                
 
Function isMember(byref objADObject,groupName)
	
	if not objGroupList.Exists(objADObject.sAMAccountName) then

		
		objGroupList.add objADObject.sAMAccountName,""
		
		objGroupList.add objADObject.sAMAccountName & "|" & GetPrimaryGroup(objADObject),""

	
		For Each objGroup in objADObject.Groups
			if not objGroupList.Exists(objADObject.sAMAccountName & "|" & objGroup.sAMAccountName) then
				
				objGroupList.add objADObject.sAMAccountName & "|" & objGroup.sAMAccountName,""
				
    				getNested objGroup,objADObject.sAMAccountName
			end if
		Next
		
	end if

	
	isMember =  objGroupList.exists(objADObject.sAMAccountName & "|" & groupName)

end function 

Function GetNested(byref objGroup,byval sAMAccountName)

    	On Error Resume Next
    	colMembers = objGroup.GetEx("memberOf")
	on error goto 0

	if not isEmpty(colMembers) then
    		For Each strMember in colMembers
       			Set objNestedGroup = GetObject("LDAP://" & strMember)
			item = sAMAccountName & "|" & objNestedGroup.sAMAccountName
			if objGroupList.Exists(Item) = False then
				
				objGroupList.add item,""
				
				GetNested objNestedGroup,sAMAccountName
			end if
    		Next
	end if
End Function

Function GetPrimaryGroup(objADObject)

	set objRootDSE = getobject("LDAP://RootDSE")
	searchRoot = objRootDSE.get("defaultNamingContext")

	intPrimaryGroupID = objADObject.Get("primaryGroupID")

	Set cn = CreateObject("ADODB.Connection")
	Set cmd = CreateObject("ADODB.Command")

	cn.Open "Provider=ADsDSOObject;"
	cmd.ActiveConnection = cn
	cmd.CommandText = "<LDAP://" & searchRoot & ">;(objectCategory=Group);" & _
        "distinguishedName,primaryGroupToken,sAMAccountName;subtree"  
	cmd.properties("page size") = 1000
	Set rs = cmd.Execute

	Do Until rs.EOF
    		If rs("primaryGroupToken") = intPrimaryGroupID Then
        		GetPrimaryGroup = rs("sAMAccountName")
			exit do
    		End If
    		rs.MoveNext
	Loop
	cn.close

End function
Msgbox "Done"

Open in new window

ENTPFAsked:
Who is Participating?
 
Chris DentPowerShell DeveloperCommented:

Certainly do. See below :)

Chris
' Can use RootDSE to build the LdapPath if required
Dim strLdapPath : strLdapPath = "LDAP://DomainA.ForestA.com/DC=DomainA,DC=ForestA,DC=com"
Dim strLdapFilter : strLdapFilter = "(sAMAccountName=" & strUsername & ")"

Dim objConnection : Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
' Should not need auth if remote domain is trusted
' objConnection.Properites("User ID") = strUsername
' objConnection.Properties("Password") = strPassword
' objConnection.Properties("Encrypt Password") = False
objConnection.Open "Active Directory Provider"

Dim objCommand : Set objCommand = Createobject("ADODB.Command")
Set objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000

objCommand.CommandText = "<" & strLdapPath & ">;" & _
  strLdapFilter & ";distinguishedName;subtree"

Dim objRecordSet : Set objRecordSet = objCommand.Execute

' Should be a unique match, and the users DN should be first in the set

If objRecordSet.RecordCount = 1 Then
  strUserDN = objRecordSet.Fields("distinguishedName").Value
End If

Open in new window

0
 
Chris DentPowerShell DeveloperCommented:

> I know "set objRootDSE = getobject("LDAP://RootDSE")" needs to be changed to
> "set objRootDSE = getobject("LDAP://domainA.forestA.com")

It should be:

Set objRootDSE = GetObject("LDAP://domainA.forestA.com/RootDSE")

Chances are you'll need to specify a server to connect to for every LDAP connection you have (where the server is being given by domainA.forestA.com).

I'm unsure if ADSystemInfo will work in this scenario. Does it still return the correct user distinguished name?

Chris
0
 
ENTPFAuthor Commented:
I have not tested it yet, but I was thinking that also about ADSystemInfo.. Is there another way to get the DN information for an object in a trusted forest?
0
Simplify Active Directory Administration

Administration of Active Directory does not have to be hard.  Too often what should be a simple task is made more difficult than it needs to be.The solution?  Hyena from SystemTools Software.  With ease-of-use as well as powerful importing and bulk updating capabilities.

 
Chris DentPowerShell DeveloperCommented:

NameTranslate may work, and searching the remote directory certainly will.

Chris
0
 
ENTPFAuthor Commented:
Do you have any sample code for searching the remote directory?
0
 
Chris DentPowerShell DeveloperCommented:

Incidentally, if we're doing that, we may as well return the memberOf attribute as well. No point in searching again to return more information about the same object.

Modified below.

Chris
' Can use RootDSE to build the LdapPath if required
Dim strLdapPath : strLdapPath = "LDAP://DomainA.ForestA.com/DC=DomainA,DC=ForestA,DC=com"
Dim strLdapFilter : strLdapFilter = "(sAMAccountName=" & strUsername & ")"

Dim objConnection : Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
' Should not need auth if remote domain is trusted
' objConnection.Properites("User ID") = strUsername
' objConnection.Properties("Password") = strPassword
' objConnection.Properties("Encrypt Password") = False
objConnection.Open "Active Directory Provider"

Dim objCommand : Set objCommand = Createobject("ADODB.Command")
Set objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000

objCommand.CommandText = "<" & strLdapPath & ">;" & _
  strLdapFilter & ";distinguishedName,memberOf;subtree"

Dim objRecordSet : Set objRecordSet = objCommand.Execute

' Should be a unique match, and the users DN should be first in the set

If objRecordSet.RecordCount = 1 Then
  strUserDN = objRecordSet.Fields("distinguishedName").Value

  ' The array of groups
  strGroups = objRecordSet.Fields("memberOf").Value
End If

Open in new window

0
 
ENTPFAuthor Commented:
The first one you sent works great.  The second one errors out (in a single domain queryand a trusted domain query).  The error is:
Error:  Item Cannot be found in the collection corresponding to the requested name or ordinal
Code:   800A0CC1
Source: ADOB.Recordset

Any help would be appreciated.  Thanks.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.