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