diff --git a/src/lib/ldap/client.ts b/src/lib/ldap/client.ts index bf08041..a6d34e9 100644 --- a/src/lib/ldap/client.ts +++ b/src/lib/ldap/client.ts @@ -61,25 +61,22 @@ function search( ): Promise<{ dn: string; attributes: Record }[]> { return new Promise((resolve, reject) => { const results: { dn: string; attributes: Record }[] = []; - // Paged (RFC 2696) rather than one unbounded response: a directory-wide - // browse on a real AD domain can return ~1000 entries, and ldapjs's - // single-response handling for a batch that size was observed to drop - // the connection (" closed") even though a plain `ldapsearch` with - // the identical filter completes cleanly — so the fix is on our client's - // response handling, not the query itself. ldapjs runs the multi-page - // RFC 2696 round-trips internally; callers still just see one continuous - // stream of `searchEntry` events followed by a single `end`. - // - // `attributes` is also restricted to just what callers actually read + // `attributes` is restricted to just what callers actually read // (mail/cn/displayName) instead of requesting every attribute AD has on - // an object. The real failure turned out to be @ldapjs/asn1's BER - // decoder throwing "Encoding too long" — a parser desync, most likely - // triggered while decoding some oversized/exotic AD attribute we never - // use anyway (e.g. nTSecurityDescriptor, msDS-ReplAttributeMetaData). - // Not requesting them sidesteps the bug entirely. + // an object. The original failure was @ldapjs/asn1's BER decoder + // throwing "Encoding too long" — a parser desync, most likely triggered + // while decoding some oversized/exotic AD attribute we never use anyway + // (e.g. nTSecurityDescriptor, msDS-ReplAttributeMetaData). Not requesting + // them sidesteps that bug entirely. + // + // Deliberately NOT using RFC 2696 paging here: with the response now + // this much smaller, an unpaged single request+response is simpler and + // matches what a plain `ldapsearch` against this same AD does — paging + // instead caused ldapjs's multiple sequential requests on one connection + // to get an ECONNRESET partway through. client.search( baseDn, - { filter, scope: "sub", paged: { pageSize: 200 }, attributes: ["mail", "cn", "displayName"] }, + { filter, scope: "sub", attributes: ["mail", "cn", "displayName"] }, (err, res) => { if (err) { reject(describeError(client, err));