206 lines
4.8 KiB
JavaScript
206 lines
4.8 KiB
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
|
|
}
|