Enumerate Trusts

Microsoft.Windows.Server.AD.DomainController.EnumTrusts (Task)

This task enumerates the trust relationships between Active Directory domains. Provide all or part of the domain name(s) of the source domain for which you want to enumerate trusts. Use * as a wildcard

Element properties:

TargetMicrosoft.Windows.Server.2012.R2.AD.DomainControllerRole
AccessibilityPublic
CategoryMaintenance
EnabledTrue
RemotableFalse
Timeout300

Member Modules:

ID Module Type TypeId RunAs 
WA WriteAction Microsoft.Windows.ScriptWriteAction Default

Source Code:

<Task ID="Microsoft.Windows.Server.AD.DomainController.EnumTrusts" Accessibility="Public" Enabled="true" Target="AD2012R2Core!Microsoft.Windows.Server.2012.R2.AD.DomainControllerRole" Timeout="300" Remotable="true">
<Category>Maintenance</Category>
<WriteAction ID="WA" TypeID="Windows!Microsoft.Windows.ScriptWriteAction">
<ScriptName>AD_Enumerate_Trusts.vbs</ScriptName>
<Arguments/>
<ScriptBody><Script>'*************************************************************************
' Script Name - AD Enumerate Trusts
' - This script take either 0 or 1 parameter
' - No parameter: probe trust relationship with all trust partners
' - Target domains/forests can be passed as a comma separated format.
' - Parameter must be only one and there can be whitespaces between comma
' as long as all they are quoted and passed as one long parameter
'*************************************************************************
Option Explicit

SetLocale("en-us")

'*************************************************************************
' InitializeEnvironment
' - This function prepares the followings:
' MOM Script API
' ADODB Connection
' Forest Distinguished Name from RootDSE
'*************************************************************************
Function InitializeEnvironment(ByRef strNC, ByRef oADOConn, ByRef oAPI)
Set oAPI = CreateObject("Mom.ScriptAPI")
If Err &lt;&gt; 0 Then
CreateWarningEvent "Can't create MOM Script API", oAPI
InitializeEnvironment = 1
Exit Function
End If
Set oADOConn = CreateObject("ADODB.Connection")
If Err &lt;&gt; 0 Then
CreateWarningEvent "Can't create ADODB Connection", oAPI
InitializeEnvironment = 1
Exit Function
End If
oADOConn.Provider = "ADSDsOObject"
oADOConn.Open "ADs Provider"
If Err &lt;&gt; 0 Then
CreateWarningEvent "Can't open ADODB Connection", oAPI
InitializeEnvironment = 1
Exit Function
End If
strNC = GetObject("LDAP://RootDSE").Get("defaultNamingContext")
InitializeEnvironment = 0
End Function

'*************************************************************************
' EnumerateTrusts
' - Main logic of this script is implemented in this function
' - We aim for a single LDAP query to finish up the script task instead of
' sending an LDAP query for each target
' - To do so, we engineer target domains/forests into LDAP query filter
'*************************************************************************
Function EnumerateTrusts(ByRef userInput, ByRef strNC, ByRef oADOConn, ByRef oAPI)
Dim iResult
Dim oResult
Dim strTargetFilter
Dim arrTarget
Dim arrMask
Dim arrColDomain
Dim arrColDirection
Dim arrColTransitivity
Dim iCurrentMaxLength
Dim strOutput
Dim index

If IsEmpty(userInput) Then '//trust for all domains/forests
strTargetFilter = "(objectCategory=trustedDomain)"
Else
strTargetFilter = PrepareTargetList(userInput, arrTarget)
Redim arrMask(UBound(arrTarget))
End If
Set oResult = LDAPQuery(strNC, strTargetFilter, "cn,trustAttributes,trustDirection", "subtree", oADOConn, oAPI)
If oResult.RecordCount &gt; 0 Then
Redim arrColDomain(oResult.RecordCount + 2)
arrColDomain(1) = "Domain/Forest name"
arrColDomain(0) = Len(arrColDomain(1))
Redim arrColDirection(oResult.RecordCount + 2)
arrColDirection(1) = "Direction"
arrColDirection(0) = Len(arrColDirection(1))
Redim arrColTransitivity(oResult.RecordCount + 2)
arrColTransitivity(1) = "Is transitive?"
arrColTransitivity(0) = Len(arrColTransitivity(1))
End If

