ldapjs / node-ldapjs

LDAP Client and Server API for node.js
http://ldapjs.org
MIT License
1.6k stars 436 forks source link

Compatibility Issue Between ldapjs Library and FreeRADIUS #966

Open mirawara opened 7 months ago

mirawara commented 7 months ago

I've set up an LDAP server in Node.js using the ldapjs library, and it responds perfectly when using 'ldapsearch' as a tool. I attempted to configure FreeRADIUS to contact the LDAP server, the bind succeeds upon startup, and FreeRADIUS is ready to accept requests. Unfortunately, when I try with 'radtest,' the LDAP server crashes with the following error:

node:events:497
      throw er; // Unhandled 'error' event
      ^
VError: Parser error for 192.168.0.108:57296: attribute must be a valid string
    at Parser.<anonymous> (/home/node/app/node_modules/ldapjs/lib/server.js:459:26)
    at Parser.emit (node:events:519:28)
    at Parser.write (/home/node/app/node_modules/ldapjs/lib/messages/parser.js:131:10)
    at Socket.<anonymous> (/home/node/app/node_modules/ldapjs/lib/server.js:474:19)
    at Socket.emit (node:events:519:28)
    at addChunk (node:internal/streams/readable:559:12)
    at readableAddChunkPushByteMode (node:internal/streams/readable:510:3)
    at Readable.push (node:internal/streams/readable:390:5)
    at TCP.onStreamRead (node:internal/stream_base_commons:190:23)
Emitted 'error' event on Server instance at:
    at Parser.<anonymous> (/home/node/app/node_modules/ldapjs/lib/server.js:459:12)
    at Parser.emit (node:events:519:28)
    [... lines matching original stack trace ...]
    at TCP.onStreamRead (node:internal/stream_base_commons:190:23) {
  jse_shortmsg: 'Parser error for 192.168.0.108:57296',
  jse_cause: Error: attribute must be a valid string
      at set attributes [as attributes] (/home/node/app/node_modules/@ldapjs/messages/lib/messages/search-request.js:212:15)
      at new SearchRequest (/home/node/app/node_modules/@ldapjs/messages/lib/messages/search-request.js:158:21)
      at parseToMessage (/home/node/app/node_modules/@ldapjs/messages/lib/parse-to-message.js:61:19)
      at LdapMessage.parse (/home/node/app/node_modules/@ldapjs/messages/lib/ldap-message.js:262:41)
      at Parser.write (/home/node/app/node_modules/ldapjs/lib/messages/parser.js:117:38)
      at Socket.<anonymous> (/home/node/app/node_modules/ldapjs/lib/server.js:474:19)
      at Socket.emit (node:events:519:28)
      at addChunk (node:internal/streams/readable:559:12)
      at readableAddChunkPushByteMode (node:internal/streams/readable:510:3)
      at Readable.push (node:internal/streams/readable:390:5),
  jse_info: {},
  cause: [Function: ve_cause]
}

Debugging, I noticed that it only calls the bind function (with correct DN and password, as when I use ldapsearch), which I've written like this: server.bind(baseDn, async function (req, res, next) {. So, I tried to print req, res, and next to see the differences between the call with ldapsearch and the one coming from FreeRADIUS. Using 'diff,' I observed the variances and I don't see anything strange:

╰─❯ diff correct.txt wrong.txt 
93c93
<    _peername: { address: '192.168.0.108', family: 'IPv4', port: 50162 },
---
>    _peername: { address: '192.168.0.108', family: 'IPv4', port: 57296 },
95c95
<      id: '192.168.0.108:50162',
---
>      id: '192.168.0.108:57296',
109c109
<    [Symbol(async_id_symbol)]: 283,
---
>    [Symbol(async_id_symbol)]: 323,
128,129c128,129
<  logId: '192.168.0.108:50162::1',
<  startTime: 1707298757856,
---
>  logId: '192.168.0.108:57296::1',
>  startTime: 1707298790212,
221c221
<    _peername: { address: '192.168.0.108', family: 'IPv4', port: 50162 },
---
>    _peername: { address: '192.168.0.108', family: 'IPv4', port: 57296 },
223c223
<      id: '192.168.0.108:50162',
---
>      id: '192.168.0.108:57296',
237c237
<    [Symbol(async_id_symbol)]: 283,
---
>    [Symbol(async_id_symbol)]: 323,
256c256
<  logId: '192.168.0.108:50162::1',
---
>  logId: '192.168.0.108:57296::1',

Any advice? Did I misconfigure something, or is it a bug?

Thank you in advance.

mirawara commented 7 months ago

Update: freeradius should call the search first and then the bind; however, despite having implemented the search in my node application, it only calls the bind and then crashes. This is a behavior that the library has had since version 3.0.0 onwards. With version 2.3.3, on the other hand, it works perfectly. It doesn't crash and correctly calls the search first and then the bind. Currently, I'll stick to the old version but I'm hopeful for a fix. I would like to propose something to reproduce the error but unfortunately, I don't know how to do it.