node-ldapjs icon indicating copy to clipboard operation
node-ldapjs copied to clipboard

How do i create a control

Open geoffginley opened this issue 9 years ago • 14 comments

I'm trying to reset PWD in AD while honoring password history. I'm using this article as reference. AD requires that I pass a control (1.2.840.113556.1.4.2239 or 1.2.840.113556.1.4.2066) with the modification for a reset (replace not delete/add - no original pwd).

My first question is do I use a regular Control or ServerSideSortingRequestControl? I'm guessing the later, either way when I try to create the control i get various errors.

The latest error is 'Missing required key: attributeType'

//var pwdhint = new ldap.Control({
var pwdhint = new ldap.ServerSideSortingRequestControl({
    type: "1.2.840.113556.1.4.2239",
    criticality: false,
    value: value
});  
client.modify('CN=Test,OU=Users,DC=Domain,DC=com', 
    new ldap.Change({
        operation: 'replace',
        modification: {
            unicodePwd: encodePassword(newPassword)
        }
    }), pwdhint, function(result, error){
        if (error) (console.log(error));
        console.log(result);
    });

And my second question is how do I create the "value" parameter. No matter how I create I get a TypeError. This says it should be a byte array and the previous article I referenced said the value should be "0x1"

If I pass the control without specifying the value it appears that the control is ignored. As PWD history is ignored and the ModifyResponse.controls is empty

Would appreciate some help

geoffginley avatar Jun 11 '16 12:06 geoffginley

Have you had any luck with this? I too am trying to do a password reset tool that respects the password history rules

jkramp avatar Aug 17 '16 13:08 jkramp

I was never able to successfully create the control so I took a different approach.

First i prompt user for there existing password and if they have it i do...

client.modify(usrRes[0].distinguishedName, [ new ldap.Change({ operation: 'delete', modification: { unicodePwd: encodePassword(oldpwd) } }), new ldap.Change({ operation: 'add', modification: { unicodePwd: encodePassword(newpwd) } }) ], function(err){ error handler} });

Second, which is very hacky, I prompt for some other method to authenticate them. Then I generate a password set it and set it as I do above. Then I change it using below

client.modify(usrRes[0].distinguishedName, [ new ldap.Change({ operation: 'replace', modification: { unicodePwd: encodePassword(newpwd) } }), new ldap.Change({ operation: 'replace', modification: { lockoutTime: 0 } }) ], function(err){ error handler} });

Now if you have policy for max password change in x days, you will have to set it to 0 or alternatively have to do this which again is very hacky.

client.modify(usrRes[0].distinguishedName, [ new ldap.Change({ operation: 'replace', modification: { pwdLastSet: 0 } }) ], function(err){ error handler} });

geopgin avatar Aug 17 '16 16:08 geopgin

Thanks for the quick feedback. I kind of like your 'hacky' method. Its simple and achieves the desired result. Cheers.

jkramp avatar Aug 17 '16 17:08 jkramp

This project appears to be abandoned, which is a shame with no real alternatives to LDAP for nodejs.

geopgin avatar Aug 17 '16 17:08 geopgin

It is disappointing that neither the docs nor the issue tracker appear to have a working example of a Control.

kylecordes avatar Sep 08 '17 20:09 kylecordes

For anyone who comes here for a solution on controls. This is currently working with my environment. We were tested everything using idsldapmodify with -k before implementing the connection with ldapjs. This control type is for that (-k) functionality. You can replace it with whatever you need.

let controls = new ldap.Control({
  type: "1.3.18.0.2.10.15",
  criticality: true
});

client.bindAsync(dn, password, controls);

Another thing that might pop up is the issue with AssertionError. I commented out L22-L29 in node_modules/assert-plus/assert.js:

function _toss(name, expected, oper, arg, actual) {
    // throw new assert.AssertionError({
    //     message: util.format('%s (%s) is required', name, expected),
    //     actual: (actual === undefined) ? typeof (arg) : actual(arg),
    //     expected: expected,
    //     operator: oper || '===',
    //     stackStartFunction: _toss.caller
    // });
}

Note: I also used bluebird's Promise.promisifyAll() on my client. Which is probably why there's no callback in my sample.

nomoney4me avatar Aug 27 '19 22:08 nomoney4me

We could use some documentation for creating controls. It probably wouldn't be much more than @nomoney4me has already written. A PR would be welcome.

jsumners avatar Aug 27 '19 22:08 jsumners

I tried all kind of ways to use controls but none of them worked so far. could you please provide a working example?

saostad avatar Apr 10 '20 20:04 saostad

I tried all kind of ways to use controls but none of them worked so far. could you please provide a working example?

It's not possible to help you if you do not give any indication of what you are attempting what the result of the attempt it. As stated above, https://github.com/ldapjs/node-ldapjs/issues/381#issuecomment-525503221 is a pretty good explanation. What about it does not work for you?

jsumners avatar Apr 10 '20 22:04 jsumners

this is my code:

import { Control } from "ldapjs";
const myControl = new Control({
    type: "1.2.840.113556.1.4.473",
    criticality: true,
  });

but this doesn't work with error:

'Control' only refers to a type, but is being used as a value here.

54   const myControl = new Control({

so I changed my import to

import { Control } from "ldapjs/lib/controls/";
const myControl = new Control({
    type: "1.2.840.113556.1.4.473"
  });

import works but when I tried to give it value

const myControl = new Control({
    type: "1.2.840.113556.1.4.473",
    value: "cn"
  });

it gives me error:

AssertionError [ERR_ASSERTION]: undefined (buffer) is required
    at new Control 

saostad avatar Apr 11 '20 02:04 saostad

I cannot help you with transpiled code.

The final error is stating that you have not given the control a valid value.

jsumners avatar Apr 11 '20 03:04 jsumners

could you please provide an example of how to use control with value? like server side sort base on field 'cn' descending?

saostad avatar Apr 11 '20 19:04 saostad

I have never directly crafted a control as I have never had a need to do so. You should look through the source code and the tests. Notice that this issue has a "help wanted" label on it.

jsumners avatar Apr 12 '20 12:04 jsumners

Probably this is a bug in library. here is the spec of how it should work https://tools.ietf.org/html/rfc4511#section-4.1.11

saostad avatar Apr 12 '20 22:04 saostad

👋

On February 22, 2023, we released version 3 of this library. As a result, we are closing this issue/pull request.

Please see issue #839 for more information, including how to proceed if you feel this closure is in error.

jsumners avatar Feb 22 '23 19:02 jsumners