Hi

I have had a bit of time and implemented ldaps support for table-ldap.
It is currently untested and has some todos. But I would say it's
complete enough to share. So other can comment on the code. A patch
is attached

In general it would be nice, if the extras repo could get reactivated.
Most imported would be some documentation for the existing staff.

Philipp / satanist
From 2a2671ea2a88868ec91e24803db30935d18c081d Mon Sep 17 00:00:00 2001
From: Philipp Takacs <phil...@bureaucracy.de>
Date: Tue, 23 Jan 2024 00:55:23 +0100
Subject: [PATCH] table-ldap add ldaps support

untested

based on libtls, autohell is ugly ass hell

need also some log messages
---
 configure.ac                          |  2 +-
 extras/tables/table-ldap/aldap.c      | 32 ++++++++++++++---
 extras/tables/table-ldap/aldap.h      | 20 ++++++-----
 extras/tables/table-ldap/ber.c        | 23 ++++++++++---
 extras/tables/table-ldap/ber.h        |  1 +
 extras/tables/table-ldap/table_ldap.c | 49 ++++++++++++++++++++++++---
 6 files changed, 103 insertions(+), 24 deletions(-)

diff --git a/configure.ac b/configure.ac
index 410a61b..14608b1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -577,7 +577,7 @@ AC_ARG_WITH([libssl],
 	]
 )
 ## XXX chl -lssl manually added
-LIBS="-lcrypto -lssl $LIBS"
+LIBS="-lcrypto -lssl -ltls $LIBS"
 AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL], [1],
 	[Define if your ssl headers are included
 	with #include <openssl/header.h>])],
diff --git a/extras/tables/table-ldap/aldap.c b/extras/tables/table-ldap/aldap.c
index d54a90c..9cefe1c 100644
--- a/extras/tables/table-ldap/aldap.c
+++ b/extras/tables/table-ldap/aldap.c
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <tls.h>
 
 #include "aldap.h"
 
@@ -55,6 +56,12 @@ void			 ldap_debug_elements(struct ber_element *);
 int
 aldap_close(struct aldap *al)
 {
+	if (al->ber.tls_ctx) {
+		if (tls_close(al->ber.tls_ctx) == -1)
+			return (-1);
+		tls_free(al->ber.tls_ctx);
+	}
+
 	if (close(al->ber.fd) == -1)
 		return (-1);
 
@@ -65,13 +72,14 @@ aldap_close(struct aldap *al)
 }
 
 struct aldap *
-aldap_init(int fd)
+aldap_init(int fd, struct tls *ctx)
 {
 	struct aldap *a;
 
 	if ((a = calloc(1, sizeof(*a))) == NULL)
 		return NULL;
 	a->ber.fd = fd;
+	a->ber.tls_ctx = ctx;
 
 	return a;
 }
@@ -575,10 +583,15 @@ aldap_parse_url(char *url, struct aldap_url *lu)
 	p = lu->buffer;
 
 	/* protocol */
-	if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) != 0)
+	if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) == 0) {
+		lu->protocol = LDAP;
+		p += strlen(LDAP_URL);
+	} else if (strncasecmp(LDAPS_URL, p, strlen(LDAP_URL)) == 0) {
+		lu->protocol = LDAPS;
+		p += strlen(LDAPS_URL);
+	} else {
 		goto fail;
-	lu->protocol = LDAP;
-	p += strlen(LDAP_URL);
+	}
 
 	/* host and optional port */
 	if ((forward = strchr(p, '/')) != NULL)
@@ -594,7 +607,16 @@ aldap_parse_url(char *url, struct aldap_url *lu)
 				goto fail;
 		}
 	} else {
-		lu->port = LDAP_PORT;
+		switch (lu->protocol) {
+		case LDAP:
+			lu->port = LDAP_PORT;
+			break;
+		case LDAPS:
+			lu->port = LDAPS_PORT;
+			break;
+		default:
+			goto fail;
+		}
 	}
 	/* fail if no host is given */
 	if (strlen(p) == 0)
diff --git a/extras/tables/table-ldap/aldap.h b/extras/tables/table-ldap/aldap.h
index 7cfd637..fec106b 100644
--- a/extras/tables/table-ldap/aldap.h
+++ b/extras/tables/table-ldap/aldap.h
@@ -20,6 +20,8 @@
 
 #define LDAP_URL "ldap://";
 #define LDAP_PORT 389
