--
Hello.
The following patch against src/lookups/ldap.c makes it possible to use
ldap connections over ssl (with startssl or direct ssl connection with
ldaps://). For this you must have openldap-2 or greater.
Christian Boye
--
--- ldap.c.orig Wed Dec 19 12:50:29 2001
+++ ldap.c Sat Jan 5 19:21:39 2002
@@ -13,6 +13,9 @@
#include "../exim.h"
#include "ldap.h"
+#if LDAP_VENDOR_VERSION > 20000
+#define OPENLDAP2
+#endif
/* We can't just compile this code and allow the library mechanism to omit the
functions if they are not wanted, because we need to have the LDAP headers
@@ -117,6 +120,7 @@
password password for authentication, or NULL
sizelimit max number of entries returned, or 0 for no limit
timelimit max time to wait, or 0 for no limit
+ starttls use starttls mechanism for ldap connection
Returns: OK or FAIL or DEFER
FAIL is given only if a lookup was performed successfully, but
@@ -126,7 +130,7 @@
static int
perform_ldap_search(char *ldap_url, char *server, int s_port, int search_type,
char **res, char **errmsg, BOOL *defer_break, char *user, char *password,
- int sizelimit, int timelimit)
+ int sizelimit, int timelimit, int starttls)
{
LDAPURLDesc *ludp = NULL;
LDAPMessage *result;
@@ -155,10 +159,10 @@
DEBUG(9)
debug_printf("perform_ldap_search: ldap%s URL =\"%s\" server=%s port=%d "
- "sizelimit=%d timelimit=%d\n",
+ "sizelimit=%d timelimit=%d starttls=%d\n",
(search_type == SEARCH_LDAP_MULTIPLE)? "m" :
(search_type == SEARCH_LDAP_DN)? "dn" : "",
- ldap_url, server, s_port, sizelimit, timelimit);
+ ldap_url, server, s_port, sizelimit, timelimit, starttls);
/* Check if LDAP thinks the URL is a valid LDAP URL */
@@ -220,7 +224,8 @@
if (lcp == NULL)
{
- LDAP *ld = ldap_open(host, (port != 0)? port : LDAP_PORT);
+ int version;
+ LDAP *ld = ldap_init(host, (port != 0)? port : LDAP_PORT);
if (ld == NULL)
{
*errmsg = string_sprintf("failed to open connection to LDAP server %s:%d "
@@ -230,6 +235,34 @@
DEBUG(9) debug_printf("Opened connection to LDAP server %s:%d\n", host, port);
+#ifdef OPENLDAP2
+ if ((strncasecmp(ldap_url, "ldaps://", 8) == 0) || (starttls != 0))
+ {
+ DEBUG(9) debug_printf("Get ldap protocol version");
+ if ((rc = ldap_get_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version))
+ != LDAP_SUCCESS)
+ {
+ *errmsg = string_sprintf("Cannot get ldap option - LDAP error %s: %s",
+ rc, ldap_err2string(rc));
+ goto RETURN_ERROR;
+ }
+ DEBUG(9) debug_printf("Setting ldap protocol to version 3");
+ if (version < LDAP_VERSION3)
+ {
+ version = LDAP_VERSION3;
+ ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+ }
+ DEBUG(9) debug_printf("Try to start TLS connection");
+ if ((rc = ldap_start_tls_s(ld, NULL, NULL))
+ != LDAP_SUCCESS)
+ {
+ *errnsg = string_sprintf("Cannot start TLS connection - LDAP error %s: %s",
+ rc, ldap_err2string(rc));
+ goto RETURN_ERROR;
+ }
+ }
+#endif
+
lcp = store_malloc(sizeof(LDAP_CONNECTION));
lcp->host = (host == NULL)? NULL : string_copy_malloc(host);
lcp->bound = FALSE;
@@ -260,7 +293,7 @@
strcmp(lcp->password, password) != 0))
{
DEBUG(9) debug_printf("Binding with user=%s password=%s\n", user, password);
- if ((rc = ldap_bind_s(lcp->ld, user, password, LDAP_AUTH_SIMPLE))
+ if ((rc = ldap_simple_bind_s(lcp->ld, user, password))
!= LDAP_SUCCESS)
{
*errmsg = string_sprintf("failed to bind the LDAP connection to server "
@@ -549,7 +582,7 @@
Parameter data in addition to the URL can be passed as preceding text in the
string, as items of the form XXX=yyy. The URL itself can be detected because it
-must begin "ldap:///".
+must begin "ldap://" or "ldaps://".
Arguments:
ldap_url the URL to be looked up, optionally preceded by other parameter
@@ -569,6 +602,7 @@
BOOL defer_break = FALSE;
int timelimit = LDAP_NO_LIMIT;
int sizelimit = LDAP_NO_LIMIT;
+int starttls = 0;
int sep = 0;
char *url = ldap_url;
char *user = NULL;
@@ -576,11 +610,12 @@
char *server, *list;
char buffer[512];
-/* Until the string begins "ldap://", search for the other parameter settings
-that are recognized. They are of the form NAME=VALUE, with the value being
-optionally double-quoted. There must still be a space after it, however. */
+/* Until the string begins "ldap://" or "ldaps://", search for the other
+parameter settings that are recognized. They are of the form NAME=VALUE,
+with the value being optionally double-quoted. There must still be a space
+after it, however. */
-while (strncmp(url, "ldap://", 7) != 0)
+while ((strncmp(url, "ldap://", 7) != 0) && (strncmp(url, "ldaps://", 8) != 0))
{
char *name = url;
while (*url != 0 && *url != '=') url++;
@@ -594,6 +629,7 @@
else if (strncmpic(name, "PASS=", namelen) == 0) password = value;
else if (strncmpic(name, "SIZE=", namelen) == 0) sizelimit = atoi(value);
else if (strncmpic(name, "TIME=", namelen) == 0) timelimit = atoi(value);
+ else if (strncmpic(name, "TLS=" , namelen) == 0) starttls = atoi(value);
else
{
*errmsg =
@@ -609,15 +645,15 @@
return DEFER;
}
-DEBUG(9) debug_printf("LDAP parameters: user=%s pass=%s size=%d time=%d\n",
- user, password, sizelimit, timelimit);
+DEBUG(9) debug_printf("LDAP parameters: user=%s pass=%s size=%d time=%d tls=%d\n",
+ user, password, sizelimit, timelimit, starttls);
/* No default servers, or URL contains a server name */
-if (ldap_default_servers == NULL || strncmpic(url, "ldap:///", 8) != 0)
+if (ldap_default_servers == NULL || ((strncmpic(url, "ldap:///", 8) != 0) && (strncmpic(url, "ldaps:///", 9) != 0)))
{
return perform_ldap_search(url, NULL, 0, search_type, res, errmsg,
- &defer_break, user, password, sizelimit, timelimit);
+ &defer_break, user, password, sizelimit, timelimit, starttls);
}
/* Loop through the default servers until OK or FAIL */
--