• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1460
  • Last Modified:

Circular Nested Groups AD Login Script

I have an Active Directory login script which is working great for some people but which i believe is looping when run due to circular nested groups for others. I know i could just get rid of the circular nested groups but i would prefer to manage these during the login script instead as they make my life easier.

My question is; how would i adjust the nested group enumeration function below to ignore circular nested groups? (i believe the basis for the script originally came from http://www.rlmueller.net)


 
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' FUNCTION: Enumerate Groups Start
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Function EnumGroupsStart()
	'On Error Resume Next
	
WScript.Echo "Started startenum"	

	Set objSysInfo = CreateObject("ADSystemInfo")
	strLDAPUser = objSysInfo.UserName
	Set objUser = GetObject("LDAP://" & strLDAPUser)
	EnumGroupsStart = EnumGroups(objUser, strGroups)

End Function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' FUNCTION: Enumerate Groups
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Function EnumGroups(objADObject, strGroups)
	'On Error Resume Next
	
WScript.Echo "Started enum"	
	
	' Setup dictionary object to track groups and prevent infinite loop.
	Set objList = CreateObject("Scripting.Dictionary")
	objList.CompareMode = vbTextCompare	

	Set objGroupList = CreateObject("Scripting.Dictionary")
    objGroupList.CompareMode = vbTextCompare
    	
    ' Recursive subroutine to enumerate user group memberships.
    ' Includes nested group memberships.
    Dim colstrGroups, objGroup, j
    colstrGroups = objADObject.memberOf
    
    If (IsEmpty(colstrGroups) = True) Then
       Exit Function
    End If
    If (TypeName(colstrGroups) = "String") Then
        ' Escape any forward slash characters, "/", with the backslash
        ' escape character. All other characters that should be escaped are.
        colstrGroups = Replace(colstrGroups, "/", "\/")   
        Set objGroup = GetObject("LDAP://" & colstrGroups)
	        If (objGroupList.Exists(objGroup.sAMAccountName) = False) Then
	            objGroupList.Add objGroup.sAMAccountName, True
	            strGroups = strGroups & ucase(objGroup.sAMAccountName) & ";"
	            Call EnumGroups(objGroup, strGroups)
	        End If  
        Set objGroup = Nothing
       Exit Function
    End If
    For j = 0 To UBound(colstrGroups)
        ' Escape any forward slash characters, "/", with the backslash
        ' escape character. All other characters that should be escaped are.
        colstrGroups(j) = Replace(colstrGroups(j), "/", "\/")
        Set objGroup = GetObject("LDAP://" & colstrGroups(j))
	        If (objGroupList.Exists(objGroup.sAMAccountName) = False) Then
	            objGroupList.Add objGroup.sAMAccountName, True          
	            strGroups = strGroups & ucase(objGroup.sAMAccountName) & ";"
	            Call EnumGroups(objGroup, strGroups)
	        End If       
    Next
    Set objGroup = Nothing
    EnumGroups = strGroups

End Function

Open in new window

0
MoogControls
Asked:
MoogControls
  • 2
1 Solution
 
gozolietCommented:
It looks to me like you need to make use of your objGroupList as part of your recursive function.   You test to see if a group is already listed in lines 46/59, but every time you iterate through a group you start over again.  I think the easiest fix would be to add create your objGroupList in EnumGroupsStart, and then pass it in on every function call.

0
 
gozolietCommented:
Making the above change, this seems to work in a case where I had two groups nested in each other.
EnumGroupsStart()

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' FUNCTION: Enumerate Groups Start
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Function EnumGroupsStart()
	'On Error Resume Next
	
WScript.Echo "Started startenum"	

	Set objSysInfo = CreateObject("ADSystemInfo")
	strLDAPUser = objSysInfo.UserName
	Set objUser = GetObject("LDAP://" & strLDAPUser)

	Set objGroupList = CreateObject("Scripting.Dictionary")
       objGroupList.CompareMode = vbTextCompare

	EnumGroupsStart = EnumGroups(objUser, strGroups, objGroupList)

End Function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' FUNCTION: Enumerate Groups
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Function EnumGroups(objADObject, strGroups, objGroupList)
	'On Error Resume Next
	
	' Setup dictionary object to track groups and prevent infinite loop.
	Set objList = CreateObject("Scripting.Dictionary")
	objList.CompareMode = vbTextCompare	

    ' Recursive subroutine to enumerate user group memberships.
    ' Includes nested group memberships.
    Dim colstrGroups, objGroup, j
    colstrGroups = objADObject.memberOf
    
    If (IsEmpty(colstrGroups) = True) Then
       Exit Function
    End If
    If (TypeName(colstrGroups) = "String") Then
        ' Escape any forward slash characters, "/", with the backslash
        ' escape character. All other characters that should be escaped are.
        colstrGroups = Replace(colstrGroups, "/", "\/")   
        Set objGroup = GetObject("LDAP://" & colstrGroups)
	        If (objGroupList.Exists(objGroup.sAMAccountName) = False) Then
	            objGroupList.Add objGroup.sAMAccountName, True
	            strGroups = strGroups & ucase(objGroup.sAMAccountName) & ";"
  
	            Call EnumGroups(objGroup, strGroups, objGroupList)
	        End If  
        Set objGroup = Nothing
       Exit Function
    End If
    For j = 0 To UBound(colstrGroups)
        ' Escape any forward slash characters, "/", with the backslash
        ' escape character. All other characters that should be escaped are.
        colstrGroups(j) = Replace(colstrGroups(j), "/", "\/")
        Set objGroup = GetObject("LDAP://" & colstrGroups(j))
	        If (objGroupList.Exists(objGroup.sAMAccountName) = False) Then
	            objGroupList.Add objGroup.sAMAccountName, True          
	            strGroups = strGroups & ucase(objGroup.sAMAccountName) & ";"
	            Call EnumGroups(objGroup, strGroups, objGroupList)
	        End If       
    Next
    Set objGroup = Nothing
    EnumGroups = strGroups

End Function

Open in new window

0
 
MoogControlsAuthor Commented:
Awesome! Works a treat. Thank you very very much for your quick response.
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.

Join & Write a Comment

Featured Post

Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now