"added ability to deserialize ldap persistent search controls"
This commit is contained in:
parent
959fa2587b
commit
ee88fc7019
|
@ -5,15 +5,16 @@ var util = require('util');
|
||||||
|
|
||||||
var asn1 = require('asn1');
|
var asn1 = require('asn1');
|
||||||
|
|
||||||
|
var PersistentSearchControl = require('./persistent_search_control');
|
||||||
var Protocol = require('./protocol');
|
var Protocol = require('./protocol');
|
||||||
|
|
||||||
|
var log4js = require('log4js');
|
||||||
|
|
||||||
///--- Globals
|
///--- Globals
|
||||||
|
var LOG = log4js.getLogger('control.js');
|
||||||
var Ber = asn1.Ber;
|
var Ber = asn1.Ber;
|
||||||
|
|
||||||
|
var OID_PERSISTENT_SEARCH_CONTROL = '2.16.840.1.113730.3.4.3';
|
||||||
|
|
||||||
///--- API
|
///--- API
|
||||||
|
|
||||||
|
@ -47,35 +48,10 @@ function Control(options) {
|
||||||
}
|
}
|
||||||
module.exports = Control;
|
module.exports = Control;
|
||||||
|
|
||||||
|
|
||||||
Control.prototype.toString = function() {
|
Control.prototype.toString = function() {
|
||||||
return this.json;
|
return this.json;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Control.prototype.parse = function(ber) {
|
|
||||||
assert.ok(ber);
|
|
||||||
|
|
||||||
if (ber.readSequence() === null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var end = ber.offset + ber.length;
|
|
||||||
|
|
||||||
if (ber.length) {
|
|
||||||
this.type = ber.readString();
|
|
||||||
if (ber.offset < end) {
|
|
||||||
if (ber.peek() === 0x01) // Boolean, optional
|
|
||||||
this.criticality = ber.readBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ber.offset < end)
|
|
||||||
this.value = ber.readString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Control.prototype.toBer = function(ber) {
|
Control.prototype.toBer = function(ber) {
|
||||||
assert.ok(ber);
|
assert.ok(ber);
|
||||||
|
|
||||||
|
|
35
lib/index.js
35
lib/index.js
|
@ -4,18 +4,22 @@ var Client = require('./client');
|
||||||
var Attribute = require('./attribute');
|
var Attribute = require('./attribute');
|
||||||
var Change = require('./change');
|
var Change = require('./change');
|
||||||
var Control = require('./control');
|
var Control = require('./control');
|
||||||
|
var PersistentSearchControl = require('./persistent_search_control');
|
||||||
var Protocol = require('./protocol');
|
var Protocol = require('./protocol');
|
||||||
var Server = require('./server');
|
var Server = require('./server');
|
||||||
|
|
||||||
|
var assert = require('assert');
|
||||||
var dn = require('./dn');
|
var dn = require('./dn');
|
||||||
var errors = require('./errors');
|
var errors = require('./errors');
|
||||||
var filters = require('./filters');
|
var filters = require('./filters');
|
||||||
|
var log4js = require('log4js');
|
||||||
var logStub = require('./log_stub');
|
var logStub = require('./log_stub');
|
||||||
var messages = require('./messages');
|
var messages = require('./messages');
|
||||||
var schema = require('./schema');
|
var schema = require('./schema');
|
||||||
var url = require('./url');
|
var url = require('./url');
|
||||||
|
|
||||||
|
var LOG = log4js.getLogger(this);
|
||||||
|
var OID_PERSISTENT_SEARCH_CONTROL = '2.16.840.1.113730.3.4.3';
|
||||||
|
|
||||||
/// Hack a few things we need (i.e., "monkey patch" the prototype)
|
/// Hack a few things we need (i.e., "monkey patch" the prototype)
|
||||||
|
|
||||||
|
@ -57,6 +61,35 @@ module.exports = {
|
||||||
Change: Change,
|
Change: Change,
|
||||||
Control: Control,
|
Control: Control,
|
||||||
|
|
||||||
|
getControl: function(ber) {
|
||||||
|
assert.ok(ber);
|
||||||
|
|
||||||
|
if (ber.readSequence() === null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var end = ber.offset + ber.length;
|
||||||
|
var options = {};
|
||||||
|
if (ber.length) {
|
||||||
|
options.type = ber.readString();
|
||||||
|
if (ber.offset < end) {
|
||||||
|
if (ber.peek() === 0x01) // Boolean, optional
|
||||||
|
options.criticality = ber.readBoolean();
|
||||||
|
}
|
||||||
|
if (ber.offset < end) {
|
||||||
|
if (options.type == OID_PERSISTENT_SEARCH_CONTROL) {
|
||||||
|
// send the buffer directly to the PSC
|
||||||
|
options.value = ber.readString(0x04, true);
|
||||||
|
return new PersistentSearchControl(options);
|
||||||
|
} else {
|
||||||
|
options.value = ber.readString();
|
||||||
|
return new Control(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
PersistentSearchControl: PersistentSearchControl,
|
||||||
|
|
||||||
DN: dn.DN,
|
DN: dn.DN,
|
||||||
RDN: dn.RDN,
|
RDN: dn.RDN,
|
||||||
parseDN: dn.parse,
|
parseDN: dn.parse,
|
||||||
|
|
|
@ -8,6 +8,7 @@ var asn1 = require('asn1');
|
||||||
var Control = require('../control');
|
var Control = require('../control');
|
||||||
var Protocol = require('../protocol');
|
var Protocol = require('../protocol');
|
||||||
|
|
||||||
|
var log4js = require('log4js');
|
||||||
var logStub = require('../log_stub');
|
var logStub = require('../log_stub');
|
||||||
|
|
||||||
///--- Globals
|
///--- Globals
|
||||||
|
@ -16,7 +17,7 @@ var Ber = asn1.Ber;
|
||||||
var BerReader = asn1.BerReader;
|
var BerReader = asn1.BerReader;
|
||||||
var BerWriter = asn1.BerWriter;
|
var BerWriter = asn1.BerWriter;
|
||||||
|
|
||||||
|
var LOG = log4js.getLogger('Message');
|
||||||
|
|
||||||
///--- API
|
///--- API
|
||||||
|
|
||||||
|
@ -76,11 +77,13 @@ LDAPMessage.prototype.parse = function(ber) {
|
||||||
ber.readSequence();
|
ber.readSequence();
|
||||||
var end = ber.offset + ber.length;
|
var end = ber.offset + ber.length;
|
||||||
while (ber.offset < end) {
|
while (ber.offset < end) {
|
||||||
var c = new Control();
|
var getControl = require('../index').getControl;
|
||||||
if (c.parse(ber))
|
var c = getControl(ber);
|
||||||
|
if (c) {
|
||||||
this.controls.push(c);
|
this.controls.push(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.log.isTraceEnabled())
|
if (this.log.isTraceEnabled())
|
||||||
this.log.trace('Parsing done: %j', this.json);
|
this.log.trace('Parsing done: %j', this.json);
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
var assert = require('assert');
|
||||||
|
var asn1 = require('asn1');
|
||||||
|
var buffer = require('buffer');
|
||||||
|
var log4js = require('log4js');
|
||||||
|
var Control = require('./control');
|
||||||
|
var util = require('util');
|
||||||
|
var Ber = asn1.Ber;
|
||||||
|
|
||||||
|
var LOG = log4js.getLogger('PersistentSearchControl');
|
||||||
|
|
||||||
|
function PersistentSearchControl(options) {
|
||||||
|
if (options) {
|
||||||
|
if (typeof(options) !== 'object')
|
||||||
|
throw new TypeError('options must be an object');
|
||||||
|
if (options.type && typeof(options.type) !== 'string')
|
||||||
|
throw new TypeError('options.type must be a string');
|
||||||
|
if (options.criticality !== undefined &&
|
||||||
|
typeof(options.criticality) !== 'boolean')
|
||||||
|
throw new TypeError('options.criticality must be a boolean');
|
||||||
|
if (options.value && typeof(options.value) !== 'object')
|
||||||
|
throw new TypeError('options.value must be a buffer');
|
||||||
|
} else {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.type = options.type || '';
|
||||||
|
this.criticality = options.criticality || false;
|
||||||
|
this.value = options.value || undefined;
|
||||||
|
|
||||||
|
if (this.value) {
|
||||||
|
// parse out this.value into the PSC object
|
||||||
|
var ber = new Ber.Reader(this.value);
|
||||||
|
ber.readSequence();
|
||||||
|
this.value = {
|
||||||
|
changeTypes: ber.readInt(),
|
||||||
|
changesOnly: ber.readBoolean(),
|
||||||
|
returnECs: ber.readBoolean()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
this.__defineGetter__('json', function() {
|
||||||
|
return {
|
||||||
|
controlType: self.type,
|
||||||
|
criticality: self.criticality,
|
||||||
|
controlValue: self.value
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
module.exports = PersistentSearchControl;
|
||||||
|
|
||||||
|
// returns a psc given a fully populated psc object
|
||||||
|
PersistentSearchControl.prototype.get = function(options) {
|
||||||
|
if (options) {
|
||||||
|
if (typeof(options) !== 'object')
|
||||||
|
throw new TypeError('options must be an object');
|
||||||
|
if (options.type && typeof(options.type) !== 'string')
|
||||||
|
throw new TypeError('options.type must be a string');
|
||||||
|
if (options.criticality !== undefined &&
|
||||||
|
typeof(options.criticality) !== 'boolean')
|
||||||
|
throw new TypeError('options.criticality must be a boolean');
|
||||||
|
if (options.value && typeof(options.value) !== 'object') {
|
||||||
|
throw new TypeError('options.value must be an object');
|
||||||
|
} else {
|
||||||
|
if (options.value.changeTypes &&
|
||||||
|
typeof(options.value.changeTypes) !== 'number')
|
||||||
|
throw new TypeError('options.value.changeTypes must be a number');
|
||||||
|
if (options.value.changesOnly !== undefined &&
|
||||||
|
typeof(options.value.changesOnly) !== 'boolean')
|
||||||
|
throw new TypeError('options.value.changesOnly must be a boolean');
|
||||||
|
if (options.value.returnECs !== undefined &&
|
||||||
|
typeof(options.value.returnECs) !== 'boolean')
|
||||||
|
throw new TypeError('options.value.returnECs must be a boolean');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.type = options.type || '';
|
||||||
|
this.criticality = options.criticality || false;
|
||||||
|
this.value = options.value || undefined;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
this.__defineGetter__('json', function() {
|
||||||
|
return {
|
||||||
|
controlType: self.type,
|
||||||
|
criticality: self.criticality,
|
||||||
|
controlValue: self.value
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
PersistentSearchControl.prototype.toBer = function(ber) {
|
||||||
|
assert.ok(ber);
|
||||||
|
|
||||||
|
ber.startSequence();
|
||||||
|
ber.writeString(this.type || '');
|
||||||
|
ber.writeBoolean(this.criticality);
|
||||||
|
|
||||||
|
var pscWriter = new Ber.Writer();
|
||||||
|
|
||||||
|
// write the value subsequence
|
||||||
|
pscWriter.startSequence();
|
||||||
|
pscWriter.writeInt(this.value.changeTypes);
|
||||||
|
pscWriter.writeBoolean(this.value.changesOnly);
|
||||||
|
pscWriter.writeBoolean(this.value.returnECs);
|
||||||
|
pscWriter.endSequence();
|
||||||
|
|
||||||
|
// write the pscValue as a octetstring to the ber
|
||||||
|
ber.writeBuffer(pscWriter.buffer, 0x04);
|
||||||
|
|
||||||
|
ber.endSequence();
|
||||||
|
};
|
|
@ -20,6 +20,7 @@
|
||||||
"asn1": "0.1.8",
|
"asn1": "0.1.8",
|
||||||
"buffertools": "1.0.5",
|
"buffertools": "1.0.5",
|
||||||
"dtrace-provider": "0.0.3",
|
"dtrace-provider": "0.0.3",
|
||||||
|
"log4js": "0.4.1",
|
||||||
"nopt": "1.0.10",
|
"nopt": "1.0.10",
|
||||||
"sprintf": "0.1.1"
|
"sprintf": "0.1.1"
|
||||||
},
|
},
|
||||||
|
|
|
@ -10,6 +10,7 @@ var asn1 = require('asn1');
|
||||||
var BerReader = asn1.BerReader;
|
var BerReader = asn1.BerReader;
|
||||||
var BerWriter = asn1.BerWriter;
|
var BerWriter = asn1.BerWriter;
|
||||||
var Control;
|
var Control;
|
||||||
|
var getControl;
|
||||||
|
|
||||||
|
|
||||||
///--- Tests
|
///--- Tests
|
||||||
|
@ -17,6 +18,8 @@ var Control;
|
||||||
test('load library', function(t) {
|
test('load library', function(t) {
|
||||||
Control = require('../lib/index').Control;
|
Control = require('../lib/index').Control;
|
||||||
t.ok(Control);
|
t.ok(Control);
|
||||||
|
getControl = require('../lib/index').getControl;
|
||||||
|
t.ok(getControl);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -47,9 +50,7 @@ test('parse', function(t) {
|
||||||
ber.writeString('foo');
|
ber.writeString('foo');
|
||||||
ber.endSequence();
|
ber.endSequence();
|
||||||
|
|
||||||
var c = new Control();
|
var c = getControl(new BerReader(ber.buffer));
|
||||||
t.ok(c);
|
|
||||||
t.ok(c.parse(new BerReader(ber.buffer)));
|
|
||||||
|
|
||||||
t.ok(c);
|
t.ok(c);
|
||||||
t.equal(c.type, '2.16.840.1.113730.3.4.2');
|
t.equal(c.type, '2.16.840.1.113730.3.4.2');
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||||
|
|
||||||
|
var test = require('tap').test;
|
||||||
|
|
||||||
|
var asn1 = require('asn1');
|
||||||
|
var log4js = require('log4js');
|
||||||
|
var sys = require('sys');
|
||||||
|
|
||||||
|
var BerReader = asn1.BerReader;
|
||||||
|
var BerWriter = asn1.BerWriter;
|
||||||
|
var getControl;
|
||||||
|
var PersistentSearchControl;
|
||||||
|
|
||||||
|
///--- Globals
|
||||||
|
var LOG = log4js.getLogger('persistent_search_control.test');
|
||||||
|
|
||||||
|
///--- Tests
|
||||||
|
|
||||||
|
test('load library', function(t) {
|
||||||
|
PersistentSearchControl = require('../lib/index').PersistentSearchControl;
|
||||||
|
t.ok(PersistentSearchControl);
|
||||||
|
getControl = require('../lib/index').getControl;
|
||||||
|
t.ok(getControl);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('new no args', function(t) {
|
||||||
|
t.ok(new PersistentSearchControl());
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('new with args', function(t) {
|
||||||
|
var options = {
|
||||||
|
type: '2.16.840.1.113730.3.4.3',
|
||||||
|
criticality: true,
|
||||||
|
value: {
|
||||||
|
changeTypes: 15,
|
||||||
|
changesOnly: false,
|
||||||
|
returnECs: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var c = new PersistentSearchControl();
|
||||||
|
c.get(options);
|
||||||
|
t.ok(c);
|
||||||
|
t.equal(c.type, '2.16.840.1.113730.3.4.3');
|
||||||
|
t.ok(c.criticality);
|
||||||
|
|
||||||
|
t.equal(c.value.changeTypes, 15);
|
||||||
|
t.equal(c.value.changesOnly, false);
|
||||||
|
t.equal(c.value.returnECs, false);
|
||||||
|
|
||||||
|
|
||||||
|
var writer = new BerWriter();
|
||||||
|
c.toBer(writer);
|
||||||
|
var reader = new BerReader(writer.buffer);
|
||||||
|
var psc = getControl(reader);
|
||||||
|
t.ok(psc);
|
||||||
|
t.equal(psc.type, '2.16.840.1.113730.3.4.3');
|
||||||
|
t.ok(psc.criticality);
|
||||||
|
t.equal(psc.value.changeTypes, 15);
|
||||||
|
t.equal(psc.value.changesOnly, false);
|
||||||
|
t.equal(psc.value.returnECs, false);
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('getControl with args', function(t) {
|
||||||
|
var buf = new Buffer([
|
||||||
|
0x30, 0x26, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30,
|
||||||
|
0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e,
|
||||||
|
0x34, 0x2e, 0x33, 0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01,
|
||||||
|
0xff, 0x01, 0x01, 0xff]);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
type: '2.16.840.1.113730.3.4.3',
|
||||||
|
criticality: false,
|
||||||
|
value: {
|
||||||
|
changeTypes: 15,
|
||||||
|
changesOnly: true,
|
||||||
|
returnECs: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var ber = new BerReader(buf);
|
||||||
|
var psc = getControl(ber);
|
||||||
|
LOG.info(psc.value);
|
||||||
|
t.ok(psc);
|
||||||
|
t.equal(psc.type, '2.16.840.1.113730.3.4.3');
|
||||||
|
t.equal(psc.criticality, false);
|
||||||
|
t.equal(psc.value.changeTypes, 15);
|
||||||
|
t.equal(psc.value.changesOnly, true);
|
||||||
|
t.equal(psc.value.returnECs, true);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('tober', function(t) {
|
||||||
|
var ber = new BerWriter();
|
||||||
|
var options = {
|
||||||
|
type: '2.16.840.1.113730.3.4.3',
|
||||||
|
criticality: true,
|
||||||
|
value: {
|
||||||
|
changeTypes: 15,
|
||||||
|
changesOnly: false,
|
||||||
|
returnECs: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var psc = new PersistentSearchControl();
|
||||||
|
psc.get(options);
|
||||||
|
psc.toBer(ber);
|
||||||
|
|
||||||
|
var c = getControl(new BerReader(ber.buffer));
|
||||||
|
t.ok(c);
|
||||||
|
t.equal(c.type, '2.16.840.1.113730.3.4.3');
|
||||||
|
t.ok(c.criticality);
|
||||||
|
t.equal(c.value.changeTypes, 15);
|
||||||
|
t.equal(c.value.changesOnly, false);
|
||||||
|
t.equal(c.value.returnECs, false);
|
||||||
|
t.end();
|
||||||
|
});
|
Loading…
Reference in New Issue