jeremycx / node-LDAP

LDAP binding for node.js
MIT License
221 stars 43 forks source link

Allow you to specify a ca certificate file #118

Open jjhoughton opened 5 years ago

jjhoughton commented 5 years ago
A lot of firms will use their own Certificate Authority on their
internal network. When using such a setup previously the only
option was to turn certificate validation off.

reference https://linux.die.net/man/3/ldap_set_option

This patch was originall written by James Moxon and was taken
from here: https://github.com/jjhoughton/napi-ldap/pull/1

NOTE: The string gets duplicated when calling ldap_set_option so
NOTE: there should be no use after free errors.

openldap-2.4.48/libraries/libldap/tls2.c: 761
    case LDAP_OPT_X_TLS_CACERTFILE:
        if ( lo->ldo_tls_cacertfile ) LDAP_FREE( lo->ldo_tls_cacertfile );
        lo->ldo_tls_cacertfile = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL;
        return 0;

Signed-off-by: James Moxon <jameswmoxon@gmail.com>
Signed-off-by: Joshua Houghton <joshua.houghton@yandex.ru>
Reviewed-by: SteveJM
jjhoughton commented 5 years ago

Didn't mean to do a pull against this repo just yet will reopen once i've tested it

jeremycx commented 5 years ago

The intended way of handling a custom root CA is to use the system-wide mechanism to add teh root CA (follow the instructions that accompany all the other libldap tools). If you can get the command line ldapsearch to connect with your LDAP server, then node-ldap will do so as well.

jjhoughton commented 4 years ago

yes I couldn't get this to work for some reason. Even with a legit (non self signed) cert from go daddy

TLSMC: MozNSS compatibility interception begins.
tlsmc_intercept_initialization: INFO: entry options follow:
tlsmc_intercept_initialization: INFO: cacertdir = `(null)'
tlsmc_intercept_initialization: INFO: certfile = `(null)'
tlsmc_intercept_initialization: INFO: keyfile = `(null)'
tlsmc_convert: INFO: trying to open NSS DB with CACertDir = `(null)'.
tlsmc_convert: INFO: cannot open the NSS DB, expecting PEM configuration is present.
tlsmc_intercept_initialization: INFO: altered options follow:
tlsmc_intercept_initialization: INFO: cacertdir = `(null)'
tlsmc_intercept_initialization: INFO: certfile = `(null)'
tlsmc_intercept_initialization: INFO: keyfile = `(null)'
tlsmc_intercept_initialization: INFO: successfully intercepted TLS initialization. Continuing with OpenSSL only.
TLSMC: MozNSS compatibility interception ends.
ldap_simple_bind
ldap_sasl_bind
ldap_send_initial_request
ldap_new_connection 1 1 0
ldap_int_open_connection
ldap_connect_to_host: TCP ldap.jumpcloud.com:636
ldap_new_socket: 17
ldap_prepare_socket: 17
ldap_connect_to_host: Trying 52.29.98.95:636
ldap_pvt_connect: fd: 17 tm: 1 async: 0
ldap_ndelay_on: 17
attempting to connect: 
connect errno: 115
ldap_int_poll: fd: 17 tm: 1
ldap_is_sock_ready: 17
ldap_ndelay_off: 17
ldap_pvt_connect: 0
TLS trace: SSL_connect:before/connect initialization
TLS trace: SSL_connect:SSLv2/v3 write client hello A
TLS trace: SSL_connect:error in SSLv2/v3 read server hello A
ldap_int_tls_start: ldap_int_tls_connect needs read
ldap_int_poll: fd: 17 tm: 1
ldap_is_sock_ready: 17
ldap_ndelay_off: 17
TLS trace: SSL_connect:unknown state
TLS certificate verification: depth: 3, err: 19, subject: /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority, issuer: /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
TLS certificate verification: Error, self signed certificate in certificate chain
TLS trace: SSL3 alert write:fatal:unknown CA
TLS trace: SSL_connect:error in error
TLS trace: SSL_connect:error in error
TLS: can't connect: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed (self signed certificate in certificate chain).
ldap_err2string
ldap_err2string
ldap_result ld 0x34c47c0 msgid -1
wait4msg ld 0x34c47c0 msgid -1 (timeout 0 usec)
wait4msg continue ld 0x34c47c0 msgid -1 all 1
** ld 0x34c47c0 Connections:
** ld 0x34c47c0 Outstanding Requests:
   Empty
  ld 0x34c47c0 request count 0 (abandoned 0)
** ld 0x34c47c0 Response Queue:
   Empty
  ld 0x34c47c0 response count 0

This was using your library

jjhoughton commented 4 years ago

Have you ever managed to get this working yourself? Maybe it's the build of node I'm using but certificate validation doesn't seem to be working correctly. I know if I make a https request it works fine. I'm using centos7 and node 8

jeremycx commented 4 years ago

This is the important part of the error above:

TLS trace: SSL3 alert write:fatal:unknown CA

You need to install the root CA cert for GoDaddy globally for the machine. This is an openSSL thing - a couple of quick searches will find instructions for doing this.

In short, if you can't run ldapsearch successfully on the command line, then you're not done yet :)

This binding uses openldap libraries, which are linked to your openSSL libraries, so openSSL rules are in effect.

jeremycx commented 4 years ago

Further, don't get confused: this cert error has nothing to do with node, https, or anything other then libopenldap (which is linked to openssl's libssl). Get openldap working, then this node binding will start working.

jjhoughton commented 4 years ago

Hi Jeremy

Really appreciate your time replying to the ticket.

We have tried openssl s_client -connect ldap.jumpcloud.com:636 and that gives a 'Verify return code: 0 (ok)' which is fine.

We also tried ldapsearch without any issues. You can see in the output below that some tls things get populated which don't get populated in node-LDAP.

tlsmc_intercept_initialization: INFO: entry options follow:
tlsmc_intercept_initialization: INFO: cacertdir = `/etc/openldap/certs'
tlsmc_intercept_initialization: INFO: certfile = `(null)'
tlsmc_intercept_initialization: INFO: keyfile = `(null)'
tlsmc_convert: INFO: trying to open NSS DB with CACertDir = `/etc/openldap/certs'.
tlsmc_open_nssdb: INFO: trying to initialize moznss using security dir `/etc/openldap/certs` prefix ``.
tlsmc_open_nssdb: INFO: initialized MozNSS context.
tlsmc_convert: INFO: trying with PEM dir = `/tmp/openldap-tlsmc-certs--556FC2A737AA21158119CB3F5FD41F2F0DC095F3909B5CA12DAD520084FEAB2E'.

