123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- from win32com.adsi import adsi
- from win32com.adsi.adsicon import *
- from win32com.adsi import adsicon
- import pythoncom, pywintypes, win32security
- 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()
|