<DataSourceModuleType ID="AD_Client_Serverless_Bind.DataSource" Accessibility="Internal">
<Configuration>
<xsd:element name="IntervalSeconds" type="xsd:int"/>
<xsd:element name="TargetComputerName" type="xsd:string"/>
<xsd:element name="LogSuccessEvent" type="xsd:boolean"/>
<xsd:element name="TimeoutSeconds" type="xsd:int"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" ParameterType="int" Selector="$Config/IntervalSeconds$"/>
<OverrideableParameter ID="LogSuccessEvent" ParameterType="string" Selector="$Config/LogSuccessEvent$"/>
<OverrideableParameter ID="TimeoutSeconds" ParameterType="int" Selector="$Config/TimeoutSeconds$"/>
</OverrideableParameters>
<ModuleImplementation>
<Composite>
<MemberModules>
<DataSource ID="DS" TypeID="System!System.CommandExecuterPropertyBagSource">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<ApplicationName>%windir%\system32\cscript.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>//nologo $file/AD_Client_Serverless_Bind.vbs$ $Config/TargetComputerName$ $Config/LogSuccessEvent$</CommandLine>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>AD_Client_Serverless_Bind.vbs</Name>
<Contents><Script>
'*************************************************************************
' Script Name - AD Client Serverless Bind
'
' Purpose - Does a serverless bind and determines whether the returned
' DC is in the same site as the client
'
' Assumptions - Script is run by a timed event
'
' Parameters - LogSuccessEvent - Logs an event when the script completes.
'
' (c) Copyright 2002, Microsoft Corporation, All Rights Reserved
' Proprietary and confidential to Microsoft Corporation
'*************************************************************************
Sub Main()
On Error Resume Next
Dim dtStart
dtStart = Now
If Not(IsTargetAgentless) Then
' Obtain the RootDSE of any Domain Controller that this client computer can connect to.
Dim oRootDSE
Set oRootDSE = GetObject("LDAP://RootDSE")
If 0 <> Err Then
ScriptError "attempting to bind to the RootDSE of any DC in the domain."
Else
' Now query the root DSE to get the site of the DC
Dim strSite, strServerName, strDNSHostName
strServerName = oRootDSE.Get("ServerName")
strDNSHostName = oRootDSE.Get("DNSHostName")
If 0 <> Err Then
ScriptError "attempting to obtain the 'ServerName' and the 'DNSHostName' attributes of the DC '" & strDNSHostName & "'."
End If
End If
' Create OOMADS Object for querying the directory. Fail script execution of creation fails.
Dim oOOMADS
Set oOOMADS = CreateObject("McActiveDir.ActiveDirectory")
If (0 <> Err.Number) Or (Not(IsObject(oOOMADS))) Then
Dim errorString
errorString = "The script '" & SCRIPT_NAME & "' failed to create object " & _
"'McActiveDir.ActiveDirectory'. This is an unexpected error." & vbCrLf & vbCrLf & _
GetErrorString(Err) & vbCrLf & vbCrLf & _
"The Active Directory Management Pack Objects (OOMADs) components are not installed on the Domain Controller. These components are required for the monitoring scripts to run successfully. See Alert Knowledge for additional details."
CreateEvent EVENT_ID_SCRIPT_FAILURE, EVENT_TYPE_WARNING, errorString
Else
' Check if the DC responding to the RootDSE query is supposed to cover the site to which this Client monitoring machine belongs.
Dim bClosestSite
bClosestSite = oOOMADS.IsDCInClosestSite(strDNSHostName)
If 0 <> Err.number Then
Dim strClosestSiteError
strClosestSiteError = "attempting to determine if the DC '" & strDNSHostName & "' is configured to cover the AD local site of the machine '" & TargetFQDNComputer & "'." & vbCrLf & vbCrLf
If Err.number = &H80004005 Then
' If we get error E_FAIL, OOMADS has determined that the ClientSiteName property of the computer object for TargetFQDNComputer is not associated to any site. Let the user know so he can fix this.
strClosestSiteError = strClosestSiteError & "The computer object for the client machine is not associated to any Active Directory Site." & vbCrLf & vbCrLf
strClosestSiteError = strClosestSiteError & "To fix this issue, associate the machine's computer object to an Active Directory Site."
End If
ScriptError strClosestSiteError
Else
If Not bClosestSite Then
Dim strDcSite, strClientSite
Dim strMessage
strMessage = "A serverless bind returned a domain controller that was not " & _
"in the same site as the client machine." & vbCrLf & vbCrLf
strMessage = strMessage & "Client Machine: " & TargetFQDNComputer & vbCrLf
strMessage = strMessage & "Client Site: " & strClientSite & vbCrLf
strMessage = strMessage & "Domain Controller Responding to Serverless bind: " & strDNSHostName & vbCrLf
strMessage = strMessage & "Domain Controller Site: " & strDcSite
CreateEvent EVENT_ID_DC_OUT_OF_SITE, EVENT_TYPE_WARNING, strMessage
Set oBag = oAPI.CreateTypedPropertyBag(StateDataType)
oBag.AddValue "State", "BAD"
oBag.AddValue "EventID", "" & EVENT_ID_DC_OUT_OF_SITE
oBag.AddValue "ErrorString", strMessage
oAPI.AddItem oBag
Else
Set oBag = oAPI.CreateTypedPropertyBag(StateDataType)
oBag.AddValue "State", "GOOD"
oBag.AddValue "EventID", "" & EVENT_ID_DC_NOT_OUT_OF_SITE
oAPI.AddItem oBag
If bLogSuccessEvent Then
CreateEvent EVENT_ID_SUCCESS, EVENT_TYPE_INFORMATION, "The script '" & SCRIPT_NAME & _
"' completed successfully in " & DateDiff("s", dtStart, Now) & _
" second(s)."
End If
End If
End If
End If
Call oAPI.ReturnItems()
Else
CreateEvent EVENT_ID_AGENTLESS, EVENT_TYPE_ERROR, "The AD Management Pack does not support the agentless management mode." & vbCrLf & _
"The script '" & SCRIPT_NAME & "' will not execute." & vbCrLf & _
"To prevent this alert being generated again, either change the monitoring " & _
"mode of the computer '" & TargetFQDNComputer & "' to agent-managed " & _
"or disable the rule that generated this alert."
End If
End Sub
'******************************************************************************
Function GetLocalSiteName()
'
' Purpose: To retrieve the site name for this computer.
'
' Returns: String, the site name (or an empty string if it cannot be determined)
'
Dim oADSysInfo
Set oADSysInfo = CreateObject("ADSystemInfo")
If Err <> 0 Then
ScriptError "creating the 'ADSystemInfo' object."
GetLocalSiteName = "Unknown"
Else
GetLocalSiteName = oADSysInfo.SiteName
End If
End Function
'******************************************************************************
Function GetDCSiteName(strDcName)
'
' Purpose: To retrieve the site name for a given DC.
'
' Returns: String, the site name (or an empty string if it cannot be determined)
'
Dim oADSysInfo
Set oADSysInfo = CreateObject("ADSystemInfo")
If Err <> 0 Then
ScriptError "creating the 'ADSystemInfo' object."
GetDCSiteName = "Unknown"
Else
GetDCSiteName = oADSysInfo.GetDCSiteName(strDcName)
End If
End Function
'******************************************************************************
Sub CreateEvent(lEventID, lEventType, strMessage)
'
' Purpose: To generate a MOM event
'
' Arguments: lEventID, the event code
' lEventType, the severity of the event
' strMessage, the message to include in the event
'
On Error Resume Next
oAPI.LogScriptEvent "AD Client Serverless Bind" ,lEventID, lEventType, strMessage
End Sub
'******************************************************************************
Sub ScriptError(strContext)
'
' Purpose: To generate an alert for the current error and then throw the
' exception so it can be caught at a higher level.
'
' Arguments: strContext - the current context, this is added to the message
' that is alerted to the user
'
' Returns: nothing
'
Dim strError
strError = "The script '" & SCRIPT_NAME & "' encountered an error while " & strContext & _
GetErrorString(Err)
CreateEvent EVENT_ID_SCRIPT_FAILURE, EVENT_TYPE_WARNING, strError
End Sub
'******************************************************************************
Function GetErrorString(oErr)
'
' Purpose: Attempts to find the description for an error if an error with
' no description is passed in.
'
' Parameters: oErr, the error object
'
' Return: String, the description for the error. (Includes the error code.)
'
Dim lErr, strErr
lErr = oErr
strErr = oErr.Description
On Error Resume Next
If 0 >= Len(strErr) Then
' If we don't have an error description, then check to see if the error
' is a 0x8007xxxx error. If it is, then look it up.
Const ErrorMask = &HFFFF0000
Const HiWord8007 = &H80070000
Const LoWordMask = 65535 ' This is equivalent to 0x0000FFFF
If (lErr And ErrorMask) = HiWord8007 Then
' Attempt to use 'net helpmsg' to get a description for the error.
Dim oShell
Set oShell = CreateObject("WScript.Shell")
If Err = 0 Then
Dim oExec
Set oExec = oShell.Exec("net helpmsg " & (lErr And LoWordMask))
Dim strMessage, i
Do
strMessage = oExec.stdout.ReadLine()
i = i + 1
Loop While (Len(strMessage) = 0) And (i < 5)
strErr = strMessage
End If
End If
End If
GetErrorString = vbCrLf & "The error returned was: '" & strErr & "' (0x" & Hex(lErr) & ")"
End Function