Node-ldapjs: LDAPS (ldap over ssl) working with ssl certificates

Created on 12 Oct 2015  路  12Comments  路  Source: ldapjs/node-ldapjs

hi all,

i have generated self-signed certificate and i have used following code snippet to access certificates on same machine while using ldaps:///

var tlsOptions = {
// This is necessary only if the server uses the self-signed certificate
ca: [ fs.readFileSync('/etc/ldap/cacert.pem') ]
};

var ldap = require('ldapjs');
var client = ldap.createClient({url: 'ldaps://plat.com:636',tlsOptions: tlsOptions});

this works fine if the ldap server and certificate are on same machine, but it fails if the ldap server is on remote machine.

any help/guidance regarding such issue?

question help-wanted documentation

Most helpful comment

Hi pfmooney!

I have spent a lot of time discovering the solution. The following code works fine in my case. Just wanted a little bit guidance. Please have a look on following code and tell me is it the correct approach?

//Server.js file

var fs = require('fs');
var tls = require('tls');

var tlsOptions = {
key: fs.readFileSync('/etc/ldap/serverkey.pem'),
cert: fs.readFileSync('/etc/ldap/servercrt.pem'),
requestCert: true,
rejectUnauthorized: true,
ca: [ fs.readFileSync('/etc/ssl/certs/cacert.pem') ]
};

var server = tls.createServer(tlsOptions, function(socket) {
console.log(socket.getPeerCertificate());
console.log('client connected', socket.authorized ? 'authorized' : 'unauthorized');
socket.write("welcome Client!\n");
socket.setEncoding('utf8');
socket.pipe(socket);
});
server.on('data',function(data){
console.log(data);
});
server.on('uncaughtException', function(error) {
console.log('error ',error);
});
server.listen(8002, function() {
console.log('server bound');
});

//Client.js file

var fs = require('fs');
var tls = require('tls');
var ldap = require('ldapjs');

var tlsOptions = {
host: 'plat.com',
key: fs.readFileSync('/etc/mycerts/clientkey.pem'),
cert: fs.readFileSync('/etc/mycerts/clientcrt.pem'),
ca: fs.readFileSync('/etc/ssl/certs/cacert.pem')
};

var server = tls.connect(8002,tlsOptions,function() {
console.log('tls connect');
console.log('client connected', server.authorized ? 'authorized' : 'unauthorized');
process.stdin.resume();
process.stdin.pipe(server);

    if ( server.authorized )
    {
            var client = ldap.createClient({url: 'ldaps://plat.com:636',tlsOptions:tlsOptions});
            client.bind(dn, password, function (err) {
            cb(err === null, err);
            });

//Perform LDAP search operation
var opts = {
filter: '(&(objectclass=organizationalRole))',
scope: 'sub',
attributes: ['cn'] };

            client.search('dc=plat,dc=com', opts, function(err, res) {
            res.on('searchEntry', function(entry) {
                          console.log('entry: ' + JSON.stringify(entry.object));
            });
            res.on('searchReference', function(referral) {
                          console.log('referral: ' + referral.uris.join());
            });
            res.on('error', function(err) {
                         console.error('error: ' + err.message);
            });
            res.on('end', function(result) {
                        console.log('status: ' + result.status);
            });
       });
  }

});
server.setEncoding('utf8');
server.on('data',function(data){
console.log('data section: ',data);
});

server.on('secureConnect',function(data){
console.log('secure connect section: ',data);
});

server.on('error', function(error) {
console.log('client closing...',error);
});

All 12 comments

Because ldapjs uses the tls.TLSSocket/tls.TLSServer API for TLS sockets, I would suggest looking to that documentation in order to interpret any errors you may be observing.

Thanks prmooney.

can you please give some examples how to start TLS in ldap. Because i spent much time starting TLS but i was not successful. But LDAP with SSL was successfully working for me. That's why i chose ssl.

And also it was working fine with the above code snippet on same machines.

I'm stuck at this problem for days. Please guide me

I would suggest starting with the node.js documentation on TLS.

yes i have followed the documentation

https://nodejs.org/api/tls.html

Also tried following code snippet and other combinations as well

var tls = require('tls');
var fs = require('fs');

var options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),

// This is necessary only if using the client certificate authentication.
requestCert: true,

// This is necessary only if the client uses the self-signed certificate.
ca: [ fs.readFileSync('client-cert.pem') ]
};

var server = tls.createServer(options, function(socket) {
console.log('server connected',
socket.authorized ? 'authorized' : 'unauthorized');
socket.write("welcome!\n");
socket.setEncoding('utf8');
socket.pipe(socket);
});
server.listen(8000, function() {
console.log('server bound');
});

But get the exception i.e.,
events.js:72
throw er; // Unhandled 'error' event
^
Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE
at SecurePair. (tls.js:1370:32)
at SecurePair.EventEmitter.emit (events.js:92:17)
at SecurePair.maybeInitFinished (tls.js:982:10)
at CleartextStream.read as _read
at CleartextStream.Readable.read (_stream_readable.js:320:10)
at EncryptedStream.write as _write
at doWrite (_stream_writable.js:223:10)
at writeOrBuffer (_stream_writable.js:213:5)
at EncryptedStream.Writable.write (_stream_writable.js:180:11)
at write (_stream_readable.js:583:24)

I'm continuously getting below error:

events.js:72
throw er; // Unhandled 'error' event
^
Error: socket hang up
at SecurePair.error (tls.js:1013:23)
at EncryptedStream.CryptoStream._done (tls.js:705:22)
at CleartextStream.read as _read
at CleartextStream.Readable.read (_stream_readable.js:320:10)
at EncryptedStream.onCryptoStreamFinish (tls.js:301:47)
at EncryptedStream.g (events.js:180:16)
at EncryptedStream.EventEmitter.emit (events.js:117:20)
at finishMaybe (_stream_writable.js:356:12)
at endWritable (_stream_writable.js:363:3)
at EncryptedStream.Writable.end (_stream_writable.js:341:5)

