Kano001's picture
Upload 261 files
10865e1 verified
raw
history blame
4.17 kB
import pythoncom
import pywintypes
import win32security
from win32com.adsi import adsi, adsicon
from win32com.adsi.adsicon import *
options = None # set to optparse options object
ADsTypeNameMap = {}
def getADsTypeName(type_val):
# convert integer type to the 'typename' as known in the headerfiles.
if not ADsTypeNameMap:
for n, v in adsicon.__dict__.items():
if n.startswith("ADSTYPE_"):
ADsTypeNameMap[v] = n
return ADsTypeNameMap.get(type_val, hex(type_val))
def _guid_from_buffer(b):
return pywintypes.IID(b, True)
def _sid_from_buffer(b):
return str(pywintypes.SID(b))
_null_converter = lambda x: x
converters = {
"objectGUID": _guid_from_buffer,
"objectSid": _sid_from_buffer,
"instanceType": getADsTypeName,
}
def log(level, msg, *args):
if options.verbose >= level:
print("log:", msg % args)
def getGC():
cont = adsi.ADsOpenObject(
"GC:", options.user, options.password, 0, adsi.IID_IADsContainer
)
enum = adsi.ADsBuildEnumerator(cont)
# Only 1 child of the global catalog.
for e in enum:
gc = e.QueryInterface(adsi.IID_IDirectorySearch)
return gc
return None
def print_attribute(col_data):
prop_name, prop_type, values = col_data
if values is not None:
log(2, "property '%s' has type '%s'", prop_name, getADsTypeName(prop_type))
value = [converters.get(prop_name, _null_converter)(v[0]) for v in values]
if len(value) == 1:
value = value[0]
print(" %s=%r" % (prop_name, value))
else:
print(" %s is None" % (prop_name,))
def search():
gc = getGC()
if gc is None:
log(0, "Can't find the global catalog")
return
prefs = [(ADS_SEARCHPREF_SEARCH_SCOPE, (ADS_SCOPE_SUBTREE,))]
hr, statuses = gc.SetSearchPreference(prefs)
log(3, "SetSearchPreference returned %d/%r", hr, statuses)
if options.attributes:
attributes = options.attributes.split(",")
else:
attributes = None
h = gc.ExecuteSearch(options.filter, attributes)
hr = gc.GetNextRow(h)
while hr != S_ADS_NOMORE_ROWS:
print("-- new row --")
if attributes is None:
# Loop over all columns returned
while 1:
col_name = gc.GetNextColumnName(h)
if col_name is None:
break
data = gc.GetColumn(h, col_name)
print_attribute(data)
else:
# loop over attributes specified.
for a in attributes:
try:
data = gc.GetColumn(h, a)
print_attribute(data)
except adsi.error as details:
if details[0] != E_ADS_COLUMN_NOT_SET:
raise
print_attribute((a, None, None))
hr = gc.GetNextRow(h)
gc.CloseSearchHandle(h)
def main():
global options
from optparse import OptionParser
parser = OptionParser()
parser.add_option(
"-f", "--file", dest="filename", help="write report to FILE", metavar="FILE"
)
parser.add_option(
"-v",
"--verbose",
action="count",
default=1,
help="increase verbosity of output",
)
parser.add_option(
"-q", "--quiet", action="store_true", help="suppress output messages"
)
parser.add_option("-U", "--user", help="specify the username used to connect")
parser.add_option("-P", "--password", help="specify the password used to connect")
parser.add_option(
"",
"--filter",
default="(&(objectCategory=person)(objectClass=User))",
help="specify the search filter",
)
parser.add_option(
"", "--attributes", help="comma sep'd list of attribute names to print"
)
options, args = parser.parse_args()
if options.quiet:
if options.verbose != 1:
parser.error("Can not use '--verbose' and '--quiet'")
options.verbose = 0
if args:
parser.error("You need not specify args")
search()
if __name__ == "__main__":
main()