2011-10-18 20:25:56 +00:00
|
|
|
#!/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');
|
2013-04-24 18:45:19 +00:00
|
|
|
var Logger = require('bunyan');
|
2011-10-18 20:25:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
///--- 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,
|
2011-10-18 23:26:38 +00:00
|
|
|
'control': Array,
|
2014-04-23 00:46:14 +00:00
|
|
|
'insecure': Boolean,
|
2011-10-18 20:25:56 +00:00
|
|
|
'password': String,
|
2011-12-20 23:04:59 +00:00
|
|
|
'persistent': Boolean,
|
2012-09-19 20:39:31 +00:00
|
|
|
'paged': Number,
|
2011-10-18 20:25:56 +00:00
|
|
|
'scope': String,
|
2012-01-20 02:02:10 +00:00
|
|
|
'timeout': Number,
|
2011-10-18 20:25:56 +00:00
|
|
|
'url': url
|
|
|
|
};
|
|
|
|
|
|
|
|
var shortOpts = {
|
2011-10-18 23:26:38 +00:00
|
|
|
'c': ['--control'],
|
2011-10-18 20:25:56 +00:00
|
|
|
'd': ['--debug'],
|
|
|
|
'b': ['--base'],
|
|
|
|
'D': ['--binddn'],
|
2014-04-23 00:46:14 +00:00
|
|
|
'i': ['--insecure'],
|
2011-10-18 20:25:56 +00:00
|
|
|
'w': ['--password'],
|
2011-12-20 23:04:59 +00:00
|
|
|
'p': ['--persistent'],
|
2012-09-19 20:39:31 +00:00
|
|
|
'g': ['--paged'],
|
2011-10-18 20:25:56 +00:00
|
|
|
's': ['--scope'],
|
2012-01-20 02:02:10 +00:00
|
|
|
't': ['--timeout'],
|
2011-10-18 20:25:56 +00:00
|
|
|
'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());
|
|
|
|
}
|
|
|
|
|
2014-04-23 00:46:14 +00:00
|
|
|
if (parsed.insecure === undefined &&
|
|
|
|
process.env.LDAPJS_TLS_INSECURE !== undefined) {
|
|
|
|
if (process.env.LDAPJS_TLS_INSECURE === '0') {
|
|
|
|
parsed.insecure = false;
|
|
|
|
} else {
|
|
|
|
parsed.insecure = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-18 20:25:56 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-04-24 18:45:19 +00:00
|
|
|
var logLevel = 'info';
|
2011-10-18 20:25:56 +00:00
|
|
|
|
|
|
|
if (parsed.debug)
|
2013-04-24 18:45:19 +00:00
|
|
|
logLevel = (parsed.debug > 1 ? 'trace' : 'debug');
|
2011-10-18 20:25:56 +00:00
|
|
|
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 = '';
|
2011-10-18 23:26:38 +00:00
|
|
|
if (!parsed.control)
|
|
|
|
parsed.control = [];
|
2011-12-20 23:04:59 +00:00
|
|
|
if (!parsed.persistent)
|
|
|
|
parsed.persistent = false;
|
2011-10-18 20:25:56 +00:00
|
|
|
|
2013-04-24 18:45:19 +00:00
|
|
|
var log = new Logger({
|
|
|
|
name: 'ldapjs',
|
|
|
|
component: 'client',
|
|
|
|
stream: process.stderr,
|
|
|
|
level: logLevel
|
|
|
|
});
|
|
|
|
|
2011-10-18 20:25:56 +00:00
|
|
|
var client = ldap.createClient({
|
|
|
|
url: parsed.url,
|
2013-04-24 18:45:19 +00:00
|
|
|
log: log,
|
2014-04-23 00:46:14 +00:00
|
|
|
timeout: parsed.timeout || false,
|
|
|
|
tlsOptions: {
|
|
|
|
rejectUnauthorized: !parsed.insecure
|
|
|
|
}
|
2011-10-18 20:25:56 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
client.on('error', function(err) {
|
|
|
|
perror(err);
|
|
|
|
});
|
|
|
|
|
2012-01-20 02:02:10 +00:00
|
|
|
client.on('timeout', function(req) {
|
|
|
|
process.stderr.write('Timeout reached\n');
|
|
|
|
process.exit(1);
|
|
|
|
});
|
|
|
|
|
2011-10-18 20:25:56 +00:00
|
|
|
client.bind(parsed.binddn, parsed.password, function(err, res) {
|
|
|
|
if (err)
|
|
|
|
perror(err);
|
|
|
|
|
2011-10-18 23:26:38 +00:00
|
|
|
var controls = [];
|
|
|
|
parsed.control.forEach(function(c) {
|
|
|
|
controls.push(new ldap.Control({
|
|
|
|
type: c,
|
|
|
|
criticality: true
|
|
|
|
}));
|
|
|
|
});
|
2011-12-20 23:04:59 +00:00
|
|
|
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);
|
|
|
|
}
|
2012-09-19 20:39:31 +00:00
|
|
|
if (parsed.paged) {
|
|
|
|
var ctrl = new ldap.PagedResultsControl({ value: { size: parsed.paged } });
|
|
|
|
controls.push(ctrl);
|
|
|
|
}
|
2011-10-18 20:25:56 +00:00
|
|
|
var req = {
|
|
|
|
scope: parsed.scope || 'sub',
|
|
|
|
filter: parsed.argv.remain[0],
|
|
|
|
attributes: parsed.argv.remain.length > 1 ? parsed.argv.remain.slice(1) : []
|
|
|
|
};
|
2011-10-18 23:26:38 +00:00
|
|
|
client.search(parsed.base, req, controls, function(err, res) {
|
2011-10-18 20:25:56 +00:00
|
|
|
if (err)
|
|
|
|
perror(err);
|
|
|
|
|
|
|
|
res.on('searchEntry', function(entry) {
|
2011-12-20 23:04:59 +00:00
|
|
|
process.stdout.write(JSON.stringify(entry.object, null, 2) + '\n');
|
2011-10-18 20:25:56 +00:00
|
|
|
});
|
|
|
|
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;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|