5

Active Directory: VBscript to enumerate the message restrictions (send to rights) of a distributionlist

Finally I can show you my script to enumerate the message restrictions (send to rights as I tend to call then) on a distributionlist. The send to rights consists of 2 pieces, the users and the groups rights.
The users with send to rights are enumerated in the authOrig attribute of the distribution list AD object, the groups are allocated in the dLMemSubmitPerms attribute. Both attributes are arrays.
I also found out that when a listed user or resource mailbox had send as rights on it’s Active Directory object the users listed in the send as also have send to rights on the distribution list.

Follow the next steps to run the script (no admin rights needed):

* find the distinguished name of the nested group (adsiedit.msc)
* open your favorite text editor
* copy and paste the script into the editor
* change the distinguished name
* save the script (for example c:tempenumeratesendtorights.vbs)
* open a command prompt
* go to “c:temp”
* give “cscript enumeratesendtorights.vbs” (without quotes) and enter

The script:

' Name : enumeratesendtorights.vbs
' Description : script to enumerate the message restrictions (send to rights) of a distributionlist
' Author : dirk adamsky - deludi bv
' Version : 1.10 added check on attribute type based on input from Pedro (see comments)
' Date : 11-03-2010 (v.1.00 date 08-02-2010)
' Level: advanced

Set objSourceGroup = GetObject("LDAP://CN=distribution list (all members),OU=groups,DC=test,DC=org")
If objSourceGroup.authOrig <> "" Then
	If TypeName(objSourceGroup.authOrig) = "String" Then
		GetSendToRights ("LDAP://" & objSourceGroup.authOrig)
	Else
		For Each User In objSourceGroup.authOrig
			GetSendToRights ("LDAP://" & User)
		Next
	End If
End If
If objSourceGroup.dLMemSubmitPerms <> "" Then
	If TypeName(objSourceGroup.dLMemSubmitPerms) = "String" Then
		EnumNestedgroup objSourceGroup.dLMemSubmitPerms
	Else
		For Each Group in objSourceGroup.dLMemSubmitPerms
			EnumNestedgroup Group
		Next
	End If
End If
Set objSourceGroup = Nothing

Function GetSendToRights(strUserDN)
	On Error Resume Next
	Set objAccount = GetObject(strUserDN)
	Wscript.Echo objAccount.Mail & " ; " & objAccount.DisplayName & " ; direct send to rights"
	Set objSecurityDescriptor = objAccount.Get("ntSecurityDescriptor")
	Set objDacl = objSecurityDescriptor.DiscretionaryAcl
	Set objAce = CreateObject("AccessControlEntry")
	For Each objAce In objDacl
		If objAce.ObjectType = "{AB721A54-1E2F-11D0-9819-00AA0040529B}" Then
			If (Left(objAce.Trustee,3) <> "S-1" And objAce.Trustee <> "NT AUTHORITYSELF") Then
				GetUserDetails Mid(objAce.Trustee,9)
			End If
		End If
	Next
End Function

Function GetUserDetails(strPreW2K)
	Set adoCommand = CreateObject("ADODB.Command")
	Set adoConnection = CreateObject("ADODB.Connection")
	adoConnection.Provider = "ADsDSOObject"
	adoConnection.Open "Active Directory Provider"
	adoCommand.ActiveConnection = adoConnection

	' Search entire Active Directory domain.
	Set objRootDSE = GetObject("LDAP://RootDSE")
	strDNSDomain = objRootDSE.Get("defaultNamingContext")
	strBase = "<LDAP://" & strDNSDomain & ">"

	' Filter on user objects.
	strFilter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=" &  strPreW2K & "))"

	' Comma delimited list of attribute values to retrieve.
	strAttributes = "mail, displayname"

	' Construct the LDAP syntax query.
	strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
	adoCommand.CommandText = strQuery
	adoCommand.Properties("Page Size") = 100
	adoCommand.Properties("Timeout") = 30
	adoCommand.Properties("Cache Results") = False

	' Run the query.
	Set adoRecordset = adoCommand.Execute
	Wscript.Echo adoRecordset.Fields("mail").Value & " ; " & adoRecordset.Fields("displayname").Value & " ; indirect send to rights"
	' Clean up.
	adoRecordset.Close
	adoConnection.Close

	Set adoRecordset = Nothing
	Set objRootDSE = Nothing
	Set adoConnection = Nothing
	Set adoCommand = Nothing
End Function	

Sub EnumNestedgroup(strGroupDN)
	Set objGroup = GetObject("LDAP://" & strGroupDN)
	For Each objMember in objGroup.Members
		If (LCase(objMember.Class) = "group") Then
			Call EnumNestedgroup(objMember.AdsPath)
		Else
			GetSendToRights objMember.AdsPath
		End If
	Next
	Set objGroup = Nothing
End Sub

When you have problems/questions with the script please post a reply.

Happy scripting.

Best regards,

Dirk Adamsky


Related Posts:
  • Active Directory: VBscript to enumerate the members of nested groups V2
  • Active Directory and WMI: VBscript to enumerate a sorted list of all mailboxes and their size in your AD domain
  • Active Directory: VBscript to count users with multiple entries in a nested distribution group

  • 5 Responses so far.

    1. Pedro says:

      When a group has only a permited sender (User, but with a DL the same problem should happen) the script fails with “error: Object not a collection”.
      For Each User In objSourceGroup.authOrig

      If there is only one object authOrig it is not an array but a single object, wich cannot be enumerated

    2. dirk adamsky says:

      Hi Pedro,

      Thank you for the input.
      I tested the script with a distribution group multiple entries for both authorig and dlsubmitperms.
      I have checked your findings: you are right, the For…Next loop does not function when the attribute has only one member. This is rather curious behaviour: I would say: typical MS….
      An array with one value is still an array.
      I have tested the Ubound function, but that also fails with one entry. I will continue the search but it can take a couple of days…..

    3. dirk adamsky says:

      Hi Pedro,

      I found the solution: with the function ‘TypeName’ it is possible to determine the type of an attribute.
      The possible values are:

      value: empty type: empty
      value: single user/group type: string
      value: multiple users/groups type: variant()

      I added extra checks: one if the attribute has a value and two if the value is single or multiple.

      Again: thank you for the input.

      Happy scripting.

      Best regards,

      Dirk Adamsky

    4. M says:

      Hello:

      Thanks for the script. It should work for mailboxes and PFs also (with minor mods if necessary). It would be nice to add the following:
      1.) Prompt user to enter the e-mail address of the object. This is easier for the user and won’t require editing the script every time.
      2.) Use the e-mail address to query AD for the object.
      3.) Save the results to a text file with the e-mail address of the object in the file name, ie, SomeOjbect@abc.com_AllowedSenders.txt.

      I might get around to doing all the above if I have some time since I’ve done something similar for another script.

      Regards,
      M

    Leave a Reply