From Fedora Project Wiki

OpenLDAP and MozNSS Compatibility Layer

Introduction

OpenLDAP in Fedora had been compiled with NSS (MozNSS, i.e. Mozilla Network Security Services) as a crypto library for several years. This effort was driven only by Fedora downstream and its derivatives. However, this implementation had not been optimal and for that it was later decided to move back to OpenSSL which is the preferred crypto library within OpenLDAP upstream community.

In order to make the transition to OpenSSL smoother for users of OpenLDAP it was decided to implement a mechanism which would allow to use NSS databases (which is the PKI store within NSS) while the actual crypto library used would be OpenSSL (which uses PEM files as a PKI store). This resulted in implementation of MozNSS Compatibility Layer (abbreviated TLSMC).

Lifespan

TLSMC is currently downstream only and it is currently not planned to spread it wider.

TLSMC has been introduced in Fedora 28 with an approval through a change proposal, before originally tracked in bugzilla, with openldap-2.4.45-4.fc28, at the same time compiling with OpenSSL instead of NSS.

TLSMC has been dropped in Fedora 29 with an approval through a change proposal, with openldap-2.4.45-9.fc29, and the change is effective as of this commit.

Building

In order to compile with TLSMC (given the patch is included) one has to run ./configure with --enable-moznss-compatibility=yes.

Configuration

One can control the runtime availability of TLSMC by setting the LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY to either LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY_ENABLED or LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY_DISABLED (the default in Fedora 28 is to enable it). The respective userspace options take values yes/true/on and no/false/off, and are the following:

  • ldap.conf(5) - TLS_MOZNSS_COMPATIBILITY
  • slapd.conf(5) - TLSMozNSSCompatibility
  • slapd-config(5) - olcTLSMozNSSCompatibility

Behavior

TLSMC is a routine which is executed each time just before new TLS context is created internally (specificaly at the beginning of ldap_int_tls_init_ctx). This routine tries to open an NSS database based on OpenLDAP's TLS_* parameters as it would do when built with NSS. If it succeeds to do so it tries to extract the user certificate, user private key, and CA certificates, then putting them in a uniquely created folder and setting the runtime TLS_* parameters to the values pointing to the newly created PEM files to be used by OpenSSL later on. If it fails to open the NSS database then it silently expects the configuration is in OpenSSL style. Finally, only OpenSSL continues to do its work.

Fingerprint data

In order to not extract the data from an NSS database every time the new TLS context is created the TLSMC creates a fingerprint of the state the current configuration represents. This fingerprint takes into account relevant TLS_* parameters, the effective UID of the POSIX user, and timestamps of the NSS database. These data represent the state which, when encountered next time, let the TLSMC know it does not have to extract the certificates again and that it can reuse the existent files if present. The fingerprint is stored in a README file. A hash of the fingerprint is then included in the name of the base folder.

Extracted data structure

The extracted data structure looks for example like this:

/tmp/openldap-tlsmc-nssdb-nopass--6FCBA2496C72F8F233D1D9943450965BCAC06902131799DD62645BC60D420A2C/
├── cacerts
│   ├── cert0.pem
│   └── ee8c0644.0 -> cert0.pem
├── cert.pem
├── key.pem
└── README

The base directory is always located in the /tmp folder and its name is built with the following template: openldap-tlsmc-<nss-db-dir-name>-<nss-db-prefix>-<fingerprint-hash>. The cacerts subdirectory contains extracted trusted CA certificates and follows the OpenSSL rehash format (see openssl-rehash(1)). The README file contains unique data the fingerprint hash is created from. The rest of the files should be self-explanatory.

Permissions of the files are set so that only user that created them can actually access them. This should prevent private information leakage.

Known issues

The issues listed here exhibit themselves mostly when the configuration is not correct. Therefore, the fix is generally to correct the configuration. However, they are listed here in case one stumbles upon them so that they are easily recognized.

Fail to configure TLS in cn=config with incosistent TLS setup

It has been noticed that when e. g. one tries to configure olcTLSCertificateFile with one change record and the olcTLSCertificateKeyFile with another change record, the slapd fails to set up a new TLS context in between the two operations. This is due to the difference in when the crypto libraries create new context: MozNSS does so effectively on a new connection, OpenSSL does so as soon as possible (e. g. at the slapd's startup or, here, when a change in configuration occurs). Therefore, it is recommended to change the setup in one change record, like so:

dn: cn=config
changetype: modify
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/server.crt.pem
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/server.key.pem

Handling of incorrect CA certificates setups

Previously with MozNSS, OpenLDAP was more tolerant to incorrect configurations.

MozNSS implementation did not mind using certificates from TLS_CACERTDIR as long as they were present in PEM format in the directory; the usage of OpenSSL rehash as described in the respective manual pages was rather a very loose requirement. OpenSSL uses the features brought by the rehash algorithm extensively and fails when the folder does not respect the format.

The very similar behaviour was seen with the TLS_CACERT option where MozNSS would ignore inability to load CA certificates from the configured path, and it would continue trying to load them from the TLS_CACERTDIR location. This is not the case with OpenSSL and all the TLS-related options should be configured correctly.

slapd fails to start when TLS is misconfigured

Previously with MozNSS, slapd did not fail at the startup when the TLS was misconfigured in a way that prohibits it to create a TLS context, rather a secure ldaps port would be open and listening, and any new connection would immediately fail due to inability to create a new TLS context at the connection's creation. As the TLS context is created on the slapd's startup, now, the failure to setup the TLS context causes the slapd process to quit early.