#!/usr/bin/env node // -*- mode: js -*- // Copyright 2011 Mark Cavage. All rights reserved. var path = require('path'); var url = require('url'); var nopt = require('nopt'); var ldap = require('../lib/index'); var Logger = require('bunyan'); ///--- Globals nopt.typeDefs.DN = { type: ldap.DN, validate: function(data, k, val) { data[k] = ldap.parseDN(val); } }; nopt.typeDefs.Filter = { type: ldap.Filter, validate: function(data, k, val) { data[k] = ldap.parseFilter(val); } }; var opts = { 'debug': Number, 'base': ldap.DN, 'binddn': ldap.DN, 'control': Array, 'insecure': Boolean, 'password': String, 'persistent': Boolean, 'paged': Number, 'scope': String, 'timeout': Number, 'url': url }; var shortOpts = { 'c': ['--control'], 'd': ['--debug'], 'b': ['--base'], 'D': ['--binddn'], 'i': ['--insecure'], 'w': ['--password'], 'p': ['--persistent'], 'g': ['--paged'], 's': ['--scope'], 't': ['--timeout'], 'u': ['--url'] }; ///--- Helpers function usage(code, message) { var _opts = ''; Object.keys(shortOpts).forEach(function(k) { if (!Array.isArray(shortOpts[k])) return; var longOpt = shortOpts[k][0].replace('--', ''); var type = opts[longOpt].name || 'string'; if (type && type === 'boolean') type = ''; type = type.toLowerCase(); _opts += ' [--' + longOpt + ' ' + type + ']'; }); _opts += ' filter [attributes...]'; var msg = (message ? message + '\n' : '') + 'usage: ' + path.basename(process.argv[1]) + _opts; process.stderr.write(msg + '\n'); process.exit(code); } function perror(err) { if (parsed.debug) { process.stderr.write(err.stack + '\n'); } else { process.stderr.write(err.message + '\n'); } process.exit(1); } ///--- Mainline var parsed; try { parsed = nopt(opts, shortOpts, process.argv, 2); } catch (e) { usage(1, e.toString()); } if (parsed.insecure === undefined && process.env.LDAPJS_TLS_INSECURE !== undefined) { if (process.env.LDAPJS_TLS_INSECURE === '0') { parsed.insecure = false; } else { parsed.insecure = true; } } if (parsed.help) usage(0); if (parsed.argv.remain.length < 1) usage(1, 'filter required'); try { ldap.parseFilter(parsed.argv.remain[0]); } catch (e) { usage(1, e.message); } var logLevel = 'info'; if (parsed.debug) logLevel = (parsed.debug > 1 ? 'trace' : 'debug'); if (!parsed.url) parsed.url = 'ldap://127.0.0.1:389'; if (!parsed.binddn) parsed.binddn = ''; if (!parsed.password) parsed.password = ''; if (!parsed.base) parsed.base = ''; if (!parsed.control) parsed.control = []; if (!parsed.persistent) parsed.persistent = false; var log = new Logger({ name: 'ldapjs', component: 'client', stream: process.stderr, level: logLevel }); var client = ldap.createClient({ url: parsed.url, log: log, timeout: parsed.timeout || false, tlsOptions: { rejectUnauthorized: !parsed.insecure } }); client.on('error', function(err) { perror(err); }); client.on('timeout', function(req) { process.stderr.write('Timeout reached\n'); process.exit(1); }); client.bind(parsed.binddn, parsed.password, function(err, res) { if (err) perror(err); var controls = []; parsed.control.forEach(function(c) { controls.push(new ldap.Control({ type: c, criticality: true })); }); if (parsed.persistent) { var pCtrl = new ldap.PersistentSearchControl({ type: '2.16.840.1.113730.3.4.3', value: { changeTypes: 15, changesOnly: false, returnECs: true } }); controls.push(pCtrl); } if (parsed.paged) { var ctrl = new ldap.PagedResultsControl({ value: { size: parsed.paged } }); controls.push(ctrl); } var req = { scope: parsed.scope || 'sub', filter: parsed.argv.remain[0], attributes: parsed.argv.remain.length > 1 ? parsed.argv.remain.slice(1) : [] }; client.search(parsed.base, req, controls, function(err, res) { if (err) perror(err); res.on('searchEntry', function(entry) { process.stdout.write(JSON.stringify(entry.object, null, 2) + '\n'); }); res.on('error', function(err) { perror(err); }); res.on('end', function(res) { if (res.status !== 0) process.stderr.write(ldap.getMessage(res.status) + '\n'); client.unbind(function() { return; }); }); }); });