First commit
This commit is contained in:
9
node_modules/@ldapjs/controls/.eslintrc
generated
vendored
Normal file
9
node_modules/@ldapjs/controls/.eslintrc
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest"
|
||||
},
|
||||
|
||||
"extends": [
|
||||
"standard"
|
||||
]
|
||||
}
|
||||
10
node_modules/@ldapjs/controls/.github/workflows/main.yml
generated
vendored
Normal file
10
node_modules/@ldapjs/controls/.github/workflows/main.yml
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
name: "CI"
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
call-core-ci:
|
||||
uses: ldapjs/.github/.github/workflows/node-ci.yml@main
|
||||
5
node_modules/@ldapjs/controls/.taprc.yml
generated
vendored
Normal file
5
node_modules/@ldapjs/controls/.taprc.yml
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
files:
|
||||
- 'index.test.js'
|
||||
- 'lib/**/*.test.js'
|
||||
|
||||
coverage-map: coverage-map.js
|
||||
22
node_modules/@ldapjs/controls/LICENSE
generated
vendored
Normal file
22
node_modules/@ldapjs/controls/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011 Mark Cavage, All rights reserved.
|
||||
Copyright (c) 2022 The LDAPJS Collaborators.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE
|
||||
12
node_modules/@ldapjs/controls/Readme.md
generated
vendored
Normal file
12
node_modules/@ldapjs/controls/Readme.md
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# @ldapjs/controls
|
||||
|
||||
This package provides implementations of [LDAP controls][controls]. The
|
||||
primary purpose of this library is to facilitate client and server
|
||||
implementations in the [`ldapjs`](https://npm.im/ldapjs) package.
|
||||
|
||||
## Docs
|
||||
|
||||
At this time, one must reference the code to learn about the available
|
||||
controls and their methods.
|
||||
|
||||
[controls]: https://datatracker.ietf.org/doc/html/rfc4511#section-4.1.11
|
||||
13
node_modules/@ldapjs/controls/coverage-map.js
generated
vendored
Normal file
13
node_modules/@ldapjs/controls/coverage-map.js
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
module.exports = testFile => {
|
||||
if (testFile.startsWith('virtual-list-view-request-control') === true) {
|
||||
// Do not count towards coverage as it is disabled.
|
||||
return false
|
||||
}
|
||||
|
||||
if (testFile.startsWith('virtual-list-view-response-control') === true) {
|
||||
// Do not count towards coverage as it is disabled.
|
||||
return false
|
||||
}
|
||||
|
||||
testFile.replace(/\.test\.js$/, '.js')
|
||||
}
|
||||
103
node_modules/@ldapjs/controls/index.js
generated
vendored
Normal file
103
node_modules/@ldapjs/controls/index.js
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
'use strict'
|
||||
|
||||
const { Ber } = require('@ldapjs/asn1')
|
||||
|
||||
const Control = require('./lib/control')
|
||||
const EntryChangeNotificationControl = require('./lib/controls/entry-change-notification-control')
|
||||
const PagedResultsControl = require('./lib/controls/paged-results-control')
|
||||
const PasswordPolicyControl = require('./lib/controls/password-policy-control')
|
||||
const PersistentSearchControl = require('./lib/controls/persistent-search-control')
|
||||
const ServerSideSortingRequestControl = require('./lib/controls/server-side-sorting-request-control')
|
||||
const ServerSideSortingResponseControl = require('./lib/controls/server-side-sorting-response-control')
|
||||
const VirtualListViewRequestControl = require('./lib/controls/virtual-list-view-request-control')
|
||||
const VirtualListViewResponseControl = require('./lib/controls/virtual-list-view-response-control')
|
||||
|
||||
module.exports = {
|
||||
|
||||
getControl: function getControl (ber) {
|
||||
if (!ber) throw TypeError('ber must be provided')
|
||||
|
||||
if (ber.readSequence() === null) { return null }
|
||||
|
||||
let type
|
||||
const opts = {
|
||||
criticality: false,
|
||||
value: null
|
||||
}
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (ber.length) {
|
||||
const end = ber.offset + ber.length
|
||||
|
||||
type = ber.readString()
|
||||
/* istanbul ignore else */
|
||||
if (ber.offset < end) {
|
||||
/* istanbul ignore else */
|
||||
if (ber.peek() === Ber.Boolean) { opts.criticality = ber.readBoolean() }
|
||||
}
|
||||
|
||||
if (ber.offset < end) { opts.value = ber.readString(Ber.OctetString, true) }
|
||||
}
|
||||
|
||||
let control
|
||||
switch (type) {
|
||||
case EntryChangeNotificationControl.OID: {
|
||||
control = new EntryChangeNotificationControl(opts)
|
||||
break
|
||||
}
|
||||
|
||||
case PagedResultsControl.OID: {
|
||||
control = new PagedResultsControl(opts)
|
||||
break
|
||||
}
|
||||
|
||||
case PasswordPolicyControl.OID: {
|
||||
control = new PasswordPolicyControl(opts)
|
||||
break
|
||||
}
|
||||
|
||||
case PersistentSearchControl.OID: {
|
||||
control = new PersistentSearchControl(opts)
|
||||
break
|
||||
}
|
||||
|
||||
case ServerSideSortingRequestControl.OID: {
|
||||
control = new ServerSideSortingRequestControl(opts)
|
||||
break
|
||||
}
|
||||
|
||||
case ServerSideSortingResponseControl.OID: {
|
||||
control = new ServerSideSortingResponseControl(opts)
|
||||
break
|
||||
}
|
||||
|
||||
case VirtualListViewRequestControl.OID: {
|
||||
control = new VirtualListViewRequestControl(opts)
|
||||
break
|
||||
}
|
||||
|
||||
case VirtualListViewResponseControl.OID: {
|
||||
control = new VirtualListViewResponseControl(opts)
|
||||
break
|
||||
}
|
||||
|
||||
default: {
|
||||
opts.type = type
|
||||
control = new Control(opts)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return control
|
||||
},
|
||||
|
||||
Control,
|
||||
EntryChangeNotificationControl,
|
||||
PagedResultsControl,
|
||||
PasswordPolicyControl,
|
||||
PersistentSearchControl,
|
||||
ServerSideSortingRequestControl,
|
||||
ServerSideSortingResponseControl,
|
||||
VirtualListViewRequestControl,
|
||||
VirtualListViewResponseControl
|
||||
}
|
||||
161
node_modules/@ldapjs/controls/index.test.js
generated
vendored
Normal file
161
node_modules/@ldapjs/controls/index.test.js
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
const { BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
const controls = require('.')
|
||||
|
||||
tap.test('#getControl', t => {
|
||||
t.test('requires a BER to parse', async t => {
|
||||
try {
|
||||
controls.getControl()
|
||||
t.fail('should throw exception')
|
||||
} catch (error) {
|
||||
t.match(error, /ber must be provided/)
|
||||
}
|
||||
})
|
||||
|
||||
t.test('returns null for empty BER', async t => {
|
||||
const result = controls.getControl(new BerReader(Buffer.alloc(0)))
|
||||
t.equal(result, null)
|
||||
})
|
||||
|
||||
t.test('parses a BER (control)', async t => {
|
||||
const ber = new BerWriter()
|
||||
ber.startSequence()
|
||||
ber.writeString('2.16.840.1.113730.3.4.2')
|
||||
ber.writeBoolean(true)
|
||||
ber.writeString('foo')
|
||||
ber.endSequence()
|
||||
|
||||
const control = controls.getControl(new BerReader(ber.buffer))
|
||||
|
||||
t.ok(control)
|
||||
t.equal(control.type, '2.16.840.1.113730.3.4.2')
|
||||
t.ok(control.criticality)
|
||||
t.equal(control.value.toString('utf8'), 'foo')
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('parses BER with no value', function (t) {
|
||||
const ber = new BerWriter()
|
||||
ber.startSequence()
|
||||
ber.writeString('2.16.840.1.113730.3.4.2')
|
||||
ber.endSequence()
|
||||
|
||||
const control = controls.getControl(new BerReader(ber.buffer))
|
||||
|
||||
t.ok(control)
|
||||
t.equal(control.type, '2.16.840.1.113730.3.4.2')
|
||||
t.equal(control.criticality, false)
|
||||
t.notOk(control.value, null)
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('returns a EntryChangeNotificationControl', async t => {
|
||||
const ecnc = new controls.EntryChangeNotificationControl({
|
||||
type: controls.EntryChangeNotificationControl.OID,
|
||||
criticality: true,
|
||||
value: {
|
||||
changeType: 8,
|
||||
previousDN: 'cn=foobarbazcar',
|
||||
changeNumber: 123456789
|
||||
}
|
||||
})
|
||||
|
||||
const ber = new BerWriter()
|
||||
ecnc.toBer(ber)
|
||||
|
||||
const c = controls.getControl(new BerReader(ber.buffer))
|
||||
t.ok(c)
|
||||
t.equal(c.type, controls.EntryChangeNotificationControl.OID)
|
||||
t.ok(c.criticality)
|
||||
t.equal(c.value.changeType, 8)
|
||||
t.equal(c.value.previousDN, 'cn=foobarbazcar')
|
||||
t.equal(c.value.changeNumber, 123456789)
|
||||
})
|
||||
|
||||
t.test('returns a PagedResultsControl', async t => {
|
||||
const prc = new controls.PagedResultsControl({
|
||||
type: controls.PagedResultsControl.OID,
|
||||
criticality: true,
|
||||
value: {
|
||||
size: 20,
|
||||
cookie: Buffer.alloc(0)
|
||||
}
|
||||
})
|
||||
|
||||
const ber = new BerWriter()
|
||||
prc.toBer(ber)
|
||||
|
||||
const c = controls.getControl(new BerReader(ber.buffer))
|
||||
t.ok(c)
|
||||
t.equal(c.type, controls.PagedResultsControl.OID)
|
||||
t.ok(c.criticality)
|
||||
t.equal(c.value.size, 20)
|
||||
t.equal(Buffer.compare(c.value.cookie, Buffer.alloc(0)), 0)
|
||||
})
|
||||
|
||||
t.test('returns a PasswordPolicyControl', async t => {
|
||||
const ppc = new controls.PasswordPolicyControl({
|
||||
type: controls.PasswordPolicyControl.OID,
|
||||
criticality: true,
|
||||
value: {
|
||||
error: 1,
|
||||
timeBeforeExpiration: 2
|
||||
}
|
||||
})
|
||||
|
||||
const ber = new BerWriter()
|
||||
ppc.toBer(ber)
|
||||
|
||||
const c = controls.getControl(new BerReader(ber.buffer))
|
||||
t.ok(c)
|
||||
t.equal(c.type, controls.PasswordPolicyControl.OID)
|
||||
t.ok(c.criticality)
|
||||
t.equal(c.value.error, 1)
|
||||
t.equal(c.value.timeBeforeExpiration, 2)
|
||||
})
|
||||
|
||||
t.test('returns a PersistentSearchControl', async t => {
|
||||
const buf = Buffer.from([
|
||||
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])
|
||||
|
||||
const ber = new BerReader(buf)
|
||||
const psc = controls.getControl(ber)
|
||||
t.ok(psc)
|
||||
t.equal(psc.type, controls.PersistentSearchControl.OID)
|
||||
t.equal(psc.criticality, false)
|
||||
t.equal(psc.value.changeTypes, 15)
|
||||
t.equal(psc.value.changesOnly, true)
|
||||
t.equal(psc.value.returnECs, true)
|
||||
})
|
||||
|
||||
t.test('returns a ServerSideSortingRequestControl', async t => {
|
||||
const sssc = new controls.ServerSideSortingRequestControl()
|
||||
const ber = new BerWriter()
|
||||
sssc.toBer(ber)
|
||||
|
||||
const c = controls.getControl(new BerReader(ber.buffer))
|
||||
t.ok(c)
|
||||
t.equal(c.type, controls.ServerSideSortingRequestControl.OID)
|
||||
t.equal(c.value.length, 0)
|
||||
})
|
||||
|
||||
t.test('returns a ServerSideSortingResponseControl', async t => {
|
||||
const sssc = new controls.ServerSideSortingResponseControl()
|
||||
const ber = new BerWriter()
|
||||
sssc.toBer(ber)
|
||||
|
||||
const c = controls.getControl(new BerReader(ber.buffer))
|
||||
t.ok(c)
|
||||
t.equal(c.type, controls.ServerSideSortingResponseControl.OID)
|
||||
t.equal(c.criticality, false)
|
||||
t.notOk(c.value.result)
|
||||
t.notOk(c.value.failedAttribute)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
88
node_modules/@ldapjs/controls/lib/control.js
generated
vendored
Normal file
88
node_modules/@ldapjs/controls/lib/control.js
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
'use strict'
|
||||
|
||||
const { BerWriter } = require('@ldapjs/asn1')
|
||||
|
||||
/**
|
||||
* Baseline LDAP control object. Implements
|
||||
* https://tools.ietf.org/html/rfc4511#section-4.1.11
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
class Control {
|
||||
/**
|
||||
* @typedef {object} ControlParams
|
||||
* @property {string} [type=''] The dotted decimal control type value.
|
||||
* @property {boolean} [criticality=false] Criticality value for the control.
|
||||
* @property {string|Buffer} [value] The value for the control. If this is
|
||||
* a `string` then it will be written as-is. If it is an instance of `Buffer`
|
||||
* then it will be written by `value.toString()` when generating a BER
|
||||
* instance.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a new baseline LDAP control.
|
||||
*
|
||||
* @param {ControlParams} [options]
|
||||
*/
|
||||
constructor (options = {}) {
|
||||
const opts = Object.assign({ type: '', criticality: false, value: null }, options)
|
||||
this.type = opts.type
|
||||
this.criticality = opts.criticality
|
||||
this.value = opts.value
|
||||
}
|
||||
|
||||
get [Symbol.toStringTag] () {
|
||||
return 'LdapControl'
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the control into a plain JavaScript object that can be passed
|
||||
* to the constructor as an options object. If an instance has a `_pojo(obj)`
|
||||
* method then the built object will be sent to that method and the resulting
|
||||
* mutated object returned.
|
||||
*
|
||||
* @returns {object} A plain JavaScript object that represents an LDAP control.
|
||||
*/
|
||||
get pojo () {
|
||||
const obj = {
|
||||
type: this.type,
|
||||
value: this.value,
|
||||
criticality: this.criticality
|
||||
}
|
||||
|
||||
if (typeof this._pojo === 'function') {
|
||||
this._pojo(obj)
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the instance into a [BER](http://luca.ntop.org/Teaching/Appunti/asn1.html)
|
||||
* representation.
|
||||
*
|
||||
* @param {BerWriter} [ber] An empty `BerWriter` instance to populate.
|
||||
*
|
||||
* @returns {object} A BER object.
|
||||
*/
|
||||
toBer (ber = new BerWriter()) {
|
||||
ber.startSequence()
|
||||
ber.writeString(this.type || '')
|
||||
ber.writeBoolean(this.criticality)
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (typeof (this._toBer) === 'function') {
|
||||
this._toBer(ber)
|
||||
} else if (this.value !== undefined) {
|
||||
if (typeof this.value === 'string') {
|
||||
ber.writeString(this.value)
|
||||
} else if (Buffer.isBuffer(this.value)) {
|
||||
ber.writeString(this.value.toString())
|
||||
}
|
||||
}
|
||||
|
||||
ber.endSequence()
|
||||
return ber
|
||||
}
|
||||
}
|
||||
module.exports = Control
|
||||
159
node_modules/@ldapjs/controls/lib/control.test.js
generated
vendored
Normal file
159
node_modules/@ldapjs/controls/lib/control.test.js
generated
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
const { BerWriter } = require('@ldapjs/asn1')
|
||||
const Control = require('./control')
|
||||
|
||||
tap.test('constructor', t => {
|
||||
t.test('new no args', function (t) {
|
||||
t.ok(new Control())
|
||||
t.equal(Object.prototype.toString.call(new Control()), '[object LdapControl]')
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.test('new with args', function (t) {
|
||||
const c = new Control({
|
||||
type: '2.16.840.1.113730.3.4.2',
|
||||
criticality: true
|
||||
})
|
||||
t.ok(c)
|
||||
t.equal(c.type, '2.16.840.1.113730.3.4.2')
|
||||
t.ok(c.criticality)
|
||||
t.end()
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('pojo', t => {
|
||||
t.test('passes through _pojo', async t => {
|
||||
class Foo extends Control {
|
||||
_pojo (obj) {
|
||||
obj.foo = 'foo'
|
||||
}
|
||||
}
|
||||
const control = new Foo()
|
||||
t.strictSame(control.pojo, {
|
||||
type: '',
|
||||
value: null,
|
||||
criticality: false,
|
||||
foo: 'foo'
|
||||
})
|
||||
})
|
||||
|
||||
t.test('returns basic object', async t => {
|
||||
const control = new Control({ type: '1.2.3', criticality: false, value: 'foo' })
|
||||
t.strictSame(control.pojo, {
|
||||
type: '1.2.3',
|
||||
value: 'foo',
|
||||
criticality: false
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('toBer', t => {
|
||||
t.test('converts empty instance to BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString('')
|
||||
target.writeBoolean(false)
|
||||
target.endSequence()
|
||||
|
||||
const control = new Control()
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.test('converts instance to BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString('2.16.840.1.113730.3.4.2')
|
||||
target.writeBoolean(true)
|
||||
target.writeString('foo')
|
||||
target.endSequence()
|
||||
|
||||
const control = new Control({
|
||||
type: '2.16.840.1.113730.3.4.2',
|
||||
criticality: true,
|
||||
value: Buffer.from('foo', 'utf8')
|
||||
})
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.test('converts instance to BER (side effect manner)', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString('2.16.840.1.113730.3.4.2')
|
||||
target.writeBoolean(true)
|
||||
target.writeString('foo')
|
||||
target.endSequence()
|
||||
|
||||
const control = new Control({
|
||||
type: '2.16.840.1.113730.3.4.2',
|
||||
criticality: true,
|
||||
value: Buffer.from('foo', 'utf8')
|
||||
})
|
||||
const ber = new BerWriter()
|
||||
control.toBer(ber)
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.test('converts instance to BER with string value', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString('2.16.840.1.113730.3.4.2')
|
||||
target.writeBoolean(true)
|
||||
target.writeString('foo')
|
||||
target.endSequence()
|
||||
|
||||
const control = new Control({
|
||||
type: '2.16.840.1.113730.3.4.2',
|
||||
criticality: true,
|
||||
value: 'foo'
|
||||
})
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.test('ignores unrecognized value', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString('2.16.840.1.113730.3.4.2')
|
||||
target.writeBoolean(true)
|
||||
target.writeBoolean(false)
|
||||
target.endSequence()
|
||||
|
||||
const control = new Control({
|
||||
type: '2.16.840.1.113730.3.4.2',
|
||||
criticality: true,
|
||||
value: false
|
||||
})
|
||||
const ber = control.toBer()
|
||||
|
||||
t.not(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.test('passes through _toBer', async t => {
|
||||
t.plan(2)
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString('')
|
||||
target.writeBoolean(false)
|
||||
target.endSequence()
|
||||
|
||||
const control = new Control()
|
||||
control._toBer = (ber) => t.ok(ber)
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
107
node_modules/@ldapjs/controls/lib/controls/entry-change-notification-control.js
generated
vendored
Normal file
107
node_modules/@ldapjs/controls/lib/controls/entry-change-notification-control.js
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
'use strict'
|
||||
|
||||
const { BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
const isObject = require('../is-object')
|
||||
const hasOwn = require('../has-own')
|
||||
const Control = require('../control')
|
||||
|
||||
/**
|
||||
* @typedef {object} EntryChangeNotificationControlValue
|
||||
* @property {number} changeType One of 1 (add), 2 (delete), 4 (modify),
|
||||
* or 8 (modifyDN).
|
||||
* @property {string} previousDN Only set when operation is a modifyDN op.
|
||||
* @property {number} changeNumber
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements:
|
||||
* https://datatracker.ietf.org/doc/html/draft-ietf-ldapext-psearch-03.txt#section-5
|
||||
*
|
||||
* @extends Control
|
||||
*/
|
||||
class EntryChangeNotificationControl extends Control {
|
||||
static OID = '2.16.840.1.113730.3.4.7'
|
||||
|
||||
/**
|
||||
* @typedef {ControlParams} EntryChangeNotificationParams
|
||||
* @property {EntryChangeNotificationControlValue | Buffer} [value]
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new persistent search control.
|
||||
*
|
||||
* @param {EntryChangeNotificationParams} [options]
|
||||
*/
|
||||
constructor (options = {}) {
|
||||
options.type = EntryChangeNotificationControl.OID
|
||||
super(options)
|
||||
|
||||
this._value = {
|
||||
changeType: 4
|
||||
}
|
||||
|
||||
if (hasOwn(options, 'value') === false) {
|
||||
return
|
||||
}
|
||||
|
||||
if (Buffer.isBuffer(options.value)) {
|
||||
this.#parse(options.value)
|
||||
} else if (isObject(options.value)) {
|
||||
this._value = options.value
|
||||
} else {
|
||||
throw new TypeError('options.value must be a Buffer or Object')
|
||||
}
|
||||
}
|
||||
|
||||
get value () {
|
||||
return this._value
|
||||
}
|
||||
|
||||
set value (obj) {
|
||||
this._value = Object.assign({}, this._value, obj)
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a BER buffer that represents a
|
||||
* {@link EntryChangeNotificationControlValue}, read that buffer into the
|
||||
* current instance.
|
||||
*/
|
||||
#parse (buffer) {
|
||||
const ber = new BerReader(buffer)
|
||||
/* istanbul ignore else */
|
||||
if (ber.readSequence()) {
|
||||
this._value = {
|
||||
changeType: ber.readInt()
|
||||
}
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (this._value.changeType === 8) {
|
||||
// If the operation was moddn, then parse the optional previousDN attr.
|
||||
this._value.previousDN = ber.readString()
|
||||
}
|
||||
|
||||
this._value.changeNumber = ber.readInt()
|
||||
}
|
||||
}
|
||||
|
||||
_toBer (ber) {
|
||||
const writer = new BerWriter()
|
||||
writer.startSequence()
|
||||
writer.writeInt(this._value.changeType)
|
||||
if (this._value.previousDN) { writer.writeString(this._value.previousDN) }
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this._value, 'changeNumber')) {
|
||||
writer.writeInt(parseInt(this._value.changeNumber, 10))
|
||||
}
|
||||
writer.endSequence()
|
||||
|
||||
ber.writeBuffer(writer.buffer, 0x04)
|
||||
return ber
|
||||
}
|
||||
|
||||
_updatePlainObject (obj) {
|
||||
obj.controlValue = this.value
|
||||
return obj
|
||||
}
|
||||
}
|
||||
module.exports = EntryChangeNotificationControl
|
||||
133
node_modules/@ldapjs/controls/lib/controls/entry-change-notification-control.test.js
generated
vendored
Normal file
133
node_modules/@ldapjs/controls/lib/controls/entry-change-notification-control.test.js
generated
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
const { BerWriter } = require('@ldapjs/asn1')
|
||||
const ECNC = require('./entry-change-notification-control')
|
||||
const Control = require('../control')
|
||||
|
||||
tap.test('contructor', t => {
|
||||
t.test('new no args', async t => {
|
||||
const control = new ECNC()
|
||||
t.ok(control)
|
||||
t.type(control, ECNC)
|
||||
t.type(control, Control)
|
||||
t.equal(control.type, ECNC.OID)
|
||||
t.same(control.value, {
|
||||
changeType: 4
|
||||
})
|
||||
})
|
||||
|
||||
t.test('new with args', async t => {
|
||||
const control = new ECNC({
|
||||
type: '2.16.840.1.113730.3.4.7',
|
||||
criticality: true,
|
||||
value: {
|
||||
changeType: 1
|
||||
}
|
||||
})
|
||||
t.ok(control)
|
||||
t.equal(control.type, '2.16.840.1.113730.3.4.7')
|
||||
t.ok(control.criticality)
|
||||
t.same(control.value, {
|
||||
changeType: 1
|
||||
})
|
||||
})
|
||||
|
||||
t.test('with value buffer', async t => {
|
||||
const value = new BerWriter()
|
||||
value.startSequence()
|
||||
value.writeInt(8)
|
||||
value.writeString('dn=foo')
|
||||
value.writeInt(42)
|
||||
value.endSequence()
|
||||
|
||||
const control = new ECNC({ value: value.buffer })
|
||||
t.same(control.value, {
|
||||
changeType: 8,
|
||||
previousDN: 'dn=foo',
|
||||
changeNumber: 42
|
||||
})
|
||||
})
|
||||
|
||||
t.test('throws for bad value', async t => {
|
||||
t.throws(() => new ECNC({ value: 42 }))
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('pojo', t => {
|
||||
t.test('adds control value', async t => {
|
||||
const control = new ECNC({
|
||||
value: {
|
||||
changeType: 8,
|
||||
previousDN: 'dn=foo',
|
||||
changeNumber: 42
|
||||
}
|
||||
})
|
||||
t.strictSame(control.pojo, {
|
||||
type: ECNC.OID,
|
||||
criticality: false,
|
||||
value: {
|
||||
changeType: 8,
|
||||
previousDN: 'dn=foo',
|
||||
changeNumber: 42
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('toBer', t => {
|
||||
t.test('converts empty instance to BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString(ECNC.OID)
|
||||
target.writeBoolean(false) // Control.criticality
|
||||
|
||||
const value = new BerWriter()
|
||||
value.startSequence()
|
||||
value.writeInt(4)
|
||||
// value.writeInt(0)
|
||||
value.endSequence()
|
||||
|
||||
target.writeBuffer(value.buffer, 0x04)
|
||||
target.endSequence()
|
||||
|
||||
const control = new ECNC()
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.test('converts instance with full values to BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString(ECNC.OID)
|
||||
target.writeBoolean(false) // Control.criticality
|
||||
|
||||
const value = new BerWriter()
|
||||
value.startSequence()
|
||||
value.writeInt(8)
|
||||
value.writeString('dn=foo')
|
||||
value.writeInt(42)
|
||||
value.endSequence()
|
||||
|
||||
target.writeBuffer(value.buffer, 0x04)
|
||||
target.endSequence()
|
||||
|
||||
const control = new ECNC({
|
||||
value: {
|
||||
changeType: 8,
|
||||
previousDN: 'dn=foo',
|
||||
changeNumber: 42
|
||||
}
|
||||
})
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
103
node_modules/@ldapjs/controls/lib/controls/paged-results-control.js
generated
vendored
Normal file
103
node_modules/@ldapjs/controls/lib/controls/paged-results-control.js
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
'use strict'
|
||||
|
||||
const { Ber, BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
const isObject = require('../is-object')
|
||||
const hasOwn = require('../has-own')
|
||||
const Control = require('../control')
|
||||
|
||||
/**
|
||||
* @typedef {object} PagedResultsControlValue
|
||||
* @property {number} size The requested page size from a client, or the result
|
||||
* set size estimate from the server.
|
||||
* @property {Buffer} cookie Identifier for the result set.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements:
|
||||
* https://datatracker.ietf.org/doc/html/rfc2696#section-2
|
||||
*
|
||||
* @extends Control
|
||||
*/
|
||||
class PagedResultsControl extends Control {
|
||||
static OID = '1.2.840.113556.1.4.319'
|
||||
|
||||
/**
|
||||
* @typedef {ControlParams} PagedResultsParams
|
||||
* @property {PagedResultsControlValue | Buffer} [value]
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new paged results control.
|
||||
*
|
||||
* @param {PagedResultsParams} [options]
|
||||
*/
|
||||
constructor (options = {}) {
|
||||
options.type = PagedResultsControl.OID
|
||||
super(options)
|
||||
|
||||
this._value = {
|
||||
size: 0,
|
||||
cookie: Buffer.alloc(0)
|
||||
}
|
||||
|
||||
if (hasOwn(options, 'value') === false) {
|
||||
return
|
||||
}
|
||||
|
||||
if (Buffer.isBuffer(options.value)) {
|
||||
this.#parse(options.value)
|
||||
} else if (isObject(options.value)) {
|
||||
this.value = options.value
|
||||
} else {
|
||||
throw new TypeError('options.value must be a Buffer or Object')
|
||||
}
|
||||
}
|
||||
|
||||
get value () {
|
||||
return this._value
|
||||
}
|
||||
|
||||
set value (obj) {
|
||||
this._value = Object.assign({}, this._value, obj)
|
||||
if (typeof this._value.cookie === 'string') {
|
||||
this._value.cookie = Buffer.from(this._value.cookie)
|
||||
}
|
||||
}
|
||||
|
||||
#parse (buffer) {
|
||||
const ber = new BerReader(buffer)
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (ber.readSequence()) {
|
||||
this._value = {}
|
||||
this._value.size = ber.readInt()
|
||||
this._value.cookie = ber.readString(Ber.OctetString, true)
|
||||
// readString returns '' instead of a zero-length buffer
|
||||
if (!this._value.cookie) {
|
||||
this._value.cookie = Buffer.alloc(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_toBer (ber) {
|
||||
const writer = new BerWriter()
|
||||
writer.startSequence()
|
||||
writer.writeInt(this._value.size)
|
||||
if (this._value.cookie && this._value.cookie.length > 0) {
|
||||
writer.writeBuffer(this._value.cookie, Ber.OctetString)
|
||||
} else {
|
||||
// writeBuffer rejects zero-length buffers
|
||||
writer.writeString('')
|
||||
}
|
||||
writer.endSequence()
|
||||
|
||||
ber.writeBuffer(writer.buffer, Ber.OctetString)
|
||||
return ber
|
||||
}
|
||||
|
||||
_updatePlainObject (obj) {
|
||||
obj.controlValue = this.value
|
||||
return obj
|
||||
}
|
||||
}
|
||||
module.exports = PagedResultsControl
|
||||
139
node_modules/@ldapjs/controls/lib/controls/paged-results-control.test.js
generated
vendored
Normal file
139
node_modules/@ldapjs/controls/lib/controls/paged-results-control.test.js
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
const { BerWriter } = require('@ldapjs/asn1')
|
||||
const PSC = require('./paged-results-control')
|
||||
const Control = require('../control')
|
||||
|
||||
tap.test('contructor', t => {
|
||||
t.test('new no args', async t => {
|
||||
const control = new PSC()
|
||||
t.ok(control)
|
||||
t.type(control, PSC)
|
||||
t.type(control, Control)
|
||||
t.equal(control.type, PSC.OID)
|
||||
t.equal(control.value.size, 0)
|
||||
t.equal(Buffer.alloc(0).compare(control.value.cookie), 0)
|
||||
})
|
||||
|
||||
t.test('new with args', async t => {
|
||||
const control = new PSC({
|
||||
type: '1.2.840.113556.1.4.319',
|
||||
criticality: true,
|
||||
value: {
|
||||
size: 1,
|
||||
cookie: 'foo'
|
||||
}
|
||||
})
|
||||
t.ok(control)
|
||||
t.equal(control.type, '1.2.840.113556.1.4.319')
|
||||
t.ok(control.criticality)
|
||||
t.equal(control.value.size, 1)
|
||||
t.equal(Buffer.from('foo').compare(control.value.cookie), 0)
|
||||
})
|
||||
|
||||
t.test('with value buffer', async t => {
|
||||
const value = new BerWriter()
|
||||
value.startSequence()
|
||||
value.writeInt(1)
|
||||
value.writeBuffer(Buffer.from('foo'), 0x04)
|
||||
value.endSequence()
|
||||
|
||||
const control = new PSC({ value: value.buffer })
|
||||
t.equal(control.value.size, 1)
|
||||
t.equal(Buffer.from('foo').compare(control.value.cookie), 0)
|
||||
})
|
||||
|
||||
t.test('with value buffer (empty cookie)', async t => {
|
||||
const value = new BerWriter()
|
||||
value.startSequence()
|
||||
value.writeInt(1)
|
||||
value.endSequence()
|
||||
|
||||
const control = new PSC({ value: value.buffer })
|
||||
t.equal(control.value.size, 1)
|
||||
t.equal(Buffer.alloc(0).compare(control.value.cookie), 0)
|
||||
})
|
||||
|
||||
t.test('throws for bad value', async t => {
|
||||
t.throws(() => new PSC({ value: 42 }))
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('pojo', t => {
|
||||
t.test('adds control value', async t => {
|
||||
const control = new PSC({
|
||||
value: {
|
||||
size: 1,
|
||||
cookie: 'foo'
|
||||
}
|
||||
})
|
||||
t.same(control.pojo, {
|
||||
type: PSC.OID,
|
||||
criticality: false,
|
||||
value: {
|
||||
size: 1,
|
||||
cookie: Buffer.from('foo')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('toBer', t => {
|
||||
t.test('converts empty instance to BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString(PSC.OID)
|
||||
target.writeBoolean(false) // Control.criticality
|
||||
|
||||
const value = new BerWriter()
|
||||
value.startSequence()
|
||||
value.writeInt(1)
|
||||
value.writeString('foo')
|
||||
value.endSequence()
|
||||
|
||||
target.writeBuffer(value.buffer, 0x04)
|
||||
target.endSequence()
|
||||
|
||||
const control = new PSC({
|
||||
value: {
|
||||
size: 1,
|
||||
cookie: 'foo'
|
||||
}
|
||||
})
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.test('converts empty instance to BER (empty cookie)', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString(PSC.OID)
|
||||
target.writeBoolean(false) // Control.criticality
|
||||
|
||||
const value = new BerWriter()
|
||||
value.startSequence()
|
||||
value.writeInt(1)
|
||||
value.writeString('')
|
||||
value.endSequence()
|
||||
|
||||
target.writeBuffer(value.buffer, 0x04)
|
||||
target.endSequence()
|
||||
|
||||
const control = new PSC({
|
||||
value: {
|
||||
size: 1
|
||||
}
|
||||
})
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
118
node_modules/@ldapjs/controls/lib/controls/password-policy-control.js
generated
vendored
Normal file
118
node_modules/@ldapjs/controls/lib/controls/password-policy-control.js
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
'use strict'
|
||||
|
||||
const { BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
const isObject = require('../is-object')
|
||||
const hasOwn = require('../has-own')
|
||||
const Control = require('../control')
|
||||
|
||||
/**
|
||||
* @typedef {object} PasswordPolicyResponseControlValue
|
||||
* @property {number} error One of 0 (passwordExpired), 1 (accountLocked),
|
||||
* 2 (changeAfterReset), 3 (passwordModNotAllowed), 4 (mustSupplyOldPassword),
|
||||
* 5 (insufficientPasswordQuality), 6 (passwordTooShort), 7 (passwordTooYoung),
|
||||
* 8 (passwordInHistory), 9 (passwordTooYoung)
|
||||
* @property {number} timeBeforeExpiration
|
||||
* @property {number} graceAuthNsRemaining
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements both request and response controls:
|
||||
* https://datatracker.ietf.org/doc/html/draft-behera-ldap-password-policy-11#name-controls-used-for-password-
|
||||
*
|
||||
* @extends Control
|
||||
*/
|
||||
class PasswordPolicyControl extends Control {
|
||||
static OID = '1.3.6.1.4.1.42.2.27.8.5.1'
|
||||
|
||||
/**
|
||||
* @typedef {ControlParams} PasswordPolicyResponseParams
|
||||
* @property {PasswordPolicyResponseControlValue | Buffer} [value]
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new password policy control.
|
||||
*
|
||||
* @param {PasswordPolicyResponseParams} [options]
|
||||
*/
|
||||
constructor (options = {}) {
|
||||
options.type = PasswordPolicyControl.OID
|
||||
super(options)
|
||||
|
||||
this._value = {}
|
||||
|
||||
if (hasOwn(options, 'value') === false) {
|
||||
return
|
||||
}
|
||||
|
||||
if (Buffer.isBuffer(options.value)) {
|
||||
this.#parse(options.value)
|
||||
} else if (isObject(options.value)) {
|
||||
if (hasOwn(options.value, 'timeBeforeExpiration') === true && hasOwn(options.value, 'graceAuthNsRemaining') === true) {
|
||||
throw new Error('options.value must contain either timeBeforeExpiration or graceAuthNsRemaining, not both')
|
||||
}
|
||||
this._value = options.value
|
||||
} else {
|
||||
throw new TypeError('options.value must be a Buffer or Object')
|
||||
}
|
||||
}
|
||||
|
||||
get value () {
|
||||
return this._value
|
||||
}
|
||||
|
||||
set value (obj) {
|
||||
this._value = Object.assign({}, this._value, obj)
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a BER buffer that represents a
|
||||
* {@link PasswordPolicyResponseControlValue}, read that buffer into the
|
||||
* current instance.
|
||||
*/
|
||||
#parse (buffer) {
|
||||
const ber = new BerReader(buffer)
|
||||
if (ber.readSequence()) {
|
||||
this._value = {}
|
||||
if (ber.peek() === 0xa0) {
|
||||
ber.readSequence(0xa0)
|
||||
if (ber.peek() === 0x80) {
|
||||
this._value.timeBeforeExpiration = ber._readTag(0x80)
|
||||
} else if (ber.peek() === 0x81) {
|
||||
this._value.graceAuthNsRemaining = ber._readTag(0x81)
|
||||
}
|
||||
}
|
||||
if (ber.peek() === 0x81) {
|
||||
this._value.error = ber._readTag(0x81)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_toBer (ber) {
|
||||
if (!this._value || Object.keys(this._value).length === 0) { return }
|
||||
|
||||
const writer = new BerWriter()
|
||||
writer.startSequence()
|
||||
if (hasOwn(this._value, 'timeBeforeExpiration')) {
|
||||
writer.startSequence(0xa0)
|
||||
writer.writeInt(this._value.timeBeforeExpiration, 0x80)
|
||||
writer.endSequence()
|
||||
} else if (hasOwn(this._value, 'graceAuthNsRemaining')) {
|
||||
writer.startSequence(0xa0)
|
||||
writer.writeInt(this._value.graceAuthNsRemaining, 0x81)
|
||||
writer.endSequence()
|
||||
}
|
||||
if (hasOwn(this._value, 'error')) {
|
||||
writer.writeInt(this._value.error, 0x81)
|
||||
}
|
||||
writer.endSequence()
|
||||
|
||||
ber.writeBuffer(writer.buffer, 0x04)
|
||||
return ber
|
||||
}
|
||||
|
||||
_updatePlainObject (obj) {
|
||||
obj.controlValue = this.value
|
||||
return obj
|
||||
}
|
||||
}
|
||||
module.exports = PasswordPolicyControl
|
||||
113
node_modules/@ldapjs/controls/lib/controls/password-policy-control.test.js
generated
vendored
Normal file
113
node_modules/@ldapjs/controls/lib/controls/password-policy-control.test.js
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
const { BerWriter } = require('@ldapjs/asn1')
|
||||
const PPC = require('./password-policy-control')
|
||||
const Control = require('../control')
|
||||
|
||||
tap.test('contructor', t => {
|
||||
t.test('new no args', async t => {
|
||||
const control = new PPC()
|
||||
t.ok(control)
|
||||
t.type(control, PPC)
|
||||
t.type(control, Control)
|
||||
t.equal(control.type, PPC.OID)
|
||||
t.same(control.value, {})
|
||||
})
|
||||
|
||||
t.test('new with args', async t => {
|
||||
const control = new PPC({
|
||||
type: '1.3.6.1.4.1.42.2.27.8.5.1',
|
||||
criticality: true,
|
||||
value: {
|
||||
error: 1,
|
||||
timeBeforeExpiration: 2
|
||||
}
|
||||
})
|
||||
t.ok(control)
|
||||
t.equal(control.type, '1.3.6.1.4.1.42.2.27.8.5.1')
|
||||
t.ok(control.criticality)
|
||||
t.same(control.value, {
|
||||
error: 1,
|
||||
timeBeforeExpiration: 2
|
||||
})
|
||||
})
|
||||
|
||||
t.test('with value buffer', async t => {
|
||||
const value = new BerWriter()
|
||||
value.startSequence()
|
||||
value.writeInt(5, 0x81)
|
||||
value.endSequence()
|
||||
|
||||
const control = new PPC({ value: value.buffer })
|
||||
t.same(control.value, {
|
||||
error: 5
|
||||
})
|
||||
})
|
||||
|
||||
t.test('throws for bad value', async t => {
|
||||
t.throws(() => new PPC({ value: 42 }))
|
||||
t.throws(() => new PPC({ value: { timeBeforeExpiration: 1, graceAuthNsRemaining: 2 } }))
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('pojo', t => {
|
||||
t.test('adds control value', async t => {
|
||||
const control = new PPC()
|
||||
t.same(control.pojo, {
|
||||
type: PPC.OID,
|
||||
criticality: false,
|
||||
value: {}
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('toBer', t => {
|
||||
t.test('converts empty instance to BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString(PPC.OID)
|
||||
target.writeBoolean(false) // Control.criticality
|
||||
target.endSequence()
|
||||
|
||||
const control = new PPC()
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.test('converts full instance to BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString(PPC.OID)
|
||||
target.writeBoolean(true) // Control.criticality
|
||||
|
||||
const value = new BerWriter()
|
||||
value.startSequence()
|
||||
value.startSequence(0xa0)
|
||||
value.writeInt(2, 0x81)
|
||||
value.endSequence()
|
||||
value.writeInt(1, 0x81)
|
||||
value.endSequence()
|
||||
|
||||
target.writeBuffer(value.buffer, 0x04)
|
||||
target.endSequence()
|
||||
|
||||
const control = new PPC({
|
||||
criticality: true,
|
||||
value: {
|
||||
error: 1,
|
||||
graceAuthNsRemaining: 2
|
||||
}
|
||||
})
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
100
node_modules/@ldapjs/controls/lib/controls/persistent-search-control.js
generated
vendored
Normal file
100
node_modules/@ldapjs/controls/lib/controls/persistent-search-control.js
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
'use strict'
|
||||
|
||||
const { BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
const isObject = require('../is-object')
|
||||
const hasOwn = require('../has-own')
|
||||
const Control = require('../control')
|
||||
|
||||
/**
|
||||
* @typedef {object} PersistentSearchControlValue
|
||||
* @property {number} changeTypes A bitwise OR of 1 (add), 2 (delete),
|
||||
* 4 (modify), and 8 (modifyDN).
|
||||
* @property {boolean} changesOnly
|
||||
* @property {boolean} returnECs
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements:
|
||||
* https://datatracker.ietf.org/doc/html/draft-ietf-ldapext-psearch-03.txt
|
||||
*
|
||||
* @extends Control
|
||||
*/
|
||||
class PersistentSearchControl extends Control {
|
||||
static OID = '2.16.840.1.113730.3.4.3'
|
||||
|
||||
/**
|
||||
* @typedef {ControlParams} PersistentSearchParams
|
||||
* @property {PersistentSearchControlValue | Buffer} [value]
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new persistent search control.
|
||||
*
|
||||
* @param {PersistentSearchParams} [options]
|
||||
*/
|
||||
constructor (options = {}) {
|
||||
options.type = PersistentSearchControl.OID
|
||||
super(options)
|
||||
|
||||
this._value = {
|
||||
changeTypes: 15,
|
||||
changesOnly: true,
|
||||
returnECs: true
|
||||
}
|
||||
|
||||
if (hasOwn(options, 'value') === false) {
|
||||
return
|
||||
}
|
||||
|
||||
if (Buffer.isBuffer(options.value)) {
|
||||
this.#parse(options.value)
|
||||
} else if (isObject(options.value)) {
|
||||
this._value = options.value
|
||||
} else {
|
||||
throw new TypeError('options.value must be a Buffer or Object')
|
||||
}
|
||||
}
|
||||
|
||||
get value () {
|
||||
return this._value
|
||||
}
|
||||
|
||||
set value (obj) {
|
||||
this._value = Object.assign({}, this._value, obj)
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a BER buffer that represents a {@link PersistentSearchControlValue},
|
||||
* read that buffer into the current instance.
|
||||
*/
|
||||
#parse (buffer) {
|
||||
const ber = new BerReader(buffer)
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (ber.readSequence()) {
|
||||
this._value = {
|
||||
changeTypes: ber.readInt(),
|
||||
changesOnly: ber.readBoolean(),
|
||||
returnECs: ber.readBoolean()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_toBer (ber) {
|
||||
const writer = new BerWriter()
|
||||
writer.startSequence()
|
||||
writer.writeInt(this._value.changeTypes)
|
||||
writer.writeBoolean(this._value.changesOnly)
|
||||
writer.writeBoolean(this._value.returnECs)
|
||||
writer.endSequence()
|
||||
|
||||
ber.writeBuffer(writer.buffer, 0x04)
|
||||
return ber
|
||||
}
|
||||
|
||||
_updatePlainObject (obj) {
|
||||
obj.controlValue = this.value
|
||||
return obj
|
||||
}
|
||||
}
|
||||
module.exports = PersistentSearchControl
|
||||
106
node_modules/@ldapjs/controls/lib/controls/persistent-search-control.test.js
generated
vendored
Normal file
106
node_modules/@ldapjs/controls/lib/controls/persistent-search-control.test.js
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
const { BerWriter } = require('@ldapjs/asn1')
|
||||
const PSC = require('./persistent-search-control')
|
||||
const Control = require('../control')
|
||||
|
||||
tap.test('contructor', t => {
|
||||
t.test('new no args', async t => {
|
||||
const control = new PSC()
|
||||
t.ok(control)
|
||||
t.type(control, PSC)
|
||||
t.type(control, Control)
|
||||
t.equal(control.type, PSC.OID)
|
||||
t.same(control.value, {
|
||||
changeTypes: 15,
|
||||
changesOnly: true,
|
||||
returnECs: true
|
||||
})
|
||||
})
|
||||
|
||||
t.test('new with args', async t => {
|
||||
const control = new PSC({
|
||||
type: '2.16.840.1.113730.3.4.3',
|
||||
criticality: true,
|
||||
value: {
|
||||
changeTypes: 1,
|
||||
changesOnly: false,
|
||||
returnECs: true
|
||||
}
|
||||
})
|
||||
t.ok(control)
|
||||
t.equal(control.type, '2.16.840.1.113730.3.4.3')
|
||||
t.ok(control.criticality)
|
||||
t.same(control.value, {
|
||||
changeTypes: 1,
|
||||
changesOnly: false,
|
||||
returnECs: true
|
||||
})
|
||||
})
|
||||
|
||||
t.test('with value buffer', async t => {
|
||||
const value = new BerWriter()
|
||||
value.startSequence()
|
||||
value.writeInt(2)
|
||||
value.writeBoolean(true)
|
||||
value.writeBoolean(false)
|
||||
value.endSequence()
|
||||
|
||||
const control = new PSC({ value: value.buffer })
|
||||
t.same(control.value, {
|
||||
changeTypes: 2,
|
||||
changesOnly: true,
|
||||
returnECs: false
|
||||
})
|
||||
})
|
||||
|
||||
t.test('throws for bad value', async t => {
|
||||
t.throws(() => new PSC({ value: 42 }))
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('pojo', t => {
|
||||
t.test('adds control value', async t => {
|
||||
const control = new PSC()
|
||||
t.same(control.pojo, {
|
||||
type: PSC.OID,
|
||||
criticality: false,
|
||||
value: {
|
||||
changeTypes: 15,
|
||||
changesOnly: true,
|
||||
returnECs: true
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('toBer', t => {
|
||||
t.test('converts empty instance to BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString(PSC.OID)
|
||||
target.writeBoolean(false) // Control.criticality
|
||||
|
||||
const value = new BerWriter()
|
||||
value.startSequence()
|
||||
value.writeInt(15)
|
||||
value.writeBoolean(true)
|
||||
value.writeBoolean(true)
|
||||
value.endSequence()
|
||||
|
||||
target.writeBuffer(value.buffer, 0x04)
|
||||
target.endSequence()
|
||||
|
||||
const control = new PSC()
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
132
node_modules/@ldapjs/controls/lib/controls/server-side-sorting-request-control.js
generated
vendored
Normal file
132
node_modules/@ldapjs/controls/lib/controls/server-side-sorting-request-control.js
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
'use strict'
|
||||
|
||||
const { Ber, BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
const isObject = require('../is-object')
|
||||
const hasOwn = require('../has-own')
|
||||
const Control = require('../control')
|
||||
|
||||
/**
|
||||
* @typedef {object} SortKeyItem
|
||||
* @property {string} attributeType
|
||||
* @property {string} orderingRule
|
||||
* @property {boolean} reverseOrder
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {SortKeyItem[]} ServerSideSortingRequestControlValue
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements:
|
||||
* https://datatracker.ietf.org/doc/html/draft-ietf-ldapext-sorting#section-3.1
|
||||
*
|
||||
* @extends Control
|
||||
*/
|
||||
class ServerSideSortingRequestControl extends Control {
|
||||
static OID = '1.2.840.113556.1.4.473'
|
||||
|
||||
/**
|
||||
* @typedef {ControlParams} ServerSideSortingRequestParams
|
||||
* @property {ServerSideSortingRequestControlValue | SortKeyItem | Buffer} [value]
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new server side sorting request control.
|
||||
*
|
||||
* @param {ServerSideSortingRequestParams} [options]
|
||||
*/
|
||||
constructor (options = { value: [] }) {
|
||||
options.type = ServerSideSortingRequestControl.OID
|
||||
super(options)
|
||||
|
||||
const inputValue = options.value ?? []
|
||||
if (Buffer.isBuffer(inputValue)) {
|
||||
this.#parse(inputValue)
|
||||
} else if (Array.isArray(inputValue)) {
|
||||
for (const obj of inputValue) {
|
||||
if (isObject(obj) === false) {
|
||||
throw new Error('Control value must be an object')
|
||||
}
|
||||
if (hasOwn(obj, 'attributeType') === false) {
|
||||
throw new Error('Missing required key: attributeType')
|
||||
}
|
||||
}
|
||||
this.value = inputValue
|
||||
} else if (isObject(inputValue)) {
|
||||
if (hasOwn(inputValue, 'attributeType') === false) {
|
||||
throw new Error('Missing required key: attributeType')
|
||||
}
|
||||
this.value = [inputValue]
|
||||
} else {
|
||||
throw new TypeError('options.value must be a Buffer, Array or Object')
|
||||
}
|
||||
}
|
||||
|
||||
get value () {
|
||||
return this._value
|
||||
}
|
||||
|
||||
set value (items) {
|
||||
if (Buffer.isBuffer(items) === true) return
|
||||
if (Array.isArray(items) === false) {
|
||||
this._value = [items]
|
||||
return
|
||||
}
|
||||
this._value = items
|
||||
}
|
||||
|
||||
#parse (buffer) {
|
||||
const ber = new BerReader(buffer)
|
||||
let item
|
||||
/* istanbul ignore else */
|
||||
if (ber.readSequence(0x30)) {
|
||||
this.value = []
|
||||
|
||||
while (ber.readSequence(0x30)) {
|
||||
item = {}
|
||||
item.attributeType = ber.readString(Ber.OctetString)
|
||||
/* istanbul ignore else */
|
||||
if (ber.peek() === 0x80) {
|
||||
item.orderingRule = ber.readString(0x80)
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
if (ber.peek() === 0x81) {
|
||||
item.reverseOrder = (ber._readTag(0x81) !== 0)
|
||||
}
|
||||
this.value.push(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_pojo (obj) {
|
||||
obj.value = this.value
|
||||
return obj
|
||||
}
|
||||
|
||||
_toBer (ber) {
|
||||
if (this.value.length === 0) { return }
|
||||
|
||||
const writer = new BerWriter()
|
||||
writer.startSequence(0x30)
|
||||
for (let i = 0; i < this.value.length; i++) {
|
||||
const item = this.value[i]
|
||||
writer.startSequence(0x30)
|
||||
/* istanbul ignore else */
|
||||
if (hasOwn(item, 'attributeType')) {
|
||||
writer.writeString(item.attributeType, Ber.OctetString)
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
if (hasOwn(item, 'orderingRule')) {
|
||||
writer.writeString(item.orderingRule, 0x80)
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
if (hasOwn(item, 'reverseOrder')) {
|
||||
writer.writeBoolean(item.reverseOrder, 0x81)
|
||||
}
|
||||
writer.endSequence()
|
||||
}
|
||||
writer.endSequence()
|
||||
ber.writeBuffer(writer.buffer, 0x04)
|
||||
}
|
||||
}
|
||||
module.exports = ServerSideSortingRequestControl
|
||||
144
node_modules/@ldapjs/controls/lib/controls/server-side-sorting-request-control.test.js
generated
vendored
Normal file
144
node_modules/@ldapjs/controls/lib/controls/server-side-sorting-request-control.test.js
generated
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
const { BerWriter } = require('@ldapjs/asn1')
|
||||
const SSSRC = require('./server-side-sorting-request-control')
|
||||
const Control = require('../control')
|
||||
|
||||
tap.test('contructor', t => {
|
||||
t.test('new no args', async t => {
|
||||
const control = new SSSRC()
|
||||
t.ok(control)
|
||||
t.type(control, SSSRC)
|
||||
t.type(control, Control)
|
||||
t.equal(control.type, SSSRC.OID)
|
||||
t.same(control.value, [])
|
||||
})
|
||||
|
||||
t.test('new with args', async t => {
|
||||
const control = new SSSRC({
|
||||
type: '1.2.840.113556.1.4.473',
|
||||
criticality: true,
|
||||
value: [{ attributeType: 'foo' }]
|
||||
})
|
||||
t.ok(control)
|
||||
t.equal(control.type, '1.2.840.113556.1.4.473')
|
||||
t.ok(control.criticality)
|
||||
t.same(control.value, [{ attributeType: 'foo' }])
|
||||
})
|
||||
|
||||
t.test('new with object', async t => {
|
||||
const control = new SSSRC({
|
||||
type: '1.2.840.113556.1.4.473',
|
||||
criticality: true,
|
||||
value: { attributeType: 'foo' }
|
||||
})
|
||||
t.ok(control)
|
||||
t.equal(control.type, '1.2.840.113556.1.4.473')
|
||||
t.ok(control.criticality)
|
||||
t.same(control.value, [{ attributeType: 'foo' }])
|
||||
})
|
||||
|
||||
t.test('with value buffer', async t => {
|
||||
const value = new BerWriter()
|
||||
value.startSequence(0x30) // Open "array"
|
||||
value.startSequence(0x30) // Start "item"
|
||||
value.writeString('foo', 0x04)
|
||||
value.writeString('bar', 0x80)
|
||||
value.writeBoolean(false, 0x81)
|
||||
value.endSequence() // End item
|
||||
value.endSequence() // Close array
|
||||
|
||||
const control = new SSSRC({ value: value.buffer })
|
||||
t.same(control.value, [{
|
||||
attributeType: 'foo',
|
||||
orderingRule: 'bar',
|
||||
reverseOrder: false
|
||||
}])
|
||||
})
|
||||
|
||||
t.test('throws for bad value', async t => {
|
||||
t.throws(() => new SSSRC({ value: 42 }))
|
||||
})
|
||||
|
||||
t.test('throws for bad object value', async t => {
|
||||
t.throws(() => new SSSRC({ value: { foo: 'bar' } }))
|
||||
})
|
||||
|
||||
t.test('throws for bad array value', async t => {
|
||||
t.throws(() => new SSSRC({ value: [42] }))
|
||||
t.throws(() => new SSSRC({ value: [{ foo: 'bar' }] }))
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('pojo', t => {
|
||||
t.test('adds control value', async t => {
|
||||
const control = new SSSRC()
|
||||
t.same(control.pojo, {
|
||||
type: SSSRC.OID,
|
||||
criticality: false,
|
||||
value: []
|
||||
})
|
||||
})
|
||||
|
||||
t.test('_pojo', async t => {
|
||||
const control = new SSSRC()
|
||||
const obj = control._pojo({ value: 'change_me' })
|
||||
t.strictSame(obj, { value: [] })
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('toBer', t => {
|
||||
t.test('converts empty instance to BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString(SSSRC.OID)
|
||||
target.writeBoolean(false) // Control.criticality
|
||||
target.endSequence()
|
||||
|
||||
const control = new SSSRC()
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.test('converts full instance BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString(SSSRC.OID)
|
||||
target.writeBoolean(false) // Control.criticality
|
||||
|
||||
const value = new BerWriter()
|
||||
value.startSequence(0x30) // Open "array"
|
||||
value.startSequence(0x30) // Start "item"
|
||||
value.writeString('one', 0x04)
|
||||
value.writeString('one', 0x80)
|
||||
value.writeBoolean(false, 0x81)
|
||||
value.endSequence() // End item
|
||||
value.startSequence(0x30) // Start "item"
|
||||
value.writeString('two', 0x04)
|
||||
value.writeString('two', 0x80)
|
||||
value.writeBoolean(true, 0x81)
|
||||
value.endSequence() // End item
|
||||
value.endSequence() // Close array
|
||||
|
||||
target.writeBuffer(value.buffer, 0x04)
|
||||
target.endSequence()
|
||||
|
||||
const control = new SSSRC({
|
||||
value: [
|
||||
{ attributeType: 'one', orderingRule: 'one', reverseOrder: false },
|
||||
{ attributeType: 'two', orderingRule: 'two', reverseOrder: true }
|
||||
]
|
||||
})
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(Buffer.from(target.buffer), ber.buffer), 0)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
129
node_modules/@ldapjs/controls/lib/controls/server-side-sorting-response-control.js
generated
vendored
Normal file
129
node_modules/@ldapjs/controls/lib/controls/server-side-sorting-response-control.js
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
'use strict'
|
||||
|
||||
const { BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
const Control = require('../control')
|
||||
const isObject = require('../is-object')
|
||||
const hasOwn = require('../has-own')
|
||||
const { resultCodes: RESULT_CODES } = require('@ldapjs/protocol')
|
||||
|
||||
const validCodeNames = [
|
||||
'SUCCESS',
|
||||
'OPERATIONS_ERROR',
|
||||
'TIME_LIMIT_EXCEEDED',
|
||||
'STRONGER_AUTH_REQUIRED',
|
||||
'ADMIN_LIMIT_EXCEEDED',
|
||||
'NO_SUCH_ATTRIBUTE',
|
||||
'INAPPROPRIATE_MATCHING',
|
||||
'INSUFFICIENT_ACCESS_RIGHTS',
|
||||
'BUSY',
|
||||
'UNWILLING_TO_PERFORM',
|
||||
'OTHER'
|
||||
]
|
||||
|
||||
const filteredCodes = Object.entries(RESULT_CODES).filter(([k, v]) => validCodeNames.includes(k))
|
||||
const VALID_CODES = new Map([
|
||||
...filteredCodes,
|
||||
...filteredCodes.map(([k, v]) => { return [v, k] })
|
||||
])
|
||||
|
||||
/**
|
||||
* @typedef {object} ServerSideSortingResponseControlResult
|
||||
* @property {number} result
|
||||
* @property {string} failedAttribute
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements:
|
||||
* https://datatracker.ietf.org/doc/html/draft-ietf-ldapext-sorting#section-3.2
|
||||
*
|
||||
* @extends Control
|
||||
*/
|
||||
class ServerSideSortingResponseControl extends Control {
|
||||
static OID = '1.2.840.113556.1.4.474'
|
||||
|
||||
/**
|
||||
* A map of possible response codes. Includes `CODE => VALUE` and
|
||||
* `VALUE => CODE`. For example, `RESPONSE_CODES.get(0)` returns
|
||||
* `LDAP_SUCCESS`, and `RESPONSE_CODES.get('LDAP_SUCCESS')` returns `0`.
|
||||
*/
|
||||
static RESPONSE_CODES = Object.freeze(VALID_CODES)
|
||||
|
||||
/**
|
||||
* @typedef {ControlParams} ServerSideSortingResponseParams
|
||||
* @property {ServerSideSortingResponseControlResult | Buffer} value
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new server side sorting response control.
|
||||
*
|
||||
* @param {ServerSideSortingResponseParams} [options]
|
||||
*/
|
||||
constructor (options = {}) {
|
||||
options.type = ServerSideSortingResponseControl.OID
|
||||
options.criticality = false
|
||||
super(options)
|
||||
|
||||
this.value = {}
|
||||
|
||||
if (hasOwn(options, 'value') === false || !options.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const value = options.value
|
||||
if (Buffer.isBuffer(value)) {
|
||||
this.#parse(value)
|
||||
} else if (isObject(value)) {
|
||||
if (VALID_CODES.has(value.result) === false) {
|
||||
throw new Error('Invalid result code')
|
||||
}
|
||||
if (hasOwn(value, 'failedAttribute') && (typeof value.failedAttribute) !== 'string') {
|
||||
throw new Error('failedAttribute must be String')
|
||||
}
|
||||
|
||||
this.value = value
|
||||
} else {
|
||||
throw new TypeError('options.value must be a Buffer or Object')
|
||||
}
|
||||
}
|
||||
|
||||
get value () {
|
||||
return this._value
|
||||
}
|
||||
|
||||
set value (obj) {
|
||||
this._value = Object.assign({}, this._value, obj)
|
||||
}
|
||||
|
||||
#parse (buffer) {
|
||||
const ber = new BerReader(buffer)
|
||||
/* istanbul ignore else */
|
||||
if (ber.readSequence(0x30)) {
|
||||
this._value = {}
|
||||
this._value.result = ber.readEnumeration()
|
||||
/* istanbul ignore else */
|
||||
if (ber.peek() === 0x80) {
|
||||
this._value.failedAttribute = ber.readString(0x80)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_pojo (obj) {
|
||||
obj.value = this.value
|
||||
return obj
|
||||
}
|
||||
|
||||
_toBer (ber) {
|
||||
if (!this._value || Object.keys(this._value).length === 0) { return }
|
||||
|
||||
const writer = new BerWriter()
|
||||
writer.startSequence(0x30)
|
||||
writer.writeEnumeration(this.value.result)
|
||||
/* istanbul ignore else */
|
||||
if (this.value.result !== RESULT_CODES.SUCCESS && this.value.failedAttribute) {
|
||||
writer.writeString(this.value.failedAttribute, 0x80)
|
||||
}
|
||||
writer.endSequence()
|
||||
ber.writeBuffer(writer.buffer, 0x04)
|
||||
}
|
||||
}
|
||||
module.exports = ServerSideSortingResponseControl
|
||||
125
node_modules/@ldapjs/controls/lib/controls/server-side-sorting-response-control.test.js
generated
vendored
Normal file
125
node_modules/@ldapjs/controls/lib/controls/server-side-sorting-response-control.test.js
generated
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
const { BerWriter } = require('@ldapjs/asn1')
|
||||
const SSSRC = require('./server-side-sorting-response-control')
|
||||
const Control = require('../control')
|
||||
|
||||
tap.test('constructor', t => {
|
||||
t.test('new no args', async t => {
|
||||
const control = new SSSRC()
|
||||
t.ok(control)
|
||||
t.type(control, SSSRC)
|
||||
t.type(control, Control)
|
||||
t.equal(control.type, SSSRC.OID)
|
||||
t.same(control.value, {})
|
||||
})
|
||||
|
||||
t.test('new with args', async t => {
|
||||
const control = new SSSRC({
|
||||
type: '1.2.840.113556.1.4.474',
|
||||
criticality: true,
|
||||
value: {
|
||||
result: SSSRC.RESPONSE_CODES.get('OPERATIONS_ERROR'),
|
||||
failedAttribute: 'foo'
|
||||
}
|
||||
})
|
||||
t.ok(control)
|
||||
t.equal(control.type, '1.2.840.113556.1.4.474')
|
||||
t.equal(control.criticality, false)
|
||||
t.same(control.value, {
|
||||
result: 1,
|
||||
failedAttribute: 'foo'
|
||||
})
|
||||
})
|
||||
|
||||
t.test('with value buffer', async t => {
|
||||
const value = new BerWriter()
|
||||
value.startSequence(0x30)
|
||||
value.writeEnumeration(1)
|
||||
value.writeString('foo', 0x80)
|
||||
value.endSequence()
|
||||
|
||||
const control = new SSSRC({ value: value.buffer })
|
||||
t.same(control.value, {
|
||||
result: 1,
|
||||
failedAttribute: 'foo'
|
||||
})
|
||||
})
|
||||
|
||||
t.test('throws for bad value', async t => {
|
||||
t.throws(() => new SSSRC({ value: 42 }))
|
||||
t.throws(() => new SSSRC({ value: {} }))
|
||||
t.throws(() => new SSSRC({
|
||||
value: {
|
||||
result: 1,
|
||||
failedAttribute: 42
|
||||
}
|
||||
}))
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('pojo', t => {
|
||||
t.test('adds control value', async t => {
|
||||
const control = new SSSRC()
|
||||
t.same(control.pojo, {
|
||||
type: SSSRC.OID,
|
||||
criticality: false,
|
||||
value: {}
|
||||
})
|
||||
})
|
||||
|
||||
t.test('_pojo', async t => {
|
||||
const control = new SSSRC()
|
||||
t.strictSame(control._pojo({ value: 'change_me' }), {
|
||||
value: {}
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('toBer', t => {
|
||||
t.test('converts empty instance to BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString(SSSRC.OID)
|
||||
target.writeBoolean(false) // Control.criticality
|
||||
target.endSequence()
|
||||
|
||||
const control = new SSSRC()
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.test('converts full instance to BER', async t => {
|
||||
const target = new BerWriter()
|
||||
target.startSequence()
|
||||
target.writeString(SSSRC.OID)
|
||||
target.writeBoolean(false) // Control.criticality
|
||||
|
||||
const value = new BerWriter()
|
||||
value.startSequence(0x30)
|
||||
value.writeEnumeration(1)
|
||||
value.writeString('foo', 0x80)
|
||||
value.endSequence()
|
||||
|
||||
target.writeBuffer(value.buffer, 0x04)
|
||||
target.endSequence()
|
||||
|
||||
const control = new SSSRC({
|
||||
value: {
|
||||
result: SSSRC.RESPONSE_CODES.get('OPERATIONS_ERROR'),
|
||||
failedAttribute: 'foo'
|
||||
}
|
||||
})
|
||||
const ber = control.toBer()
|
||||
|
||||
t.equal(Buffer.compare(ber.buffer, target.buffer), 0)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
116
node_modules/@ldapjs/controls/lib/controls/virtual-list-view-request-control.js
generated
vendored
Normal file
116
node_modules/@ldapjs/controls/lib/controls/virtual-list-view-request-control.js
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
'use strict'
|
||||
|
||||
const { BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
const isObject = require('../is-object')
|
||||
const hasOwn = require('../has-own')
|
||||
const Control = require('../control')
|
||||
|
||||
/**
|
||||
* @typedef {object} VirtualListViewControlValue
|
||||
* @property {number} beforeCount
|
||||
* @property {number} afterCount
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements:
|
||||
* https://datatracker.ietf.org/doc/html/draft-ietf-ldapext-ldapv3-vlv-07#section-6.1
|
||||
*
|
||||
* @extends Control
|
||||
*/
|
||||
class VirtualListViewRequestControl extends Control {
|
||||
static OID = '2.16.840.1.113730.3.4.9'
|
||||
|
||||
/**
|
||||
* @typedef {ControlParams} VirtualListViewRequestParams
|
||||
* @property {Buffer|VirtualListViewControlValue} [value]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {VirtualListViewRequestParams} [options]
|
||||
*/
|
||||
constructor (options = {}) {
|
||||
options.type = VirtualListViewRequestControl.OID
|
||||
super(options)
|
||||
|
||||
if (hasOwn(options, 'value') === false) {
|
||||
// return
|
||||
throw Error('control is not enabled')
|
||||
}
|
||||
|
||||
if (Buffer.isBuffer(options.value)) {
|
||||
this.#parse(options.value)
|
||||
} else if (isObject(options.value)) {
|
||||
if (Object.prototype.hasOwnProperty.call(options.value, 'beforeCount') === false) {
|
||||
throw new Error('Missing required key: beforeCount')
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(options.value, 'afterCount') === false) {
|
||||
throw new Error('Missing required key: afterCount')
|
||||
}
|
||||
this._value = options.value
|
||||
} else {
|
||||
throw new TypeError('options.value must be a Buffer or Object')
|
||||
}
|
||||
|
||||
throw Error('control is not enabled')
|
||||
}
|
||||
|
||||
get value () {
|
||||
return this._value
|
||||
}
|
||||
|
||||
set value (items) {
|
||||
if (Buffer.isBuffer(items) === true) return
|
||||
if (Array.isArray(items) === false) {
|
||||
this._value = [items]
|
||||
return
|
||||
}
|
||||
this._value = items
|
||||
}
|
||||
|
||||
#parse (buffer) {
|
||||
const ber = new BerReader(buffer)
|
||||
if (ber.readSequence()) {
|
||||
this._value = {}
|
||||
this._value.beforeCount = ber.readInt()
|
||||
this._value.afterCount = ber.readInt()
|
||||
if (ber.peek() === 0xa0) {
|
||||
if (ber.readSequence(0xa0)) {
|
||||
this._value.targetOffset = ber.readInt()
|
||||
this._value.contentCount = ber.readInt()
|
||||
}
|
||||
}
|
||||
if (ber.peek() === 0x81) {
|
||||
this._value.greaterThanOrEqual = ber.readString(0x81)
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
_pojo (obj) {
|
||||
obj.value = this.value
|
||||
return obj
|
||||
}
|
||||
|
||||
_toBer (ber) {
|
||||
if (!this._value || this._value.length === 0) {
|
||||
return
|
||||
}
|
||||
const writer = new BerWriter()
|
||||
writer.startSequence(0x30)
|
||||
writer.writeInt(this._value.beforeCount)
|
||||
writer.writeInt(this._value.afterCount)
|
||||
if (this._value.targetOffset !== undefined) {
|
||||
writer.startSequence(0xa0)
|
||||
writer.writeInt(this._value.targetOffset)
|
||||
writer.writeInt(this._value.contentCount)
|
||||
writer.endSequence()
|
||||
} else if (this._value.greaterThanOrEqual !== undefined) {
|
||||
writer.writeString(this._value.greaterThanOrEqual, 0x81)
|
||||
}
|
||||
writer.endSequence()
|
||||
ber.writeBuffer(writer.buffer, 0x04)
|
||||
}
|
||||
}
|
||||
module.exports = VirtualListViewRequestControl
|
||||
110
node_modules/@ldapjs/controls/lib/controls/virtual-list-view-request-control.test.js
generated
vendored
Normal file
110
node_modules/@ldapjs/controls/lib/controls/virtual-list-view-request-control.test.js
generated
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
tap.test('stubbed', async t => {
|
||||
t.pass()
|
||||
})
|
||||
|
||||
/**
|
||||
* This test is disabled. The commented code below is directly copied from
|
||||
* the original test file in the core `node-ldapjs` repo. The actual test
|
||||
* suite should follow the patterns of the
|
||||
* server-side-sorting-request-control.test.js test suite.
|
||||
*
|
||||
* See https://github.com/ldapjs/node-ldapjs/pull/797#issuecomment-1094132289
|
||||
*/
|
||||
|
||||
// 'use strict'
|
||||
|
||||
// const { test } = require('tap')
|
||||
// const { BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
// const { getControl, VirtualListViewRequestControl: VLVRControl } = require('../../lib')
|
||||
|
||||
// test('VLV request - new no args', function (t) {
|
||||
// t.ok(new VLVRControl())
|
||||
// t.end()
|
||||
// })
|
||||
|
||||
// test('VLV request - new with args', function (t) {
|
||||
// const c = new VLVRControl({
|
||||
// criticality: true,
|
||||
// value: {
|
||||
// beforeCount: 0,
|
||||
// afterCount: 3,
|
||||
// targetOffset: 1,
|
||||
// contentCount: 0
|
||||
// }
|
||||
// })
|
||||
// t.ok(c)
|
||||
// t.equal(c.type, '2.16.840.1.113730.3.4.9')
|
||||
// t.ok(c.criticality)
|
||||
// t.equal(c.value.beforeCount, 0)
|
||||
// t.equal(c.value.afterCount, 3)
|
||||
// t.equal(c.value.targetOffset, 1)
|
||||
// t.equal(c.value.contentCount, 0)
|
||||
|
||||
// t.end()
|
||||
// })
|
||||
|
||||
// test('VLV request - toBer - with offset', function (t) {
|
||||
// const vlvc = new VLVRControl({
|
||||
// criticality: true,
|
||||
// value: {
|
||||
// beforeCount: 0,
|
||||
// afterCount: 3,
|
||||
// targetOffset: 1,
|
||||
// contentCount: 0
|
||||
// }
|
||||
// })
|
||||
|
||||
// const ber = new BerWriter()
|
||||
// vlvc.toBer(ber)
|
||||
|
||||
// const c = getControl(new BerReader(ber.buffer))
|
||||
// t.ok(c)
|
||||
// t.equal(c.type, '2.16.840.1.113730.3.4.9')
|
||||
// t.ok(c.criticality)
|
||||
// t.equal(c.value.beforeCount, 0)
|
||||
// t.equal(c.value.afterCount, 3)
|
||||
// t.equal(c.value.targetOffset, 1)
|
||||
// t.equal(c.value.contentCount, 0)
|
||||
|
||||
// t.end()
|
||||
// })
|
||||
|
||||
// test('VLV request - toBer - with assertion', function (t) {
|
||||
// const vlvc = new VLVRControl({
|
||||
// criticality: true,
|
||||
// value: {
|
||||
// beforeCount: 0,
|
||||
// afterCount: 3,
|
||||
// greaterThanOrEqual: '*foo*'
|
||||
// }
|
||||
// })
|
||||
|
||||
// const ber = new BerWriter()
|
||||
// vlvc.toBer(ber)
|
||||
|
||||
// const c = getControl(new BerReader(ber.buffer))
|
||||
// t.ok(c)
|
||||
// t.equal(c.type, '2.16.840.1.113730.3.4.9')
|
||||
// t.ok(c.criticality)
|
||||
// t.equal(c.value.beforeCount, 0)
|
||||
// t.equal(c.value.afterCount, 3)
|
||||
// t.equal(c.value.greaterThanOrEqual, '*foo*')
|
||||
|
||||
// t.end()
|
||||
// })
|
||||
|
||||
// test('VLV request - toBer - empty', function (t) {
|
||||
// const vlvc = new VLVRControl()
|
||||
// const ber = new BerWriter()
|
||||
// vlvc.toBer(ber)
|
||||
|
||||
// const c = getControl(new BerReader(ber.buffer))
|
||||
// t.ok(c)
|
||||
// t.equal(c.type, '2.16.840.1.113730.3.4.9')
|
||||
// t.equal(c.criticality, false)
|
||||
// t.notOk(c.value.result)
|
||||
// t.end()
|
||||
// })
|
||||
150
node_modules/@ldapjs/controls/lib/controls/virtual-list-view-response-control.js
generated
vendored
Normal file
150
node_modules/@ldapjs/controls/lib/controls/virtual-list-view-response-control.js
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
'use strict'
|
||||
|
||||
const { Ber, BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
const isObject = require('../is-object')
|
||||
const hasOwn = require('../has-own')
|
||||
const Control = require('../control')
|
||||
const { resultCodes: RESULT_CODES } = require('@ldapjs/protocol')
|
||||
|
||||
const validCodeNames = [
|
||||
'SUCCESS',
|
||||
'OPERATIONS_ERROR',
|
||||
'UNWILLING_TO_PERFORM',
|
||||
'INSUFFICIENT_ACCESS_RIGHTS',
|
||||
'BUSY',
|
||||
'TIME_LIMIT_EXCEEDED',
|
||||
'STRONGER_AUTH_REQUIRED',
|
||||
'ADMIN_LIMIT_EXCEEDED',
|
||||
'SORT_CONTROL_MISSING',
|
||||
'OFFSET_RANGE_ERROR',
|
||||
'CONTROL_ERROR',
|
||||
'OTHER'
|
||||
]
|
||||
|
||||
const filteredCodes = Object.entries(RESULT_CODES).filter(([k, v]) => validCodeNames.includes(k))
|
||||
const VALID_CODES = new Map([
|
||||
...filteredCodes,
|
||||
...filteredCodes.map(([k, v]) => { return [v, k] })
|
||||
])
|
||||
|
||||
// TODO: complete this doc block based on the "implements" spec link
|
||||
/**
|
||||
* @typedef {object} VirtualListViewResponseControlValue
|
||||
* @property {number} result A valid LDAP response code for the control.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements:
|
||||
* https://datatracker.ietf.org/doc/html/draft-ietf-ldapext-ldapv3-vlv-07#section-6.2
|
||||
*
|
||||
* @extends Control
|
||||
*/
|
||||
class VirtualListViewResponseControl extends Control {
|
||||
static OID = '2.16.840.1.113730.3.4.10'
|
||||
|
||||
/**
|
||||
* A map of possible response codes. Includes `CODE => VALUE` and
|
||||
* `VALUE => CODE`. For example, `RESPONSE_CODES.get(0)` returns
|
||||
* `LDAP_SUCCESS`, and `RESPONSE_CODES.get('LDAP_SUCCESS')` returns `0`.
|
||||
*/
|
||||
static RESPONSE_CODES = Object.freeze(VALID_CODES)
|
||||
|
||||
/**
|
||||
* @typedef {ControlParams} VirtualListViewResponseParams
|
||||
* @property {Buffer|VirtualListViewResponseControlValue} [value]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {VirtualListViewResponseParams} options
|
||||
*/
|
||||
constructor (options = {}) {
|
||||
options.type = VirtualListViewResponseControl.OID
|
||||
options.criticality = false
|
||||
super(options)
|
||||
|
||||
this.value = {}
|
||||
|
||||
if (hasOwn(options, 'value') === false || !options.value) {
|
||||
// return
|
||||
throw Error('control not enabled')
|
||||
}
|
||||
|
||||
const value = options.value
|
||||
if (Buffer.isBuffer(value)) {
|
||||
this.#parse(options.value)
|
||||
} else if (isObject(value)) {
|
||||
if (VALID_CODES.has(value.result) === false) {
|
||||
throw new Error('Invalid result code')
|
||||
}
|
||||
this.value = options.value
|
||||
} else {
|
||||
throw new TypeError('options.value must be a Buffer or Object')
|
||||
}
|
||||
|
||||
throw Error('control not enabled')
|
||||
}
|
||||
|
||||
get value () {
|
||||
return this._value
|
||||
}
|
||||
|
||||
set value (obj) {
|
||||
this._value = Object.assign({}, this._value, obj)
|
||||
}
|
||||
|
||||
#parse (buffer) {
|
||||
const ber = new BerReader(buffer)
|
||||
if (ber.readSequence()) {
|
||||
this._value = {}
|
||||
|
||||
if (ber.peek(0x02)) {
|
||||
this._value.targetPosition = ber.readInt()
|
||||
}
|
||||
|
||||
if (ber.peek(0x02)) {
|
||||
this._value.contentCount = ber.readInt()
|
||||
}
|
||||
|
||||
this._value.result = ber.readEnumeration()
|
||||
this._value.cookie = ber.readString(Ber.OctetString, true)
|
||||
|
||||
// readString returns '' instead of a zero-length buffer
|
||||
if (!this._value.cookie) {
|
||||
this._value.cookie = Buffer.alloc(0)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
_pojo (obj) {
|
||||
obj.value = this.value
|
||||
return obj
|
||||
}
|
||||
|
||||
_toBer (ber) {
|
||||
if (this.value.length === 0) { return }
|
||||
|
||||
const writer = new BerWriter()
|
||||
writer.startSequence()
|
||||
if (this.value.targetPosition !== undefined) {
|
||||
writer.writeInt(this.value.targetPosition)
|
||||
}
|
||||
if (this.value.contentCount !== undefined) {
|
||||
writer.writeInt(this.value.contentCount)
|
||||
}
|
||||
|
||||
writer.writeEnumeration(this.value.result)
|
||||
if (this.value.cookie && this.value.cookie.length > 0) {
|
||||
writer.writeBuffer(this.value.cookie, Ber.OctetString)
|
||||
} else {
|
||||
writer.writeString('') // writeBuffer rejects zero-length buffers
|
||||
}
|
||||
|
||||
writer.endSequence()
|
||||
ber.writeBuffer(writer.buffer, 0x04)
|
||||
}
|
||||
}
|
||||
module.exports = VirtualListViewResponseControl
|
||||
84
node_modules/@ldapjs/controls/lib/controls/virtual-list-view-response-control.test.js
generated
vendored
Normal file
84
node_modules/@ldapjs/controls/lib/controls/virtual-list-view-response-control.test.js
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
tap.test('stubbed', async t => {
|
||||
t.pass()
|
||||
})
|
||||
|
||||
/**
|
||||
* This test is disabled. The commented code below is directly copied from
|
||||
* the original test file in the core `node-ldapjs` repo. The actual test
|
||||
* suite should follow the patterns of the
|
||||
* server-side-sorting-response-control.test.js test suite.
|
||||
*
|
||||
* See https://github.com/ldapjs/node-ldapjs/pull/797#issuecomment-1094132289
|
||||
*/
|
||||
|
||||
// 'use strict'
|
||||
|
||||
// const { test } = require('tap')
|
||||
// const { BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
// const ldap = require('../../lib')
|
||||
// const { getControl, VirtualListViewResponseControl: VLVResponseControl } = require('../../lib')
|
||||
// const OID = '2.16.840.1.113730.3.4.10'
|
||||
|
||||
// test('VLV response - new no args', function (t) {
|
||||
// const c = new VLVResponseControl()
|
||||
// t.ok(c)
|
||||
// t.equal(c.type, OID)
|
||||
// t.equal(c.criticality, false)
|
||||
// t.end()
|
||||
// })
|
||||
|
||||
// test('VLV response - new with args', function (t) {
|
||||
// const c = new VLVResponseControl({
|
||||
// criticality: true,
|
||||
// value: {
|
||||
// result: ldap.LDAP_SUCCESS,
|
||||
// targetPosition: 0,
|
||||
// contentCount: 10
|
||||
// }
|
||||
// })
|
||||
// t.ok(c)
|
||||
// t.equal(c.type, OID)
|
||||
// t.equal(c.criticality, false)
|
||||
// t.equal(c.value.result, ldap.LDAP_SUCCESS)
|
||||
// t.equal(c.value.targetPosition, 0)
|
||||
// t.equal(c.value.contentCount, 10)
|
||||
// t.end()
|
||||
// })
|
||||
|
||||
// test('VLV response - toBer', function (t) {
|
||||
// const vlpc = new VLVResponseControl({
|
||||
// value: {
|
||||
// targetPosition: 0,
|
||||
// contentCount: 10,
|
||||
// result: ldap.LDAP_SUCCESS
|
||||
// }
|
||||
// })
|
||||
|
||||
// const ber = new BerWriter()
|
||||
// vlpc.toBer(ber)
|
||||
|
||||
// const c = getControl(new BerReader(ber.buffer))
|
||||
// t.ok(c)
|
||||
// t.equal(c.type, OID)
|
||||
// t.equal(c.criticality, false)
|
||||
// t.equal(c.value.result, ldap.LDAP_SUCCESS)
|
||||
// t.equal(c.value.targetPosition, 0)
|
||||
// t.equal(c.value.contentCount, 10)
|
||||
// t.end()
|
||||
// })
|
||||
|
||||
// test('VLV response - toBer - empty', function (t) {
|
||||
// const vlpc = new VLVResponseControl()
|
||||
// const ber = new BerWriter()
|
||||
// vlpc.toBer(ber)
|
||||
|
||||
// const c = getControl(new BerReader(ber.buffer))
|
||||
// t.ok(c)
|
||||
// t.equal(c.type, OID)
|
||||
// t.equal(c.criticality, false)
|
||||
// t.notOk(c.value.result)
|
||||
// t.end()
|
||||
// })
|
||||
5
node_modules/@ldapjs/controls/lib/has-own.js
generated
vendored
Normal file
5
node_modules/@ldapjs/controls/lib/has-own.js
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = function hasOwn (obj, prop) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, prop)
|
||||
}
|
||||
5
node_modules/@ldapjs/controls/lib/is-object.js
generated
vendored
Normal file
5
node_modules/@ldapjs/controls/lib/is-object.js
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = function isObject (input) {
|
||||
return Object.prototype.toString.call(input) === '[object Object]'
|
||||
}
|
||||
10
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/.github/workflows/main.yml
generated
vendored
Normal file
10
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/.github/workflows/main.yml
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
name: "CI"
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
call-core-ci:
|
||||
uses: ldapjs/.github/.github/workflows/node-ci.yml@main
|
||||
4
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/.taprc.yml
generated
vendored
Normal file
4
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/.taprc.yml
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
check-coverage: false
|
||||
|
||||
files:
|
||||
- 'lib/**/*.test.js'
|
||||
22
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/LICENSE
generated
vendored
Normal file
22
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011 Mark Cavage, All rights reserved.
|
||||
Copyright (c) 2022 The LDAPJS Collaborators.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE
|
||||
39
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/README.md
generated
vendored
Normal file
39
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/README.md
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# `@ldapjs/asn1`
|
||||
|
||||
`@ldapjs/asn1` is a library for encoding and decoding ASN.1 datatypes in pure
|
||||
JS. Currently BER encoding is supported.
|
||||
|
||||
### Decoding
|
||||
|
||||
The following reads an ASN.1 sequence with a boolean.
|
||||
|
||||
var Ber = require('@ldapjs/asn1').Ber;
|
||||
|
||||
var reader = new Ber.Reader(Buffer.from([0x30, 0x03, 0x01, 0x01, 0xff]));
|
||||
|
||||
reader.readSequence();
|
||||
console.log('Sequence len: ' + reader.length);
|
||||
if (reader.peek() === Ber.Boolean)
|
||||
console.log(reader.readBoolean());
|
||||
|
||||
### Encoding
|
||||
|
||||
The following generates the same payload as above.
|
||||
|
||||
var Ber = require('@ldapjs/asn1').Ber;
|
||||
|
||||
var writer = new Ber.Writer();
|
||||
|
||||
writer.startSequence();
|
||||
writer.writeBoolean(true);
|
||||
writer.endSequence();
|
||||
|
||||
console.log(writer.buffer);
|
||||
|
||||
## Installation
|
||||
|
||||
npm install asn1
|
||||
|
||||
## Bugs
|
||||
|
||||
See <https://github.com/ldapjs/asn1/issues>.
|
||||
12
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/errors.js
generated
vendored
Normal file
12
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/errors.js
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||
|
||||
module.exports = {
|
||||
|
||||
newInvalidAsn1Error: function (msg) {
|
||||
const e = new Error()
|
||||
e.name = 'InvalidAsn1Error'
|
||||
e.message = msg || ''
|
||||
return e
|
||||
}
|
||||
|
||||
}
|
||||
24
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/index.js
generated
vendored
Normal file
24
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/index.js
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||
|
||||
const errors = require('./errors')
|
||||
const types = require('./types')
|
||||
|
||||
const Reader = require('./reader')
|
||||
const Writer = require('./writer')
|
||||
|
||||
// --- Exports
|
||||
|
||||
module.exports = {
|
||||
|
||||
Reader: Reader,
|
||||
|
||||
Writer: Writer
|
||||
|
||||
}
|
||||
|
||||
for (const t in types) {
|
||||
if (Object.prototype.hasOwnProperty.call(types, t)) { module.exports[t] = types[t] }
|
||||
}
|
||||
for (const e in errors) {
|
||||
if (Object.prototype.hasOwnProperty.call(errors, e)) { module.exports[e] = errors[e] }
|
||||
}
|
||||
227
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/reader.js
generated
vendored
Normal file
227
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/reader.js
generated
vendored
Normal file
@ -0,0 +1,227 @@
|
||||
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||
|
||||
const assert = require('assert')
|
||||
const ASN1 = require('./types')
|
||||
const errors = require('./errors')
|
||||
|
||||
// --- Globals
|
||||
|
||||
const newInvalidAsn1Error = errors.newInvalidAsn1Error
|
||||
|
||||
// --- API
|
||||
|
||||
function Reader (data) {
|
||||
if (!data || !Buffer.isBuffer(data)) { throw new TypeError('data must be a node Buffer') }
|
||||
|
||||
this._buf = data
|
||||
this._size = data.length
|
||||
|
||||
// These hold the "current" state
|
||||
this._len = 0
|
||||
this._offset = 0
|
||||
}
|
||||
|
||||
Object.defineProperty(Reader.prototype, Symbol.toStringTag, { value: 'BerReader' })
|
||||
|
||||
Object.defineProperty(Reader.prototype, 'length', {
|
||||
enumerable: true,
|
||||
get: function () { return (this._len) }
|
||||
})
|
||||
|
||||
Object.defineProperty(Reader.prototype, 'offset', {
|
||||
enumerable: true,
|
||||
get: function () { return (this._offset) }
|
||||
})
|
||||
|
||||
Object.defineProperty(Reader.prototype, 'remain', {
|
||||
get: function () { return (this._size - this._offset) }
|
||||
})
|
||||
|
||||
Object.defineProperty(Reader.prototype, 'buffer', {
|
||||
get: function () { return (this._buf.slice(this._offset)) }
|
||||
})
|
||||
|
||||
/**
|
||||
* Reads a single byte and advances offset; you can pass in `true` to make this
|
||||
* a "peek" operation (i.e., get the byte, but don't advance the offset).
|
||||
*
|
||||
* @param {Boolean} peek true means don't move offset.
|
||||
* @return {Number} the next byte, null if not enough data.
|
||||
*/
|
||||
Reader.prototype.readByte = function (peek) {
|
||||
if (this._size - this._offset < 1) { return null }
|
||||
|
||||
const b = this._buf[this._offset] & 0xff
|
||||
|
||||
if (!peek) { this._offset += 1 }
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
Reader.prototype.peek = function () {
|
||||
return this.readByte(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a (potentially) variable length off the BER buffer. This call is
|
||||
* not really meant to be called directly, as callers have to manipulate
|
||||
* the internal buffer afterwards.
|
||||
*
|
||||
* As a result of this call, you can call `Reader.length`, until the
|
||||
* next thing called that does a readLength.
|
||||
*
|
||||
* @return {Number} the amount of offset to advance the buffer.
|
||||
* @throws {InvalidAsn1Error} on bad ASN.1
|
||||
*/
|
||||
Reader.prototype.readLength = function (offset) {
|
||||
if (offset === undefined) { offset = this._offset }
|
||||
|
||||
if (offset >= this._size) { return null }
|
||||
|
||||
let lenB = this._buf[offset++] & 0xff
|
||||
if (lenB === null) { return null }
|
||||
|
||||
if ((lenB & 0x80) === 0x80) {
|
||||
lenB &= 0x7f
|
||||
|
||||
if (lenB === 0) { throw newInvalidAsn1Error('Indefinite length not supported') }
|
||||
|
||||
if (lenB > 4) { throw newInvalidAsn1Error('encoding too long') }
|
||||
|
||||
if (this._size - offset < lenB) { return null }
|
||||
|
||||
this._len = 0
|
||||
for (let i = 0; i < lenB; i++) { this._len = (this._len << 8) + (this._buf[offset++] & 0xff) }
|
||||
} else {
|
||||
// Wasn't a variable length
|
||||
this._len = lenB
|
||||
}
|
||||
|
||||
return offset
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the next sequence in this BER buffer.
|
||||
*
|
||||
* To get the length of the sequence, call `Reader.length`.
|
||||
*
|
||||
* @return {Number} the sequence's tag.
|
||||
*/
|
||||
Reader.prototype.readSequence = function (tag) {
|
||||
const seq = this.peek()
|
||||
if (seq === null) { return null }
|
||||
if (tag !== undefined && tag !== seq) {
|
||||
throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
|
||||
': got 0x' + seq.toString(16))
|
||||
}
|
||||
|
||||
const o = this.readLength(this._offset + 1) // stored in `length`
|
||||
if (o === null) { return null }
|
||||
|
||||
this._offset = o
|
||||
return seq
|
||||
}
|
||||
|
||||
Reader.prototype.readInt = function () {
|
||||
return this._readTag(ASN1.Integer)
|
||||
}
|
||||
|
||||
Reader.prototype.readBoolean = function (tag) {
|
||||
return (this._readTag(tag || ASN1.Boolean) !== 0)
|
||||
}
|
||||
|
||||
Reader.prototype.readEnumeration = function () {
|
||||
return this._readTag(ASN1.Enumeration)
|
||||
}
|
||||
|
||||
Reader.prototype.readString = function (tag, retbuf) {
|
||||
if (!tag) { tag = ASN1.OctetString }
|
||||
|
||||
const b = this.peek()
|
||||
if (b === null) { return null }
|
||||
|
||||
if (b !== tag) {
|
||||
throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
|
||||
': got 0x' + b.toString(16))
|
||||
}
|
||||
|
||||
const o = this.readLength(this._offset + 1) // stored in `length`
|
||||
|
||||
if (o === null) { return null }
|
||||
|
||||
if (this.length > this._size - o) { return null }
|
||||
|
||||
this._offset = o
|
||||
|
||||
if (this.length === 0) { return retbuf ? Buffer.alloc(0) : '' }
|
||||
|
||||
const str = this._buf.slice(this._offset, this._offset + this.length)
|
||||
this._offset += this.length
|
||||
|
||||
return retbuf ? str : str.toString('utf8')
|
||||
}
|
||||
|
||||
Reader.prototype.readOID = function (tag) {
|
||||
if (!tag) { tag = ASN1.OID }
|
||||
|
||||
const b = this.readString(tag, true)
|
||||
if (b === null) { return null }
|
||||
|
||||
const values = []
|
||||
let value = 0
|
||||
|
||||
for (let i = 0; i < b.length; i++) {
|
||||
const byte = b[i] & 0xff
|
||||
|
||||
value <<= 7
|
||||
value += byte & 0x7f
|
||||
if ((byte & 0x80) === 0) {
|
||||
values.push(value)
|
||||
value = 0
|
||||
}
|
||||
}
|
||||
|
||||
value = values.shift()
|
||||
values.unshift(value % 40)
|
||||
values.unshift((value / 40) >> 0)
|
||||
|
||||
return values.join('.')
|
||||
}
|
||||
|
||||
Reader.prototype._readTag = function (tag) {
|
||||
assert.ok(tag !== undefined)
|
||||
|
||||
const b = this.peek()
|
||||
|
||||
if (b === null) { return null }
|
||||
|
||||
if (b !== tag) {
|
||||
throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
|
||||
': got 0x' + b.toString(16))
|
||||
}
|
||||
|
||||
const o = this.readLength(this._offset + 1) // stored in `length`
|
||||
if (o === null) { return null }
|
||||
|
||||
if (this.length > 4) { throw newInvalidAsn1Error('Integer too long: ' + this.length) }
|
||||
|
||||
if (this.length > this._size - o) { return null }
|
||||
this._offset = o
|
||||
|
||||
const fb = this._buf[this._offset]
|
||||
let value = 0
|
||||
|
||||
let i
|
||||
for (i = 0; i < this.length; i++) {
|
||||
value <<= 8
|
||||
value |= (this._buf[this._offset++] & 0xff)
|
||||
}
|
||||
|
||||
if ((fb & 0x80) === 0x80 && i !== 4) { value -= (1 << (i * 8)) }
|
||||
|
||||
return value >> 0
|
||||
}
|
||||
|
||||
// --- Exported API
|
||||
|
||||
module.exports = Reader
|
||||
182
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/reader.test.js
generated
vendored
Normal file
182
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/reader.test.js
generated
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||
|
||||
const { test } = require('tap')
|
||||
const BerReader = require('./reader')
|
||||
|
||||
test('load library', function (t) {
|
||||
t.ok(BerReader)
|
||||
try {
|
||||
const reader = new BerReader()
|
||||
t.equal(reader, null, 'reader')
|
||||
t.fail('Should have thrown')
|
||||
} catch (e) {
|
||||
t.ok(e instanceof TypeError, 'Should have been a type error')
|
||||
}
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read byte', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0xde]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readByte(), 0xde, 'wrong value')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read 1 byte int', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x02, 0x01, 0x03]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readInt(), 0x03, 'wrong value')
|
||||
t.equal(reader.length, 0x01, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read 2 byte int', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x02, 0x02, 0x7e, 0xde]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readInt(), 0x7ede, 'wrong value')
|
||||
t.equal(reader.length, 0x02, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read 3 byte int', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x02, 0x03, 0x7e, 0xde, 0x03]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readInt(), 0x7ede03, 'wrong value')
|
||||
t.equal(reader.length, 0x03, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read 4 byte int', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x02, 0x04, 0x7e, 0xde, 0x03, 0x01]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readInt(), 0x7ede0301, 'wrong value')
|
||||
t.equal(reader.length, 0x04, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read 1 byte negative int', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x02, 0x01, 0xdc]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readInt(), -36, 'wrong value')
|
||||
t.equal(reader.length, 0x01, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read 2 byte negative int', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x02, 0x02, 0xc0, 0x4e]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readInt(), -16306, 'wrong value')
|
||||
t.equal(reader.length, 0x02, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read 3 byte negative int', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x02, 0x03, 0xff, 0x00, 0x19]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readInt(), -65511, 'wrong value')
|
||||
t.equal(reader.length, 0x03, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read 4 byte negative int', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x02, 0x04, 0x91, 0x7c, 0x22, 0x1f]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readInt(), -1854135777, 'wrong value')
|
||||
t.equal(reader.length, 0x04, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read boolean true', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x01, 0x01, 0xff]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readBoolean(), true, 'wrong value')
|
||||
t.equal(reader.length, 0x01, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read boolean false', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x01, 0x01, 0x00]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readBoolean(), false, 'wrong value')
|
||||
t.equal(reader.length, 0x01, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read enumeration', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x0a, 0x01, 0x20]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readEnumeration(), 0x20, 'wrong value')
|
||||
t.equal(reader.length, 0x01, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read string', function (t) {
|
||||
const dn = 'cn=foo,ou=unit,o=test'
|
||||
const buf = Buffer.alloc(dn.length + 2)
|
||||
buf[0] = 0x04
|
||||
buf[1] = Buffer.byteLength(dn)
|
||||
buf.write(dn, 2)
|
||||
const reader = new BerReader(buf)
|
||||
t.ok(reader)
|
||||
t.equal(reader.readString(), dn, 'wrong value')
|
||||
t.equal(reader.length, dn.length, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('read sequence', function (t) {
|
||||
const reader = new BerReader(Buffer.from([0x30, 0x03, 0x01, 0x01, 0xff]))
|
||||
t.ok(reader)
|
||||
t.equal(reader.readSequence(), 0x30, 'wrong value')
|
||||
t.equal(reader.length, 0x03, 'wrong length')
|
||||
t.equal(reader.readBoolean(), true, 'wrong value')
|
||||
t.equal(reader.length, 0x01, 'wrong length')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('anonymous LDAPv3 bind', function (t) {
|
||||
const BIND = Buffer.alloc(14)
|
||||
BIND[0] = 0x30 // Sequence
|
||||
BIND[1] = 12 // len
|
||||
BIND[2] = 0x02 // ASN.1 Integer
|
||||
BIND[3] = 1 // len
|
||||
BIND[4] = 0x04 // msgid (make up 4)
|
||||
BIND[5] = 0x60 // Bind Request
|
||||
BIND[6] = 7 // len
|
||||
BIND[7] = 0x02 // ASN.1 Integer
|
||||
BIND[8] = 1 // len
|
||||
BIND[9] = 0x03 // v3
|
||||
BIND[10] = 0x04 // String (bind dn)
|
||||
BIND[11] = 0 // len
|
||||
BIND[12] = 0x80 // ContextSpecific (choice)
|
||||
BIND[13] = 0 // simple bind
|
||||
|
||||
// Start testing ^^
|
||||
const ber = new BerReader(BIND)
|
||||
t.equal(ber.readSequence(), 48, 'Not an ASN.1 Sequence')
|
||||
t.equal(ber.length, 12, 'Message length should be 12')
|
||||
t.equal(ber.readInt(), 4, 'Message id should have been 4')
|
||||
t.equal(ber.readSequence(), 96, 'Bind Request should have been 96')
|
||||
t.equal(ber.length, 7, 'Bind length should have been 7')
|
||||
t.equal(ber.readInt(), 3, 'LDAP version should have been 3')
|
||||
t.equal(ber.readString(), '', 'Bind DN should have been empty')
|
||||
t.equal(ber.length, 0, 'string length should have been 0')
|
||||
t.equal(ber.readByte(), 0x80, 'Should have been ContextSpecific (choice)')
|
||||
t.equal(ber.readByte(), 0, 'Should have been simple bind')
|
||||
t.equal(null, ber.readByte(), 'Should be out of data')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('long string', function (t) {
|
||||
const buf = Buffer.alloc(256)
|
||||
const s =
|
||||
'2;649;CN=Red Hat CS 71GA Demo,O=Red Hat CS 71GA Demo,C=US;' +
|
||||
'CN=RHCS Agent - admin01,UID=admin01,O=redhat,C=US [1] This is ' +
|
||||
'Teena Vradmin\'s description.'
|
||||
buf[0] = 0x04
|
||||
buf[1] = 0x81
|
||||
buf[2] = 0x94
|
||||
buf.write(s, 3)
|
||||
const ber = new BerReader(buf.slice(0, 3 + s.length))
|
||||
t.equal(ber.readString(), s)
|
||||
t.end()
|
||||
})
|
||||
35
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/types.js
generated
vendored
Normal file
35
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/types.js
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||
|
||||
module.exports = {
|
||||
EOC: 0,
|
||||
Boolean: 1,
|
||||
Integer: 2,
|
||||
BitString: 3,
|
||||
OctetString: 4,
|
||||
Null: 5,
|
||||
OID: 6,
|
||||
ObjectDescriptor: 7,
|
||||
External: 8,
|
||||
Real: 9, // float
|
||||
Enumeration: 10,
|
||||
PDV: 11,
|
||||
Utf8String: 12,
|
||||
RelativeOID: 13,
|
||||
Sequence: 16,
|
||||
Set: 17,
|
||||
NumericString: 18,
|
||||
PrintableString: 19,
|
||||
T61String: 20,
|
||||
VideotexString: 21,
|
||||
IA5String: 22,
|
||||
UTCTime: 23,
|
||||
GeneralizedTime: 24,
|
||||
GraphicString: 25,
|
||||
VisibleString: 26,
|
||||
GeneralString: 28,
|
||||
UniversalString: 29,
|
||||
CharacterString: 30,
|
||||
BMPString: 31,
|
||||
Constructor: 32,
|
||||
Context: 128
|
||||
}
|
||||
298
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/writer.js
generated
vendored
Normal file
298
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/writer.js
generated
vendored
Normal file
@ -0,0 +1,298 @@
|
||||
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||
|
||||
const assert = require('assert')
|
||||
const ASN1 = require('./types')
|
||||
const errors = require('./errors')
|
||||
|
||||
// --- Globals
|
||||
|
||||
const newInvalidAsn1Error = errors.newInvalidAsn1Error
|
||||
|
||||
const DEFAULT_OPTS = {
|
||||
size: 1024,
|
||||
growthFactor: 8
|
||||
}
|
||||
|
||||
// --- Helpers
|
||||
|
||||
function merge (from, to) {
|
||||
assert.ok(from)
|
||||
assert.equal(typeof (from), 'object')
|
||||
assert.ok(to)
|
||||
assert.equal(typeof (to), 'object')
|
||||
|
||||
const keys = Object.getOwnPropertyNames(from)
|
||||
keys.forEach(function (key) {
|
||||
if (to[key]) { return }
|
||||
|
||||
const value = Object.getOwnPropertyDescriptor(from, key)
|
||||
Object.defineProperty(to, key, value)
|
||||
})
|
||||
|
||||
return to
|
||||
}
|
||||
|
||||
// --- API
|
||||
|
||||
function Writer (options) {
|
||||
options = merge(DEFAULT_OPTS, options || {})
|
||||
|
||||
this._buf = Buffer.alloc(options.size || 1024)
|
||||
this._size = this._buf.length
|
||||
this._offset = 0
|
||||
this._options = options
|
||||
|
||||
// A list of offsets in the buffer where we need to insert
|
||||
// sequence tag/len pairs.
|
||||
this._seq = []
|
||||
}
|
||||
|
||||
Object.defineProperty(Writer.prototype, Symbol.toStringTag, { value: 'BerWriter' })
|
||||
|
||||
Object.defineProperty(Writer.prototype, 'buffer', {
|
||||
get: function () {
|
||||
if (this._seq.length) { throw newInvalidAsn1Error(this._seq.length + ' unended sequence(s)') }
|
||||
|
||||
return (this._buf.slice(0, this._offset))
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Append a raw buffer to the current writer instance. No validation to
|
||||
* determine if the buffer represents a valid BER encoding is performed.
|
||||
*
|
||||
* @param {Buffer} buffer The buffer to append. If this is not a valid BER
|
||||
* sequence of data, it will invalidate the BER represented by the `BerWriter`.
|
||||
*
|
||||
* @throws If the input is not an instance of Buffer.
|
||||
*/
|
||||
Writer.prototype.appendBuffer = function appendBuffer (buffer) {
|
||||
if (Buffer.isBuffer(buffer) === false) {
|
||||
throw Error('buffer must be an instance of Buffer')
|
||||
}
|
||||
for (const b of buffer.values()) {
|
||||
this.writeByte(b)
|
||||
}
|
||||
}
|
||||
|
||||
Writer.prototype.writeByte = function (b) {
|
||||
if (typeof (b) !== 'number') { throw new TypeError('argument must be a Number') }
|
||||
|
||||
this._ensure(1)
|
||||
this._buf[this._offset++] = b
|
||||
}
|
||||
|
||||
Writer.prototype.writeInt = function (i, tag) {
|
||||
if (typeof (i) !== 'number') { throw new TypeError('argument must be a Number') }
|
||||
if (typeof (tag) !== 'number') { tag = ASN1.Integer }
|
||||
|
||||
let sz = 4
|
||||
|
||||
while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000 >> 0)) &&
|
||||
(sz > 1)) {
|
||||
sz--
|
||||
i <<= 8
|
||||
}
|
||||
|
||||
if (sz > 4) { throw newInvalidAsn1Error('BER ints cannot be > 0xffffffff') }
|
||||
|
||||
this._ensure(2 + sz)
|
||||
this._buf[this._offset++] = tag
|
||||
this._buf[this._offset++] = sz
|
||||
|
||||
while (sz-- > 0) {
|
||||
this._buf[this._offset++] = ((i & 0xff000000) >>> 24)
|
||||
i <<= 8
|
||||
}
|
||||
}
|
||||
|
||||
Writer.prototype.writeNull = function () {
|
||||
this.writeByte(ASN1.Null)
|
||||
this.writeByte(0x00)
|
||||
}
|
||||
|
||||
Writer.prototype.writeEnumeration = function (i, tag) {
|
||||
if (typeof (i) !== 'number') { throw new TypeError('argument must be a Number') }
|
||||
if (typeof (tag) !== 'number') { tag = ASN1.Enumeration }
|
||||
|
||||
return this.writeInt(i, tag)
|
||||
}
|
||||
|
||||
Writer.prototype.writeBoolean = function (b, tag) {
|
||||
if (typeof (b) !== 'boolean') { throw new TypeError('argument must be a Boolean') }
|
||||
if (typeof (tag) !== 'number') { tag = ASN1.Boolean }
|
||||
|
||||
this._ensure(3)
|
||||
this._buf[this._offset++] = tag
|
||||
this._buf[this._offset++] = 0x01
|
||||
this._buf[this._offset++] = b ? 0xff : 0x00
|
||||
}
|
||||
|
||||
Writer.prototype.writeString = function (s, tag) {
|
||||
if (typeof (s) !== 'string') { throw new TypeError('argument must be a string (was: ' + typeof (s) + ')') }
|
||||
if (typeof (tag) !== 'number') { tag = ASN1.OctetString }
|
||||
|
||||
const len = Buffer.byteLength(s)
|
||||
this.writeByte(tag)
|
||||
this.writeLength(len)
|
||||
if (len) {
|
||||
this._ensure(len)
|
||||
this._buf.write(s, this._offset)
|
||||
this._offset += len
|
||||
}
|
||||
}
|
||||
|
||||
Writer.prototype.writeBuffer = function (buf, tag) {
|
||||
if (typeof (tag) !== 'number') { throw new TypeError('tag must be a number') }
|
||||
if (!Buffer.isBuffer(buf)) { throw new TypeError('argument must be a buffer') }
|
||||
|
||||
this.writeByte(tag)
|
||||
this.writeLength(buf.length)
|
||||
this._ensure(buf.length)
|
||||
buf.copy(this._buf, this._offset, 0, buf.length)
|
||||
this._offset += buf.length
|
||||
}
|
||||
|
||||
Writer.prototype.writeStringArray = function (strings) {
|
||||
if (Array.isArray(strings) === false) { throw new TypeError('argument must be an Array[String]') }
|
||||
|
||||
const self = this
|
||||
strings.forEach(function (s) {
|
||||
self.writeString(s)
|
||||
})
|
||||
}
|
||||
|
||||
// This is really to solve DER cases, but whatever for now
|
||||
Writer.prototype.writeOID = function (s, tag) {
|
||||
if (typeof (s) !== 'string') { throw new TypeError('argument must be a string') }
|
||||
if (typeof (tag) !== 'number') { tag = ASN1.OID }
|
||||
|
||||
if (!/^([0-9]+\.){3,}[0-9]+$/.test(s)) { throw new Error('argument is not a valid OID string') }
|
||||
|
||||
function encodeOctet (bytes, octet) {
|
||||
if (octet < 128) {
|
||||
bytes.push(octet)
|
||||
} else if (octet < 16384) {
|
||||
bytes.push((octet >>> 7) | 0x80)
|
||||
bytes.push(octet & 0x7F)
|
||||
} else if (octet < 2097152) {
|
||||
bytes.push((octet >>> 14) | 0x80)
|
||||
bytes.push(((octet >>> 7) | 0x80) & 0xFF)
|
||||
bytes.push(octet & 0x7F)
|
||||
} else if (octet < 268435456) {
|
||||
bytes.push((octet >>> 21) | 0x80)
|
||||
bytes.push(((octet >>> 14) | 0x80) & 0xFF)
|
||||
bytes.push(((octet >>> 7) | 0x80) & 0xFF)
|
||||
bytes.push(octet & 0x7F)
|
||||
} else {
|
||||
bytes.push(((octet >>> 28) | 0x80) & 0xFF)
|
||||
bytes.push(((octet >>> 21) | 0x80) & 0xFF)
|
||||
bytes.push(((octet >>> 14) | 0x80) & 0xFF)
|
||||
bytes.push(((octet >>> 7) | 0x80) & 0xFF)
|
||||
bytes.push(octet & 0x7F)
|
||||
}
|
||||
}
|
||||
|
||||
const tmp = s.split('.')
|
||||
const bytes = []
|
||||
bytes.push(parseInt(tmp[0], 10) * 40 + parseInt(tmp[1], 10))
|
||||
tmp.slice(2).forEach(function (b) {
|
||||
encodeOctet(bytes, parseInt(b, 10))
|
||||
})
|
||||
|
||||
const self = this
|
||||
this._ensure(2 + bytes.length)
|
||||
this.writeByte(tag)
|
||||
this.writeLength(bytes.length)
|
||||
bytes.forEach(function (b) {
|
||||
self.writeByte(b)
|
||||
})
|
||||
}
|
||||
|
||||
Writer.prototype.writeLength = function (len) {
|
||||
if (typeof (len) !== 'number') { throw new TypeError('argument must be a Number') }
|
||||
|
||||
this._ensure(4)
|
||||
|
||||
if (len <= 0x7f) {
|
||||
this._buf[this._offset++] = len
|
||||
} else if (len <= 0xff) {
|
||||
this._buf[this._offset++] = 0x81
|
||||
this._buf[this._offset++] = len
|
||||
} else if (len <= 0xffff) {
|
||||
this._buf[this._offset++] = 0x82
|
||||
this._buf[this._offset++] = len >> 8
|
||||
this._buf[this._offset++] = len
|
||||
} else if (len <= 0xffffff) {
|
||||
this._buf[this._offset++] = 0x83
|
||||
this._buf[this._offset++] = len >> 16
|
||||
this._buf[this._offset++] = len >> 8
|
||||
this._buf[this._offset++] = len
|
||||
} else {
|
||||
throw newInvalidAsn1Error('Length too long (> 4 bytes)')
|
||||
}
|
||||
}
|
||||
|
||||
Writer.prototype.startSequence = function (tag) {
|
||||
if (typeof (tag) !== 'number') { tag = ASN1.Sequence | ASN1.Constructor }
|
||||
|
||||
this.writeByte(tag)
|
||||
this._seq.push(this._offset)
|
||||
this._ensure(3)
|
||||
this._offset += 3
|
||||
}
|
||||
|
||||
Writer.prototype.endSequence = function () {
|
||||
const seq = this._seq.pop()
|
||||
const start = seq + 3
|
||||
const len = this._offset - start
|
||||
|
||||
if (len <= 0x7f) {
|
||||
this._shift(start, len, -2)
|
||||
this._buf[seq] = len
|
||||
} else if (len <= 0xff) {
|
||||
this._shift(start, len, -1)
|
||||
this._buf[seq] = 0x81
|
||||
this._buf[seq + 1] = len
|
||||
} else if (len <= 0xffff) {
|
||||
this._buf[seq] = 0x82
|
||||
this._buf[seq + 1] = len >> 8
|
||||
this._buf[seq + 2] = len
|
||||
} else if (len <= 0xffffff) {
|
||||
this._shift(start, len, 1)
|
||||
this._buf[seq] = 0x83
|
||||
this._buf[seq + 1] = len >> 16
|
||||
this._buf[seq + 2] = len >> 8
|
||||
this._buf[seq + 3] = len
|
||||
} else {
|
||||
throw newInvalidAsn1Error('Sequence too long')
|
||||
}
|
||||
}
|
||||
|
||||
Writer.prototype._shift = function (start, len, shift) {
|
||||
assert.ok(start !== undefined)
|
||||
assert.ok(len !== undefined)
|
||||
assert.ok(shift)
|
||||
|
||||
this._buf.copy(this._buf, start + shift, start, start + len)
|
||||
this._offset += shift
|
||||
}
|
||||
|
||||
Writer.prototype._ensure = function (len) {
|
||||
assert.ok(len)
|
||||
|
||||
if (this._size - this._offset < len) {
|
||||
let sz = this._size * this._options.growthFactor
|
||||
if (sz - this._offset < len) { sz += len }
|
||||
|
||||
const buf = Buffer.alloc(sz)
|
||||
|
||||
this._buf.copy(buf, 0, 0, this._offset)
|
||||
this._buf = buf
|
||||
this._size = sz
|
||||
}
|
||||
}
|
||||
|
||||
// --- Exported API
|
||||
|
||||
module.exports = Writer
|
||||
344
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/writer.test.js
generated
vendored
Normal file
344
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/ber/writer.test.js
generated
vendored
Normal file
@ -0,0 +1,344 @@
|
||||
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||
|
||||
const { test } = require('tap')
|
||||
const BerWriter = require('./writer')
|
||||
|
||||
test('write byte', function (t) {
|
||||
const writer = new BerWriter()
|
||||
|
||||
writer.writeByte(0xC2)
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
t.equal(ber.length, 1, 'Wrong length')
|
||||
t.equal(ber[0], 0xC2, 'value wrong')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write 1 byte int', function (t) {
|
||||
const writer = new BerWriter()
|
||||
|
||||
writer.writeInt(0x7f)
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
t.equal(ber.length, 3, 'Wrong length for an int: ' + ber.length)
|
||||
t.equal(ber[0], 0x02, 'ASN.1 tag wrong (2) -> ' + ber[0])
|
||||
t.equal(ber[1], 0x01, 'length wrong(1) -> ' + ber[1])
|
||||
t.equal(ber[2], 0x7f, 'value wrong(3) -> ' + ber[2])
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write 2 byte int', function (t) {
|
||||
const writer = new BerWriter()
|
||||
|
||||
writer.writeInt(0x7ffe)
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
t.equal(ber.length, 4, 'Wrong length for an int')
|
||||
t.equal(ber[0], 0x02, 'ASN.1 tag wrong')
|
||||
t.equal(ber[1], 0x02, 'length wrong')
|
||||
t.equal(ber[2], 0x7f, 'value wrong (byte 1)')
|
||||
t.equal(ber[3], 0xfe, 'value wrong (byte 2)')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write 3 byte int', function (t) {
|
||||
const writer = new BerWriter()
|
||||
|
||||
writer.writeInt(0x7ffffe)
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
t.equal(ber.length, 5, 'Wrong length for an int')
|
||||
t.equal(ber[0], 0x02, 'ASN.1 tag wrong')
|
||||
t.equal(ber[1], 0x03, 'length wrong')
|
||||
t.equal(ber[2], 0x7f, 'value wrong (byte 1)')
|
||||
t.equal(ber[3], 0xff, 'value wrong (byte 2)')
|
||||
t.equal(ber[4], 0xfe, 'value wrong (byte 3)')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write 4 byte int', function (t) {
|
||||
const writer = new BerWriter()
|
||||
|
||||
writer.writeInt(0x7ffffffe)
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
|
||||
t.equal(ber.length, 6, 'Wrong length for an int')
|
||||
t.equal(ber[0], 0x02, 'ASN.1 tag wrong')
|
||||
t.equal(ber[1], 0x04, 'length wrong')
|
||||
t.equal(ber[2], 0x7f, 'value wrong (byte 1)')
|
||||
t.equal(ber[3], 0xff, 'value wrong (byte 2)')
|
||||
t.equal(ber[4], 0xff, 'value wrong (byte 3)')
|
||||
t.equal(ber[5], 0xfe, 'value wrong (byte 4)')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write 1 byte negative int', function (t) {
|
||||
const writer = new BerWriter()
|
||||
|
||||
writer.writeInt(-128)
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
|
||||
t.equal(ber.length, 3, 'Wrong length for an int')
|
||||
t.equal(ber[0], 0x02, 'ASN.1 tag wrong')
|
||||
t.equal(ber[1], 0x01, 'length wrong')
|
||||
t.equal(ber[2], 0x80, 'value wrong (byte 1)')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write 2 byte negative int', function (t) {
|
||||
const writer = new BerWriter()
|
||||
|
||||
writer.writeInt(-22400)
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
|
||||
t.equal(ber.length, 4, 'Wrong length for an int')
|
||||
t.equal(ber[0], 0x02, 'ASN.1 tag wrong')
|
||||
t.equal(ber[1], 0x02, 'length wrong')
|
||||
t.equal(ber[2], 0xa8, 'value wrong (byte 1)')
|
||||
t.equal(ber[3], 0x80, 'value wrong (byte 2)')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write 3 byte negative int', function (t) {
|
||||
const writer = new BerWriter()
|
||||
|
||||
writer.writeInt(-481653)
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
|
||||
t.equal(ber.length, 5, 'Wrong length for an int')
|
||||
t.equal(ber[0], 0x02, 'ASN.1 tag wrong')
|
||||
t.equal(ber[1], 0x03, 'length wrong')
|
||||
t.equal(ber[2], 0xf8, 'value wrong (byte 1)')
|
||||
t.equal(ber[3], 0xa6, 'value wrong (byte 2)')
|
||||
t.equal(ber[4], 0x8b, 'value wrong (byte 3)')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write 4 byte negative int', function (t) {
|
||||
const writer = new BerWriter()
|
||||
|
||||
writer.writeInt(-1522904131)
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
|
||||
t.equal(ber.length, 6, 'Wrong length for an int')
|
||||
t.equal(ber[0], 0x02, 'ASN.1 tag wrong')
|
||||
t.equal(ber[1], 0x04, 'length wrong')
|
||||
t.equal(ber[2], 0xa5, 'value wrong (byte 1)')
|
||||
t.equal(ber[3], 0x3a, 'value wrong (byte 2)')
|
||||
t.equal(ber[4], 0x53, 'value wrong (byte 3)')
|
||||
t.equal(ber[5], 0xbd, 'value wrong (byte 4)')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write boolean', function (t) {
|
||||
const writer = new BerWriter()
|
||||
|
||||
writer.writeBoolean(true)
|
||||
writer.writeBoolean(false)
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
t.equal(ber.length, 6, 'Wrong length')
|
||||
t.equal(ber[0], 0x01, 'tag wrong')
|
||||
t.equal(ber[1], 0x01, 'length wrong')
|
||||
t.equal(ber[2], 0xff, 'value wrong')
|
||||
t.equal(ber[3], 0x01, 'tag wrong')
|
||||
t.equal(ber[4], 0x01, 'length wrong')
|
||||
t.equal(ber[5], 0x00, 'value wrong')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write string', function (t) {
|
||||
const writer = new BerWriter()
|
||||
writer.writeString('hello world')
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
t.equal(ber.length, 13, 'wrong length')
|
||||
t.equal(ber[0], 0x04, 'wrong tag')
|
||||
t.equal(ber[1], 11, 'wrong length')
|
||||
t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write buffer', function (t) {
|
||||
const writer = new BerWriter()
|
||||
// write some stuff to start with
|
||||
writer.writeString('hello world')
|
||||
let ber = writer.buffer
|
||||
const buf = Buffer.from([0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01,
|
||||
0xff, 0x01, 0x01, 0xff])
|
||||
writer.writeBuffer(buf.slice(2, buf.length), 0x04)
|
||||
ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
t.equal(ber.length, 26, 'wrong length')
|
||||
t.equal(ber[0], 0x04, 'wrong tag')
|
||||
t.equal(ber[1], 11, 'wrong length')
|
||||
t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value')
|
||||
t.equal(ber[13], buf[0], 'wrong tag')
|
||||
t.equal(ber[14], buf[1], 'wrong length')
|
||||
for (let i = 13, j = 0; i < ber.length && j < buf.length; i++, j++) {
|
||||
t.equal(ber[i], buf[j], 'buffer contents not identical')
|
||||
}
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('write string array', function (t) {
|
||||
const writer = new BerWriter()
|
||||
writer.writeStringArray(['hello world', 'fubar!'])
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
|
||||
t.equal(ber.length, 21, 'wrong length')
|
||||
t.equal(ber[0], 0x04, 'wrong tag')
|
||||
t.equal(ber[1], 11, 'wrong length')
|
||||
t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value')
|
||||
|
||||
t.equal(ber[13], 0x04, 'wrong tag')
|
||||
t.equal(ber[14], 6, 'wrong length')
|
||||
t.equal(ber.slice(15).toString('utf8'), 'fubar!', 'wrong value')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('resize internal buffer', function (t) {
|
||||
const writer = new BerWriter({ size: 2 })
|
||||
writer.writeString('hello world')
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
t.equal(ber.length, 13, 'wrong length')
|
||||
t.equal(ber[0], 0x04, 'wrong tag')
|
||||
t.equal(ber[1], 11, 'wrong length')
|
||||
t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('sequence', function (t) {
|
||||
const writer = new BerWriter({ size: 25 })
|
||||
writer.startSequence()
|
||||
writer.writeString('hello world')
|
||||
writer.endSequence()
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
t.equal(ber.length, 15, 'wrong length')
|
||||
t.equal(ber[0], 0x30, 'wrong tag')
|
||||
t.equal(ber[1], 13, 'wrong length')
|
||||
t.equal(ber[2], 0x04, 'wrong tag')
|
||||
t.equal(ber[3], 11, 'wrong length')
|
||||
t.equal(ber.slice(4).toString('utf8'), 'hello world', 'wrong value')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('nested sequence', function (t) {
|
||||
const writer = new BerWriter({ size: 25 })
|
||||
writer.startSequence()
|
||||
writer.writeString('hello world')
|
||||
writer.startSequence()
|
||||
writer.writeString('hello world')
|
||||
writer.endSequence()
|
||||
writer.endSequence()
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
t.equal(ber.length, 30, 'wrong length')
|
||||
t.equal(ber[0], 0x30, 'wrong tag')
|
||||
t.equal(ber[1], 28, 'wrong length')
|
||||
t.equal(ber[2], 0x04, 'wrong tag')
|
||||
t.equal(ber[3], 11, 'wrong length')
|
||||
t.equal(ber.slice(4, 15).toString('utf8'), 'hello world', 'wrong value')
|
||||
t.equal(ber[15], 0x30, 'wrong tag')
|
||||
t.equal(ber[16], 13, 'wrong length')
|
||||
t.equal(ber[17], 0x04, 'wrong tag')
|
||||
t.equal(ber[18], 11, 'wrong length')
|
||||
t.equal(ber.slice(19, 30).toString('utf8'), 'hello world', 'wrong value')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('LDAP bind message', function (t) {
|
||||
const dn = 'cn=foo,ou=unit,o=test'
|
||||
const writer = new BerWriter()
|
||||
writer.startSequence()
|
||||
writer.writeInt(3) // msgid = 3
|
||||
writer.startSequence(0x60) // ldap bind
|
||||
writer.writeInt(3) // ldap v3
|
||||
writer.writeString(dn)
|
||||
writer.writeByte(0x80)
|
||||
writer.writeByte(0x00)
|
||||
writer.endSequence()
|
||||
writer.endSequence()
|
||||
const ber = writer.buffer
|
||||
|
||||
t.ok(ber)
|
||||
t.equal(ber.length, 35, 'wrong length (buffer)')
|
||||
t.equal(ber[0], 0x30, 'wrong tag')
|
||||
t.equal(ber[1], 33, 'wrong length')
|
||||
t.equal(ber[2], 0x02, 'wrong tag')
|
||||
t.equal(ber[3], 1, 'wrong length')
|
||||
t.equal(ber[4], 0x03, 'wrong value')
|
||||
t.equal(ber[5], 0x60, 'wrong tag')
|
||||
t.equal(ber[6], 28, 'wrong length')
|
||||
t.equal(ber[7], 0x02, 'wrong tag')
|
||||
t.equal(ber[8], 1, 'wrong length')
|
||||
t.equal(ber[9], 0x03, 'wrong value')
|
||||
t.equal(ber[10], 0x04, 'wrong tag')
|
||||
t.equal(ber[11], dn.length, 'wrong length')
|
||||
t.equal(ber.slice(12, 33).toString('utf8'), dn, 'wrong value')
|
||||
t.equal(ber[33], 0x80, 'wrong tag')
|
||||
t.equal(ber[34], 0x00, 'wrong len')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('Write OID', function (t) {
|
||||
const oid = '1.2.840.113549.1.1.1'
|
||||
const writer = new BerWriter()
|
||||
writer.writeOID(oid)
|
||||
|
||||
const expected = Buffer.from([0x06, 0x09, 0x2a, 0x86,
|
||||
0x48, 0x86, 0xf7, 0x0d,
|
||||
0x01, 0x01, 0x01])
|
||||
const ber = writer.buffer
|
||||
t.equal(ber.compare(expected), 0)
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('appendBuffer appends a buffer', async t => {
|
||||
const expected = Buffer.from([0x04, 0x03, 0x66, 0x6f, 0x6f, 0x66, 0x6f, 0x6f])
|
||||
const writer = new BerWriter()
|
||||
writer.writeString('foo')
|
||||
writer.appendBuffer(Buffer.from('foo'))
|
||||
t.equal(Buffer.compare(writer.buffer, expected), 0)
|
||||
})
|
||||
18
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/index.js
generated
vendored
Normal file
18
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/lib/index.js
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
|
||||
|
||||
// If you have no idea what ASN.1 or BER is, see this:
|
||||
// https://web.archive.org/web/20220314051854/http://luca.ntop.org/Teaching/Appunti/asn1.html
|
||||
|
||||
const Ber = require('./ber/index')
|
||||
|
||||
// --- Exported API
|
||||
|
||||
module.exports = {
|
||||
|
||||
Ber: Ber,
|
||||
|
||||
BerReader: Ber.Reader,
|
||||
|
||||
BerWriter: Ber.Writer
|
||||
|
||||
}
|
||||
34
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/package.json
generated
vendored
Normal file
34
node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1/package.json
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"originalAuthor": "Joyent (joyent.com)",
|
||||
"contributors": [
|
||||
"Mark Cavage <mcavage@gmail.com>",
|
||||
"David Gwynne <loki@animata.net>",
|
||||
"Yunong Xiao <yunong@joyent.com>",
|
||||
"Alex Wilson <alex.wilson@joyent.com>"
|
||||
],
|
||||
"name": "@ldapjs/asn1",
|
||||
"description": "Contains parsers and serializers for ASN.1 (currently BER only)",
|
||||
"version": "1.2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/ldapjs/asn1.git"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"devDependencies": {
|
||||
"@fastify/pre-commit": "^2.0.2",
|
||||
"standard": "^16.0.4",
|
||||
"tap": "^16.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tap --no-coverage-report -R terse",
|
||||
"test:cov": "tap -R terse",
|
||||
"test:cov:html": "tap -R terse --coverage-report=html",
|
||||
"test:watch": "tap -w --no-coverage-report -R terse",
|
||||
"lint": "standard"
|
||||
},
|
||||
"license": "MIT",
|
||||
"pre-commit": [
|
||||
"lint",
|
||||
"test"
|
||||
]
|
||||
}
|
||||
45
node_modules/@ldapjs/controls/package.json
generated
vendored
Normal file
45
node_modules/@ldapjs/controls/package.json
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "@ldapjs/controls",
|
||||
"version": "2.1.0",
|
||||
"description": "LDAP control objects",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"lint:ci": "eslint .",
|
||||
"test": "tap --no-coverage-report -R terse",
|
||||
"test:cov": "tap -R terse",
|
||||
"test:cov:html": "tap -R terse --coverage-report=html",
|
||||
"test:watch": "tap -w --no-coverage-report -R terse"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@github.com/ldapjs/controls.git"
|
||||
},
|
||||
"keywords": [
|
||||
"ldapjs"
|
||||
],
|
||||
"author": "James Sumners",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/ldapjs/controls/issues"
|
||||
},
|
||||
"homepage": "https://github.com/ldapjs/controls#readme",
|
||||
"devDependencies": {
|
||||
"@fastify/pre-commit": "^2.0.2",
|
||||
"eslint": "^8.34.0",
|
||||
"eslint-config-standard": "^17.0.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-n": "^15.6.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"tap": "^16.3.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ldapjs/asn1": "^1.2.0",
|
||||
"@ldapjs/protocol": "^1.2.1"
|
||||
},
|
||||
"pre-commit": [
|
||||
"lint",
|
||||
"test"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user