https://bugs.openldap.org/show_bug.cgi?id=10065
--- Comment #2 from sean@teletech.com.au --- ** Motivation **
slapd employs a very fine-grained access permission model with many permission categories that can be applied down to the attribute level. This is complex code that presents a very large attack surface to the network. Additionally, specifying access rules is complex and error prone.
In many cases, the ldap server will have only a few fixed clients and a much more coarse-grained approach can be taken to access control. This does not prevent fine grained controls but rather, summarily denies access to actors without valid credentials. It also dramatically reduces the attack surface available to unauthenticated actors. It also benefits from the greater scrutiny of the TLS code in the proxy (that is used to provide TLS security to a wide range of applications).
** Use Case **
+-------------+ | LDAP client |--+ +-------------+ | | haproxy slapd +-------------+ | ldaps +---------+ pldap +-------------+ | LDAP client |--+--------| proxy |---------| LDAP server | +-------------+ | +---------+ 127/8 +-------------+ | +-------------+ | | LDAP client |--+ +-------------+
** Implementation considerations **
Normally LDAP servers will not allow plaintext logins over unencrypted channels. The LDAP clients would expect the "PLAIN" and "EXTERNAL" mechanisms to be available after authenticating with TLS to the LDAP proxy. In a naive arrangement, the LDAP server would be unaware of the security provided by the proxy and would therfore, NOT offer "PLAIN" and "EXTERNAL" mechanisms.
But slapd is NOT naive. It supports the haproxy "Proxy Protocol V2". This protocol allows the proxy to send information to slapd about the LDAP client that has connected. This information would normally include the client's IP protocol and IP address. It may also include details of the encryption used. See "proxy-protocol.txt" section 2.2.6. (See references)
The information about encryption may not always be available however, so static configuration of slapd may also be advantagious.
** Security Considerations **
Access to the "pldap" port of the slapd server must be secured at the network level. Anyone able to access this port could impersonate a valid user without having their credentials.
One way this may be achieved is by configuring slapd to listen on the "localhost" address. As external machines are forbidden by the operating system to access this address, this will immediately restrict access to processes running on the same machine.
Alternately, the connections may be carried over a UNIX domain IPC socket. This is not currently supported by slapd.
As a third alternative, the slapd <-> proxy link may itself be encrypted with TLS using the "pldaps" scheme. This would however, have the undesirable side effect of erasing the "authid" provided by the proxy's TLS layer.
** SLAPD CHANGES REQUIRED **
Slapd employs the Cyrus-sasl library to implement the SASL functions of the LDAP service. The decision on which authentication mechanisms to offer is taken by the Cyrus-sasl library based on information provided by the application (i.e. slapd). In particular, Cyrus-sasl will offer the "EXTERNAL" authentication mechanism if slapd passes it an "authid" and it will offer the "PLAIN" authentication mechanism if slapd informs it that the connection is encrypted (this can be overridden).
The "EXTERNAL" mechanism
By default, slapd does not construct an authid, and so "EXTERNAL" authentication will not be offered. For "ldapi" scheme connections, slapd constructs an authid based on the socket name and user id. For "ldaps" scheme connections, slapd constructs an authid based on the certificate subject DN. See https://openldap.org/doc/admin26/sasl.html section 15.2.4 In these two cases, the "EXTERNAL" mechanism will be offered. For "pldap" scheme connections, slapd does NOT construct an authid.
** THIS SHOULD BE CONFIGURABLE **
For "pldap" scheme connections, the "EXTERNAL" mechanism will NOT be offered.
The "PLAIN" mechanism
By default, slapd specifies a "Security Strength Factor" (ssf) of zero. This informs Cyrus-sasl that the connection is not encrypted and the "PLAIN" mechanism should not be offered. For "ldapi" scheme connections, slapd specifes an ssf of "olcLocalSSF" from it's configuration or 71 if "olcLocalSSF" has not been set. For "ldaps" scheme connections, slapd queries the TLS layer for the encryption strength and sets the ssf as reported by the TLS layer. In these two cases, the "PLAIN" mechanism will be offered. For "pldap" scheme connections, slapd specifies an ssf of zero.
** THIS SHOULD BE CONFIGURABLE **
For "pldap" scheme connections, the "PLAIN" mechanism will NOT be offered.
** Looking at the code **
Below is an analysis of pertinent lines in the slapd source. The line numbers were taken from the Github mirror "https://github.com/openldap/openldap/blob/master/" at the time of writing.
We see in daemon.c. line 2290 where the "Proxy Protocol V2" information gets decoded. It is at this point that a decision should be made about the security properties of the link between the LDAP client and the proxy. The "authid" and "ssf" local variables should be set to reflect the security provided by the external proxy.
Two approaches could be taken, either: 1) Additional TLS related information in the protocol packet could be decoded and an "authid" constructed with that information. The ssf could also be derived from the reported ciphers. 2) An "authid" could be constructed from the IP address. As the address has been securely bound to the authentication credentials by the proxy TLS layer, this should be safe. The ssf could be provided in the slapd configuration in a similar manner to olcLocalSSF. Eg "olcProxySSF" ??
Project: OpenLAP/slapd...
servers/slapd/daemon.c:2101: slap_listener() { servers/slapd/daemon.c:2109: slap_ssf_t ssf = 0; /* "PLAIN" is NOT offered by default */ servers/slapd/daemon.c:2109: struct berval authid = BER_BVNULL; /* "EXTERNAL" is NOT offered by default */
servers/slapd/daemon.c:2247: case AF_LOCAL: servers/slapd/daemon.c:2259: slap_ssf_t ssf = local_ssf; /* "PLAIN" IS offered on AF_LOCAL */ servers/slapd/daemon.c:2272 sprintf( authid.bv_val, ... ) /* "EXTERNAL" IS offered on AF_LOCAL */
servers/slapd/daemon.c:2288: case AF_INET: servers/slapd/daemon.c:2289: if ( sl->sl_is_proxied ) { servers/slapd/daemon.c:2290: proxyp() servers/slapd/daemon.c:????: ssf = **FIXME** /* "PLAIN" MAY be desired here */ servers/slapd/daemon.c:????: authid = **FIXME** /* "EXTERNAL" MAY be desired here */
servers/slapd/daemon.c:2364: connection_init(,,,,, ssf , authid ,); servers/slapd/connection.c:307: connection_init(,,,,, ssf , authid ,) { servers/slapd/connection.c:535: slap_sasl_external( , ssf , authid ); servers/slapd/sasl.c:1482: sasl_setprop(, SASL_SSF_EXTERNAL, &sasl_ssf );
/* "PLAIN" and "EXTERNAL" for TLS */ servers/slapd/connection.c:1342: if ( c->c_is_tls ) { servers/slapd/connection.c:1343: ldap_pvt_tls_accept(,) servers/slapd/connection.c:1367: c->c_tls_ssf = (slap_ssf_t) ldap_pvt_tls_get_strength( ssl ); libraries/libldap/tls_o.c:1018: SSL_CIPHER_get_bits(SSL_get_current_cipher(s), NULL); servers/slapd/connection.c:1383: slap_sasl_external(, c->c_tls_ssf, &authid); servers/slapd/sasl.c:1482: sasl_setprop(, SASL_SSF_EXTERNAL, &sasl_ssf );
servers/slapd/root_dse.c:334: supportedSASLMechanisms = slap_sasl_mechs( conn ); servers/slapd/sasl.c:1538: slap_sasl_mechs() { servers/slapd/sasl.c:1551: sasl_listmech()
** References **
RFC4512 / 5.1 Specifies the "root DSE" and in particular "supportedSASLMechanisms" RFC4513 Specifies LDAP's use of SASL RFC4422 Specifies SASL http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt Haproxy, "Proxy Protocol V2" specification https://openldap.org/doc/admin26/sasl.html section 15.2.4