Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ldapjs-search 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. #!/usr/bin/env node
  2. // -*- mode: js -*-
  3. // Copyright 2011 Mark Cavage. All rights reserved.
  4. var path = require('path');
  5. var dashdash = require('dashdash');
  6. var ldap = require('../lib/index');
  7. var Logger = require('bunyan');
  8. ///--- Globals
  9. dashdash.addOptionType({
  10. name: 'ldap.Filter',
  11. takesArg: true,
  12. helpArg: 'LDAP_FILTER',
  13. parseArg: function (option, optstr, arg) {
  14. return ldap.parseFilter(arg);
  15. }
  16. });
  17. dashdash.addOptionType({
  18. name: 'ldap.scope',
  19. takesArg: true,
  20. helpArg: 'SCOPE',
  21. parseArg: function (option, optstr, arg) {
  22. if (!/^base|one|sub$/.test(arg)) {
  23. throw new TypeError('Scope must be <base|one|sub>');
  24. }
  25. return arg;
  26. }
  27. });
  28. dashdash.addOptionType({
  29. name: 'ldap.outputFormat',
  30. takesArg: true,
  31. helpArg: 'FORMAT',
  32. parseArg: function (option, optstr, arg) {
  33. var formats = ['json', 'jsonl', 'jsona'];
  34. if (formats.indexOf(arg) === -1) {
  35. throw new TypeError('Must be valid format type');
  36. }
  37. return arg;
  38. }
  39. });
  40. var opts = [
  41. {
  42. names: ['base', 'b'],
  43. type: 'string',
  44. help: 'Base DN of search',
  45. helpArg: 'BASE_DN',
  46. default: ''
  47. },
  48. {
  49. names: ['scope', 's'],
  50. type: 'ldap.scope',
  51. help: 'Search scope <base|sub|one>',
  52. helpArg: 'SCOPE',
  53. default: 'sub'
  54. },
  55. {
  56. names: ['timeout', 't'],
  57. type: 'integer',
  58. help: 'Search timeout',
  59. helpArg: 'SECS'
  60. },
  61. {
  62. names: ['persistent', 'p'],
  63. type: 'bool',
  64. help: 'Enable persistent search control',
  65. default: false
  66. },
  67. {
  68. names: ['paged', 'g'],
  69. type: 'number',
  70. help: 'Enable paged search result control',
  71. helpArg: 'PAGE_SIZE'
  72. },
  73. {
  74. names: ['control', 'c'],
  75. type: 'arrayOfString',
  76. help: 'Send addition control OID',
  77. helpArg: 'OID',
  78. default: []
  79. },
  80. { group: 'General Options' },
  81. {
  82. names: ['help', 'h'],
  83. type: 'bool',
  84. help: 'Print this help and exit.'
  85. },
  86. {
  87. names: ['debug', 'd'],
  88. type: 'integer',
  89. help: 'Set debug level <0-2>',
  90. helpArg: 'LEVEL'
  91. },
  92. { group: 'Output Options' },
  93. {
  94. names: ['format', 'o'],
  95. type: 'ldap.outputFormat',
  96. helpWrap: false,
  97. help: ('Specify and output format. One of:\n' +
  98. ' json: JSON objects (default)\n' +
  99. ' jsonl: Line-delimited JSON\n' +
  100. ' jsona: Array of JSON objects\n'),
  101. default: 'json'
  102. },
  103. { group: 'Connection Options' },
  104. {
  105. names: ['url', 'u'],
  106. type: 'string',
  107. help: 'LDAP server URL',
  108. helpArg: 'URL',
  109. default: 'ldap://127.0.0.1:389'
  110. },
  111. {
  112. names: ['binddn', 'D'],
  113. type: 'string',
  114. help: 'Bind DN',
  115. helpArg: 'BIND_DN',
  116. default: ''
  117. },
  118. {
  119. names: ['password', 'w'],
  120. type: 'string',
  121. help: 'Bind password',
  122. helpArg: 'PASSWD',
  123. default: ''
  124. },
  125. {
  126. names: ['insecure', 'i'],
  127. type: 'bool',
  128. env: 'LDAPJS_TLS_INSECURE',
  129. help: 'Disable SSL certificate verification',
  130. default: false
  131. }
  132. ];
  133. var parser = dashdash.createParser({options: opts});
  134. ///--- Helpers
  135. function usage(code, message) {
  136. var msg = (message ? message + '\n' : '') +
  137. 'Usage: ' + path.basename(process.argv[1]) +
  138. ' [OPTIONS] FILTER [ATTRIBUTES...]\n\n' +
  139. parser.help({includeEnv: true});
  140. process.stderr.write(msg + '\n');
  141. process.exit(code);
  142. }
  143. function perror(err) {
  144. if (parsed.debug) {
  145. process.stderr.write(err.stack + '\n');
  146. } else {
  147. process.stderr.write(err.message + '\n');
  148. }
  149. process.exit(1);
  150. }
  151. function EntryFormatter(fp, format) {
  152. this.format = format;
  153. this.started = false;
  154. this.ended = false;
  155. this.fp = fp;
  156. }
  157. EntryFormatter.prototype.write = function write(entry) {
  158. switch (this.format) {
  159. case 'json':
  160. this.fp.write(JSON.stringify(entry.object, null, 2) + '\n');
  161. break;
  162. case 'jsonl':
  163. this.fp.write(JSON.stringify(entry.object) + '\n');
  164. break;
  165. case 'jsona':
  166. this.fp.write((this.started) ? ',\n' : '[\n');
  167. this.started = true;
  168. // pretty-print with indent
  169. this.fp.write(
  170. JSON.stringify(entry.object, null, 2)
  171. .split('\n')
  172. .map(function (line) { return ' ' + line; })
  173. .join('\n'));
  174. break;
  175. default:
  176. throw new Error('invalid output format');
  177. }
  178. };
  179. EntryFormatter.prototype.end = function end() {
  180. if (this.ended) {
  181. return;
  182. }
  183. this.ended = true;
  184. if (this.format === 'jsona') {
  185. this.fp.write('\n]\n');
  186. }
  187. };
  188. ///--- Mainline
  189. var parsed;
  190. process.stdout.on('error', function (err) {
  191. if (err.code === 'EPIPE') {
  192. process.exit(0);
  193. } else {
  194. throw err;
  195. }
  196. });
  197. try {
  198. parsed = parser.parse(process.argv);
  199. } catch (e) {
  200. usage(1, e.toString());
  201. }
  202. if (parsed.help)
  203. usage(0);
  204. if (parsed._args.length < 1)
  205. usage(1, 'filter required');
  206. try {
  207. ldap.parseFilter(parsed._args[0]);
  208. } catch (e) {
  209. usage(1, e.message);
  210. }
  211. var logLevel = 'info';
  212. if (parsed.debug)
  213. logLevel = (parsed.debug > 1 ? 'trace' : 'debug');
  214. var formatter = new EntryFormatter(process.stdout, parsed.format);
  215. var log = new Logger({
  216. name: 'ldapjs',
  217. component: 'client',
  218. stream: process.stderr,
  219. level: logLevel
  220. });
  221. var client = ldap.createClient({
  222. url: parsed.url,
  223. log: log,
  224. strictDN: false,
  225. timeout: parsed.timeout || false,
  226. tlsOptions: {
  227. rejectUnauthorized: !parsed.insecure
  228. }
  229. });
  230. client.on('error', function (err) {
  231. perror(err);
  232. });
  233. client.on('timeout', function (req) {
  234. process.stderr.write('Timeout reached\n');
  235. process.exit(1);
  236. });
  237. client.bind(parsed.binddn, parsed.password, function (err, res) {
  238. if (err)
  239. perror(err);
  240. var controls = [];
  241. parsed.control.forEach(function (c) {
  242. controls.push(new ldap.Control({
  243. type: c,
  244. criticality: true
  245. }));
  246. });
  247. if (parsed.persistent) {
  248. var pCtrl = new ldap.PersistentSearchControl({
  249. type: '2.16.840.1.113730.3.4.3',
  250. value: {
  251. changeTypes: 15,
  252. changesOnly: false,
  253. returnECs: true
  254. }
  255. });
  256. controls.push(pCtrl);
  257. }
  258. var req = {
  259. scope: parsed.scope || 'sub',
  260. filter: parsed._args[0],
  261. attributes: parsed._args.length > 1 ? parsed._args.slice(1) : []
  262. };
  263. if (parsed.paged) {
  264. req.paged = {
  265. pageSize: parsed.paged
  266. };
  267. }
  268. client.search(parsed.base, req, controls, function (err, res) {
  269. if (err)
  270. perror(err);
  271. res.on('searchEntry', function (entry) {
  272. formatter.write(entry);
  273. });
  274. res.on('error', function (err) {
  275. formatter.end();
  276. perror(err);
  277. });
  278. res.on('end', function (res) {
  279. formatter.end();
  280. if (res.status !== 0) {
  281. process.stderr.write(ldap.getMessage(res.status) + '\n');
  282. }
  283. client.unbind(function () {
  284. return;
  285. });
  286. });
  287. });
  288. });