Following is my server-side code:

var tlsOptions= {
key: fs.readFileSync('/home/aneela/client-ldapjs/serverkey.pem'),
cert: fs.readFileSync('/home/aneela/client-ldapjs/servercrt.pem'),
requestCert: true,
// This is necessary only if the server uses the self-signed certificate
rejectUnauthorized: true,
ca: [ fs.readFileSync('/etc/ldap/servercrt.pem') ]
};

var server = tls.createServer(tlsOptions, function(socket) {
console.log('client connected', socket.authorized ? 'authorized' : 'unauthorized');
process.stdin.resume();
process.stdin.pipe(server);
});
server.listen(8001, function() {
console.log('server bound');
});

Following is my client-side code:
var tlsOptions = {
// These are necessary only if using the client certificate authentication
key: fs.readFileSync('/etc/ldap/serverkey.pem'),
cert: fs.readFileSync('/etc/ldap/servercrt.pem'),
ca: CAcerts, //where CAcerts is the certificate chain
requestCert: true,
rejectUnauthorized: true
};

var server = tls.connect(8001,tlsOptions, function() {

    console.log('client connected', server.authorized ? 'authorized' : 'unauthorized');
    if(!server.authorized) {
console.log("authorizationError: " + server.authorizationError);

}
process.stdin.resume();
process.stdin.pipe(server);
});

server.setEncoding('utf8');
server.on('data',function(data){
console.log(data);
});
server.on('end', function() {
console.log('client closing...');
server.close();
});

Hi pfmooney!

I have spent a lot of time discovering the solution. The following code works fine in my case. Just wanted a little bit guidance. Please have a look on following code and tell me is it the correct approach?

//Server.js file

var fs = require('fs');
var tls = require('tls');

var tlsOptions = {
key: fs.readFileSync('/etc/ldap/serverkey.pem'),
cert: fs.readFileSync('/etc/ldap/servercrt.pem'),
requestCert: true,
rejectUnauthorized: true,
ca: [ fs.readFileSync('/etc/ssl/certs/cacert.pem') ]
};

var server = tls.createServer(tlsOptions, function(socket) {
console.log(socket.getPeerCertificate());
console.log('client connected', socket.authorized ? 'authorized' : 'unauthorized');
socket.write("welcome Client!\n");
socket.setEncoding('utf8');
socket.pipe(socket);
});
server.on('data',function(data){
console.log(data);
});
server.on('uncaughtException', function(error) {
console.log('error ',error);
});
server.listen(8002, function() {
console.log('server bound');
});

//Client.js file

var fs = require('fs');
var tls = require('tls');
var ldap = require('ldapjs');

var tlsOptions = {
host: 'plat.com',
key: fs.readFileSync('/etc/mycerts/clientkey.pem'),
cert: fs.readFileSync('/etc/mycerts/clientcrt.pem'),
ca: fs.readFileSync('/etc/ssl/certs/cacert.pem')
};

var server = tls.connect(8002,tlsOptions,function() {
console.log('tls connect');
console.log('client connected', server.authorized ? 'authorized' : 'unauthorized');
process.stdin.resume();
process.stdin.pipe(server);

    if ( server.authorized )
    {
            var client = ldap.createClient({url: 'ldaps://plat.com:636',tlsOptions:tlsOptions});
            client.bind(dn, password, function (err) {
            cb(err === null, err);
            });

//Perform LDAP search operation
var opts = {
filter: '(&(objectclass=organizationalRole))',
scope: 'sub',
attributes: ['cn'] };

            client.search('dc=plat,dc=com', opts, function(err, res) {
            res.on('searchEntry', function(entry) {
                          console.log('entry: ' + JSON.stringify(entry.object));
            });
            res.on('searchReference', function(referral) {
                          console.log('referral: ' + referral.uris.join());
            });
            res.on('error', function(err) {
                         console.error('error: ' + err.message);
            });
            res.on('end', function(result) {
                        console.log('status: ' + result.status);
            });
       });
  }

});
server.setEncoding('utf8');
server.on('data',function(data){
console.log('data section: ',data);
});

server.on('secureConnect',function(data){
console.log('secure connect section: ',data);
});

server.on('error', function(error) {
console.log('client closing...',error);
});

Hi @aneelaSaleem @pfmooney Were you able to get a final solution for this? I am also facing a similar issue.

Please use backticks for syntax highlighting, it's much easier to read

```js
your code goes here
```

I'm sorry to bump this, but I am still unable to use the createClient to connect to an OpenLDAP server using a certificate key:crt pair. I've been looking for days and trying so many ways of doing this, and I still am unable to get anything to work. Can someone please give a concrete example of how this works using this API? The documentation doesn't even cover the basics. I've also looked at the source code and I can't really make out how it is handled either. I'm out of options here...

Had a similar issue here but solved it by https://github.com/ldapjs/node-ldapjs/issues/229

Unsure though if that's satisfactory for you, since it doesn't involve actually using certificates, though it does connect to a secure LDAPS server successfully with

tlsOptions = { 'rejectUnauthorized': false }

The LDAPS server I am talking to seems to accept this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

djholly123 picture djholly123  路  3Comments

atiertant picture atiertant  路  6Comments

gdw2 picture gdw2  路  3Comments

jjayaraman picture jjayaraman  路  5Comments

ivanhuay picture ivanhuay  路  5Comments