search.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. from win32com.adsi import adsi
  2. from win32com.adsi.adsicon import *
  3. from win32com.adsi import adsicon
  4. import pythoncom, pywintypes, win32security
  5. options = None # set to optparse options object
  6. ADsTypeNameMap = {}
  7. def getADsTypeName(type_val):
  8. # convert integer type to the 'typename' as known in the headerfiles.
  9. if not ADsTypeNameMap:
  10. for n, v in adsicon.__dict__.items():
  11. if n.startswith("ADSTYPE_"):
  12. ADsTypeNameMap[v] = n
  13. return ADsTypeNameMap.get(type_val, hex(type_val))
  14. def _guid_from_buffer(b):
  15. return pywintypes.IID(b, True)
  16. def _sid_from_buffer(b):
  17. return str(pywintypes.SID(b))
  18. _null_converter = lambda x: x
  19. converters = {
  20. 'objectGUID' : _guid_from_buffer,
  21. 'objectSid' : _sid_from_buffer,
  22. 'instanceType' : getADsTypeName,
  23. }
  24. def log(level, msg, *args):
  25. if options.verbose >= level:
  26. print("log:", msg % args)
  27. def getGC():
  28. cont = adsi.ADsOpenObject("GC:", options.user, options.password, 0, adsi.IID_IADsContainer)
  29. enum = adsi.ADsBuildEnumerator(cont)
  30. # Only 1 child of the global catalog.
  31. for e in enum:
  32. gc = e.QueryInterface(adsi.IID_IDirectorySearch)
  33. return gc
  34. return None
  35. def print_attribute(col_data):
  36. prop_name, prop_type, values = col_data
  37. if values is not None:
  38. log(2, "property '%s' has type '%s'", prop_name, getADsTypeName(prop_type))
  39. value = [converters.get(prop_name, _null_converter)(v[0]) for v in values]
  40. if len(value) == 1:
  41. value = value[0]
  42. print(" %s=%r" % (prop_name, value))
  43. else:
  44. print(" %s is None" % (prop_name,))
  45. def search():
  46. gc = getGC()
  47. if gc is None:
  48. log(0, "Can't find the global catalog")
  49. return
  50. prefs = [(ADS_SEARCHPREF_SEARCH_SCOPE, (ADS_SCOPE_SUBTREE,))]
  51. hr, statuses = gc.SetSearchPreference(prefs)
  52. log(3, "SetSearchPreference returned %d/%r", hr, statuses)
  53. if options.attributes:
  54. attributes = options.attributes.split(",")
  55. else:
  56. attributes = None
  57. h = gc.ExecuteSearch(options.filter, attributes)
  58. hr = gc.GetNextRow(h)
  59. while hr != S_ADS_NOMORE_ROWS:
  60. print("-- new row --")
  61. if attributes is None:
  62. # Loop over all columns returned
  63. while 1:
  64. col_name = gc.GetNextColumnName(h)
  65. if col_name is None:
  66. break
  67. data = gc.GetColumn(h, col_name)
  68. print_attribute(data)
  69. else:
  70. # loop over attributes specified.
  71. for a in attributes:
  72. try:
  73. data = gc.GetColumn(h, a)
  74. print_attribute(data)
  75. except adsi.error as details:
  76. if details[0] != E_ADS_COLUMN_NOT_SET:
  77. raise
  78. print_attribute( (a, None, None) )
  79. hr = gc.GetNextRow(h)
  80. gc.CloseSearchHandle(h)
  81. def main():
  82. global options
  83. from optparse import OptionParser
  84. parser = OptionParser()
  85. parser.add_option("-f", "--file", dest="filename",
  86. help="write report to FILE", metavar="FILE")
  87. parser.add_option("-v", "--verbose",
  88. action="count", default=1,
  89. help="increase verbosity of output")
  90. parser.add_option("-q", "--quiet",
  91. action="store_true",
  92. help="suppress output messages")
  93. parser.add_option("-U", "--user",
  94. help="specify the username used to connect")
  95. parser.add_option("-P", "--password",
  96. help="specify the password used to connect")
  97. parser.add_option("", "--filter",
  98. default = "(&(objectCategory=person)(objectClass=User))",
  99. help="specify the search filter")
  100. parser.add_option("", "--attributes",
  101. help="comma sep'd list of attribute names to print")
  102. options, args = parser.parse_args()
  103. if options.quiet:
  104. if options.verbose != 1:
  105. parser.error("Can not use '--verbose' and '--quiet'")
  106. options.verbose = 0
  107. if args:
  108. parser.error("You need not specify args")
  109. search()
  110. if __name__=='__main__':
  111. main()