?
Solved

Script that queries cross-forest group memberships

Posted on 2010-01-05
7
Medium Priority
?
1,197 Views
Last Modified: 2013-12-24
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

0
Comment
Question by:ENTPF
  • 4
  • 3
7 Comments
 
LVL 71

Expert Comment

by:Chris Dent
ID: 26189552

> 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
 

Author Comment

by:ENTPF
ID: 26189739
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
 
LVL 71

Expert Comment

by:Chris Dent
ID: 26189745

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

Chris
0
Veeam Disaster Recovery in Microsoft Azure

Veeam PN for Microsoft Azure is a FREE solution designed to simplify and automate the setup of a DR site in Microsoft Azure using lightweight software-defined networking. It reduces the complexity of VPN deployments and is designed for businesses of ALL sizes.

 

Author Comment

by:ENTPF
ID: 26189808
Do you have any sample code for searching the remote directory?
0
 
LVL 71

Accepted Solution

by:
Chris Dent earned 2000 total points
ID: 26189850

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
 
LVL 71

Expert Comment

by:Chris Dent
ID: 26189892

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
 

Author Comment

by:ENTPF
ID: 26191603
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

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Backups and Disaster RecoveryIn this post, we’ll look at strategies for backups and disaster recovery.
Wouldn't it be nice if objects in Active Directory automatically moved into the correct Organizational Units? This is what AutoAD aims to do and as a plus, it automatically creates Sites, Subnets, and Organizational Units.
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question