Re: Another Scripting Newbie - admin check
- From: "Richard Mueller [MVP]" <rlmueller-NOSPAM@xxxxxxxxxxxxxxxxxxxx>
- Date: Fri, 16 Feb 2007 11:31:16 -0600
"STFW" <STFW@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:3CF5DB67-94DD-4898-97DF-1440ED390CDE@xxxxxxxxxxxxxxxx
The goal is to find out who is running with admin rights (and then laterwe
worry about trying to get users to run as domain users only). In the past
typically added a user to the local Administrator group to workaroundcheck
programs that wouldn't run as a limited user. I'm looking for a way to
many XP workstations on a WS2003 domain for admins. So I guess I'mlooking
to get a report of what users are members of all local groups on all
computers in a domain.
This is not an easy task, but the question has come up before and I have a
limited solution. I say limited because you can grant admin rights to users
directly. Also, the local Administrators group can be renamed. The script
below discovers all users (and groups) that are members of the local
Administrators group on all computers in the domain. It finds direct
members, members due to group nesting of local groups, members of domain
groups that are members of the local Administrators group (like "Domain
Admins") and members due to nesting of domain groups. This program checks if
each computer is available. It uses a dictionary object so that domain group
membership is documented only once (like "Domain Admins"), not once for
every computer. This only documents the local Administrators groups, not all
groups. It should be run at a command prompt using the cscript host, so the
output can be redirected to a text file:
===============
Option Explicit
Dim objRootDSE, strDNSDomain, adoConnection, adoCommand
Dim strBase, strFilter, strAttributes, strQuery
Dim adoRecordset, strComputer
Dim objLocalAdmGroup
Dim objShell, objFSO, strTemp, strTempFile
Dim objTrans, strNetBIOSDomain, objGroupList
Const ADS_NAME_INITTYPE_GC = 3
Const ADS_NAME_TYPE_NT4 = 3
Const ADS_NAME_TYPE_1779 = 1
Set objShell = CreateObject("Wscript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTrans = CreateObject("NameTranslate")
objTrans.Init ADS_NAME_INITTYPE_GC, ""
' Specify temporary file to save ping results.
strTemp = objShell.ExpandEnvironmentStrings("%TEMP%")
strTempFile = strTemp & "\RunResult.tmp"
' Setup dictionary object so membership of each domain
' group is enumerated once.
Set objGroupList = CreateObject("Scripting.Dictionary")
objGroupList.CompareMode = vbTextCompare
' Determine DNS domain from RootDSE object.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
' Determine NetBIOS domain name (with trailing backslash).
objTrans.Set ADS_NAME_TYPE_1779, strDNSDomain
strNetBIOSDomain = objTrans.Get(ADS_NAME_TYPE_NT4)
' Use ADO to search Active Directory for computers.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
adoCommand.ActiveConnection = adoConnection
' Search entire domain.
strBase = "<LDAP://" & strDNSDomain & ">"
' Filter on computer objects.
strFilter = "(objectCategory=computer)"
' Comma delimited list of attribute values to retrieve.
strAttributes = "sAMAccountName"
' Construct the LDAP syntax query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
' Run the query.
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 60
adoCommand.Properties("Cache Results") = False
Set adoRecordset = adoCommand.Execute
' Enumerate the recordset.
Do Until adoRecordset.EOF
' NetBIOS name of computer is sAMAccountName
' with trailing "$" removed.
strComputer = adoRecordset.Fields("sAMAccountName").Value
strComputer = Left(strComputer, Len(strComputer) - 1)
If (IsConnectible(strComputer, 1, 759) = True) Then
' Bind to the local Administrators group on each computer
' with the WinNT provider. Trap error if group not found.
On Error Resume Next
Set objLocalAdmGroup = GetObject("WinNT://" & strComputer _
& "/Administrators,group")
If (Err.Number = 0) Then
On Error GoTo 0
Wscript.Echo strComputer
' Enumerate members of this group.
Call EnumLocalGroup(objLocalAdmGroup, "-- ")
Else
On Error GoTo 0
Wscript.Echo strComputer _
& " has no local Administrators group"
End If
Else
Wscript.Echo strComputer & " not available"
End If
adoRecordset.MoveNext
Loop
adoRecordset.Close
' Clean up.
adoConnection.Close
Function IsConnectible(strHost, intPings, intTO)
' Returns True if strHost can be pinged.
' Based on a program by Alex Angelopoulos and Torgeir Bakken.
' Variables strTempFile, objShell, and objFSO have global scope
' and must be declared in the main program.
Dim objFile, strResults
If (intPings = "") Then
intPings = 2
End If
If (intTO = "") Then
intTO = 750
End If
Const OpenAsDefault = -2
Const FailIfNotExist = 0
Const ForReading = 1
objShell.Run "%comspec% /c ping -n " & intPings & " -w " & intTO _
& " " & strHost & ">" & strTempFile, 0, True
Set objFile = objFSO.OpenTextFile(strTempFile, ForReading, _
FailIfNotExist, OpenAsDefault)
strResults = objFile.ReadAll
objFile.Close
Select Case InStr(strResults, "TTL=")
Case 0
IsConnectible = False
Case Else
IsConnectible = True
End Select
End Function
Sub EnumLocalGroup(ByVal objLocalGroup, ByVal strOffset)
' Recursive subroutine to enumerate members of a local group.
Dim objMember, blnLocal
For Each objMember In objLocalGroup.Members
' Check if objMember is local.
If (InStr(LCase(objMember.AdsPath), "/" _
& LCase(strComputer) & "/") > 0) Then
' objMember is a local object.
blnLocal = True
Wscript.Echo strOffset & objMember.Name & " (local " _
& objMember.Class & ")"
Else
' objMember is a domain object.
blnLocal = False
Wscript.Echo strOffset & objMember.Name & " (domain " _
& objMember.Class & ")"
End if
' Check if objMember is a group.
If (LCase(objMember.Class) = "group") Then
If (blnLocal = True) Then
' objMember is a local group.
Call EnumLocalGroup(objMember, "--" & strOffset)
Else
' objMember is a domain group.
Call EnumDomainGroup(objMember, "--" & strOffset, True)
End If
End If
Next
End Sub
Sub EnumDomainGroup(ByVal objDomainGroup, ByVal strOffset, blnNT)
' Recursive subroutine to enumerate members of a domain group.
Dim strGroupDN, objGroup, objMember
' If group object bound with WinNT provider, bind with LDAP provider.
If (blnNT = True) Then
objTrans.Set ADS_NAME_TYPE_NT4, strNetBIOSDomain _
& objDomainGroup.Name
strGroupDN = objTrans.Get(ADS_NAME_TYPE_1779)
Set objGroup = GetObject("LDAP://" & strGroupDN)
Else
Set objGroup = objDomainGroup
End If
' Check if this group enumerated already.
If (objGroupList.Exists(objGroup.distinguishedName) = True) Then
' Group membership already enumerated.
Wscript.Echo strOffset & "duplicate domain group already enumerated"
Else
' Enumerate members of domain group.
objGroupList.Add objGroup.distinguishedName, True
For Each objMember In objGroup.Members
Wscript.Echo strOffset & objMember.sAMAccountName _
& " (domain " & objMember.Class & ")"
' Check if objMember is a group.
If (LCase(objMember.Class) = "group") Then
Call EnumDomainGroup(objMember, "--" & strOffset, False)
End If
Next
End If
End Sub
--
Richard
Microsoft MVP Scripting and ADSI
Hilltop Lab web site - http://www.rlmueller.net
--
.
- Follow-Ups:
- Re: Another Scripting Newbie - admin check
- From: STFW
- Re: Another Scripting Newbie - admin check
- Prev by Date: Re: Scripting Newbie
- Next by Date: Re: Another Scripting Newbie - admin check
- Previous by thread: Re: Scripting Newbie
- Next by thread: Re: Another Scripting Newbie - admin check
- Index(es):
Relevant Pages
|
Loading