While Not oResult.EOF
'//display status of each trust
If Not IsEmpty(userInput) Then '//this if statement is somewhat paranoid check, can be removed after extensive testing.
If MarkTarget(oResult.Fields("cn").Value, arrTarget, arrMask) &lt;&gt; 0 Then
CreateWarningEvent "there's no such domain"
EnumerateTrusts = 1
Exit Function
End If
End If
arrColDomain(index + 2) = oResult.Fields("cn").Value
If arrColDomain(0) &lt; len(arrColDomain(index + 2)) Then
arrColDomain(0) = Len(arrColDomain(index + 2))
End If
arrColDirection(index + 2) = TranslateTrustDirection(oResult)
If arrColDirection(0) &lt; len(arrColDirection(index + 2)) Then
arrColDirection(0) = Len(arrColDirection(index + 2))
End If
arrColTransitivity(index + 2) = TranslateTrustTransitivity(oResult)
If arrColTransitivity(0) &lt; len(arrColTransitivity(index + 2)) Then
arrColTransitivity(0) = Len(arrColTransitivity(index + 2))
End If
index = index + 1
oResult.MoveNext
Wend
If Not IsEmpty(arrTarget) Then
If UBound(arrTarget) &gt;= index Then '//there are at least one target with which current domain does not have trust
Dim i
strOutput = VbCrLf &amp; "[WARNING] Trust relationship is not defined for following domain(s)/forest(s): " &amp; VbCrLf
For i = 0 To UBound(arrMask)
If IsEmpty(arrMask(i)) Then
strOutput = strOutput &amp; "&gt;&gt; " &amp; arrTarget(i) &amp; VbCrLf
End If
Next
End If
End If
iResult = DisplayTrustInfo(strOutput, arrColDomain, arrColDirection, arrColTransitivity, oAPI)
End Function

'*************************************************************************
' DisplayTrustInfo
' - This draws a well arranged box view of trust information
'*************************************************************************
Function DisplayTrustInfo(ByRef strOutput, ByRef arrColDomain, ByRef arrColDirection, ByRef arrColTransitivity, ByRef oAPI)
Dim i
Dim iRowLength
If Not IsEmpty(arrColDomain) Then
iRowLength = arrColDomain(0) + arrColDirection(0) + arrColTransitivity(0) + 10
strOutput = strOutput &amp; VbCrLf &amp; "[Trust Enumeration Result]" &amp; VbCrLf
strOutput = strOutput &amp; String(iRowLength, "-") &amp; VbCrLf
For i=1 To UBound(arrColDomain) - 1
Dim strLine
strLine = "| " &amp; arrColDomain(i) &amp; String(arrColDomain(0) - Len(arrColDomain(i)), " ")
strLine = strLine &amp; " | " &amp; arrColDirection(i) &amp; String(arrColDirection(0) - Len(arrColDirection(i)), " ")
strLine = strLine &amp; " | " &amp; arrColTransitivity(i) &amp; String(arrColTransitivity(0) - Len(arrColTransitivity(i)), " ") &amp; " |" &amp; VbCrLf
strLine = strLine &amp; String(iRowLength, "-") &amp; VbCrLf
strOutput = strOutput &amp; strLine
Next
End If
CreateEventOutput strOutput, oAPI
End Function

'*************************************************************************
' MarkTarget
' - This function helps find out if there's any domains/forests passed
' by user which don't have trust information.
' - Since we don't have a hashtable support for this script, we have to
' take O(n) way of mark off the existing targets
'*************************************************************************
Function MarkTarget(ByRef strTarget, ByRef arrTarget, ByRef arrMask)
Dim i
For i=0 To UBound(arrTarget)
If arrTarget(i) = strTarget Then
arrMask(i) = 1
Exit For
End If
Next
If i &gt; UBound(arrTarget) Then '//Record name does not exist in target list, this must not happen. After enough testing, this could be removed
MarkTarget = 1
Exit Function
End If
MarkTarget = 0
End Function