compared with the logs from node-LDAP

tlsmc_intercept_initialization: INFO: entry options follow:
tlsmc_intercept_initialization: INFO: cacertdir = `(null)'
tlsmc_intercept_initialization: INFO: certfile = `(null)'
tlsmc_intercept_initialization: INFO: keyfile = `(null)'
tlsmc_convert: INFO: trying to open NSS DB with CACertDir = `(null)'.
tlsmc_convert: INFO: cannot open the NSS DB, expecting PEM configuration is present.
tlsmc_intercept_initialization: INFO: altered options follow:
tlsmc_intercept_initialization: INFO: cacertdir = `(null)'
tlsmc_intercept_initialization: INFO: certfile = `(null)'
tlsmc_intercept_initialization: INFO: keyfile = `(null)'
tlsmc_intercept_initialization: INFO: successfully intercepted TLS initialization. Continuing with OpenSSL only.
TLSMC: MozNSS compatibility interception ends.

We have tried this on a fresh installed box too in case the certs had been tampered with, but we are facing the same issue. It is odd that nobody has reported problems with certs signed by a root CA so we think it is probably something in our environment. Have you had this working yourself?

Kind regards

Josh

jeremycx commented 4 years ago

Been using it for years using global configuration (which is quite valuable as it synchronizes login/authentication with ldapsearch with node. Looks like a bunch of stuff is different with your installation however.

This is new to me: https://fedoraproject.org/wiki/OpenLDAP-and-MozNSS-Compatibility-Layer

SO - the trick here is to get the debug output for

tlsmc_intercept_initialization: INFO: cacertdir =(null)' to read tlsmc_intercept_initialization: INFO: cacertdir = /etc/openldap/certs'

I'd try meddling with some env vars to see if you can get the aboive to change:

bash$ SSLCACERTDIR=/etc/openldap/certs node testfile.js OR bash$ SSL_CERT_DIR=/etc/openldap/certs node testfile.js

jjhoughton commented 4 years ago

Hi Jeremy,

We have previously tried those environment variables plus those listed in the man page for ldap.conf (TLS_*) but none seem to have an effect in node. We just tried it on a fresh install and they still appear as (null).

Installed Packages Name : openldap Arch : x86_64 Version : 2.4.44 Release : 20.el7

Out of interest how to does compare to the version and operating system you are using?

Josh

jeremycx commented 4 years ago

FreeBSD/openLDAP

I think the main issue is that it's now MozNSS under the hood for you, and the behaviour has changed. I'm always loathe to add multiple ways of doing the same thing, but in this case, since we're backed into a corner, let's do the pull request above.

jjhoughton commented 4 years ago

FreeBSD/openLDAP

I think the main issue is that it's now MozNSS under the hood for you, and the behaviour has changed. I'm always loathe to add multiple ways of doing the same thing, but in this case, since we're backed into a corner, let's do the pull request above.

So not even Linux! I agree with you it's not ideal. I'd like to do some investigation first as to why it's not working now that I know it's working on BSD. If I can't figure out why I'll test the above pr and get it ready for merging as I still haven't tested it yet. This was why I closed it originally.