SPN Query

Craig Wiand, Microsoft Corporation

This script queries the Active Directory Global Catalog for a security principal with a specified service principal name (SPN). To use the script, copy the code, paste it into Notepad, and then save the script with a .vbs file extension (for example, spn_query.vbs).

To use the script, you must include a mandatory first parameter: the SPN you are looking for in the directory.  For example:

spn_query.vbs spn_query.vbs MSSqlSvc/Server1

Note that the parameter will be passed into an LDAP query, which means that all LDAP matching rules apply.  You can use an asterisk (*) as a wildcard, but keep in mind that the directory service optimizes trailing wildcards much better than wildcards used in the middle of the query. This type of query (with the asterisk located at the end of the SPN) provides acceptable performance:

MSSqlSvc*

This type - with the asterisk located in the middle of the SPN - might not:

MSSqlSvc/*.corp.com

In addition, you can provide an optional second parameter specifying a server or forest name. This should only be used when a particular Global Catalog server (GC) should be targeted, or when a GC in another forest must be queried.  When the second parameter is not specified the script uses the Windows Locator service to find the best GC for the computer running the script.

The script will query the Global Catalog server and display the locations and SPNs of any returned objects.  For computers it also displays the DNS hostname; for users it displays the logon name.

Script Code

' Copyright (c) Microsoft Corporation 2004 -
' File:        querySpn.vbs
' Contents:   Query a given SPN in a given forest to find the owners
' History:     7/7/2004   Craig Wiand   Created    
Option Explicit     
Const DUMP_SPNs = True
Dim oConnection, oCmd, oRecordSet
Dim oGC, oNSP
Dim strGCPath, strClass, strSPN, strADOQuery
Dim vObjClass, vSPNs, vName

ParseCommandLine()

'--- Set up the connection ---
Set oConnection = CreateObject("ADODB.Connection")
Set oCmd = CReateObject("ADODB.Command")
oConnection.Provider = "ADsDSOObject"
oConnection.Open "ADs Provider"
Set oCmd.ActiveConnection = oConnection
oCmd.Properties("Page Size") = 1000

'--- Build the query string ---
strADOQuery = "<" + strGCPath + ">;(servicePrincipalName=" + strSPN + ");" & _
    "dnsHostName,distinguishedName,servicePrincipalName,objectClass," & _
        "samAccountName;subtree"
oCmd.CommandText = strADOQuery

'--- Execute the query for the object in the directory ---
Set oRecordSet = oCmd.Execute
If oRecordSet.EOF and oRecordSet.Bof Then
  Wscript.Echo "No SPNs found!"
Else
 While Not oRecordset.Eof
   Wscript.Echo oRecordset.Fields("distinguishedName")
   vObjClass = oRecordset.Fields("objectClass")
   strClass = vObjClass( UBound(vObjClass) )
   Wscript.Echo "Class: " & strClass
   If UCase(strClass) = "COMPUTER" Then
      Wscript.Echo "Computer DNS: " & oRecordset.Fields("dnsHostName")
   Else
      Wscript.Echo "User Logon: " & oRecordset.Fields("samAccountName")
   End If
   
   If DUMP_SPNs Then
      '--- Display the SPNs on the object --- 
      vSPNs = oRecordset.Fields("servicePrincipalName")
      For Each vName in vSPNs
         Wscript.Echo "-- " + vName
      Next
   End If
   Wscript.Echo
   oRecordset.MoveNext
 Wend
End If

oRecordset.Close
oConnection.Close

Sub ShowUsage()
   Wscript.Echo " USAGE:    " & WScript.ScriptName & _
        " SpnToFind [GC Servername or Forestname]"
   Wscript.Echo
   Wscript.Echo " EXAMPLES: " 
   Wscript.Echo "           " & WScript.ScriptName & _
        " MSSQLSvc/MySQL.company.com:1433"
   Wscript.Echo "           " & WScript.ScriptName & _
        " HOST/Server1 Corp.com"
   Wscript.Quit 0
End Sub

Sub ParseCommandLine()
  If WScript.Arguments.Count <> 1 And WScript.Arguments.Count <> 2 Then
ShowUsage()
  Else
   strSPN = WScript.Arguments(0)
   If WScript.Arguments.Count = 2 Then
      strGCPath = "GC://" & WScript.Arguments(1)
   Else
    '--- Get GC -- 
    Set oNSP = GetObject("GC:")
    For Each oGC in oNSP
      strGCPath = oGC.ADsPath
    Next
   End If
 End If 
End Sub

For online peer support, join The Official Scripting Guys Forum!

Disclaimer

This sample script is not supported under any Microsoft standard support program or service. The sample script is provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.