@ldapjs/messages
Version:
API for creating and parsing LDAP messages
206 lines (172 loc) • 4.95 kB
JavaScript
'use strict'
const { operations } = require('@ldapjs/protocol')
const { getControl } = require('@ldapjs/controls')
const messageClasses = {
AbandonRequest: require('./messages/abandon-request'),
AddRequest: require('./messages/add-request'),
BindRequest: require('./messages/bind-request'),
CompareRequest: require('./messages/compare-request'),
DeleteRequest: require('./messages/delete-request'),
ExtensionRequest: require('./messages/extension-request'),
ModifyRequest: require('./messages/modify-request'),
ModifyDnRequest: require('./messages/modifydn-request'),
SearchRequest: require('./messages/search-request'),
UnbindRequest: require('./messages/unbind-request'),
AbandonResponse: require('./messages/abandon-response'),
AddResponse: require('./messages/add-response'),
BindResponse: require('./messages/bind-response'),
CompareResponse: require('./messages/compare-response'),
DeleteResponse: require('./messages/delete-response'),
ExtensionResponse: require('./messages/extension-response'),
ModifyResponse: require('./messages/modify-response'),
ModifyDnResponse: require('./messages/modifydn-response'),
// Search result messages.
SearchResultEntry: require('./messages/search-result-entry'),
SearchResultReference: require('./messages/search-result-reference'),
SearchResultDone: require('./messages/search-result-done'),
// Miscellaneous messages.
IntermediateResponse: require('./messages/intermediate-response')
}
/**
* Utility function that inspects a BER object and parses it into an instance
* of a specific LDAP message.
*
* @param {import('@ldapjs/asn1').BerReader} ber An object that represents a
* full LDAP Message sequence as described in
* https://www.rfc-editor.org/rfc/rfc4511.html#section-4.1.1.
*
* @returns {LdapMessage} Some specific instance of the base LDAP Message
* type.
*
* @throws When the input data is malformed.
*/
module.exports = function parseToMessage (ber) {
const inputType = Object.prototype.toString.apply(ber)
if (inputType !== '[object BerReader]') {
throw TypeError(`Expected BerReader but got ${inputType}.`)
}
ber.readSequence()
const messageId = ber.readInt()
const messageType = identifyType(ber)
const MessageClass = messageClasses[messageType]
const pojoMessage = MessageClass.parseToPojo(ber)
const message = new MessageClass({
messageId,
...pojoMessage
})
// Look for controls
if (ber.peek() === 0xa0) {
ber.readSequence()
const end = ber.offset + ber.length
while (ber.offset < end) {
const c = getControl(ber)
/* istanbul ignore else */
if (c) {
message.addControl(c)
}
}
}
return message
}
/**
* Determines the type of LDAP message the BER represents, e.g. a "Bind Request"
* message.
*
* @param {BerReader} ber
*
* @returns {string}
*/
function identifyType (ber) {
let result
switch (ber.peek()) {
case operations.LDAP_REQ_ABANDON: {
result = 'AbandonRequest'
break
}
case 0x00: {
result = 'AbandonResponse'
break
}
case operations.LDAP_REQ_ADD: {
result = 'AddRequest'
break
}
case operations.LDAP_RES_ADD: {
result = 'AddResponse'
break
}
case operations.LDAP_REQ_BIND: {
result = 'BindRequest'
break
}
case operations.LDAP_RES_BIND: {
result = 'BindResponse'
break
}
case operations.LDAP_REQ_COMPARE: {
result = 'CompareRequest'
break
}
case operations.LDAP_RES_COMPARE: {
result = 'CompareResponse'
break
}
case operations.LDAP_REQ_DELETE: {
result = 'DeleteRequest'
break
}
case operations.LDAP_RES_DELETE: {
result = 'DeleteResponse'
break
}
case operations.LDAP_REQ_EXTENSION: {
result = 'ExtensionRequest'
break
}
case operations.LDAP_RES_EXTENSION: {
result = 'ExtensionResponse'
break
}
case operations.LDAP_REQ_MODIFY: {
result = 'ModifyRequest'
break
}
case operations.LDAP_RES_MODIFY: {
result = 'ModifyResponse'
break
}
case operations.LDAP_REQ_MODRDN: {
result = 'ModifyDnRequest'
break
}
case operations.LDAP_RES_MODRDN: {
result = 'ModifyDnResponse'
break
}
case operations.LDAP_REQ_SEARCH: {
result = 'SearchRequest'
break
}
case operations.LDAP_RES_SEARCH_ENTRY: {
result = 'SearchResultEntry'
break
}
case operations.LDAP_RES_SEARCH_REF: {
result = 'SearchResultReference'
break
}
case operations.LDAP_RES_SEARCH_DONE: {
result = 'SearchResultDone'
break
}
case operations.LDAP_REQ_UNBIND: {
result = 'UnbindRequest'
break
}
case operations.LDAP_RES_INTERMEDIATE: {
result = 'IntermediateResponse'
break
}
}
return result
}