|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- 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()
|