summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/table_ldap.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/smtpd/table_ldap.c')
-rw-r--r--usr.sbin/smtpd/table_ldap.c912
1 files changed, 405 insertions, 507 deletions
diff --git a/usr.sbin/smtpd/table_ldap.c b/usr.sbin/smtpd/table_ldap.c
index f3aff8b43a7..51d170144cb 100644
--- a/usr.sbin/smtpd/table_ldap.c
+++ b/usr.sbin/smtpd/table_ldap.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: table_ldap.c,v 1.4 2013/05/24 17:03:14 eric Exp $ */
+/* $OpenBSD: table_ldap.c,v 1.5 2013/07/20 09:06:46 eric Exp $ */
/*
- * Copyright (c) 2010-2012 Gilles Chehade <gilles@poolp.org>
+ * Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,237 +17,422 @@
*/
#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/tree.h>
-#include <sys/socket.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <event.h>
-#include <fcntl.h>
-#include <imsg.h>
-#include <stdio.h>
+#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include "smtpd.h"
-#include "aldap.h"
+#include "smtpd-defines.h"
+#include "smtpd-api.h"
#include "log.h"
+#include "aldap.h"
-#define MAX_LDAP_IDENTIFIER 32
-#define MAX_LDAP_URL 256
-#define MAX_LDAP_USERNAME 256
-#define MAX_LDAP_PASSWORD 256
-#define MAX_LDAP_BASELEN 128
-#define MAX_LDAP_FILTERLEN 1024
-#define MAX_LDAP_FIELDLEN 128
-
-static void *table_ldap_open(struct table *);
-static int table_ldap_update(struct table *);
-static int table_ldap_config(struct table *);
-static int table_ldap_lookup(void *, const char *, enum table_service, union lookup *);
-static int table_ldap_fetch(void *, enum table_service, union lookup *);
-static void table_ldap_close(void *);
-static struct aldap *ldap_client_connect(const char *);
-
-struct table_backend table_backend_ldap = {
- K_ALIAS|K_CREDENTIALS|K_DOMAIN|K_USERINFO, /* K_NETADDR|K_SOURCE,*/
- table_ldap_config,
- table_ldap_open,
- table_ldap_update,
- table_ldap_close,
- table_ldap_lookup,
- table_ldap_fetch
+#define MAX_LDAP_IDENTIFIER 32
+#define MAX_LDAP_URL 256
+#define MAX_LDAP_USERNAME 256
+#define MAX_LDAP_PASSWORD 256
+#define MAX_LDAP_BASELEN 128
+#define MAX_LDAP_FILTERLEN 1024
+#define MAX_LDAP_FIELDLEN 128
+
+
+enum {
+ LDAP_ALIAS = 0,
+ LDAP_DOMAIN,
+ LDAP_CREDENTIALS,
+ LDAP_NETADDR,
+ LDAP_USERINFO,
+ LDAP_SOURCE,
+ LDAP_MAILADDR,
+ LDAP_ADDRNAME,
+
+ LDAP_MAX
};
-struct table_ldap_handle {
- struct aldap *aldap;
- struct table *table;
+#define MAX_ATTRS 6
+
+struct query {
+ char *filter;
+ char *attrs[MAX_ATTRS];
+ int attrn;
};
-static int parse_attributes(char **, const char *, size_t);
-static int table_ldap_internal_query(struct aldap *, const char *,
- const char *, char **, char ***, size_t);
+static int table_ldap_update(void);
+static int table_ldap_check(int, const char *);
+static int table_ldap_lookup(int, const char *, char *, size_t);
+static int table_ldap_fetch(int, char *, size_t);
-static int table_ldap_alias(struct table_ldap_handle *, const char *, union lookup *);
-static int table_ldap_credentials(struct table_ldap_handle *, const char *, union lookup *);
-static int table_ldap_domain(struct table_ldap_handle *, const char *, union lookup *);
-static int table_ldap_userinfo(struct table_ldap_handle *, const char *, union lookup *);
+static int ldap_config(void);
+static int ldap_open(void);
+static int ldap_query(const char *, char **, char ***, size_t);
+static int ldap_parse_attributes(char **, const char *, const char *, size_t);
+static int ldap_run_query(int type, const char *, char *, size_t);
+static char *config;
-static int
-table_ldap_config(struct table *table)
+static char *url;
+static char *username;
+static char *password;
+static char *basedn;
+
+static struct aldap *aldap;
+static struct query queries[LDAP_MAX];
+
+int
+main(int argc, char **argv)
{
- struct table *cfg = NULL;
+ int ch;
- /* no config ? broken */
- if (table->t_config[0] == '\0')
- return 0;
+ log_init(1);
+ log_verbose(~0);
- cfg = table_create("static", table->t_name, "conf", table->t_config);
- if (!table_config(cfg))
- goto err;
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch (ch) {
+ default:
+ log_warnx("warn: table-ldap: bad option");
+ return (1);
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
- /* sanity checks */
- if (table_get(cfg, "url") == NULL) {
- log_warnx("table_ldap: missing 'url' configuration");
- goto err;
+ if (argc != 1) {
+ log_warnx("warn: table-ldap: bogus argument(s)");
+ return (1);
}
- if (table_get(cfg, "basedn") == NULL) {
- log_warnx("table_ldap: missing 'basedn' configuration");
- goto err;
+ config = argv[0];
+
+ if (!ldap_config()) {
+ log_warnx("warn: table-ldap: could not parse config");
+ return (1);
}
- return 1;
+ log_debug("debug: table-ldap: done reading config");
-err:
- table_destroy(cfg);
- return 0;
+ if (!ldap_open()) {
+ log_warnx("warn: table-ldap: failed to connect");
+ return (1);
+ }
+
+ log_debug("debug: table-ldap: connected");
+ table_api_on_update(table_ldap_update);
+ table_api_on_check(table_ldap_check);
+ table_api_on_lookup(table_ldap_lookup);
+ table_api_on_fetch(table_ldap_fetch);
+ table_api_dispatch();
+
+ return (0);
}
static int
-table_ldap_update(struct table *table)
+table_ldap_update(void)
{
- return 1;
+ return (1);
}
-static void *
-table_ldap_open(struct table *table)
+static int
+table_ldap_check(int service, const char *key)
{
- struct table *cfg = NULL;
- struct table_ldap_handle *tlh = NULL;
- struct aldap_message *message = NULL;
- char *url = NULL;
- char *username = NULL;
- char *password = NULL;
-
- cfg = table_find(table->t_name, "conf");
- if (table_get(cfg, "url") == NULL ||
- table_get(cfg, "username") == NULL ||
- table_get(cfg, "password") == NULL)
- goto err;
-
- url = xstrdup(table_get(cfg, "url"), "table_ldap_open");
- username = xstrdup(table_get(cfg, "username"), "table_ldap_open");
- password = xstrdup(table_get(cfg, "password"), "table_ldap_open");
-
- tlh = xcalloc(1, sizeof(*tlh), "table_ldap_open");
- tlh->table = table;
- tlh->aldap = ldap_client_connect(url);
- if (tlh->aldap == NULL) {
- log_warnx("table_ldap_open: ldap_client_connect error");
- goto err;
+ switch(service) {
+ case K_ALIAS:
+ case K_DOMAIN:
+ case K_CREDENTIALS:
+ case K_USERINFO:
+ return ldap_run_query(service, key, NULL, 0);
+ default:
+ return (-1);
}
+}
- if (aldap_bind(tlh->aldap, username, password) == -1) {
- log_warnx("table_ldap_open: aldap_bind error");
- goto err;
+static int
+table_ldap_lookup(int service, const char *key, char *dst, size_t sz)
+{
+ switch(service) {
+ case K_ALIAS:
+ case K_DOMAIN:
+ case K_CREDENTIALS:
+ case K_USERINFO:
+ return ldap_run_query(service, key, dst, sz);
+ default:
+ return (-1);
}
+}
- if ((message = aldap_parse(tlh->aldap)) == NULL) {
- log_warnx("table_ldap_open: aldap_parse");
- goto err;
+static int
+table_ldap_fetch(int service, char *dst, size_t sz)
+{
+ return (-1);
+}
+
+static struct aldap *
+ldap_connect(const char *addr)
+{
+ struct aldap_url lu;
+ struct addrinfo hints, *res0, *res;
+ char *buf;
+ int error, fd = -1;
+
+ if ((buf = strdup(addr)) == NULL)
+ return (NULL);
+
+ /* XXX buf leak */
+
+ if (aldap_parse_url(buf, &lu) != 1) {
+ log_warnx("warn: table-ldap: ldap_parse_url fail");
+ return (NULL);
}
- switch (aldap_get_resultcode(message)) {
- case LDAP_SUCCESS:
- log_warnx("table_ldap_open: ldap server accepted credentials");
- break;
- case LDAP_INVALID_CREDENTIALS:
- log_warnx("table_ldap_open: ldap server refused credentials");
- goto err;
- default:
- log_warnx("table_ldap_open: failed to bind, result #%d", aldap_get_resultcode(message));
- goto err;
+ bzero(&hints, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM; /* DUMMY */
+ error = getaddrinfo(lu.host, NULL, &hints, &res0);
+ if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
+ return (NULL);
+ if (error) {
+ log_warnx("warn: table-ldap: could not parse \"%s\": %s",
+ lu.host, gai_strerror(error));
+ return (NULL);
}
- return tlh;
+ for (res = res0; res; res = res->ai_next) {
+ if (res->ai_family != AF_INET && res->ai_family != AF_INET6)
+ continue;
+
+ fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (fd == -1)
+ continue;
-err:
- if (tlh) {
- if (tlh->aldap != NULL)
- aldap_close(tlh->aldap);
- free(tlh);
+ 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);
+ }
+ 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);
+ }
+
+ close(fd);
+ fd = -1;
}
- if (message != NULL)
- aldap_freemsg(message);
- return NULL;
+
+ return (NULL);
}
-static void
-table_ldap_close(void *hdl)
+static int
+read_value(char **store, const char *key, const char *value)
{
- struct table_ldap_handle *tlh = hdl;
+ log_debug("debug: table-ldap: reading key \"%s\" -> \"%s\"",
+ key, value);
+
+ if (*store) {
+ log_warnx("warn: table-ldap: duplicate key %s", key);
+ return (0);
+ }
+
+ if ((*store = strdup(value)) == NULL) {
+ log_warn("warn: table-ldap: strdup");
+ return (0);
+ }
- aldap_close(tlh->aldap);
- free(tlh);
+ return (1);
}
static int
-table_ldap_lookup(void *hdl, const char *key, enum table_service service,
- union lookup *lk)
+ldap_parse_attributes(char **attributes, const char *key, const char *line,
+ size_t expect)
{
- struct table_ldap_handle *tlh = hdl;
-
- switch (service) {
- case K_ALIAS:
- return table_ldap_alias(tlh, key, lk);
-
- case K_CREDENTIALS:
- return table_ldap_credentials(tlh, key, lk);
+ char buffer[1024];
+ char *p;
+ size_t m, n;
- case K_DOMAIN:
- return table_ldap_domain(tlh, key, lk);
+ log_debug("debug: table-ldap: parsing attribute \"%s\" (%zu) -> \"%s\"",
+ key, expect, line);
- case K_USERINFO:
- return table_ldap_userinfo(tlh, key, lk);
+ if (strlcpy(buffer, line, sizeof buffer) >= sizeof buffer)
+ return (0);
- default:
- break;
+ m = 1;
+ for (p = buffer; *p; ++p) {
+ if (*p == ',') {
+ *p = 0;
+ m++;
+ }
}
+ if (expect != m)
+ return (0);
- return 0;
+ p = buffer;
+ for (n = 0; n < expect; ++n)
+ attributes[n] = NULL;
+ for (n = 0; n < m; ++n) {
+ attributes[n] = strdup(p);
+ if (attributes[n] == NULL) {
+ log_warnx("warn: table-ldap: strdup");
+ return (0); /* XXX cleanup */
+ }
+ p += strlen(p) + 1;
+ }
+ return (1);
}
static int
-table_ldap_fetch(void *hdl, enum table_service service, union lookup *lk)
+ldap_config(void)
{
- /* fetch not support for LDAP at this point */
- return -1;
+ size_t flen;
+ FILE *fp;
+ char *key, *value, *buf, *lbuf;
+
+ fp = fopen(config, "r");
+ if (fp == NULL)
+ return (0);
+
+ lbuf = NULL;
+ while ((buf = fgetln(fp, &flen))) {
+ if (buf[flen - 1] == '\n')
+ buf[flen - 1] = '\0';
+ else {
+ lbuf = malloc(flen + 1);
+ if (lbuf == NULL) {
+ log_warn("warn: table-ldap: malloc");
+ return (0);
+ }
+ memcpy(lbuf, buf, flen);
+ lbuf[flen] = '\0';
+ buf = lbuf;
+ }
+
+ key = buf;
+ while (isspace((int)*key))
+ ++key;
+ if (*key == '\0' || *key == '#')
+ continue;
+ value = key;
+ strsep(&value, " \t:");
+ if (value) {
+ while (*value) {
+ if (!isspace(*value) &&
+ !(*value == ':' && isspace(*(value + 1))))
+ break;
+ ++value;
+ }
+ if (*value == '\0')
+ value = NULL;
+ }
+
+ if (value == NULL) {
+ log_warnx("warn: table-ldap: missing value for key %s", key);
+ continue;
+ }
+
+ if (!strcmp(key, "url"))
+ read_value(&url, key, value);
+ else if (!strcmp(key, "username"))
+ read_value(&username, key, value);
+ else if (!strcmp(key, "password"))
+ read_value(&password, key, value);
+ else if (!strcmp(key, "basedn"))
+ read_value(&basedn, key, value);
+
+ else if (!strcmp(key, "alias_filter"))
+ read_value(&queries[LDAP_ALIAS].filter, key, value);
+ else if (!strcmp(key, "alias_attributes"))
+ ldap_parse_attributes(queries[LDAP_ALIAS].attrs,
+ key, value, 1);
+
+ else if (!strcmp(key, "credentials_filter"))
+ read_value(&queries[LDAP_CREDENTIALS].filter, key, value);
+ else if (!strcmp(key, "credentials_attributes"))
+ ldap_parse_attributes(queries[LDAP_CREDENTIALS].attrs,
+ key, value, 2);
+
+ else if (!strcmp(key, "domain_filter"))
+ read_value(&queries[LDAP_DOMAIN].filter, key, value);
+ else if (!strcmp(key, "domain_attributes"))
+ ldap_parse_attributes(queries[LDAP_DOMAIN].attrs,
+ key, value, 1);
+
+ else if (!strcmp(key, "userinfo_filter"))
+ read_value(&queries[LDAP_USERINFO].filter, key, value);
+ else if (!strcmp(key, "userinfo_attributes"))
+ ldap_parse_attributes(queries[LDAP_USERINFO].attrs,
+ key, value, 4);
+ else
+ log_warnx("warn: table-ldap: bogus entry \"%s\"", key);
+ }
+
+ free(lbuf);
+ fclose(fp);
+ return (1);
}
static int
-filter_expand(char **expfilter, const char *filter, const char *key)
+ldap_open(void)
{
- if (asprintf(expfilter, filter, key) < 0)
- return 0;
- return 1;
+ struct aldap_message *amsg = NULL;
+
+ aldap = ldap_connect(url);
+ if (aldap == NULL) {
+ log_warnx("warn: table-ldap: ldap_connect error");
+ goto err;
+ }
+
+ if (aldap_bind(aldap, username, password) == -1) {
+ log_warnx("warn: table-ldap: aldap_bind error");
+ goto err;
+ }
+
+ if ((amsg = aldap_parse(aldap)) == NULL) {
+ log_warnx("warn: table-ldap: aldap_parse");
+ goto err;
+ }
+
+ switch (aldap_get_resultcode(amsg)) {
+ case LDAP_SUCCESS:
+ log_debug("debug: table-ldap: ldap server accepted credentials");
+ break;
+ case LDAP_INVALID_CREDENTIALS:
+ log_warnx("warn: table-ldap: ldap server refused credentials");
+ goto err;
+ default:
+ log_warnx("warn: table-ldap: failed to bind, result #%d",
+ aldap_get_resultcode(amsg));
+ goto err;
+ }
+
+ if (amsg)
+ aldap_freemsg(amsg);
+ return (1);
+
+err:
+ if (aldap)
+ aldap_close(aldap);
+ if (amsg)
+ aldap_freemsg(amsg);
+ return (0);
}
static int
-table_ldap_internal_query(struct aldap *aldap, const char *basedn,
- const char *filter, char **attributes, char ***outp, size_t n)
+ldap_query(const char *filter, char **attributes, char ***outp, size_t n)
{
- struct aldap_message *m = NULL;
- struct aldap_page_control *pg = NULL;
- int ret;
- int found;
- size_t i;
- char basedn__[MAX_LDAP_BASELEN];
- char filter__[MAX_LDAP_FILTERLEN];
-
- if (strlcpy(basedn__, basedn, sizeof basedn__)
- >= sizeof basedn__)
+ struct aldap_message *m = NULL;
+ struct aldap_page_control *pg = NULL;
+ int ret, found;
+ size_t i;
+ char basedn__[MAX_LDAP_BASELEN];
+ char filter__[MAX_LDAP_FILTERLEN];
+
+ if (strlcpy(basedn__, basedn, sizeof basedn__) >= sizeof basedn__)
return -1;
- if (strlcpy(filter__, filter, sizeof filter__)
- >= sizeof filter__)
+ if (strlcpy(filter__, filter, sizeof filter__) >= sizeof filter__)
return -1;
found = 0;
do {
@@ -296,360 +481,73 @@ end:
return ret;
}
-
-static int
-table_ldap_credentials(struct table_ldap_handle *tlh, const char *key, union lookup *lk)
-{
- struct aldap *aldap = tlh->aldap;
- struct table *cfg = table_find(tlh->table->t_name, "conf");
- const char *filter = NULL;
- const char *basedn = NULL;
- char *expfilter = NULL;
- char *attributes[4];
- char **ret_attr[4];
- const char *attr;
- char line[1024];
- int ret = -1;
- size_t i;
-
- bzero(&attributes, sizeof attributes);
- bzero(&ret_attr, sizeof ret_attr);
-
- basedn = table_get(cfg, "basedn");
- if ((filter = table_get(cfg, "credentials_filter")) == NULL) {
- log_warnx("table_ldap: lookup: no filter configured for credentials");
- goto end;
- }
-
- if ((attr = table_get(cfg, "credentials_attributes")) == NULL) {
- log_warnx("table_ldap: lookup: no attributes configured for credentials");
- goto end;
- }
-
- if (! filter_expand(&expfilter, filter, key)) {
- log_warnx("table_ldap: lookup: couldn't expand filter");
- goto end;
- }
-
- if (! parse_attributes(attributes, attr, 2)) {
- log_warnx("table_ldap: lookup: failed to parse attributes");
- goto end;
- }
-
- if ((ret = table_ldap_internal_query(aldap, basedn, expfilter, attributes,
- ret_attr, nitems(attributes))) <= 0)
- goto end;
-
- if (lk == NULL)
- goto end;
-
- if (! bsnprintf(line, sizeof line, "%s:%s", ret_attr[0][0], ret_attr[0][1])) {
- ret = -1;
- goto end;
- }
-
- bzero(&lk->creds, sizeof(lk->creds));
- if (! text_to_credentials(&lk->creds, line))
- ret = -1;
-
-end:
- for (i = 0; i < nitems(attributes); ++i) {
- free(attributes[i]);
- if (ret_attr[i])
- aldap_free_attr(ret_attr[i]);
- }
-
- free(expfilter);
- log_debug("debug: table_ldap_credentials: ret=%d", ret);
- return ret;
-}
-
static int
-table_ldap_domain(struct table_ldap_handle *tlh, const char *key, union lookup *lk)
+ldap_run_query(int type, const char *key, char *dst, size_t sz)
{
- struct aldap *aldap = tlh->aldap;
- struct table *cfg = table_find(tlh->table->t_name, "conf");
- const char *filter = NULL;
- const char *basedn = NULL;
- char *expfilter = NULL;
- char *attributes[1];
- char **ret_attr[1];
- const char *attr;
- int ret = -1;
- size_t i;
-
- bzero(&attributes, sizeof attributes);
- bzero(&ret_attr, sizeof ret_attr);
-
- log_debug("domain: %s", key);
- basedn = table_get(cfg, "basedn");
- if ((filter = table_get(cfg, "domain_filter")) == NULL) {
- log_warnx("table_ldap: lookup: no filter configured for domain");
- goto end;
- }
-
- if ((attr = table_get(cfg, "domain_attributes")) == NULL) {
- log_warnx("table_ldap: lookup: no attributes configured for domain");
- goto end;
- }
-
- if (! filter_expand(&expfilter, filter, key)) {
- log_warnx("table_ldap: lookup: couldn't expand filter");
- goto end;
- }
-
- if (! parse_attributes(attributes, attr, 1)) {
- log_warnx("table_ldap: lookup: failed to parse attributes");
- goto end;
- }
-
- if ((ret = table_ldap_internal_query(aldap, basedn, expfilter, attributes,
- ret_attr, nitems(attributes))) <= 0)
- goto end;
-
- if (lk == NULL)
- goto end;
-
- bzero(&lk->domain, sizeof(lk->domain));
- if (strlcpy(lk->domain.name, ret_attr[0][0], sizeof(lk->domain.name))
- >= sizeof(lk->domain.name))
- ret = -1;
-
-end:
- for (i = 0; i < nitems(attributes); ++i) {
- free(attributes[i]);
- if (ret_attr[i])
- aldap_free_attr(ret_attr[i]);
- }
- free(expfilter);
- log_debug("debug: table_ldap_domain: ret=%d", ret);
- return ret;
-}
-
-static int
-table_ldap_userinfo(struct table_ldap_handle *tlh, const char *key, union lookup *lk)
-{
- struct aldap *aldap = tlh->aldap;
- struct table *cfg = table_find(tlh->table->t_name, "conf");
- const char *filter = NULL;
- const char *basedn = NULL;
- char *expfilter = NULL;
- char *attributes[4];
- char **ret_attr[4];
- const char *attr;
- char line[1024];
- int ret = -1;
- size_t i;
-
- bzero(&attributes, sizeof attributes);
- bzero(&ret_attr, sizeof ret_attr);
-
- basedn = table_get(cfg, "basedn");
- if ((filter = table_get(cfg, "userinfo_filter")) == NULL) {
- log_warnx("table_ldap: lookup: no filter configured for userinfo");
- goto end;
- }
-
- if ((attr = table_get(cfg, "userinfo_attributes")) == NULL) {
- log_warnx("table_ldap: lookup: no attributes configured for userinfo");
- goto end;
- }
-
- if (! filter_expand(&expfilter, filter, key)) {
- log_warnx("table_ldap: lookup: couldn't expand filter");
- goto end;
- }
-
- if (! parse_attributes(attributes, attr, 4)) {
- log_warnx("table_ldap: lookup: failed to parse attributes");
- goto end;
- }
-
- if ((ret = table_ldap_internal_query(aldap, basedn, expfilter, attributes,
- ret_attr, nitems(attributes))) <= 0)
- goto end;
-
- if (lk == NULL)
- goto end;
-
- if (! bsnprintf(line, sizeof line, "%s:%s:%s:%s",
- ret_attr[0][0], ret_attr[1][0], ret_attr[2][0], ret_attr[3][0])) {
- ret = -1;
- goto end;
- }
-
- bzero(&lk->userinfo, sizeof(lk->userinfo));
- if (!text_to_userinfo(&(lk->userinfo), line))
- ret = -1;
-
-end:
- for (i = 0; i < nitems(attributes); ++i) {
- free(attributes[i]);
- if (ret_attr[i])
- aldap_free_attr(ret_attr[i]);
- }
- free(expfilter);
- log_debug("debug: table_ldap_userinfo: ret=%d", ret);
- return ret;
-}
-
-static int
-table_ldap_alias(struct table_ldap_handle *tlh, const char *key, union lookup *lk)
-{
- struct aldap *aldap = tlh->aldap;
- struct table *cfg = table_find(tlh->table->t_name, "conf");
- const char *filter = NULL;
- const char *basedn = NULL;
- char *expfilter = NULL;
- char *attributes[1];
- char **ret_attr[1];
- const char *attr;
- int ret = -1;
- size_t i;
-
- bzero(&attributes, sizeof attributes);
- bzero(&ret_attr, sizeof ret_attr);
- if (lk)
- lk->expand = NULL;
-
- basedn = table_get(cfg, "basedn");
- if ((filter = table_get(cfg, "alias_filter")) == NULL) {
- log_warnx("table_ldap: lookup: no filter configured for alias");
- goto end;
- }
-
- if ((attr = table_get(cfg, "alias_attributes")) == NULL) {
- log_warnx("table_ldap: lookup: no attributes configured for alias");
- goto end;
- }
-
- if (! filter_expand(&expfilter, filter, key)) {
- log_warnx("table_ldap: lookup: couldn't expand filter");
- goto end;
+ struct query *q;
+ char **res[4], filter[MAX_LDAP_FILTERLEN];
+ int ret, i;
+
+ switch (type) {
+ case K_ALIAS: q = &queries[LDAP_ALIAS]; break;
+ case K_DOMAIN: q = &queries[LDAP_DOMAIN]; break;
+ case K_CREDENTIALS: q = &queries[LDAP_CREDENTIALS]; break;
+ case K_NETADDR: q = &queries[LDAP_NETADDR]; break;
+ case K_USERINFO: q = &queries[LDAP_USERINFO]; break;
+ case K_SOURCE: q = &queries[LDAP_SOURCE]; break;
+ case K_MAILADDR: q = &queries[LDAP_MAILADDR]; break;
+ case K_ADDRNAME: q = &queries[LDAP_ADDRNAME]; break;
+ default:
+ return (-1);
}
- if (! parse_attributes(attributes, attr, 1)) {
- log_warnx("table_ldap: lookup: failed to parse attributes");
- goto end;
+ if (snprintf(filter, sizeof(filter), q->filter, key)
+ >= (int)sizeof(filter)) {
+ log_warnx("warn: table-ldap: filter too large");
+ return (-1);
}
- if ((ret = table_ldap_internal_query(aldap, basedn, expfilter, attributes,
- ret_attr, nitems(attributes))) <= 0)
+ bzero(res, sizeof(res));
+ ret = ldap_query(filter, q->attrs, res, q->attrn);
+ if (ret <= 0 || dst == NULL)
goto end;
- if (lk == NULL)
- goto end;
-
- lk->expand = xcalloc(1, sizeof(*lk->expand), "table_ldap_alias");
- for (i = 0; ret_attr[0][i]; ++i) {
- if (! expand_line(lk->expand, ret_attr[0][i], 1)) {
- ret = -1;
- goto end;
- }
- }
+ switch (type) {
-end:
- for (i = 0; i < nitems(attributes); ++i) {
- free(attributes[i]);
- if (ret_attr[i])
- aldap_free_attr(ret_attr[i]);
- }
- if (ret != 1 && lk && lk->expand)
- expand_free(lk->expand);
-
- free(expfilter);
- log_debug("debug: table_ldap_alias: ret=%d", ret);
- return ret;
-}
-
-static struct aldap *
-ldap_client_connect(const char *addr)
-{
- struct aldap_url lu;
- struct addrinfo hints, *res0, *res;
- int error;
-
- char *url;
- int fd = -1;
-
- if ((url = strdup(addr)) == NULL)
- err(1, NULL);
-
- if (aldap_parse_url(url, &lu) != 1) {
- warnx("aldap_parse_url fail");
- goto err;
- }
- url = NULL;
-
- bzero(&hints, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM; /* DUMMY */
- error = getaddrinfo(lu.host, NULL, &hints, &res0);
- if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
- goto err;
- if (error) {
- log_warnx("ldap_client_connect: could not parse \"%s\": %s", lu.host,
- gai_strerror(error));
- goto err;
- }
-
- for (res = res0; res; res = res->ai_next) {
- if (res->ai_family != AF_INET && res->ai_family != AF_INET6)
- continue;
-
- fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (fd == -1)
- continue;
-
- 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);
- }
- 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);
+ case K_ALIAS:
+ for (i = 0; res[0][i]; i++) {
+ if (i && strlcat(dst, ", ", sz) >= sz) {
+ ret = -1;
+ break;
+ }
+ if (strlcat(dst, res[0][i], sz) >= sz) {
+ ret = -1;
+ break;
+ }
}
-
- close(fd);
- fd = -1;
+ break;
+ case K_DOMAIN:
+ if (strlcpy(dst, res[0][0], sz) >= sz)
+ ret = -1;
+ break;
+ case K_CREDENTIALS:
+ if (snprintf(dst, sz, "%s:%s", res[0][0], res[0][1]) >= (int)sz)
+ ret = -1;
+ break;
+ case K_USERINFO:
+ if (snprintf(dst, sz, "%s:%s:%s:%s", res[0][0], res[1][0],
+ res[2][0], res[3][0]) >= (int)sz)
+ ret = -1;
+ break;
}
-err:
- free(url);
- return NULL;
-}
-
-static int
-parse_attributes(char **attributes, const char *line, size_t expect)
-{
- char buffer[1024];
- char *p;
- size_t m, n;
-
- if (strlcpy(buffer, line, sizeof buffer)
- >= sizeof buffer)
- return 0;
+ if (ret == -1)
+ log_warnx("warn: table-ldap: could not format result");
- m = 1;
- for (p = buffer; *p; ++p) {
- if (*p == ',') {
- *p = 0;
- m++;
- }
- }
- if (expect != m)
- return 0;
+end:
+ for (i = 0; i < q->attrn; ++i)
+ if (res[i])
+ aldap_free_attr(res[i]);
- p = buffer;
- for (n = 0; n < expect; ++n)
- attributes[n] = NULL;
- for (n = 0; n < m; ++n) {
- attributes[n] = xstrdup(p, "parse_attributes");
- p += strlen(p) + 1;
- }
- return 1;
+ return (ret);
}