Skip to content
This repository was archived by the owner on May 14, 2024. It is now read-only.
This repository was archived by the owner on May 14, 2024. It is now read-only.

Support for SyncRequestControl #952

Open

Description

@its-sami

I'd like to use a Sync Operation as defined here, which provides similar functionality to a persistent search but is supported by OpenLDAP.

Currently, the client fails after the initial response from the server with error IntermediateResponse. What would it take to support this operation, and are there any plans to do so?

I'm using ldapjs v3.0.4

Example code:

const client = ldap.createClient({
  url: bindURL,
});

client.bind(bindDN, bindPassword, (err) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log('bind success');

  client.search(searchDN, {scope: 'base'}, new SyncRequestControl({value: {mode: 3}}), (err, res) => {
    if (err) {
      console.error(err);
      return;
    }

    res.on('searchRequest', ({ messageId, protocolOp, controls }) => {
      console.log(`searchRequest: messageId=${messageId}, protocolOp=${protocolOp}, controls=${controls.map(c => c.type)}`);
    });
    res.on('searchEntry', ({messageID, protocolOp, controls}) => {
      console.log(`entry: messageId=${messageID}, protocolOp=${protocolOp}, controls=${controls.map(c => c.type)}`);
    });
    res.on('searchReference', (referral) => {
      console.log('referral: ' + referral.uris.join());
    });
    res.on('error', (err) => {
      console.error(`error: ${err.name}, ${err.message}, [${err.code}]`);
      client.unbind();
    });
    res.on('end', (result) => {
      console.log('status: ' + result.status);
      client.unbind((err) => {
        if (err) {
          console.error(err);
          return;
        }
        console.log('unbind success');
      });
    });
  });
});

class SyncRequestControl extends Control {
  static OID = '1.3.6.1.4.1.4203.1.9.1.1';

  _value: any;

  constructor(options: any = {}) {
    options.type = SyncRequestControl.OID;
    super(options);

    if (!options.value) {
      return;
    }

    if (typeof options.value === 'object') {
      this._value = options.value;
    } else {
      // TODO check if actually a buffer
      this.parse(options.value);
    }
  }

  get value() {
    return this._value;
  }

  set value(value) {
    this._value = {...value};
  }

  private parse(ber: Buffer) {
    throw new Error('Not implemented');
  }

  _toBer (ber) {
    const writer = new BerWriter();

    writer.startSequence();
    writer.writeInt(this._value.mode, 0x0a);
    writer.endSequence();

    ber.writeBuffer(writer.buffer, 0x04)
    return ber
  }
}

Example output

> bind success
> searchRequest: messageId=2, protocolOp=99, controls=1.3.6.1.4.1.4203.1.9.1.1
> entry: messageId=2, protocolOp=100, controls=1.3.6.1.4.1.4203.1.9.1.2
> error: ProtocolError, IntermediateResponse, [2]

Activity

  1. jsumners commented on Nov 9, 2023

    @jsumners
    Member

    What I can say based upon your findings is that you're getting a message back from the server that is hitting the branch https://github.com/ldapjs/messages/blob/b73f34bc3769210af4b5805ef8d06c89d3e456ca/lib/parse-to-message.js#L198

    This meshes with the RFC you linked. See https://www.rfc-editor.org/rfc/rfc4533#section-2.5

    Thus, there will need to be some work done to recognize the message and handle it correctly. This is noted in https://github.com/ldapjs/messages/blob/b73f34bc3769210af4b5805ef8d06c89d3e456ca/lib/messages/intermediate-response.js#L26-L36

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions