Files
ldap-to-oauth2/node_modules/@ldapjs/dn/lib/utils/parse-string/index.test.js
2025-10-08 11:12:59 -04:00

215 lines
5.3 KiB
JavaScript

'use strict'
const tap = require('tap')
const { BerReader } = require('@ldapjs/asn1')
const parseString = require('./index')
tap.test('throws for non-string input', async t => {
const input = ['cn=foo']
t.throws(
() => parseString(input),
'input must be a string'
)
})
tap.test('short circuits for root dse', async t => {
t.same(parseString(''), [])
})
tap.test('parses basic single rdn', async t => {
const input = 'cn=foo'
const result = parseString(input)
t.same(result, [{ cn: 'foo' }])
})
tap.test('skips leading whitespace', async t => {
const input = ' cn=foo'
const result = parseString(input)
t.same(result, [{ cn: 'foo' }])
})
tap.test('parses basic multiple rdns', async t => {
let input = 'dc=example,dc=com'
let result = parseString(input)
t.same(
result,
[
{ dc: 'example' },
{ dc: 'com' }
]
)
// RFC 2253 §4 separator is supported.
input = 'dc=example;dc=com'
result = parseString(input)
t.same(
result,
[
{ dc: 'example' },
{ dc: 'com' }
]
)
})
tap.test('handles multivalued rdn', async t => {
const input = 'foo=bar+baz=bif'
const result = parseString(input)
t.same(result, [{ foo: 'bar', baz: 'bif' }])
})
tap.test('abruptly ending strings throw', async t => {
const baseError = 'rdn string ends abruptly with character: '
const tests = [
{ input: 'foo=bar+', expected: baseError + '+' },
{ input: 'foo=bar,', expected: baseError + ',' },
{ input: 'foo=bar;', expected: baseError + ';' }
]
for (const test of tests) {
t.throws(() => parseString(test.input), test.expected)
}
})
tap.test('adds rdn with trailing whitespace', async t => {
const input = 'foo=bar '
const result = parseString(input)
t.same(result, [{ foo: 'bar' }])
})
tap.test('parses rdn with attribute name in OID form', async t => {
const input = '0.9.2342.19200300.100.1.25=Example'
const result = parseString(input)
t.same(result, [{ '0.9.2342.19200300.100.1.25': 'Example' }])
})
tap.test('throws for invalid attribute type name', async t => {
let input = '3foo=bar'
t.throws(
() => parseString(input),
'invalid attribute type name: 3foo'
)
input = '1.2.3.abc=bar'
t.throws(
() => parseString(input),
'invalid attribute type name: 1.2.3.abc=bar'
)
input = 'føø=bar'
t.throws(
() => parseString(input),
'invalid attribute type name: føø'
)
})
tap.test('throws for abrupt end', async t => {
const input = 'foo=bar,'
t.throws(
() => parseString(input),
'rdn string ends abruptly with character: ,'
)
})
tap.test('rfc 4514 §4 examples', async t => {
const tests = [
{
input: 'UID=jsmith,DC=example,DC=net',
expected: [{ UID: 'jsmith' }, { DC: 'example' }, { DC: 'net' }]
},
{
input: 'OU=Sales+CN=J. Smith,DC=example,DC=net',
expected: [
{ OU: 'Sales', CN: 'J. Smith' },
{ DC: 'example' },
{ DC: 'net' }
]
},
{
input: 'CN=James \\"Jim\\" Smith\\, III,DC=example,DC=net',
expected: [{ CN: 'James "Jim" Smith, III' }, { DC: 'example' }, { DC: 'net' }]
},
{
input: 'CN=Before\\0dAfter,DC=example,DC=net',
expected: [{ CN: 'Before\rAfter' }, { DC: 'example' }, { DC: 'net' }]
},
{
checkBuffer: true,
input: '1.3.6.1.4.1.1466.0=#04024869',
expected: [{ '1.3.6.1.4.1.1466.0': new BerReader(Buffer.from([0x04, 0x02, 0x48, 0x69])) }]
},
{
input: 'CN=Lu\\C4\\8Di\\C4\\87',
expected: [{ CN: 'Lučić' }]
}
]
for (const test of tests) {
const result = parseString(test.input)
if (test.checkBuffer) {
for (const [i, rdn] of test.expected.entries()) {
for (const key of Object.keys(rdn)) {
t.equal(
rdn[key].buffer.compare(result[i][key].buffer),
0
)
}
}
} else {
t.same(result, test.expected)
}
}
})
tap.test('rfc 2253 §5 examples', async t => {
const tests = [
{
input: 'CN=Steve Kille,O=Isode Limited,C=GB',
expected: [{ CN: 'Steve Kille' }, { O: 'Isode Limited' }, { C: 'GB' }]
},
{
input: 'OU=Sales+CN=J. Smith,O=Widget Inc.,C=US',
expected: [{ OU: 'Sales', CN: 'J. Smith' }, { O: 'Widget Inc.' }, { C: 'US' }]
},
{
input: 'CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB',
expected: [{ CN: 'L. Eagle' }, { O: 'Sue, Grabbit and Runn' }, { C: 'GB' }]
},
{
input: 'CN=Before\\0DAfter,O=Test,C=GB',
expected: [{ CN: 'Before\rAfter' }, { O: 'Test' }, { C: 'GB' }]
},
{
checkBuffer: true,
input: '1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB',
expected: [
{ '1.3.6.1.4.1.1466.0': new BerReader(Buffer.from([0x04, 0x02, 0x48, 0x69])) },
{ O: 'Test' },
{ C: 'GB' }
]
},
{
input: 'SN=Lu\\C4\\8Di\\C4\\87',
expected: [{ SN: 'Lučić' }]
}
]
for (const test of tests) {
const result = parseString(test.input)
if (test.checkBuffer) {
for (const [i, rdn] of test.expected.entries()) {
for (const key of Object.keys(rdn)) {
if (typeof rdn[key] !== 'string') {
t.equal(
rdn[key].buffer.compare(result[i][key].buffer),
0
)
} else {
t.equal(rdn[key], result[i][key])
}
}
}
} else {
t.same(result, test.expected)
}
}
})