+#define LDAPS_URL "ldaps://"
+#define LDAPS_PORT 636
 #define LDAP_PAGED_OID  "1.2.840.113556.1.4.319"
 
 struct aldap {
@@ -69,15 +71,15 @@ enum aldap_protocol {
 };
 
 struct aldap_url {
-	int		 protocol;
-	char		*host;
-	in_port_t	 port;
-	char		*dn;
+	enum aldap_protocol	 protocol;
+	char			*host;
+	in_port_t		 port;
+	char			*dn;
 #define MAXATTR 1024
-	char		*attributes[MAXATTR];
-	int		 scope;
-	char		*filter;
-	char		*buffer;
+	char			*attributes[MAXATTR];
+	int			 scope;
+	char			*filter;
+	char			*buffer;
 };
 
 enum protocol_op {
@@ -186,7 +188,7 @@ enum ldap_subfilter {
 	LDAP_FILT_SUBS_FIN	= 2,
 };
 
-struct aldap		*aldap_init(int fd);
+struct aldap		*aldap_init(int fd, struct tls *ctx);
 int			 aldap_close(struct aldap *);
 struct aldap_message	*aldap_parse(struct aldap *);
 void			 aldap_freemsg(struct aldap_message *);
diff --git a/extras/tables/table-ldap/ber.c b/extras/tables/table-ldap/ber.c
index 0f92bb2..9bb06aa 100644
--- a/extras/tables/table-ldap/ber.c
+++ b/extras/tables/table-ldap/ber.c
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <stdarg.h>
+#include <tls.h>
 
 #include "ber.h"
 
@@ -784,8 +785,12 @@ ber_write_elements(struct ber *ber, struct ber_element *root)
 		return -1;
 
 	/* XXX this should be moved to a different function */
-	if (ber->fd != -1)
+	if (ber->fd != -1) {
+		if (ber->tls_ctx) {
+			return tls_write(ber->tls_ctx, ber->br_wbuf, len);
+		}
 		return write(ber->fd, ber->br_wbuf, len);
+	}
 
 	return (len);
 }
@@ -1233,8 +1238,12 @@ ber_getc(struct ber *b, unsigned char *c)
 	 */
 	if (b->fd == -1)
 		r = ber_readbuf(b, c, 1);
-	else
-		r = read(b->fd, c, 1);
+	else {
+		if (b->tls_ctx)
+			r = tls_read(b->tls_ctx, c, 1);
+		else
+			r = read(b->fd, c, 1);
+	}
 	return r;
 }
 
@@ -1253,8 +1262,12 @@ ber_read(struct ber *ber, void *buf, size_t len)
 	while (remain > 0) {
 		if (ber->fd == -1)
 			r = ber_readbuf(ber, b, remain);
-		else
-			r = read(ber->fd, b, remain);
+		else {
+			if (ber->tls_ctx)
+				r = tls_read(ber->tls_ctx, b, remain);
+			else
+				r = read(ber->fd, b, remain);
+		}
 		if (r == -1) {
 			if (errno == EINTR || errno == EAGAIN)
 				continue;
diff --git a/extras/tables/table-ldap/ber.h b/extras/tables/table-ldap/ber.h
index d656508..4987fc2 100644
--- a/extras/tables/table-ldap/ber.h
+++ b/extras/tables/table-ldap/ber.h
@@ -34,6 +34,7 @@ struct ber_element {
 
 struct ber {
 	int		 fd;
+	struct tls	*tls_ctx;
 	unsigned char	*br_wbuf;
 	unsigned char	*br_wptr;
 	unsigned char	*br_wend;
diff --git a/extras/tables/table-ldap/table_ldap.c b/extras/tables/table-ldap/table_ldap.c
index 090cfb4..bdfb13b 100644
--- a/extras/tables/table-ldap/table_ldap.c
+++ b/extras/tables/table-ldap/table_ldap.c
@@ -27,6 +27,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <tls.h>
 
 #include <smtpd-api.h>
 #include "aldap.h"
@@ -80,6 +81,34 @@ table_ldap_fetch(int service, struct dict *params, char *dst, size_t sz)
 	return -1;
 }
 
+static struct tls *
+ldaps_connect(int fd, char *hostname)
+{
+	/* XXX log */
+	struct tls *ctx = NULL;
+	struct tls_config *config = tls_config_new();
+	if (!config)
+		goto fail;
+	if (tls_config_set_ca_path(config, "/etc/ssl/certs") == -1)
+		goto fail;
+	if ((ctx = tls_client()) == NULL)
+		goto fail;
+	if (tls_configure(ctx, config) == -1)
+		goto fail;
+	if (tls_connect_socket(ctx, fd, hostname) == -1)
+		goto fail;
+	if (tls_handshake(ctx) == -1)
+		goto fail;
+	
+	tls_config_free(config);
+	return ctx;
+fail:
+	tls_close(ctx);
+	tls_free(ctx);
+	tls_config_free(config);
+	return NULL;
+}
+
 static struct aldap *
 ldap_connect(const char *addr)
 {
@@ -121,13 +150,25 @@ ldap_connect(const char *addr)
 		if (res->ai_family == AF_INET) {
 			struct sockaddr_in sin4 = *(struct sockaddr_in *)res->ai_addr;
 			sin4.sin_port = htons(lu.port);
-			if (connect(fd, (struct sockaddr *)&sin4, res->ai_addrlen) == 0)
-				return aldap_init(fd);
+			if (connect(fd, (struct sockaddr *)&sin4, res->ai_addrlen) == 0) {
+				if (lu.protocol == LDAPS) {
+					struct tls *ctx = NULL;
+					if ((ctx = ldaps_connect(fd, lu.host)))
+						return aldap_init(fd, ctx);
+				} else
+					return aldap_init(fd, NULL);
+			}
 		} else if (res->ai_family == AF_INET6) {
 			struct sockaddr_in6 sin6 = *(struct sockaddr_in6 *)res->ai_addr;
 			sin6.sin6_port = htons(lu.port);
-			if (connect(fd, (struct sockaddr *)&sin6, res->ai_addrlen) == 0)
-				return aldap_init(fd);
+			if (connect(fd, (struct sockaddr *)&sin6, res->ai_addrlen) == 0) {
+				if (lu.protocol == LDAPS) {
+					struct tls *ctx = NULL;
+					if ((ctx = ldaps_connect(fd, lu.host)))
+						return aldap_init(fd, ctx);
+				} else
+					return aldap_init(fd, NULL);
+			}
 		}
 
 		close(fd);
-- 
2.39.2

Reply via email to