'*************************************************************************
' TranslateTrustDirection
' - http://msdn2.microsoft.com/en-us/library/cc223768.aspx
'*************************************************************************
Function TranslateTrustDirection(ByRef oTrust)
Dim strResult
Select Case Hex(oTrust.Fields("trustDirection").Value)
Case "0"
strResult = "Trust direction disabled"
Case "1"
strResult = "Inbound"
Case "2"
strResult = "Outbound"
Case "3"
strResult = "Bidirectional"
End Select
TranslateTrustDirection = strResult
End Function

'*************************************************************************
' TranslateTrustTransitivity
' - http://msdn2.microsoft.com/en-us/library/cc223779.aspx
'*************************************************************************
Function TranslateTrustTransitivity(ByRef oTrust)
Dim strResult
Select Case Hex(oTrust.Fields("trustAttributes").Value)
Case "1"
strResult = "No"
Case "2"
strResult = "Yes (Up level only)"
Case "4"
strResult = "Yes (Qurantined domain)"
Case "8"
strResult = "Yes (Forest transitive)"
Case "10"
strResult = "Yes (Cross organization)"
Case "20"
strResult = "Yes (Within forest)"
Case "40"
strResult = "Yes (Treat as external)"
Case "80"
strResult = "Yes (Uses RC4 encryption)"
End Select
TranslateTrustTransitivity = strResult
End Function

'*************************************************************************
' PrepareTargetList
' - only calls if there's user input provided for targets
' - i.e. (&amp;(|(|(cn=dimsum.com)(cn=ntdev.contoso.com))(cn=tikka-masala.com))(objectCategory=trustedDomain))
'*************************************************************************
Function PrepareTargetList(ByRef userInput, ByRef arrTarget)
Dim filterTargets
Dim i
arrTarget = Split(userInput, ",")
For i=0 To UBound(arrTarget)
arrTarget(i) = Trim(arrTarget(i))
Next
filterTargets = "(cn=" &amp; arrTarget(0) &amp; ")"
For i=1 To UBound(arrTarget)
filterTargets = "(| " &amp; filterTargets &amp; "(cn=" &amp; arrTarget(i) &amp; "))"
Next
prepareTargetList = "(&amp; (objectCategory=trustedDomain) " &amp; filterTargets &amp; ")"
End Function

'*************************************************************************
' LDAPQuery
' - Excutes LDAP query and returns the result as an object
'*************************************************************************
Function LDAPQuery(ByRef strPath, ByRef strFilter, ByRef strFields, ByRef strScope, ByRef oADOConn, ByRef oAPI)
Dim oResult
Dim strQuery
On Error Resume Next
strQuery = "&lt;LDAP://" &amp; strPath &amp;"&gt;;" &amp; strFilter &amp; ";" &amp; strFields &amp; ";" &amp; strScope
Set oResult = oADOConn.Execute(strQuery)
If Err &lt;&gt; 0 Then
CreateWarningEvent "LDAP query failed: " &amp; strQuery, oAPI
Set oResult = Nothing
End If
Set LDAPQuery = oResult
End Function

'*************************************************************************
' CreateWarningEvent
'*************************************************************************
Sub CreateWarningEvent(ByRef strMessage, ByRef oAPI)
oAPI.LogScriptEvent "AD_Enumerate_Trusts.vbs", 1000, 2, strMessage
WScript.Echo strMessage
End Sub

'*************************************************************************
' CreateEventOutput
'*************************************************************************
Sub CreateEventOutput(ByRef strOutput, ByRef oAPI)
oAPI.LogScriptEvent "AD_Enumerate_Trusts.vbs", 2000, 4, strOutput
WScript.Echo strOutput
End Sub

'*************************************************************************
' Main
'*************************************************************************
Sub Main()
Dim oAPI
Dim oADOConn
Dim strNC
Dim iResult
Dim userInput
If WScript.Arguments.Count &gt; 0 Then
userInput = WScript.Arguments(0)
End If
iResult = InitializeEnvironment(strNC, oADOConn, oAPI)
If iResult &lt;&gt; 0 Then
Exit Sub
End If
iResult = EnumerateTrusts(userInput, strNC, oADOConn, oAPI)
If iResult &lt;&gt; 0 Then
CreateEventOutput "AD Enumerate Trusts failed, please see eventlog for more information", oAPI
Exit Sub
End If
End Sub

Call Main()
</Script></ScriptBody>
<TimeoutSeconds>300</TimeoutSeconds>
</WriteAction>
</Task>