Guest User

Untitled

a guest
May 7th, 2018
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.76 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. from ldap3 import Server, ServerPool, Connection, FIRST, AUTO_BIND_NO_TLS, SUBTREE
  5. import argparse
  6. from os import path
  7. import sys
  8. import asyncio
  9. import signal
  10. import logging
  11.  
  12. logger = logging.getLogger('myapp')
  13. hdlr = logging.FileHandler('myapp.log')
  14. formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
  15. hdlr.setFormatter(formatter)
  16. logger.addHandler(hdlr)
  17. logger.setLevel(logging.WARNING)
  18.  
  19. queue = asyncio.Queue()
  20.  
  21.  
  22. def signal_handler(signal, frame):
  23. sys.exit(0)
  24.  
  25.  
  26. def stdin_producer():
  27. line = sys.stdin.readline()
  28. logger.error('{} len {}'.format(line, len(line)))
  29. asyncio.async(queue.put(line))
  30.  
  31.  
  32. async def consumer(args, bindpasswd, conn):
  33. while True:
  34. try:
  35. input = await queue.get()
  36. if len(input) == 0:
  37. raise RuntimeError
  38. else:
  39. input = input.split()
  40.  
  41. except Exception as exc:
  42. if isinstance(conn, Connection):
  43. if conn.bound:
  44. conn.unbind()
  45. break
  46. sys.exit()
  47.  
  48. try:
  49. id = input[0]
  50. username = input[1]
  51. ou = input[2]
  52.  
  53. if args.strip_realm:
  54. username = username.split('@')[0]
  55. if args.strip_domain and '\\' in username:
  56. username = username.split('\\')[1]
  57.  
  58. if isinstance(conn, Connection):
  59. if conn.closed:
  60. conn = get_ldap_connection(server=args.server,
  61. port=args.port,
  62. ssl=args.ssl,
  63. timeout=int(args.timeout),
  64. binddn=args.binddn,
  65. bindpasswd=bindpasswd)
  66.  
  67. if conn.bound:
  68. try:
  69. search_result = await get_ldap_info(connection=conn,
  70. timelimit=int(args.timelimit),
  71. ou=ou,
  72. basedn=args.basedn,
  73. filter=args.filter,
  74. username=username)
  75.  
  76. except Exception as exc:
  77. print('{} BH message={}({})'.format(id, type(exc).__name__, exc))
  78. conn.strategy.close()
  79. if conn.closed:
  80. conn.bind()
  81.  
  82. else:
  83. print('{} {}'.format(id, search_result))
  84.  
  85. else:
  86. print('{} BH message="LDAP connection could not be established"'.format(id))
  87. break
  88. sys.exit()
  89. sys.stdout.flush()
  90. except:
  91. continue
  92.  
  93.  
  94. def get_ldap_connection(server=[], port='', ssl=False, timeout=0, binddn='', bindpasswd=''):
  95. try:
  96. server_pool = ServerPool([Server(item, port, use_ssl=ssl, connect_timeout=3) for item in server],
  97. FIRST,
  98. active=3,
  99. exhaust=60)
  100. conn = Connection(server_pool,
  101. auto_bind=AUTO_BIND_NO_TLS,
  102. read_only=True,
  103. receive_timeout=timeout,
  104. check_names=True,
  105. user=binddn, password=bindpasswd)
  106. except Exception as exc:
  107. print('ext_acl_ldap_group LDAP bind error {}({})'.format(type(exc).__name__, exc))
  108. return False
  109. else:
  110. return conn
  111.  
  112.  
  113. async def get_ldap_info(connection='', timelimit=0, ou='', basedn='', filter='', username=''):
  114. if not connection:
  115. return 'BH message="LDAP connection could not be established"'
  116.  
  117. try:
  118. connection.search(search_base=basedn.replace('%ou', ou),
  119. search_filter=u'(&({}))'.format(filter.replace('%u', username)),
  120. search_scope=SUBTREE,
  121. attributes=['sAMAccountName'],
  122. time_limit=timelimit,
  123. get_operational_attributes=True)
  124.  
  125. except Exception as exc:
  126. return 'BH message={}({})'.format(type(exc).__name__, exc)
  127.  
  128. else:
  129. if len(connection.response) > 0:
  130. return u'OK tag="{}"'.format(ou)
  131. else:
  132. return 'ERR'
  133.  
  134.  
  135. def create_cli():
  136. parser = argparse.ArgumentParser(description='Squid external acl ldap ou helper')
  137. parser.add_argument('-d', '--binddn', type=str, required=True,
  138. help='DN to bind as to perform searches')
  139. parser.add_argument('-w', '--bindpasswd', type=str,
  140. help='password for binddn')
  141. parser.add_argument('-W', '--secretfile',
  142. help='read password for binddn from file secretfile')
  143. parser.add_argument('-s', '--server', action='append', required=True,
  144. help='LDAP server. Can be set multiple instance. Use first active strategy')
  145. parser.add_argument('-p', '--port', type=int, default=389,
  146. help='LDAP server port (defaults to %(default)i)')
  147. parser.add_argument('-z', '--ssl', action='store_true',
  148. help='SSL encrypt the LDAP connection')
  149. parser.add_argument('-c', '--timeout', type=int, default=10,
  150. help='connect timeout (defaults to %(default)i)')
  151. parser.add_argument('-t', '--timelimit', type=int, default=10,
  152. help='search time limit (defaults to %(default)i)')
  153. parser.add_argument('-b', '--basedn', type=str, required=True,
  154. help='base dn under where to search for users. %%ou = OU')
  155. parser.add_argument('-f', '--filter', type=str, required=True,
  156. help='user search filter pattern. %%u = login')
  157. parser.add_argument('-k', '--strip-realm', action='store_true',
  158. help='strip Kerberos realm from usernames')
  159. parser.add_argument('-n', '--strip-domain', action='store_true',
  160. help='strip NT domain from usernames')
  161. return parser
  162.  
  163.  
  164. def main():
  165. signal.signal(signal.SIGINT, signal_handler)
  166. parser = create_cli()
  167. if len(sys.argv) == 1:
  168. parser.print_help()
  169. sys.exit(1)
  170. args = parser.parse_args()
  171. conn = None
  172.  
  173. if hasattr(args, 'bindpasswd') and args.bindpasswd:
  174. bindpasswd = args.bindpasswd
  175. elif hasattr(args, 'secretfile') and args.secretfile:
  176. if path.isfile(args.secretfile):
  177. try:
  178. with open(args.secretfile, 'r') as passwdfile:
  179. bindpasswd = passwdfile.readline().replace('\n', '')
  180. except Exception as exc:
  181. print('ext_acl_ldap_ou Runtime error {}({})'.format(type(exc).__name__, exc))
  182. bindpasswd = ''
  183. else:
  184. print('ext_acl_ldap_ou Password file {} not found'.format(args.secretfile))
  185. bindpasswd = ''
  186. else:
  187. print('ext_acl_ldap_ou Password for binddn is not set')
  188. bindpasswd = ''
  189. sys.stdout.flush()
  190. if bindpasswd:
  191. try:
  192. conn = get_ldap_connection(server=args.server,
  193. port=args.port,
  194. ssl=args.ssl,
  195. timeout=int(args.timeout),
  196. binddn=args.binddn,
  197. bindpasswd=bindpasswd)
  198. except:
  199. pass
  200. else:
  201. sys.exit()
  202.  
  203. loop = asyncio.get_event_loop()
  204. loop.add_reader(sys.stdin, stdin_producer)
  205. loop.run_until_complete(consumer(args, bindpasswd, conn))
  206.  
  207.  
  208. if __name__ == '__main__':
  209. main()
Add Comment
Please, Sign In to add comment