bind-request.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. 'use strict'
  2. const LdapMessage = require('../ldap-message')
  3. const Protocol = require('@ldapjs/protocol')
  4. const { BerTypes } = require('@ldapjs/asn1')
  5. /**
  6. * Implements the bind request message as described in
  7. * https://www.rfc-editor.org/rfc/rfc4511.html#section-4.2.
  8. *
  9. * The bind request is further defined by:
  10. * https://www.rfc-editor.org/rfc/rfc4513#section-5.
  11. */
  12. class BindRequest extends LdapMessage {
  13. static SIMPLE_BIND = 'simple'
  14. static SASL_BIND = 'sasl'
  15. #version = 0x03
  16. #name
  17. #authentication = BindRequest.SIMPLE_BIND
  18. #credentials = ''
  19. /**
  20. * @typedef {LdapMessageOptions} BindRequestOptions
  21. * @property {number} [version=3] Version of the protocol being used.
  22. * @property {string} [name=null] The "username" (dn) to connect with.
  23. * @property {string} [authentication='simple'] The authentication
  24. * mechanism to use. Currently, only `simple` is supported.
  25. * @property {string} [credentials=''] The password to use.
  26. */
  27. /**
  28. * @param {BindRequestOptions} [options]
  29. */
  30. constructor (options = {}) {
  31. options.protocolOp = Protocol.operations.LDAP_REQ_BIND
  32. super(options)
  33. const {
  34. version = 0x03,
  35. name = null,
  36. authentication = BindRequest.SIMPLE_BIND,
  37. credentials = ''
  38. } = options
  39. this.#version = version
  40. this.#name = name
  41. this.#authentication = authentication
  42. this.#credentials = credentials
  43. }
  44. /**
  45. * The authentication credentials for the request.
  46. *
  47. * @returns {string}
  48. */
  49. get credentials () {
  50. return this.#credentials
  51. }
  52. /**
  53. * The DN, or "username", that is to be used in the bind request.
  54. *
  55. * @type {string}
  56. */
  57. get name () {
  58. return this.#name
  59. }
  60. /**
  61. * The name of the request type.
  62. *
  63. * @type {string}
  64. */
  65. get type () {
  66. return 'BindRequest'
  67. }
  68. /**
  69. * The version number that the bind request conforms to.
  70. *
  71. * @type {number}
  72. */
  73. get version () {
  74. return this.#version
  75. }
  76. /**
  77. * Use {@link name} instead.
  78. *
  79. * @type {string}
  80. */
  81. get _dn () {
  82. return this.#name
  83. }
  84. /**
  85. * Internal use only.
  86. *
  87. * @param {import('@ldapjs/asn1').BerWriter} ber
  88. *
  89. * @returns {import('@ldapjs/asn1').BerWriter}
  90. */
  91. _toBer (ber) {
  92. ber.startSequence(Protocol.operations.LDAP_REQ_BIND)
  93. ber.writeInt(this.#version)
  94. ber.writeString(this.#name || '')
  95. // TODO add support for SASL et al
  96. ber.writeString(this.#credentials || '', BerTypes.Context)
  97. ber.endSequence()
  98. return ber
  99. }
  100. /**
  101. * Internal use only.
  102. *
  103. * @param {object}
  104. *
  105. * @returns {object}
  106. */
  107. _pojo (obj = {}) {
  108. obj.version = this.#version
  109. obj.name = this.#name
  110. obj.authenticationType = this.#authentication
  111. obj.credentials = this.#credentials
  112. return obj
  113. }
  114. /**
  115. * Implements the standardized `parseToPojo` method.
  116. *
  117. * @see LdapMessage.parseToPojo
  118. *
  119. * @param {import('@ldapjs/asn1').BerReader} ber
  120. */
  121. static parseToPojo (ber) {
  122. const protocolOp = ber.readSequence()
  123. if (protocolOp !== Protocol.operations.LDAP_REQ_BIND) {
  124. const op = protocolOp.toString(16).padStart(2, '0')
  125. throw Error(`found wrong protocol operation: 0x${op}`)
  126. }
  127. const version = ber.readInt()
  128. const name = ber.readString()
  129. const tag = ber.peek()
  130. // TODO: add support for SASL et al
  131. if (tag !== BerTypes.Context) {
  132. // Currently only support 0x80. To support SASL, must support 0x83.
  133. const authType = tag.toString(16).padStart(2, '0')
  134. throw Error(`authentication 0x${authType} not supported`)
  135. }
  136. const authentication = BindRequest.SIMPLE_BIND
  137. const credentials = ber.readString(BerTypes.Context)
  138. return {
  139. protocolOp,
  140. version,
  141. name,
  142. authentication,
  143. credentials
  144. }
  145. }
  146. }
  147. module.exports = BindRequest