summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Faurot <eric@cvs.openbsd.org>2014-02-04 13:55:35 +0000
committerEric Faurot <eric@cvs.openbsd.org>2014-02-04 13:55:35 +0000
commit75fc84794f58dbf709e6cc34d5fb7524930d108f (patch)
tree9e37af0da927e2c78efee87a28b947bfe99866cf
parent5466a3045acfc02b1542c40152b69df386bcf9e0 (diff)
socketmap table backend.
-rw-r--r--usr.sbin/smtpd/smtpd-api.h8
-rw-r--r--usr.sbin/smtpd/table_api.c20
-rw-r--r--usr.sbin/smtpd/table_proc.c13
-rw-r--r--usr.sbin/smtpd/table_socketmap.c261
4 files changed, 291 insertions, 11 deletions
diff --git a/usr.sbin/smtpd/smtpd-api.h b/usr.sbin/smtpd/smtpd-api.h
index d2bc18b1ae1..bb155a0da76 100644
--- a/usr.sbin/smtpd/smtpd-api.h
+++ b/usr.sbin/smtpd/smtpd-api.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd-api.h,v 1.13 2013/12/05 09:26:47 eric Exp $ */
+/* $OpenBSD: smtpd-api.h,v 1.14 2014/02/04 13:55:34 eric Exp $ */
/*
* Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
@@ -185,6 +185,11 @@ struct scheduler_batch {
#define PROC_TABLE_API_VERSION 1
+struct table_open_params {
+ uint32_t version;
+ char name[SMTPD_MAXLINESIZE];
+};
+
enum table_service {
K_NONE = 0x00,
K_ALIAS = 0x01, /* returns struct expand */
@@ -298,6 +303,7 @@ void table_api_on_check(int(*)(int, const char *));
void table_api_on_lookup(int(*)(int, const char *, char *, size_t));
void table_api_on_fetch(int(*)(int, char *, size_t));
int table_api_dispatch(void);
+const char *table_api_get_name(void);
/* tree.c */
#define tree_init(t) do { SPLAY_INIT(&((t)->tree)); (t)->count = 0; } while(0)
diff --git a/usr.sbin/smtpd/table_api.c b/usr.sbin/smtpd/table_api.c
index e2ad7339f2d..501053ce2d0 100644
--- a/usr.sbin/smtpd/table_api.c
+++ b/usr.sbin/smtpd/table_api.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table_api.c,v 1.3 2013/10/26 12:27:59 eric Exp $ */
+/* $OpenBSD: table_api.c,v 1.4 2014/02/04 13:55:34 eric Exp $ */
/*
* Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
@@ -44,6 +44,8 @@ static struct imsg imsg;
static size_t rlen;
static char *rdata;
static struct ibuf *buf;
+static char *name;
+
#if 0
static char *rootpath;
static char *user = SMTPD_USER;
@@ -102,19 +104,23 @@ table_msg_close(void)
static void
table_msg_dispatch(void)
{
- uint32_t version;
+ struct table_open_params op;
char res[4096];
int type, r;
switch (imsg.hdr.type) {
case PROC_TABLE_OPEN:
- table_msg_get(&version, sizeof(version));
+ table_msg_get(&op, sizeof op);
table_msg_end();
- if (version != PROC_TABLE_API_VERSION) {
+ if (op.version != PROC_TABLE_API_VERSION) {
log_warnx("warn: table-api: bad API version");
fatalx("table-api: terminating");
}
+ if ((name = strdup(op.name)) == NULL) {
+ log_warn("warn: table-api");
+ fatalx("table-api: terminating");
+ }
imsg_compose(&ibuf, PROC_TABLE_OK, 0, 0, -1, NULL, 0);
break;
@@ -228,6 +234,12 @@ table_api_on_fetch(int(*cb)(int, char *, size_t))
handler_fetch = cb;
}
+const char *
+table_api_get_name(void)
+{
+ return name;
+}
+
int
table_api_dispatch(void)
{
diff --git a/usr.sbin/smtpd/table_proc.c b/usr.sbin/smtpd/table_proc.c
index 908e4d773c5..d02f76433c5 100644
--- a/usr.sbin/smtpd/table_proc.c
+++ b/usr.sbin/smtpd/table_proc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table_proc.c,v 1.1 2013/07/19 19:53:33 eric Exp $ */
+/* $OpenBSD: table_proc.c,v 1.2 2014/02/04 13:55:34 eric Exp $ */
/*
* Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
@@ -120,9 +120,9 @@ static void *
table_proc_open(struct table *table)
{
int sp[2];
- uint32_t version;
struct table_proc_priv *priv;
char *environ_new[2];
+ struct table_open_params op;
errno = 0;
@@ -130,7 +130,7 @@ table_proc_open(struct table *table)
log_warn("warn: table-proc: socketpair");
return (NULL);
}
- priv = calloc(1, sizeof(*priv));
+ priv = xcalloc(1, sizeof(*priv), "table_proc_open");
if ((priv->pid = fork()) == -1) {
log_warn("warn: table-proc: fork");
@@ -155,9 +155,10 @@ table_proc_open(struct table *table)
close(sp[0]);
imsg_init(&priv->ibuf, sp[1]);
- version = PROC_TABLE_API_VERSION;
- imsg_compose(&priv->ibuf, PROC_TABLE_OPEN, 0, 0, -1,
- &version, sizeof(version));
+ memset(&op, 0, sizeof op);
+ op.version = PROC_TABLE_API_VERSION;
+ (void)strlcpy(op.name, table->t_name, sizeof op.name);
+ imsg_compose(&priv->ibuf, PROC_TABLE_OPEN, 0, 0, -1, &op, sizeof op);
table_proc_call(priv);
table_proc_end();
diff --git a/usr.sbin/smtpd/table_socketmap.c b/usr.sbin/smtpd/table_socketmap.c
new file mode 100644
index 00000000000..123a6b157dd
--- /dev/null
+++ b/usr.sbin/smtpd/table_socketmap.c
@@ -0,0 +1,261 @@
+/* $OpenBSD: table_socketmap.c,v 1.1 2014/02/04 13:55:34 eric Exp $ */
+
+/*
+ * 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "smtpd-defines.h"
+#include "smtpd-api.h"
+#include "log.h"
+
+static int table_socketmap_update(void);
+static int table_socketmap_lookup(int, const char *, char *, size_t);
+static int table_socketmap_check(int, const char *);
+static int table_socketmap_fetch(int, char *, size_t);
+
+static int table_socketmap_connect(const char *);
+
+static char *config;
+static int sock = -1;
+static FILE *sockstream;
+#define REPLYBUFFERSIZE 100000
+static char repbuffer[REPLYBUFFERSIZE+1];
+
+enum socketmap_reply{
+ SM_OK = 0,
+ SM_NOTFOUND,
+ SM_TEMP,
+ SM_TIMEOUT,
+ SM_PERM,
+};
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+
+ log_init(1);
+ log_verbose(~0);
+
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch (ch) {
+ default:
+ log_warnx("warn: table-socketmap: bad option");
+ return (1);
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1) {
+ log_warnx("warn: table-socketmap: bogus argument(s)");
+ return (1);
+ }
+
+ config = argv[0];
+
+ if (table_socketmap_connect(config) == 0) {
+ log_warnx("warn: table-socketmap: error connecting to %s", config);
+ return (1);
+ }
+
+ table_api_on_update(table_socketmap_update);
+ table_api_on_check(table_socketmap_check);
+ table_api_on_lookup(table_socketmap_lookup);
+ table_api_on_fetch(table_socketmap_fetch);
+ table_api_dispatch();
+
+ return (0);
+}
+
+static int
+table_socketmap_connect(const char *s)
+{
+ struct sockaddr_un sun;
+
+ if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ log_warn("warn: table-socketmap");
+ goto err;
+ }
+
+ memset(&sun, 0, sizeof sun);
+ sun.sun_family = AF_UNIX;
+ if (strlcpy(sun.sun_path, s, sizeof(sun.sun_path)) >=
+ sizeof(sun.sun_path)) {
+ log_warnx("warn: table-socketmap: socket path too long");
+ goto err;
+ }
+
+ if (connect(sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
+ log_warn("warn: table-socketmap");
+ goto err;
+ }
+
+ if ((sockstream = fdopen(sock, "w+")) == NULL) {
+ log_warn("warn: table-socketmap");
+ goto err;
+ }
+
+ return 1;
+
+err:
+ if (sock) {
+ close(sock);
+ sock = -1;
+ }
+ return 0;
+}
+
+enum socketmap_reply
+table_socketmap_query(const char *name, const char *key)
+{
+ char *buf, *lbuf = NULL;
+ size_t len;
+ int ret = SM_PERM;
+
+ memset(repbuffer, 0, sizeof repbuffer);
+ fprintf(sockstream, "%s %s\n", name, key);
+ fflush(sockstream);
+
+ buf = fgetln(sockstream, &len);
+ if (buf == NULL) {
+ log_warnx("warn: table-socketmap: socketmap has lost its socket");
+ strlcpy(repbuffer, "lost connection to socket", sizeof repbuffer);
+ ret = SM_PERM;
+ goto err;
+ }
+ if (buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+ else {
+ if ((lbuf = malloc(len + 1)) == NULL) {
+ log_warnx("warn: table-socketmap: memory exhaustion");
+ strlcpy(repbuffer, "memory exhaustion", sizeof repbuffer);
+ ret = SM_PERM;
+ goto err;
+ }
+ memcpy(lbuf, buf, len);
+ lbuf[len] = '\0';
+ buf = lbuf;
+ }
+ free(lbuf);
+ lbuf = NULL;
+
+ if (strlcpy(repbuffer, buf, sizeof repbuffer) >= sizeof repbuffer) {
+ log_warnx("warn: table-socketmap: socketmap reply too large (>%d bytes)",
+ sizeof repbuffer);
+ strlcpy(repbuffer, "socketmap reply too large (>%d bytes)", sizeof repbuffer);
+ ret = SM_PERM;
+ goto err;
+ }
+
+ if (strncasecmp(repbuffer, "OK ", 3) == 0) {
+ ret = SM_OK;
+ memmove(repbuffer, repbuffer+3, strlen(repbuffer)-2);
+ }
+ else if (strncasecmp(repbuffer, "NOTFOUND ", 9) == 0) {
+ ret = SM_NOTFOUND;
+ memmove(repbuffer, repbuffer+9, strlen(repbuffer)-8);
+ }
+ else if (strncasecmp(repbuffer, "TEMP ", 5) == 0) {
+ ret = SM_TEMP;
+ memmove(repbuffer, repbuffer+5, strlen(repbuffer)-4);
+ }
+ else if (strncasecmp(repbuffer, "TIMEOUT ", 8) == 0) {
+ ret = SM_TIMEOUT;
+ memmove(repbuffer, repbuffer+8, strlen(repbuffer)-7);
+ }
+ else if (strncasecmp(repbuffer, "PERM ", 5) == 0) {
+ ret = SM_PERM;
+ memmove(repbuffer, repbuffer+5, strlen(repbuffer)-4);
+ }
+ else {
+ ret = SM_PERM;
+ strlcpy(repbuffer, "unrecognized socketmap reply", sizeof repbuffer);
+ }
+
+err:
+ if (lbuf)
+ free(lbuf);
+ return ret;
+}
+
+static int
+table_socketmap_update(void)
+{
+ return 1;
+}
+
+static int
+table_socketmap_check(int service, const char *key)
+{
+ return (-1);
+}
+
+static int
+table_socketmap_lookup(int service, const char *key, char *dst, size_t sz)
+{
+ int r;
+ enum socketmap_reply rep;
+
+ rep = table_socketmap_query(table_api_get_name(), key);
+ if (rep == SM_NOTFOUND)
+ return 0;
+ if (rep != SM_OK) {
+ log_warnx("warn: table-socketmap: %s", repbuffer);
+ return -1;
+ }
+ if (strlcpy(dst, repbuffer, sz) >= sz) {
+ log_warnx("warn: table-socketmap: result too large");
+ return -1;
+ }
+
+ r = 1;
+ switch(service) {
+ case K_ALIAS:
+ case K_CREDENTIALS:
+ case K_USERINFO:
+ case K_DOMAIN:
+ case K_NETADDR:
+ case K_SOURCE:
+ case K_MAILADDR:
+ case K_ADDRNAME:
+ break;
+ default:
+ log_warnx("warn: table-socketmap: unknown service %d", service);
+ r = -1;
+ }
+
+ return (r);
+}
+
+static int
+table_socketmap_fetch(int service, char *key, size_t sz)
+{
+ return (-1);
+}