ldapldapjs

LdapJS server exop handling fails


I am using the LDAP server functionality of the Node.js module ldapjs version 1.0.2. I want to handle an LDAP 1.3.6.1.4.1.4203.1.11.1 extended operation (see RFC 3062 = LDAP Password Modify).

My server is configured...

   const server = ldapjs.createServer( ... );
   ...
   server.exop('1.3.6.1.4.1.4203.1.11.1', (req: any, res: any, next: any) => {
       const requestValue = req.requestValue;
   });

Calling the command ldappasswd (from debian package ldap-utils) works, handler method is called in proper way.

The data from the ldappasswd ... uid=user -A -S command with "old" as old password and "new" with new password results in the following hex values:

30 14 80 08 75 69 64 3d 73 75 72 66 81 03 6f 6c 64 82 03 6e 65 77
 0           u  i  d  =  u  s  e  r        o  l  d        n  e  w      

0x80 marks the beginning of the attribute, 0x81 the beginning of the old password, 0x82 the beginning of the new password. The value after this byte is the length, followed by the information itself.

The problem:
Inside the handler methode, requestValue is a string with invalid separator characters.

0uid=user�old�new

Converting the string to a buffer ( Buffer.from(req.reuqestValue ) results in:

<Buffer 30 14 ef bf bd 08 75 69 64 3d 75 73 65 72 ef bf bd 03 6f 6c 64 ef bf bd 03 6e 65 77>

The separator bytes 0x80, 0x81 and 0x82 are converted to ef bf bd and therefore parsing information fails, because type is lost.

Any idea how to get out the information values from the requestValue attribute?


Solution

  • The problem can be solved by installing the version next and using req.requestValueBuffer instead of req.requestValue:

    npm install --save ldapjs@next
    
       const server = ldapjs.createServer( ... );
       ...
       server.exop('1.3.6.1.4.1.4203.1.11.1', (req: any, res: any, next: any) => {
           const requestValue = req.requestValueBuffer;
       })
    

    The problem is caused by a bug in the current ldapjs master branch (ad451edc) in file lib/messages/ext_request.js line 61:

      this.requestName = ber.readString(0x80);
      if (ber.peek() === 0x81)
        try {
          this.requestValue = ber.readString(0x81);
        } catch (e) {
          this.requestValue = ber.readBuffer(0x81);
        }
    

    In case of ldappasswd data the readString() function is called (no exception thrown), and this function always converts the buffer to a string using UTF-8 decoding. That's wrong. An additional bug in this code snippet is the call of readBuffer(...) which doesn't exist on the object ber.

    In the branch next of the ldapjs repository this bug is solved by the bugfix in commit b87e4bb.

    Bugfix lib/messages/ext_request.js line 82:

      this.requestName = ber.readString(0x80)
      if (ber.peek() === 0x81) {
        this.requestValueBuffer = ber.readString(0x81, true)
        this.requestValue = this.requestValueBuffer.toString('utf8')
      }
    

    A handler method can now use req.requestValueBuffer to get the original request data bytes.