aboutsummaryrefslogtreecommitdiffstats
path: root/smtpd
diff options
context:
space:
mode:
Diffstat (limited to 'smtpd')
-rw-r--r--smtpd/aliases.c7
-rw-r--r--smtpd/bounce.c2
-rw-r--r--smtpd/ca.c3
-rw-r--r--smtpd/cert.c2
-rw-r--r--smtpd/compress_backend.c2
-rw-r--r--smtpd/compress_gzip.c2
-rw-r--r--smtpd/config.c9
-rw-r--r--smtpd/control.c7
-rw-r--r--smtpd/crypto.c2
-rw-r--r--smtpd/dict.c2
-rw-r--r--smtpd/dns.c14
-rw-r--r--smtpd/enqueue.c6
-rw-r--r--smtpd/envelope.c6
-rw-r--r--smtpd/esc.c6
-rw-r--r--smtpd/expand.c8
-rw-r--r--smtpd/filter.c868
-rw-r--r--smtpd/forward.c7
-rw-r--r--smtpd/iobuf.c2
-rw-r--r--smtpd/ioev.c6
-rw-r--r--smtpd/libressl.c213
-rw-r--r--smtpd/limit.c2
-rw-r--r--smtpd/lka.c4
-rw-r--r--smtpd/lka_filter.c2
-rw-r--r--smtpd/lka_proc.c2
-rw-r--r--smtpd/lka_report.c2
-rw-r--r--smtpd/lka_session.c4
-rw-r--r--smtpd/log.c2
-rw-r--r--smtpd/log.h6
-rw-r--r--smtpd/mail.lmtp.c2
-rw-r--r--smtpd/mail.maildir.c2
-rw-r--r--smtpd/mail.mboxfile.c9
-rw-r--r--smtpd/mail.mda.c2
-rw-r--r--smtpd/mailaddr.c2
-rw-r--r--smtpd/makemap.c18
-rw-r--r--smtpd/mda.c9
-rw-r--r--smtpd/mda_unpriv.c2
-rw-r--r--smtpd/mda_variables.c2
-rw-r--r--smtpd/mproc.c9
-rw-r--r--smtpd/mta.c23
-rw-r--r--smtpd/mta_session.c4
-rw-r--r--smtpd/parse.y44
-rw-r--r--smtpd/parser.c8
-rw-r--r--smtpd/pony.c2
-rw-r--r--smtpd/queue.c4
-rw-r--r--smtpd/queue_backend.c2
-rw-r--r--smtpd/queue_fs.c17
-rw-r--r--smtpd/queue_null.c2
-rw-r--r--smtpd/queue_proc.c2
-rw-r--r--smtpd/queue_ram.c2
-rw-r--r--smtpd/report_smtp.c6
-rw-r--r--smtpd/resolver.c8
-rw-r--r--smtpd/rfc5322.c2
-rw-r--r--smtpd/ruleset.c2
-rw-r--r--smtpd/runq.c2
-rw-r--r--smtpd/scheduler.c3
-rw-r--r--smtpd/scheduler_backend.c2
-rw-r--r--smtpd/scheduler_null.c2
-rw-r--r--smtpd/scheduler_proc.c2
-rw-r--r--smtpd/scheduler_ramqueue.c2
-rw-r--r--smtpd/smtp.c23
-rw-r--r--smtpd/smtp_session.c6
-rw-r--r--smtpd/smtpctl.c23
-rw-r--r--smtpd/smtpd-defines.h10
-rw-r--r--smtpd/smtpd.c196
-rw-r--r--smtpd/smtpd.conf19
-rw-r--r--smtpd/smtpd.h38
-rw-r--r--smtpd/spfwalk.c6
-rw-r--r--smtpd/ssl.c4
-rw-r--r--smtpd/ssl.h1
-rw-r--r--smtpd/ssl_smtpd.c2
-rw-r--r--smtpd/stat_backend.c2
-rw-r--r--smtpd/stat_ramstat.c1
-rw-r--r--smtpd/table.c38
-rw-r--r--smtpd/table_api.c3
-rw-r--r--smtpd/table_db.c9
-rw-r--r--smtpd/table_getpwnam.c2
-rw-r--r--smtpd/table_proc.c4
-rw-r--r--smtpd/table_static.c2
-rw-r--r--smtpd/to.c61
-rw-r--r--smtpd/tree.c2
-rw-r--r--smtpd/unpack_dns.c5
-rw-r--r--smtpd/util.c13
-rw-r--r--smtpd/waitq.c2
83 files changed, 1793 insertions, 75 deletions
diff --git a/smtpd/aliases.c b/smtpd/aliases.c
index 93d3fe68..be350897 100644
--- a/smtpd/aliases.c
+++ b/smtpd/aliases.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -29,7 +31,12 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#ifdef HAVE_UTIL_H
#include <util.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
#include "smtpd.h"
#include "log.h"
diff --git a/smtpd/bounce.c b/smtpd/bounce.c
index 02239988..41526d8d 100644
--- a/smtpd/bounce.c
+++ b/smtpd/bounce.c
@@ -18,6 +18,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/ca.c b/smtpd/ca.c
index 4c3bdded..2fdb302f 100644
--- a/smtpd/ca.c
+++ b/smtpd/ca.c
@@ -17,11 +17,14 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/tree.h>
+#include <grp.h> /* needed for setgroups */
#include <err.h>
#include <imsg.h>
#include <limits.h>
diff --git a/smtpd/cert.c b/smtpd/cert.c
index 05aff418..79b1df91 100644
--- a/smtpd/cert.c
+++ b/smtpd/cert.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/tree.h>
diff --git a/smtpd/compress_backend.c b/smtpd/compress_backend.c
index 516dd1ee..1b974662 100644
--- a/smtpd/compress_backend.c
+++ b/smtpd/compress_backend.c
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/compress_gzip.c b/smtpd/compress_gzip.c
index e7421cec..dd60aeec 100644
--- a/smtpd/compress_gzip.c
+++ b/smtpd/compress_gzip.c
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/config.c b/smtpd/config.c
index 552803cb..c1089104 100644
--- a/smtpd/config.c
+++ b/smtpd/config.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -204,7 +206,9 @@ set_localaddrs(struct smtpd *conf, struct table *localnames)
case AF_INET:
sain = (struct sockaddr_in *)&ss;
*sain = *(struct sockaddr_in *)p->ifa_addr;
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
sain->sin_len = sizeof(struct sockaddr_in);
+#endif
table_add(t, ss_to_text(&ss), NULL);
table_add(localnames, ss_to_text(&ss), NULL);
(void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss));
@@ -214,7 +218,9 @@ set_localaddrs(struct smtpd *conf, struct table *localnames)
case AF_INET6:
sin6 = (struct sockaddr_in6 *)&ss;
*sin6 = *(struct sockaddr_in6 *)p->ifa_addr;
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
sin6->sin6_len = sizeof(struct sockaddr_in6);
+#endif
table_add(t, ss_to_text(&ss), NULL);
table_add(localnames, ss_to_text(&ss), NULL);
(void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss));
@@ -305,7 +311,8 @@ config_process(enum smtp_proc_type proc)
fatal("fdlimit: getrlimit");
rl.rlim_cur = rl.rlim_max;
if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
- fatal("fdlimit: setrlimit");
+ if (errno != EINVAL)
+ fatal("fdlimit: setrlimit");
}
void
diff --git a/smtpd/control.c b/smtpd/control.c
index 6f9c9aca..d85bf578 100644
--- a/smtpd/control.c
+++ b/smtpd/control.c
@@ -18,6 +18,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -29,6 +31,7 @@
#include <errno.h>
#include <event.h>
#include <fcntl.h>
+#include <grp.h> /* needed for setgroups */
#include <imsg.h>
#include <pwd.h>
#include <signal.h>
@@ -292,7 +295,7 @@ control_accept(int listenfd, short event, void *arg)
uid_t euid;
gid_t egid;
- if (getdtablesize() - getdtablecount() < CONTROL_FD_RESERVE)
+ if (available_fds(CONTROL_FD_RESERVE))
goto pause;
len = sizeof(s_un);
@@ -366,7 +369,7 @@ control_close(struct ctl_conn *c)
stat_backend->decrement("control.session", 1);
- if (getdtablesize() - getdtablecount() < CONTROL_FD_RESERVE)
+ if (available_fds(CONTROL_FD_RESERVE))
return;
if (!event_pending(&control_state.ev, EV_READ, NULL)) {
diff --git a/smtpd/crypto.c b/smtpd/crypto.c
index 1cc1af7c..76f98807 100644
--- a/smtpd/crypto.c
+++ b/smtpd/crypto.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/smtpd/dict.c b/smtpd/dict.c
index 2d65812a..d5998052 100644
--- a/smtpd/dict.c
+++ b/smtpd/dict.c
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/tree.h>
diff --git a/smtpd/dns.c b/smtpd/dns.c
index 4d369e24..74499e09 100644
--- a/smtpd/dns.c
+++ b/smtpd/dns.c
@@ -18,6 +18,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/tree.h>
@@ -27,10 +29,15 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+#include <arpa/nameser_compat.h>
+#endif
#include <netdb.h>
#include <asr.h>
#include <event.h>
+#include <netdb.h>
+#include <resolv.h>
#include <imsg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -41,6 +48,11 @@
#include "log.h"
#include "unpack_dns.h"
+/* On OpenBSD, this function is not needed because we don't free addrinfo */
+#if defined(NOOP_ASR_FREEADDRINFO)
+#define asr_freeaddrinfo(x) do { } while(0);
+#endif
+
struct dns_lookup {
struct dns_session *session;
int preference;
@@ -214,7 +226,7 @@ dns_dispatch_host(struct asr_result *ar, void *arg)
}
free(lookup);
if (ar->ar_addrinfo)
- freeaddrinfo(ar->ar_addrinfo);
+ asr_freeaddrinfo(ar->ar_addrinfo);
if (ar->ar_gai_errno)
s->error = ar->ar_gai_errno;
diff --git a/smtpd/enqueue.c b/smtpd/enqueue.c
index bc59989a..dcb40cd3 100644
--- a/smtpd/enqueue.c
+++ b/smtpd/enqueue.c
@@ -18,6 +18,8 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/socket.h>
@@ -561,12 +563,12 @@ build_from(char *fake_from, struct passwd *pw)
apos, pw->pw_gecos,
pw->pw_name,
len - apos - 1, p + 1) == -1)
- err(1, NULL);
+ err(1, "asprintf");
msg.fromname[apos] = toupper((unsigned char)msg.fromname[apos]);
} else {
if (asprintf(&msg.fromname, "%.*s", len,
pw->pw_gecos) == -1)
- err(1, NULL);
+ err(1, "asprintf");
}
}
}
diff --git a/smtpd/envelope.c b/smtpd/envelope.c
index 7b80259d..9dca6cf8 100644
--- a/smtpd/envelope.c
+++ b/smtpd/envelope.c
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -301,14 +303,18 @@ ascii_load_sockaddr(struct sockaddr_storage *ss, char *buf)
return 0;
ssin6.sin6_family = AF_INET6;
memcpy(ss, &ssin6, sizeof(ssin6));
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
ss->ss_len = sizeof(struct sockaddr_in6);
+#endif
}
else {
if (inet_pton(AF_INET, buf, &ssin.sin_addr) != 1)
return 0;
ssin.sin_family = AF_INET;
memcpy(ss, &ssin, sizeof(ssin));
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
ss->ss_len = sizeof(struct sockaddr_in);
+#endif
}
return 1;
}
diff --git a/smtpd/esc.c b/smtpd/esc.c
index a07320ce..64a44c79 100644
--- a/smtpd/esc.c
+++ b/smtpd/esc.c
@@ -16,12 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/queue.h>
-#include <sys/tree.h>
-#include <sys/socket.h>
+#include "includes.h"
-#include <netinet/in.h>
-#include <netdb.h>
#include <stdio.h>
#include <limits.h>
diff --git a/smtpd/expand.c b/smtpd/expand.c
index 99b25d51..a4306fc0 100644
--- a/smtpd/expand.c
+++ b/smtpd/expand.c
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -29,6 +31,12 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
#include "smtpd.h"
#include "log.h"
diff --git a/smtpd/filter.c b/smtpd/filter.c
new file mode 100644
index 00000000..614486b7
--- /dev/null
+++ b/smtpd/filter.c
@@ -0,0 +1,868 @@
+/* $OpenBSD: filter.c,v 1.25 2017/01/09 09:53:23 reyk Exp $ */
+
+/*
+ * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
+ * Copyright (c) 2012 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 "includes.h"
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/tree.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <event.h>
+#include <imsg.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <resolv.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "smtpd.h"
+#include "log.h"
+
+enum {
+ QUERY_READY,
+ QUERY_RUNNING,
+ QUERY_DONE
+};
+
+
+struct filter_proc {
+ TAILQ_ENTRY(filter_proc) entry;
+ struct mproc mproc;
+ int hooks;
+ int flags;
+ int ready;
+};
+
+struct filter {
+ TAILQ_ENTRY(filter) entry;
+ struct filter_proc *proc;
+};
+TAILQ_HEAD(filter_lst, filter);
+
+TAILQ_HEAD(filter_query_lst, filter_query);
+struct filter_session {
+ uint64_t id;
+ int terminate;
+ struct filter_lst *filters;
+ struct filter *fcurr;
+
+ int error;
+ struct io *iev;
+ size_t idatalen;
+ FILE *ofile;
+
+ struct filter_query *eom;
+};
+
+struct filter_query {
+ uint64_t qid;
+ int type;
+ struct filter_session *session;
+
+ int state;
+ struct filter *current;
+
+ /* current data */
+ union {
+ struct {
+ struct sockaddr_storage local;
+ struct sockaddr_storage remote;
+ char hostname[HOST_NAME_MAX+1];
+ } connect;
+ char line[LINE_MAX];
+ struct mailaddr maddr;
+ size_t datalen;
+ } u;
+
+ /* current response */
+ struct {
+ int status;
+ int code;
+ char *response;
+ } smtp;
+};
+
+static void filter_imsg(struct mproc *, struct imsg *);
+static void filter_post_event(uint64_t, int, struct filter *, struct filter *);
+static struct filter_query *filter_query(struct filter_session *, int);
+static void filter_drain_query(struct filter_query *);
+static void filter_run_query(struct filter *, struct filter_query *);
+static void filter_end_query(struct filter_query *);
+static void filter_set_sink(struct filter_session *, int);
+static int filter_tx(struct filter_session *, int);
+static void filter_tx_io(struct io *, int, void *);
+
+static TAILQ_HEAD(, filter_proc) procs;
+struct dict chains;
+
+static const char * filter_session_to_text(struct filter_session *);
+static const char * filter_query_to_text(struct filter_query *);
+static const char * filter_to_text(struct filter *);
+static const char * filter_proc_to_text(struct filter_proc *);
+static const char * query_to_str(int);
+static const char * event_to_str(int);
+static const char * status_to_str(int);
+static const char * filterimsg_to_str(int);
+
+struct tree sessions;
+struct tree queries;
+
+static void
+filter_add_arg(struct filter_conf *filter, char *arg)
+{
+ if (filter->argc == MAX_FILTER_ARGS) {
+ log_warnx("warn: filter \"%s\" is full", filter->name);
+ fatalx("exiting");
+ }
+ filter->argv[filter->argc++] = arg;
+}
+
+static void
+filter_extend_chain(struct filter_lst *chain, const char *name)
+{
+ struct filter *n;
+ struct filter_lst *fchain;
+ struct filter_conf *fconf;
+ int i;
+
+ fconf = dict_xget(&env->sc_filters, name);
+ if (fconf->chain) {
+ log_debug("filter: extending with \"%s\"", name);
+ for (i = 0; i < fconf->argc; i++)
+ filter_extend_chain(chain, fconf->argv[i]);
+ }
+ else {
+ log_debug("filter: adding filter \"%s\"", name);
+ n = xcalloc(1, sizeof(*n), "filter_extend_chain");
+ fchain = dict_get(&chains, name);
+ n->proc = TAILQ_FIRST(fchain)->proc;
+ TAILQ_INSERT_TAIL(chain, n, entry);
+ }
+}
+
+void
+filter_postfork(void)
+{
+ static int prepare = 0;
+ struct filter_conf *filter;
+ void *iter;
+ struct filter_proc *proc;
+ struct filter_lst *fchain;
+ struct filter *f;
+ struct mproc *p;
+ int done, i;
+
+ if (prepare)
+ return;
+ prepare = 1;
+
+ TAILQ_INIT(&procs);
+ dict_init(&chains);
+
+ log_debug("filter: building simple chains...");
+
+ /* create all filter proc and associated chains */
+ iter = NULL;
+ while (dict_iter(&env->sc_filters, &iter, NULL, (void **)&filter)) {
+ if (filter->chain)
+ continue;
+
+ log_debug("filter: building simple chain \"%s\"", filter->name);
+ proc = xcalloc(1, sizeof(*proc), "filter_postfork");
+ p = &proc->mproc;
+ p->handler = filter_imsg;
+ p->proc = PROC_FILTER;
+ p->name = xstrdup(filter->name, "filter_postfork");
+ p->data = proc;
+ if (tracing & TRACE_DEBUG)
+ filter_add_arg(filter, "-v");
+ if (foreground_log)
+ filter_add_arg(filter, "-d");
+ if (mproc_fork(p, filter->path, filter->argv) < 0)
+ fatalx("filter_postfork");
+
+ log_debug("filter: registering proc \"%s\"", filter->name);
+ f = xcalloc(1, sizeof(*f), "filter_postfork");
+ f->proc = proc;
+
+ TAILQ_INSERT_TAIL(&procs, proc, entry);
+ fchain = xcalloc(1, sizeof(*fchain), "filter_postfork");
+ TAILQ_INIT(fchain);
+ TAILQ_INSERT_TAIL(fchain, f, entry);
+ dict_xset(&chains, filter->name, fchain);
+ filter->done = 1;
+ }
+
+ log_debug("filter: building complex chains...");
+
+ /* resolve all chains */
+ done = 0;
+ while (!done) {
+ done = 1;
+ iter = NULL;
+ while (dict_iter(&env->sc_filters, &iter, NULL,
+ (void **)&filter)) {
+ if (filter->done)
+ continue;
+ done = 0;
+ filter->done = 1;
+ for (i = 0; i < filter->argc; i++) {
+ if (!dict_get(&chains, filter->argv[i])) {
+ filter->done = 0;
+ break;
+ }
+ }
+ if (filter->done == 0)
+ continue;
+ fchain = xcalloc(1, sizeof(*fchain), "filter_postfork");
+ TAILQ_INIT(fchain);
+ log_debug("filter: building chain \"%s\"...",
+ filter->name);
+ for (i = 0; i < filter->argc; i++)
+ filter_extend_chain(fchain, filter->argv[i]);
+ log_debug("filter: done building chain \"%s\"",
+ filter->name);
+ dict_xset(&chains, filter->name, fchain);
+ }
+ }
+ log_debug("filter: done building complex chains");
+
+ fchain = xcalloc(1, sizeof(*fchain), "filter_postfork");
+ TAILQ_INIT(fchain);
+ dict_xset(&chains, "<no-filter>", fchain);
+}
+
+void
+filter_configure(void)
+{
+ static int init = 0;
+ struct filter_proc *p;
+
+ if (init)
+ return;
+ init = 1;
+
+ tree_init(&sessions);
+ tree_init(&queries);
+
+ TAILQ_FOREACH(p, &procs, entry) {
+ m_create(&p->mproc, IMSG_FILTER_REGISTER, 0, 0, -1);
+ m_add_u32(&p->mproc, FILTER_API_VERSION);
+ m_add_string(&p->mproc, p->mproc.name);
+ m_close(&p->mproc);
+ mproc_enable(&p->mproc);
+ }
+
+ if (TAILQ_FIRST(&procs) == NULL)
+ smtp_configure();
+}
+
+void
+filter_event(uint64_t id, int event)
+{
+ struct filter_session *s;
+
+ if (event == EVENT_DISCONNECT)
+ /* On disconnect, the session is virtualy dead */
+ s = tree_xpop(&sessions, id);
+ else
+ s = tree_xget(&sessions, id);
+
+ filter_post_event(id, event, TAILQ_FIRST(s->filters), NULL);
+
+ if (event == EVENT_DISCONNECT) {
+ if (s->iev)
+ io_free(s->iev);
+ if (s->ofile)
+ fclose(s->ofile);
+ free(s);
+ }
+}
+
+void
+filter_connect(uint64_t id, const struct sockaddr *local,
+ const struct sockaddr *remote, const char *host, const char *filter)
+{
+ struct filter_session *s;
+ struct filter_query *q;
+
+ s = xcalloc(1, sizeof(*s), "filter_event");
+ s->id = id;
+ if (filter == NULL)
+ filter = "<no-filter>";
+ s->filters = dict_xget(&chains, filter);
+ tree_xset(&sessions, s->id, s);
+
+ filter_event(id, EVENT_CONNECT);
+ q = filter_query(s, QUERY_CONNECT);
+
+ memmove(&q->u.connect.local, local, SA_LEN(local));
+ memmove(&q->u.connect.remote, remote, SA_LEN(remote));
+ strlcpy(q->u.connect.hostname, host, sizeof(q->u.connect.hostname));
+
+ q->smtp.status = FILTER_OK;
+ q->smtp.code = 0;
+ q->smtp.response = NULL;
+
+ filter_drain_query(q);
+}
+
+void
+filter_mailaddr(uint64_t id, int type, const struct mailaddr *maddr)
+{
+ struct filter_session *s;
+ struct filter_query *q;
+
+ s = tree_xget(&sessions, id);
+ q = filter_query(s, type);
+
+ strlcpy(q->u.maddr.user, maddr->user, sizeof(q->u.maddr.user));
+ strlcpy(q->u.maddr.domain, maddr->domain, sizeof(q->u.maddr.domain));
+
+ filter_drain_query(q);
+}
+
+void
+filter_line(uint64_t id, int type, const char *line)
+{
+ struct filter_session *s;
+ struct filter_query *q;
+
+ s = tree_xget(&sessions, id);
+ q = filter_query(s, type);
+
+ if (line)
+ strlcpy(q->u.line, line, sizeof(q->u.line));
+
+ filter_drain_query(q);
+}
+
+void
+filter_eom(uint64_t id, int type, size_t datalen)
+{
+ struct filter_session *s;
+ struct filter_query *q;
+
+ s = tree_xget(&sessions, id);
+ q = filter_query(s, type);
+ q->u.datalen = datalen;
+
+ filter_drain_query(q);
+}
+
+static void
+filter_set_sink(struct filter_session *s, int sink)
+{
+ struct mproc *p;
+
+ while (s->fcurr) {
+ if (s->fcurr->proc->hooks & HOOK_DATALINE) {
+ log_trace(TRACE_FILTERS, "filter: sending fd %d to %s",
+ sink, filter_to_text(s->fcurr));
+ p = &s->fcurr->proc->mproc;
+ m_create(p, IMSG_FILTER_PIPE, 0, 0, sink);
+ m_add_id(p, s->id);
+ m_close(p);
+ return;
+ }
+ s->fcurr = TAILQ_PREV(s->fcurr, filter_lst, entry);
+ }
+
+ log_trace(TRACE_FILTERS, "filter: chain input is %d", sink);
+ smtp_filter_fd(s->id, sink);
+}
+
+void
+filter_build_fd_chain(uint64_t id, int sink)
+{
+ struct filter_session *s;
+ int fd;
+
+ s = tree_xget(&sessions, id);
+ s->fcurr = TAILQ_LAST(s->filters, filter_lst);
+
+ fd = filter_tx(s, sink);
+ filter_set_sink(s, fd);
+}
+
+void
+filter_post_event(uint64_t id, int event, struct filter *f, struct filter *end)
+{
+ for(; f && f != end; f = TAILQ_NEXT(f, entry)) {
+ log_trace(TRACE_FILTERS, "filter: post-event event=%s filter=%s",
+ event_to_str(event), f->proc->mproc.name);
+
+ m_create(&f->proc->mproc, IMSG_FILTER_EVENT, 0, 0, -1);
+ m_add_id(&f->proc->mproc, id);
+ m_add_int(&f->proc->mproc, event);
+ m_close(&f->proc->mproc);
+ }
+}
+
+static struct filter_query *
+filter_query(struct filter_session *s, int type)
+{
+ struct filter_query *q;
+
+ q = xcalloc(1, sizeof(*q), "filter_query");
+ q->qid = generate_uid();
+ q->session = s;
+ q->type = type;
+
+ q->state = QUERY_READY;
+ q->current = TAILQ_FIRST(s->filters);
+
+ log_trace(TRACE_FILTERS, "filter: new query %s", query_to_str(type));
+
+ return (q);
+}
+
+static void
+filter_drain_query(struct filter_query *q)
+{
+ log_trace(TRACE_FILTERS, "filter: filter_drain_query %s",
+ filter_query_to_text(q));
+
+ /*
+ * The query must be passed through all filters that registered
+ * a hook, until one rejects it.
+ */
+ while (q->state != QUERY_DONE) {
+ /* Walk over all filters */
+ while (q->current) {
+ filter_run_query(q->current, q);
+ if (q->state == QUERY_RUNNING) {
+ log_trace(TRACE_FILTERS,
+ "filter: waiting for running query %s",
+ filter_query_to_text(q));
+ return;
+ }
+ }
+ q->state = QUERY_DONE;
+ }
+
+ /* Defer the response if the file is not closed yet. */
+ if (q->type == QUERY_EOM && q->session->ofile && q->smtp.status == FILTER_OK) {
+ log_debug("filter: deferring eom query...");
+ q->session->eom = q;
+ return;
+ }
+
+ filter_end_query(q);
+}
+
+static void
+filter_run_query(struct filter *f, struct filter_query *q)
+{
+ log_trace(TRACE_FILTERS,
+ "filter: running filter %s for query %s",
+ filter_to_text(f), filter_query_to_text(q));
+
+ m_create(&f->proc->mproc, IMSG_FILTER_QUERY, 0, 0, -1);
+ m_add_id(&f->proc->mproc, q->session->id);
+ m_add_id(&f->proc->mproc, q->qid);
+ m_add_int(&f->proc->mproc, q->type);
+
+ switch (q->type) {
+ case QUERY_CONNECT:
+ m_add_sockaddr(&f->proc->mproc,
+ (struct sockaddr *)&q->u.connect.local);
+ m_add_sockaddr(&f->proc->mproc,
+ (struct sockaddr *)&q->u.connect.remote);
+ m_add_string(&f->proc->mproc, q->u.connect.hostname);
+ break;
+ case QUERY_HELO:
+ m_add_string(&f->proc->mproc, q->u.line);
+ break;
+ case QUERY_MAIL:
+ case QUERY_RCPT:
+ m_add_mailaddr(&f->proc->mproc, &q->u.maddr);
+ break;
+ case QUERY_EOM:
+ m_add_u32(&f->proc->mproc, q->u.datalen);
+ break;
+ default:
+ break;
+ }
+ m_close(&f->proc->mproc);
+
+ tree_xset(&queries, q->qid, q);
+ q->state = QUERY_RUNNING;
+}
+
+static void
+filter_end_query(struct filter_query *q)
+{
+ struct filter_session *s = q->session;
+ const char *response = q->smtp.response;
+
+ log_trace(TRACE_FILTERS, "filter: filter_end_query %s",
+ filter_query_to_text(q));
+
+ if (q->type == QUERY_EOM && q->smtp.status == FILTER_OK) {
+ if (s->error || q->u.datalen != s->idatalen) {
+ response = "Internal error";
+ q->smtp.code = 451;
+ q->smtp.status = FILTER_FAIL;
+ if (!s->error)
+ log_warnx("filter: datalen mismatch on session %" PRIx64
+ ": %zu/%zu", s->id, s->idatalen, q->u.datalen);
+ }
+ }
+
+ log_trace(TRACE_FILTERS,
+ "filter: query %016"PRIx64" done: "
+ "status=%s code=%d response=\"%s\"",
+ q->qid,
+ status_to_str(q->smtp.status),
+ q->smtp.code,
+ response);
+
+ smtp_filter_response(s->id, q->type, q->smtp.status, q->smtp.code,
+ response);
+ free(q->smtp.response);
+ free(q);
+}
+
+static void
+filter_imsg(struct mproc *p, struct imsg *imsg)
+{
+ struct filter_proc *proc = p->data;
+ struct filter_session *s;
+ struct filter_query *q;
+ struct msg m;
+ const char *line;
+ uint64_t qid;
+ uint32_t datalen;
+ int type, status, code;
+
+ if (imsg == NULL) {
+ log_warnx("warn: filter \"%s\" closed unexpectedly", p->name);
+ fatalx("exiting");
+ }
+
+ log_trace(TRACE_FILTERS, "filter: imsg %s from procfilter %s",
+ filterimsg_to_str(imsg->hdr.type),
+ filter_proc_to_text(proc));
+
+ switch (imsg->hdr.type) {
+
+ case IMSG_FILTER_REGISTER:
+ if (proc->ready) {
+ log_warnx("warn: filter \"%s\" already registered",
+ proc->mproc.name);
+ exit(1);
+ }
+
+ m_msg(&m, imsg);
+ m_get_int(&m, &proc->hooks);
+ m_get_int(&m, &proc->flags);
+ m_end(&m);
+ proc->ready = 1;
+
+ log_debug("debug: filter \"%s\": hooks 0x%08x flags 0x%04x",
+ proc->mproc.name, proc->hooks, proc->flags);
+
+ TAILQ_FOREACH(proc, &procs, entry)
+ if (!proc->ready)
+ return;
+
+ smtp_configure();
+ break;
+
+ case IMSG_FILTER_RESPONSE:
+ m_msg(&m, imsg);
+ m_get_id(&m, &qid);
+ m_get_int(&m, &type);
+ if (type == QUERY_EOM)
+ m_get_u32(&m, &datalen);
+ m_get_int(&m, &status);
+ m_get_int(&m, &code);
+ if (m_is_eom(&m))
+ line = NULL;
+ else
+ m_get_string(&m, &line);
+ m_end(&m);
+
+ q = tree_xpop(&queries, qid);
+ if (q->type != type) {
+ log_warnx("warn: filter: type mismatch %d != %d",
+ q->type, type);
+ fatalx("exiting");
+ }
+ q->smtp.status = status;
+ if (code)
+ q->smtp.code = code;
+ if (line) {
+ free(q->smtp.response);
+ q->smtp.response = xstrdup(line, "filter_imsg");
+ }
+ q->state = (status == FILTER_OK) ? QUERY_READY : QUERY_DONE;
+ if (type == QUERY_EOM)
+ q->u.datalen = datalen;
+
+ q->current = TAILQ_NEXT(q->current, entry);
+ filter_drain_query(q);
+ break;
+
+ case IMSG_FILTER_PIPE:
+ m_msg(&m, imsg);
+ m_get_id(&m, &qid);
+ m_end(&m);
+
+ s = tree_xget(&sessions, qid);
+ s->fcurr = TAILQ_PREV(s->fcurr, filter_lst, entry);
+ filter_set_sink(s, imsg->fd);
+ break;
+
+ default:
+ log_warnx("warn: bad imsg from filter %s", p->name);
+ exit(1);
+ }
+}
+
+static int
+filter_tx(struct filter_session *s, int sink)
+{
+ int sp[2];
+
+ s->idatalen = 0;
+ s->eom = NULL;
+ s->error = 0;
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) == -1) {
+ log_warn("warn: filter: socketpair");
+ return (-1);
+ }
+
+ if ((s->ofile = fdopen(sink, "w")) == NULL) {
+ log_warn("warn: filter: fdopen");
+ close(sp[0]);
+ close(sp[1]);
+ return (-1);
+ }
+
+ io_set_nonblocking(sp[0]);
+ io_set_nonblocking(sp[1]);
+
+ s->iev = io_new();
+ io_set_callback(s->iev, filter_tx_io, s);
+ io_set_fd(s->iev, sp[0]);
+ io_set_read(s->iev);
+
+ return (sp[1]);
+}
+
+static void
+filter_tx_io(struct io *io, int evt, void *arg)
+{
+ struct filter_session *s = arg;
+ size_t len, n;
+ char *data;
+
+ log_trace(TRACE_FILTERS, "filter: filter_tx_io(%p, %s)",
+ s, io_strevent(evt));
+
+ switch (evt) {
+ case IO_DATAIN:
+ data = io_data(s->iev);
+ len = io_datalen(s->iev);
+
+ log_trace(TRACE_FILTERS,
+ "filter: filter_tx_io: datain (%zu) for req %016"PRIx64"",
+ len, s->id);
+
+ n = fwrite(data, 1, len, s->ofile);
+ if (n != len) {
+ log_warnx("warn: filter_tx_io: fwrite %zu/%zu", n, len);
+ s->error = 1;
+ break;
+ }
+ s->idatalen += n;
+ io_drop(s->iev, n);
+ return;
+
+ case IO_DISCONNECTED:
+ log_trace(TRACE_FILTERS,
+ "debug: filter: tx done (%zu) for req %016"PRIx64,
+ s->idatalen, s->id);
+ break;
+
+ default:
+ log_warn("warn: filter_tx_io: bad evt (%d) for req %016"PRIx64,
+ evt, s->id);
+ s->error = 1;
+ break;
+ }
+
+ io_free(s->iev);
+ s->iev = NULL;
+ fclose(s->ofile);
+ s->ofile = NULL;
+
+ /* deferred eom request */
+ if (s->eom) {
+ log_debug("filter: running eom query...");
+ filter_end_query(s->eom);
+ } else {
+ log_debug("filter: eom not received yet");
+ }
+}
+
+static const char *
+filter_query_to_text(struct filter_query *q)
+{
+ static char buf[1024];
+ char tmp[1024];
+
+ tmp[0] = '\0';
+
+ switch (q->type) {
+ case QUERY_CONNECT:
+ strlcat(tmp, "=", sizeof tmp);
+ strlcat(tmp, ss_to_text(&q->u.connect.local),
+ sizeof tmp);
+ strlcat(tmp, " <-> ", sizeof tmp);
+ strlcat(tmp, ss_to_text(&q->u.connect.remote),
+ sizeof tmp);
+ strlcat(tmp, "(", sizeof tmp);
+ strlcat(tmp, q->u.connect.hostname, sizeof tmp);
+ strlcat(tmp, ")", sizeof tmp);
+ break;
+ case QUERY_MAIL:
+ case QUERY_RCPT:
+ snprintf(tmp, sizeof tmp, "=%s@%s",
+ q->u.maddr.user, q->u.maddr.domain);
+ break;
+ case QUERY_HELO:
+ snprintf(tmp, sizeof tmp, "=%s", q->u.line);
+ break;
+ default:
+ break;
+ }
+ snprintf(buf, sizeof buf, "%016"PRIx64"[%s%s,%s]",
+ q->qid, query_to_str(q->type), tmp,
+ filter_session_to_text(q->session));
+
+ return (buf);
+}
+
+static const char *
+filter_session_to_text(struct filter_session *s)
+{
+ static char buf[1024];
+
+ if (s == NULL)
+ return "filter_session@NULL";
+
+ snprintf(buf, sizeof(buf),
+ "filter_session@%p[datalen=%zu,eom=%p,ofile=%p]",
+ s, s->idatalen, s->eom, s->ofile);
+
+ return buf;
+}
+
+static const char *
+filter_to_text(struct filter *f)
+{
+ static char buf[1024];
+
+ snprintf(buf, sizeof buf, "filter:%s", filter_proc_to_text(f->proc));
+
+ return (buf);
+}
+
+static const char *
+filter_proc_to_text(struct filter_proc *proc)
+{
+ static char buf[1024];
+
+ snprintf(buf, sizeof buf, "%s[hooks=0x%08x,flags=0x%04x]",
+ proc->mproc.name, proc->hooks, proc->flags);
+
+ return (buf);
+}
+
+#define CASE(x) case x : return #x
+
+static const char *
+filterimsg_to_str(int imsg)
+{
+ switch (imsg) {
+ CASE(IMSG_FILTER_REGISTER);
+ CASE(IMSG_FILTER_EVENT);
+ CASE(IMSG_FILTER_QUERY);
+ CASE(IMSG_FILTER_PIPE);
+ CASE(IMSG_FILTER_RESPONSE);
+ default:
+ return "IMSG_FILTER_???";
+ }
+}
+
+static const char *
+query_to_str(int query)
+{
+ switch (query) {
+ CASE(QUERY_CONNECT);
+ CASE(QUERY_HELO);
+ CASE(QUERY_MAIL);
+ CASE(QUERY_RCPT);
+ CASE(QUERY_DATA);
+ CASE(QUERY_EOM);
+ CASE(QUERY_DATALINE);
+ default:
+ return "QUERY_???";
+ }
+}
+
+static const char *
+event_to_str(int event)
+{
+ switch (event) {
+ CASE(EVENT_CONNECT);
+ CASE(EVENT_RESET);
+ CASE(EVENT_DISCONNECT);
+ CASE(EVENT_TX_BEGIN);
+ CASE(EVENT_TX_COMMIT);
+ CASE(EVENT_TX_ROLLBACK);
+ default:
+ return "EVENT_???";
+ }
+}
+
+static const char *
+status_to_str(int status)
+{
+ switch (status) {
+ CASE(FILTER_OK);
+ CASE(FILTER_FAIL);
+ CASE(FILTER_CLOSE);
+ default:
+ return "FILTER_???";
+ }
+}
diff --git a/smtpd/forward.c b/smtpd/forward.c
index d30d55e9..7494c6ce 100644
--- a/smtpd/forward.c
+++ b/smtpd/forward.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -28,7 +30,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef HAVE_UTIL_H
#include <util.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
#include <unistd.h>
#include <limits.h>
diff --git a/smtpd/iobuf.c b/smtpd/iobuf.c
index 27c404a0..46d8ef04 100644
--- a/smtpd/iobuf.c
+++ b/smtpd/iobuf.c
@@ -15,6 +15,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
diff --git a/smtpd/ioev.c b/smtpd/ioev.c
index 44690766..28de5c7b 100644
--- a/smtpd/ioev.c
+++ b/smtpd/ioev.c
@@ -15,6 +15,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/socket.h>
@@ -749,10 +751,10 @@ io_connect(struct io *io, const struct sockaddr *sa, const struct sockaddr *bsa)
io_set_nonblocking(sock);
io_set_nolinger(sock);
- if (bsa && bind(sock, bsa, bsa->sa_len) == -1)
+ if (bsa && bind(sock, bsa, SA_LEN(bsa)) == -1)
goto fail;
- if (connect(sock, sa, sa->sa_len) == -1)
+ if (connect(sock, sa, SA_LEN(sa)) == -1)
if (errno != EINPROGRESS)
goto fail;
diff --git a/smtpd/libressl.c b/smtpd/libressl.c
new file mode 100644
index 00000000..57d74389
--- /dev/null
+++ b/smtpd/libressl.c
@@ -0,0 +1,213 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/*
+ * SSL operations needed when running in a privilege separated environment.
+ * Adapted from openssl's ssl_rsa.c by Pierre-Yves Ritschard .
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include <openssl/err.h>
+#include <openssl/bio.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+
+#include "log.h"
+#include "ssl.h"
+
+#define SSL_ECDH_CURVE "prime256v1"
+
+/*
+ * Read a bio that contains our certificate in "PEM" format,
+ * possibly followed by a sequence of CA certificates that should be
+ * sent to the peer in the Certificate message.
+ */
+static int
+ssl_ctx_use_certificate_chain_bio(SSL_CTX *ctx, BIO *in)
+{
+ int ret = 0;
+ X509 *x = NULL;
+
+ ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */
+
+ x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback,
+ ctx->default_passwd_callback_userdata);
+ if (x == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
+ goto end;
+ }
+
+ ret = SSL_CTX_use_certificate(ctx, x);
+
+ if (ERR_peek_error() != 0)
+ ret = 0;
+ /* Key/certificate mismatch doesn't imply ret==0 ... */
+ if (ret) {
+ /*
+ * If we could set up our certificate, now proceed to
+ * the CA certificates.
+ */
+ X509 *ca;
+ int r;
+ unsigned long err;
+
+ if (ctx->extra_certs != NULL) {
+ sk_X509_pop_free(ctx->extra_certs, X509_free);
+ ctx->extra_certs = NULL;
+ }
+
+ while ((ca = PEM_read_bio_X509(in, NULL,
+ ctx->default_passwd_callback,
+ ctx->default_passwd_callback_userdata)) != NULL) {
+ r = SSL_CTX_add_extra_chain_cert(ctx, ca);
+ if (!r) {
+ X509_free(ca);
+ ret = 0;
+ goto end;
+ }
+ /*
+ * Note that we must not free r if it was successfully
+ * added to the chain (while we must free the main
+ * certificate, since its reference count is increased
+ * by SSL_CTX_use_certificate).
+ */
+ }
+
+ /* When the while loop ends, it's usually just EOF. */
+ err = ERR_peek_last_error();
+ if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
+ ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
+ ERR_clear_error();
+ else
+ ret = 0; /* some real error */
+ }
+
+end:
+ if (x != NULL)
+ X509_free(x);
+ return (ret);
+}
+
+int
+SSL_CTX_use_certificate_chain_mem(SSL_CTX *ctx, void *buf, int len)
+{
+ BIO *in;
+ int ret = 0;
+
+ in = BIO_new_mem_buf(buf, len);
+ if (in == NULL) {
+ SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ ret = ssl_ctx_use_certificate_chain_bio(ctx, in);
+
+end:
+ BIO_free(in);
+ return (ret);
+}
+
+#ifndef HAVE_SSL_CTX_SET_ECDH_AUTO
+void
+SSL_CTX_set_ecdh_auto(SSL_CTX *ctx, int enable)
+{
+ int nid;
+ EC_KEY *ecdh;
+
+ if (!enable)
+ return;
+
+ if ((nid = OBJ_sn2nid(SSL_ECDH_CURVE)) == 0) {
+ ssl_error("ssl_set_ecdh_auto");
+ fatal("ssl_set_ecdh_auto: unknown curve name "
+ SSL_ECDH_CURVE);
+ }
+
+ if ((ecdh = EC_KEY_new_by_curve_name(nid)) == NULL) {
+ ssl_error("ssl_set_ecdh_auto");
+ fatal("ssl_set_ecdh_auto: unable to create curve "
+ SSL_ECDH_CURVE);
+ }
+
+ SSL_CTX_set_tmp_ecdh(ctx, ecdh);
+ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
+ EC_KEY_free(ecdh);
+}
+#endif
+
+#ifndef HAVE_SSL_CTX_SET_DH_AUTO
+void
+SSL_CTX_set_dh_auto(SSL_CTX *ctx, int enable)
+{
+ if (!enable)
+ return;
+
+ /* stub until OpenSSL catches up with this ... */
+ log_warnx("OpenSSL does not support SSL_CTX_set_dh_auto (yet ?)");
+ return;
+}
+#endif
diff --git a/smtpd/limit.c b/smtpd/limit.c
index e7d0cb17..25e7a026 100644
--- a/smtpd/limit.c
+++ b/smtpd/limit.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/lka.c b/smtpd/lka.c
index 27569d19..519fb1d7 100644
--- a/smtpd/lka.c
+++ b/smtpd/lka.c
@@ -18,6 +18,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -31,6 +33,8 @@
#include <err.h>
#include <errno.h>
#include <event.h>
+#include <netdb.h>
+#include <grp.h> /* needed for setgroups */
#include <imsg.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
diff --git a/smtpd/lka_filter.c b/smtpd/lka_filter.c
index 3daa57a3..16c8f2ea 100644
--- a/smtpd/lka_filter.c
+++ b/smtpd/lka_filter.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/lka_proc.c b/smtpd/lka_proc.c
index fb3a4137..eafebbec 100644
--- a/smtpd/lka_proc.c
+++ b/smtpd/lka_proc.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/lka_report.c b/smtpd/lka_report.c
index e8eb3348..ddf7c7cf 100644
--- a/smtpd/lka_report.c
+++ b/smtpd/lka_report.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/lka_session.c b/smtpd/lka_session.c
index 0ae31548..bca6ad31 100644
--- a/smtpd/lka_session.c
+++ b/smtpd/lka_session.c
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -516,7 +518,7 @@ lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
"run with %s privileges", SMTPD_USER);
if (xn->type == EXPAND_FILENAME)
- format = "/usr/libexec/mail.mboxfile -f %%{mbox.from} %s";
+ format = PATH_LIBEXEC"/mail.mboxfile -f %%{mbox.from} %s";
else if (xn->type == EXPAND_FILTER)
format = "%s";
(void)snprintf(ep->mda_exec, sizeof(ep->mda_exec),
diff --git a/smtpd/log.c b/smtpd/log.c
index 7ec8ca42..14f681e3 100644
--- a/smtpd/log.c
+++ b/smtpd/log.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
diff --git a/smtpd/log.h b/smtpd/log.h
index 22bb4164..81d0973c 100644
--- a/smtpd/log.h
+++ b/smtpd/log.h
@@ -19,8 +19,14 @@
#ifndef LOG_H
#define LOG_H
+#include "openbsd-compat.h"
+
+#include <syslog.h>
+
#include <stdarg.h>
+#ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
+#endif
void log_init(int, int);
void log_procinit(const char *);
diff --git a/smtpd/mail.lmtp.c b/smtpd/mail.lmtp.c
index d831ca2f..685ec504 100644
--- a/smtpd/mail.lmtp.c
+++ b/smtpd/mail.lmtp.c
@@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
diff --git a/smtpd/mail.maildir.c b/smtpd/mail.maildir.c
index e1796e0e..637d3f72 100644
--- a/smtpd/mail.maildir.c
+++ b/smtpd/mail.maildir.c
@@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
diff --git a/smtpd/mail.mboxfile.c b/smtpd/mail.mboxfile.c
index 6dbcc058..bf6951d8 100644
--- a/smtpd/mail.mboxfile.c
+++ b/smtpd/mail.mboxfile.c
@@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/stat.h>
@@ -26,6 +28,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
static void mboxfile_engine(const char *sender, const char *filename);
@@ -71,7 +74,13 @@ mboxfile_engine(const char *sender, const char *filename)
time(&now);
+#ifndef O_EXLOCK
+#define O_EXLOCK 0
+#endif
fd = open(filename, O_CREAT | O_APPEND | O_WRONLY | O_EXLOCK, 0600);
+#ifndef HAVE_O_EXLOCK
+ /* XXX : do something! */
+#endif
if (fd < 0)
err(1, NULL);
diff --git a/smtpd/mail.mda.c b/smtpd/mail.mda.c
index f9fb3236..23958071 100644
--- a/smtpd/mail.mda.c
+++ b/smtpd/mail.mda.c
@@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
diff --git a/smtpd/mailaddr.c b/smtpd/mailaddr.c
index a15470d7..4346e3dc 100644
--- a/smtpd/mailaddr.c
+++ b/smtpd/mailaddr.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/makemap.c b/smtpd/makemap.c
index 51c475e6..fed53855 100644
--- a/smtpd/makemap.c
+++ b/smtpd/makemap.c
@@ -17,6 +17,11 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h> /* Needed for flock */
+#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/tree.h>
@@ -24,7 +29,13 @@
#include <sys/socket.h>
#include <ctype.h>
+#ifdef HAVE_DB_H
#include <db.h>
+#elif defined(HAVE_DB1_DB_H)
+#include <db1/db.h>
+#elif defined(HAVE_DB_185_H)
+#include <db_185.h>
+#endif
#include <err.h>
#include <errno.h>
#include <event.h>
@@ -36,12 +47,17 @@
#include <syslog.h>
#include <unistd.h>
#include <limits.h>
+#ifdef HAVE_UTIL_H
#include <util.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
#include "smtpd.h"
#include "log.h"
-#define PATH_ALIASES "/etc/mail/aliases"
+#define PATH_ALIASES SMTPD_CONFDIR "/aliases"
static void usage(void);
static int parse_map(DB *, int *, char *);
diff --git a/smtpd/mda.c b/smtpd/mda.c
index ed7911a2..a8ee7c29 100644
--- a/smtpd/mda.c
+++ b/smtpd/mda.c
@@ -19,6 +19,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -28,6 +30,7 @@
#include <err.h>
#include <errno.h>
#include <event.h>
+#include <grp.h> /* needed for setgroups */
#include <imsg.h>
#include <inttypes.h>
#include <pwd.h>
@@ -39,7 +42,11 @@
#include <time.h>
#include <unistd.h>
#include <limits.h>
+#if defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
#include <vis.h>
+#else
+#include "bsd-vis.h"
+#endif
#include "smtpd.h"
#include "log.h"
@@ -516,7 +523,7 @@ mda_getlastline(int fd, char *dst, size_t dstsz)
size_t sz = 0;
ssize_t len;
int out = 0;
-
+
if (lseek(fd, 0, SEEK_SET) < 0) {
log_warn("warn: mda: lseek");
close(fd);
diff --git a/smtpd/mda_unpriv.c b/smtpd/mda_unpriv.c
index 59c89941..60531051 100644
--- a/smtpd/mda_unpriv.c
+++ b/smtpd/mda_unpriv.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/mda_variables.c b/smtpd/mda_variables.c
index 03052e21..df453477 100644
--- a/smtpd/mda_variables.c
+++ b/smtpd/mda_variables.c
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/mproc.c b/smtpd/mproc.c
index d5a934d4..e1bf324f 100644
--- a/smtpd/mproc.c
+++ b/smtpd/mproc.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/tree.h>
@@ -60,8 +62,7 @@ mproc_fork(struct mproc *p, const char *path, char *argv[])
if (p->pid == 0) {
/* child process */
dup2(sp[0], STDIN_FILENO);
- if (closefrom(STDERR_FILENO + 1) < 0)
- exit(1);
+ closefrom(STDERR_FILENO + 1);
execv(path, argv);
err(1, "execv: %s", path);
@@ -484,8 +485,8 @@ m_add_msgid(struct mproc *m, uint32_t v)
void
m_add_sockaddr(struct mproc *m, const struct sockaddr *sa)
{
- m_add_size(m, sa->sa_len);
- m_add(m, sa, sa->sa_len);
+ m_add_size(m, SA_LEN(sa));
+ m_add(m, sa, SA_LEN(sa));
}
void
diff --git a/smtpd/mta.c b/smtpd/mta.c
index b7a841d1..a1e0c030 100644
--- a/smtpd/mta.c
+++ b/smtpd/mta.c
@@ -19,6 +19,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -31,6 +33,7 @@
#include <imsg.h>
#include <inttypes.h>
#include <netdb.h>
+#include <grp.h> /* needed for setgroups */
#include <limits.h>
#include <pwd.h>
#include <signal.h>
@@ -2093,13 +2096,13 @@ mta_host(const struct sockaddr *sa)
struct mta_host key, *h;
struct sockaddr_storage ss;
- memmove(&ss, sa, sa->sa_len);
+ memmove(&ss, sa, SA_LEN(sa));
key.sa = (struct sockaddr*)&ss;
h = SPLAY_FIND(mta_host_tree, &hosts, &key);
if (h == NULL) {
h = xcalloc(1, sizeof(*h));
- h->sa = xmemdup(sa, sa->sa_len);
+ h->sa = xmemdup(sa, SA_LEN(sa));
SPLAY_INSERT(mta_host_tree, &hosts, h);
stat_increment("mta.host", 1);
}
@@ -2144,11 +2147,11 @@ mta_host_to_text(struct mta_host *h)
static int
mta_host_cmp(const struct mta_host *a, const struct mta_host *b)
{
- if (a->sa->sa_len < b->sa->sa_len)
+ if (SA_LEN(a->sa) < SA_LEN(b->sa))
return (-1);
- if (a->sa->sa_len > b->sa->sa_len)
+ if (SA_LEN(a->sa) > SA_LEN(b->sa))
return (1);
- return (memcmp(a->sa, b->sa, a->sa->sa_len));
+ return (memcmp(a->sa, b->sa, SA_LEN(a->sa)));
}
SPLAY_GENERATE(mta_host_tree, mta_host, entry, mta_host_cmp);
@@ -2222,7 +2225,7 @@ mta_source(const struct sockaddr *sa)
struct sockaddr_storage ss;
if (sa) {
- memmove(&ss, sa, sa->sa_len);
+ memmove(&ss, sa, SA_LEN(sa));
key.sa = (struct sockaddr*)&ss;
} else
key.sa = NULL;
@@ -2231,7 +2234,7 @@ mta_source(const struct sockaddr *sa)
if (s == NULL) {
s = xcalloc(1, sizeof(*s));
if (sa)
- s->sa = xmemdup(sa, sa->sa_len);
+ s->sa = xmemdup(sa, SA_LEN(sa));
SPLAY_INSERT(mta_source_tree, &sources, s);
stat_increment("mta.source", 1);
}
@@ -2276,11 +2279,11 @@ mta_source_cmp(const struct mta_source *a, const struct mta_source *b)
return ((b->sa == NULL) ? 0 : -1);
if (b->sa == NULL)
return (1);
- if (a->sa->sa_len < b->sa->sa_len)
+ if (SA_LEN(a->sa) < SA_LEN(b->sa))
return (-1);
- if (a->sa->sa_len > b->sa->sa_len)
+ if (SA_LEN(a->sa) > SA_LEN(b->sa))
return (1);
- return (memcmp(a->sa, b->sa, a->sa->sa_len));
+ return (memcmp(a->sa, b->sa, SA_LEN(a->sa)));
}
SPLAY_GENERATE(mta_source_tree, mta_source, entry, mta_source_cmp);
diff --git a/smtpd/mta_session.c b/smtpd/mta_session.c
index 755ac86d..655c205f 100644
--- a/smtpd/mta_session.c
+++ b/smtpd/mta_session.c
@@ -19,6 +19,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -533,7 +535,7 @@ mta_connect(struct mta_session *s)
if (s->relay->port)
portno = s->relay->port;
- memmove(&ss, s->route->dst->sa, s->route->dst->sa->sa_len);
+ memmove(&ss, s->route->dst->sa, SA_LEN(s->route->dst->sa));
sa = (struct sockaddr *)&ss;
if (sa->sa_family == AF_INET)
diff --git a/smtpd/parse.y b/smtpd/parse.y
index f68ebe8e..fae944a0 100644
--- a/smtpd/parse.y
+++ b/smtpd/parse.y
@@ -22,7 +22,10 @@
*/
%{
+#include "includes.h"
+
#include <sys/types.h>
+#include <sys/time.h>
#include <sys/queue.h>
#include <sys/tree.h>
#include <sys/socket.h>
@@ -43,13 +46,16 @@
#include <limits.h>
#include <netdb.h>
#include <pwd.h>
+#include <stdarg.h>
#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
+#ifdef HAVE_UTIL_H
#include <util.h>
+#endif
#include <openssl/ssl.h>
@@ -639,41 +645,41 @@ dispatcher_local:
MBOX {
dispatcher->u.local.requires_root = 1;
dispatcher->u.local.user = xstrdup("root");
- asprintf(&dispatcher->u.local.command, "/usr/libexec/mail.local -f %%{mbox.from} %%{user.username}");
+ asprintf(&dispatcher->u.local.command, PATH_LIBEXEC"/mail.local -f %%{mbox.from} %%{user.username}");
} dispatcher_local_options
| MAILDIR {
- asprintf(&dispatcher->u.local.command, "/usr/libexec/mail.maildir");
+ asprintf(&dispatcher->u.local.command, PATH_LIBEXEC"/mail.maildir");
} dispatcher_local_options
| MAILDIR JUNK {
- asprintf(&dispatcher->u.local.command, "/usr/libexec/mail.maildir -j");
+ asprintf(&dispatcher->u.local.command, PATH_LIBEXEC"/mail.maildir -j");
} dispatcher_local_options
| MAILDIR STRING {
if (strncmp($2, "~/", 2) == 0)
asprintf(&dispatcher->u.local.command,
- "/usr/libexec/mail.maildir \"%%{user.directory}/%s\"", $2+2);
+ PATH_LIBEXEC"/mail.maildir \"%%{user.directory}/%s\"", $2+2);
else
asprintf(&dispatcher->u.local.command,
- "/usr/libexec/mail.maildir \"%s\"", $2);
+ PATH_LIBEXEC"/mail.maildir \"%s\"", $2);
} dispatcher_local_options
| MAILDIR STRING JUNK {
if (strncmp($2, "~/", 2) == 0)
asprintf(&dispatcher->u.local.command,
- "/usr/libexec/mail.maildir -j \"%%{user.directory}/%s\"", $2+2);
+ PATH_LIBEXEC"/mail.maildir -j \"%%{user.directory}/%s\"", $2+2);
else
asprintf(&dispatcher->u.local.command,
- "/usr/libexec/mail.maildir -j \"%s\"", $2);
+ PATH_LIBEXEC"/mail.maildir -j \"%s\"", $2);
} dispatcher_local_options
| LMTP STRING {
asprintf(&dispatcher->u.local.command,
- "/usr/libexec/mail.lmtp -f %%{mbox.from} -d %s %%{user.username}", $2);
+ PATH_LIBEXEC"/mail.lmtp -f %%{mbox.from} -d %s %%{user.username}", $2);
} dispatcher_local_options
| LMTP STRING RCPT_TO {
asprintf(&dispatcher->u.local.command,
- "/usr/libexec/mail.lmtp -f %%{mbox.from} -d %s %%{dest}", $2);
+ PATH_LIBEXEC"/mail.lmtp -f %%{mbox.from} -d %s %%{dest}", $2);
} dispatcher_local_options
| MDA STRING {
asprintf(&dispatcher->u.local.command,
- "/usr/libexec/mail.mda \"%s\"", $2);
+ PATH_LIBEXEC"/mail.mda \"%s\"", $2);
} dispatcher_local_options
| FORWARD_ONLY {
dispatcher->u.local.forward_only = 1;
@@ -2767,7 +2773,9 @@ create_sock_listener(struct listen_opts *lo)
lo->tag = "local";
lo->hostname = conf->sc_hostname;
l->ss.ss_family = AF_LOCAL;
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
l->ss.ss_len = sizeof(struct sockaddr *);
+#endif
l->local = 1;
conf->sc_sock_listener = l;
config_listener(l, lo);
@@ -2899,7 +2907,9 @@ host_v4(struct listen_opts *lo)
h = xcalloc(1, sizeof(*h));
sain = (struct sockaddr_in *)&h->ss;
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
sain->sin_len = sizeof(struct sockaddr_in);
+#endif
sain->sin_family = AF_INET;
sain->sin_addr.s_addr = ina.s_addr;
sain->sin_port = lo->port;
@@ -2927,7 +2937,9 @@ host_v6(struct listen_opts *lo)
h = xcalloc(1, sizeof(*h));
sin6 = (struct sockaddr_in6 *)&h->ss;
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
sin6->sin6_len = sizeof(struct sockaddr_in6);
+#endif
sin6->sin6_family = AF_INET6;
sin6->sin6_port = lo->port;
memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6));
@@ -2970,7 +2982,9 @@ host_dns(struct listen_opts *lo)
h->ss.ss_family = res->ai_family;
if (res->ai_family == AF_INET) {
sain = (struct sockaddr_in *)&h->ss;
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
sain->sin_len = sizeof(struct sockaddr_in);
+#endif
sain->sin_addr.s_addr = ((struct sockaddr_in *)
res->ai_addr)->sin_addr.s_addr;
sain->sin_port = lo->port;
@@ -2978,7 +2992,9 @@ host_dns(struct listen_opts *lo)
h->local = 1;
} else {
sin6 = (struct sockaddr_in6 *)&h->ss;
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
sin6->sin6_len = sizeof(struct sockaddr_in6);
+#endif
memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
sin6->sin6_port = lo->port;
@@ -3022,7 +3038,9 @@ interface(struct listen_opts *lo)
case AF_INET:
sain = (struct sockaddr_in *)&h->ss;
*sain = *(struct sockaddr_in *)p->ifa_addr;
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
sain->sin_len = sizeof(struct sockaddr_in);
+#endif
sain->sin_port = lo->port;
if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
h->local = 1;
@@ -3031,7 +3049,9 @@ interface(struct listen_opts *lo)
case AF_INET6:
sin6 = (struct sockaddr_in6 *)&h->ss;
*sin6 = *(struct sockaddr_in6 *)p->ifa_addr;
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
sin6->sin6_len = sizeof(struct sockaddr_in6);
+#endif
sin6->sin6_port = lo->port;
if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
h->local = 1;
@@ -3100,6 +3120,7 @@ bad:
int
is_if_in_group(const char *ifname, const char *groupname)
{
+#ifdef HAVE_STRUCT_IFGROUPREQ
unsigned int len;
struct ifgroupreq ifgr;
struct ifg_req *ifg;
@@ -3138,6 +3159,9 @@ is_if_in_group(const char *ifname, const char *groupname)
end:
close(s);
return ret;
+#else
+ return (0);
+#endif
}
static int
diff --git a/smtpd/parser.c b/smtpd/parser.c
index df90e508..997e3405 100644
--- a/smtpd/parser.c
+++ b/smtpd/parser.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/socket.h>
@@ -281,7 +283,9 @@ text_to_sockaddr(struct sockaddr *sa, int family, const char *str)
in = (struct sockaddr_in *)sa;
memset(in, 0, sizeof *in);
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
in->sin_len = sizeof(struct sockaddr_in);
+#endif
in->sin_family = PF_INET;
in->sin_addr.s_addr = ina.s_addr;
return (0);
@@ -304,7 +308,9 @@ text_to_sockaddr(struct sockaddr *sa, int family, const char *str)
in6 = (struct sockaddr_in6 *)sa;
memset(in6, 0, sizeof *in6);
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
in6->sin6_len = sizeof(struct sockaddr_in6);
+#endif
in6->sin6_family = PF_INET6;
in6->sin6_addr = in6a;
@@ -313,7 +319,7 @@ text_to_sockaddr(struct sockaddr *sa, int family, const char *str)
if (IN6_IS_ADDR_LINKLOCAL(&in6a) ||
IN6_IS_ADDR_MC_LINKLOCAL(&in6a) ||
- IN6_IS_ADDR_MC_INTFACELOCAL(&in6a))
+ IN6_IS_ADDR_MC_NODELOCAL(&in6a))
if ((in6->sin6_scope_id = if_nametoindex(cp)))
return (0);
diff --git a/smtpd/pony.c b/smtpd/pony.c
index abbde55e..75742fa7 100644
--- a/smtpd/pony.c
+++ b/smtpd/pony.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/queue.c b/smtpd/queue.c
index 489069ec..32bc55a7 100644
--- a/smtpd/queue.c
+++ b/smtpd/queue.c
@@ -18,6 +18,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -26,6 +28,8 @@
#include <err.h>
#include <event.h>
+#include <fcntl.h>
+#include <grp.h> /* needed for setgroups */
#include <imsg.h>
#include <inttypes.h>
#include <libgen.h>
diff --git a/smtpd/queue_backend.c b/smtpd/queue_backend.c
index 4337051e..7472febc 100644
--- a/smtpd/queue_backend.c
+++ b/smtpd/queue_backend.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/queue_fs.c b/smtpd/queue_fs.c
index 5960663f..869d4287 100644
--- a/smtpd/queue_fs.c
+++ b/smtpd/queue_fs.c
@@ -16,12 +16,19 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
+#if HAVE_SYS_MOUNT_H
#include <sys/mount.h>
+#endif
#include <sys/queue.h>
#include <sys/tree.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
#include <ctype.h>
#include <dirent.h>
@@ -341,8 +348,10 @@ queue_fs_message_walk(uint64_t *evpid, char *buf, size_t len,
(void)snprintf(msgid_str, sizeof msgid_str, "%08" PRIx32, msgid);
while ((dp = readdir(dir)) != NULL) {
+#if defined(HAVE_STRUCT_DIR_D_TYPE)
if (dp->d_type != DT_REG)
continue;
+#endif
/* ignore files other than envelopes */
if (strlen(dp->d_name) != 16 ||
@@ -411,6 +420,7 @@ queue_fs_envelope_walk(uint64_t *evpid, char *buf, size_t len)
static int
fsqueue_check_space(void)
{
+#ifdef __OpenBSD__
struct statfs buf;
uint64_t used;
uint64_t total;
@@ -454,7 +464,7 @@ fsqueue_check_space(void)
log_warnx("warn: temporarily rejecting messages");
return 0;
}
-
+#endif
return 1;
}
@@ -617,7 +627,12 @@ fsqueue_qwalk(void *hdl, uint64_t *evpid)
break;
if (e->fts_namelen != 16)
break;
+#if HAVE_STRUCT_STAT_ST_MTIM
if (timespeccmp(&e->fts_statp->st_mtim, &startup, >))
+#endif
+#if HAVE_STRUCT_STAT_ST_MTIMSPEC
+ if (timespeccmp(&e->fts_statp->st_mtimspec, &startup, >))
+#endif
break;
tmp = NULL;
*evpid = strtoull(e->fts_name, &tmp, 16);
diff --git a/smtpd/queue_null.c b/smtpd/queue_null.c
index c555e41d..c661e9cd 100644
--- a/smtpd/queue_null.c
+++ b/smtpd/queue_null.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/queue_proc.c b/smtpd/queue_proc.c
index 2c4beb4c..d94a6c21 100644
--- a/smtpd/queue_proc.c
+++ b/smtpd/queue_proc.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/queue_ram.c b/smtpd/queue_ram.c
index 81689f7b..2628faaf 100644
--- a/smtpd/queue_ram.c
+++ b/smtpd/queue_ram.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/report_smtp.c b/smtpd/report_smtp.c
index d2d8b27d..3f82e2cc 100644
--- a/smtpd/report_smtp.c
+++ b/smtpd/report_smtp.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -36,7 +38,11 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#if defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
#include <vis.h>
+#else
+#include "bsd-vis.h"
+#endif
#include "smtpd.h"
#include "log.h"
diff --git a/smtpd/resolver.c b/smtpd/resolver.c
index 54221416..aeb4e6bb 100644
--- a/smtpd/resolver.c
+++ b/smtpd/resolver.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/tree.h>
@@ -186,7 +188,7 @@ resolver_dispatch_request(struct mproc *proc, struct imsg *imsg)
if ((s = calloc(1, sizeof(*s))) &&
(s->host = malloc(NI_MAXHOST)) &&
(s->serv = malloc(NI_MAXSERV)) &&
- (q = getnameinfo_async(sa, sa->sa_len, s->host, NI_MAXHOST,
+ (q = getnameinfo_async(sa, SA_LEN(sa), s->host, NI_MAXHOST,
s->serv, NI_MAXSERV, flags, NULL)) &&
(event_asr_run(q, resolver_getnameinfo_cb, s))) {
s->reqid = reqid;
@@ -249,14 +251,14 @@ resolver_dispatch_result(struct mproc *proc, struct imsg *imsg)
m_get_string(&m, &cname);
m_end(&m);
- ai->ai_addr = malloc(ss.ss_len);
+ ai->ai_addr = malloc(SS_LEN(&ss));
if (ai->ai_addr == NULL) {
log_warn("%s: malloc", __func__);
free(ai);
break;
}
- memmove(ai->ai_addr, &ss, ss.ss_len);
+ memmove(ai->ai_addr, &ss, SS_LEN(&ss));
if (cname) {
ai->ai_canonname = strdup(cname);
diff --git a/smtpd/rfc5322.c b/smtpd/rfc5322.c
index 02ea7976..0af66772 100644
--- a/smtpd/rfc5322.c
+++ b/smtpd/rfc5322.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <ctype.h>
#include <errno.h>
#include <limits.h>
diff --git a/smtpd/ruleset.c b/smtpd/ruleset.c
index 7ab7755c..8fbeec01 100644
--- a/smtpd/ruleset.c
+++ b/smtpd/ruleset.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/runq.c b/smtpd/runq.c
index ce8c67ef..29b909ae 100644
--- a/smtpd/runq.c
+++ b/smtpd/runq.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>
diff --git a/smtpd/scheduler.c b/smtpd/scheduler.c
index de21342e..1f6810a7 100644
--- a/smtpd/scheduler.c
+++ b/smtpd/scheduler.c
@@ -19,6 +19,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -30,6 +32,7 @@
#include <err.h>
#include <errno.h>
#include <event.h>
+#include <grp.h> /* needed for setgroups */
#include <imsg.h>
#include <inttypes.h>
#include <libgen.h>
diff --git a/smtpd/scheduler_backend.c b/smtpd/scheduler_backend.c
index 061f1129..ad2b4cab 100644
--- a/smtpd/scheduler_backend.c
+++ b/smtpd/scheduler_backend.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/scheduler_null.c b/smtpd/scheduler_null.c
index a8c43331..40db6205 100644
--- a/smtpd/scheduler_null.c
+++ b/smtpd/scheduler_null.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/scheduler_proc.c b/smtpd/scheduler_proc.c
index 0f8c44b9..5f4e8b70 100644
--- a/smtpd/scheduler_proc.c
+++ b/smtpd/scheduler_proc.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/scheduler_ramqueue.c b/smtpd/scheduler_ramqueue.c
index 8d5efc10..0c04fc0b 100644
--- a/smtpd/scheduler_ramqueue.c
+++ b/smtpd/scheduler_ramqueue.c
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/smtp.c b/smtpd/smtp.c
index 61c99e5a..fc8253f3 100644
--- a/smtpd/smtp.c
+++ b/smtpd/smtp.c
@@ -18,6 +18,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -26,6 +28,7 @@
#include <err.h>
#include <errno.h>
#include <event.h>
+#include <grp.h> /* needed for setgroups */
#include <imsg.h>
#include <netdb.h>
#include <pwd.h>
@@ -55,6 +58,8 @@ static void smtp_accepted(struct listener *, int, const struct sockaddr_storage
#define SMTP_FD_RESERVE 5
+#define getdtablecount() 0
+
static size_t sessions;
static size_t maxsessions;
@@ -139,10 +144,26 @@ smtp_setup_listeners(void)
fatal("smtpd: socket");
}
opt = 1;
+#ifdef SO_REUSEADDR
if (setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR, &opt,
sizeof(opt)) < 0)
fatal("smtpd: setsockopt");
- if (bind(l->fd, (struct sockaddr *)&l->ss, l->ss.ss_len) == -1)
+#else
+ if (setsockopt(l->fd, SOL_SOCKET, SO_REUSEPORT, &opt,
+ sizeof(opt)) < 0)
+ fatal("smtpd: setsockopt");
+#endif
+#ifdef IPV6_V6ONLY
+ /*
+ * If using IPv6, bind only to IPv6 if possible.
+ * This avoids ambiguities with IPv4-mapped IPv6 addresses.
+ */
+ if (l->ss.ss_family == AF_INET6)
+ if (setsockopt(l->fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt,
+ sizeof(opt)) < 0)
+ fatal("smtpd: setsockopt");
+#endif
+ if (bind(l->fd, (struct sockaddr *)&l->ss, SS_LEN(&l->ss)) == -1)
fatal("smtpd: bind");
}
}
diff --git a/smtpd/smtp_session.c b/smtpd/smtp_session.c
index 0a3d1025..a166d8c9 100644
--- a/smtpd/smtp_session.c
+++ b/smtpd/smtp_session.c
@@ -19,6 +19,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -39,7 +41,11 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#if defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
#include <vis.h>
+#else
+#include "bsd-vis.h"
+#endif
#include "smtpd.h"
#include "log.h"
diff --git a/smtpd/smtpctl.c b/smtpd/smtpctl.c
index a78c26fa..6e91ac29 100644
--- a/smtpd/smtpctl.c
+++ b/smtpd/smtpctl.c
@@ -21,6 +21,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>
@@ -29,6 +31,12 @@
#include <sys/wait.h>
#include <sys/stat.h>
+#include <net/if.h>
+/* #include <net/if_media.h> */
+/* #include <net/if_types.h> */
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
#include <err.h>
#include <errno.h>
#include <event.h>
@@ -42,17 +50,30 @@
#include <syslog.h>
#include <time.h>
#include <unistd.h>
+#if defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
#include <vis.h>
+#else
+#include "bsd-vis.h"
+#endif
#include <limits.h>
#include "smtpd.h"
#include "parser.h"
#include "log.h"
+#ifndef PATH_GZCAT
#define PATH_GZCAT "/usr/bin/gzcat"
+#endif
#define PATH_CAT "/bin/cat"
#define PATH_QUEUE "/queue"
+#ifndef PATH_ENCRYPT
#define PATH_ENCRYPT "/usr/bin/encrypt"
+#endif
+
+#ifndef HAVE_DB_API
+#define makemap(x, y, z) 1
+#endif
+
int srv_connect(void);
int srv_connected(void);
@@ -1034,6 +1055,8 @@ main(int argc, char **argv)
int privileged;
char *argv_mailq[] = { "show", "queue", NULL };
+ __progname = ssh_get_progname(argv[0]);
+
sendmail_compat(argc, argv);
privileged = geteuid() == 0;
diff --git a/smtpd/smtpd-defines.h b/smtpd/smtpd-defines.h
index eba3ddd2..e4691c25 100644
--- a/smtpd/smtpd-defines.h
+++ b/smtpd/smtpd-defines.h
@@ -31,11 +31,21 @@
/* buffer size for virtual username (can be email addresses) */
#define SMTPD_VUSERNAME_SIZE (255 + 1)
+#ifndef SMTPD_USER
#define SMTPD_USER "_smtpd"
+#endif
+#ifndef PATH_CHROOT
#define PATH_CHROOT "/var/empty"
+#endif
+#ifndef SMTPD_QUEUE_USER
#define SMTPD_QUEUE_USER "_smtpq"
+#endif
+#ifndef SMTPD_QUEUE_GROUP
#define SMTPD_QUEUE_GROUP "_smtpq"
+#endif
+#ifndef PATH_SPOOL
#define PATH_SPOOL "/var/spool/smtpd"
+#endif
#define SUBADDRESSING_DELIMITER "+"
diff --git a/smtpd/smtpd.c b/smtpd/smtpd.c
index 1c87350d..97f4742d 100644
--- a/smtpd/smtpd.c
+++ b/smtpd/smtpd.c
@@ -18,6 +18,9 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
+#include <sys/file.h> /* Needed for flock */
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -27,21 +30,44 @@
#include <sys/uio.h>
#include <sys/mman.h>
+#ifdef BSD_AUTH
#include <bsd_auth.h>
+#endif
+
+#ifdef USE_PAM
+#if defined(HAVE_SECURITY_PAM_APPL_H)
+#include <security/pam_appl.h>
+#elif defined (HAVE_PAM_PAM_APPL_H)
+#include <pam/pam_appl.h>
+#endif
+#endif
+
+#ifdef HAVE_CRYPT_H
+#include <crypt.h> /* needed for crypt() */
+#endif
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <event.h>
#include <fcntl.h>
+#include <grp.h> /* needed for setgroups */
#include <fts.h>
#include <grp.h>
#include <imsg.h>
#include <inttypes.h>
+#include <libgen.h>
+#ifdef HAVE_LOGIN_CAP_H
#include <login_cap.h>
+#endif
+#ifdef HAVE_PATHS_H
#include <paths.h>
+#endif
#include <poll.h>
#include <pwd.h>
#include <signal.h>
+#ifdef HAVE_SHADOW_H
+#include <shadow.h> /* needed for getspnam() */
+#endif
#include <stdio.h>
#include <syslog.h>
#include <limits.h>
@@ -50,6 +76,9 @@
#include <sysexits.h>
#include <time.h>
#include <unistd.h>
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
#include <openssl/ssl.h>
#include <openssl/evp.h>
@@ -58,6 +87,8 @@
#include "log.h"
#include "ssl.h"
+extern char *__progname;
+
#define SMTPD_MAXARG 32
static void parent_imsg(struct mproc *, struct imsg *);
@@ -152,6 +183,10 @@ int control_socket = -1;
struct tree children;
+/* Saved arguments to main(). */
+char **saved_argv;
+int saved_argc;
+
static void
parent_imsg(struct mproc *p, struct imsg *imsg)
{
@@ -470,6 +505,25 @@ main(int argc, char *argv[])
char *rexec = NULL;
struct smtpd *conf;
+ __progname = ssh_get_progname(argv[0]);
+
+ /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
+ saved_argc = argc;
+ saved_argv = __xcalloc(argc + 1, sizeof(*saved_argv));
+ for (i = 0; i < argc; i++)
+ saved_argv[i] = __xstrdup(argv[i]);
+ saved_argv[i] = NULL;
+
+#ifndef HAVE_SETPROCTITLE
+ /* Prepare for later setproctitle emulation */
+ compat_init_setproctitle(argc, argv);
+ argv = saved_argv;
+#endif
+
+ /* this is to work around GNU getopt + portable setproctitle() fuckery */
+ save_argc = saved_argc;
+ save_argv = saved_argv;
+
if ((conf = config_default()) == NULL)
err(1, NULL);
@@ -602,6 +656,8 @@ main(int argc, char *argv[])
if (parse_config(conf, conffile, opts))
exit(1);
+ seed_rng();
+
if (strlcpy(env->sc_conffile, conffile, PATH_MAX)
>= PATH_MAX)
errx(1, "config file exceeds PATH_MAX");
@@ -832,8 +888,7 @@ start_child(int save_argc, char **save_argv, char *rexec)
if (dup2(sp[0], 3) == -1)
fatal("%s: dup2", rexec);
- if (closefrom(4) == -1)
- fatal("%s: closefrom", rexec);
+ xclosefrom(4);
for (argc = 0; argc < save_argc; argc++)
argv[argc] = save_argv[argc];
@@ -1066,6 +1121,9 @@ smtpd(void) {
offline_timeout.tv_usec = 0;
evtimer_add(&offline_ev, &offline_timeout);
+ if (pidfile(NULL) < 0)
+ err(1, "pidfile");
+
fork_processors();
purge_task();
@@ -1166,8 +1224,7 @@ fork_proc_backend(const char *key, const char *conf, const char *procname)
if (pid == 0) {
/* child process */
dup2(sp[0], STDIN_FILENO);
- if (closefrom(STDERR_FILENO + 1) < 0)
- exit(1);
+ closefrom(STDERR_FILENO + 1);
if (procname == NULL)
procname = name;
@@ -1307,8 +1364,8 @@ fork_processor(const char *name, const char *command, const char *user, const ch
setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
err(1, "fork_processor: cannot drop privileges");
- if (closefrom(STDERR_FILENO + 1) < 0)
- err(1, "closefrom");
+ xclosefrom(STDERR_FILENO + 1);
+
if (setsid() < 0)
err(1, "setsid");
if (signal(SIGPIPE, SIG_DFL) == SIG_ERR ||
@@ -1453,8 +1510,7 @@ forkmda(struct mproc *p, uint64_t id, struct deliver *deliver)
dup2(allout, STDOUT_FILENO) < 0 ||
dup2(allout, STDERR_FILENO) < 0)
err(1, "forkmda: dup2");
- if (closefrom(STDERR_FILENO + 1) < 0)
- err(1, "closefrom");
+ closefrom(STDERR_FILENO + 1);
if (setsid() < 0)
err(1, "setsid");
if (signal(SIGPIPE, SIG_DFL) == SIG_ERR ||
@@ -1565,8 +1621,7 @@ offline_enqueue(char *name)
ssize_t len;
arglist args;
- if (closefrom(STDERR_FILENO + 1) == -1)
- _exit(1);
+ closefrom(STDERR_FILENO + 1);
memset(&args, 0, sizeof(args));
@@ -2037,8 +2092,9 @@ imsg_to_str(int type)
}
}
+#ifdef BSD_AUTH
int
-parent_auth_user(const char *username, const char *password)
+parent_auth_bsd(const char *username, const char *password)
{
char user[LOGIN_NAME_MAX];
char pass[LINE_MAX];
@@ -2052,3 +2108,121 @@ parent_auth_user(const char *username, const char *password)
return LKA_OK;
return LKA_PERMFAIL;
}
+#endif
+
+#ifdef USE_PAM
+int
+pam_conv_password(int num_msg, const struct pam_message **msg,
+ struct pam_response **respp, const char *password)
+{
+ struct pam_response *response;
+
+ if (num_msg != 1)
+ return PAM_CONV_ERR;
+
+ response = calloc(1, sizeof(struct pam_response));
+ if (response == NULL || (response->resp = strdup(password)) == NULL) {
+ free(response);
+ return PAM_BUF_ERR;
+ }
+
+ *respp = response;
+ return PAM_SUCCESS;
+}
+int
+parent_auth_pam(const char *username, const char *password)
+{
+ int rc;
+ pam_handle_t *pamh = NULL;
+ struct pam_conv conv = { pam_conv_password, password };
+
+ if ((rc = pam_start(USE_PAM_SERVICE, username, &conv, &pamh)) != PAM_SUCCESS)
+ goto end;
+ if ((rc = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
+ goto end;
+ if ((rc = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS)
+ goto end;
+
+end:
+ pam_end(pamh, rc);
+
+ switch (rc) {
+ case PAM_SUCCESS:
+ return LKA_OK;
+ case PAM_SYSTEM_ERR:
+ case PAM_ABORT:
+ case PAM_AUTHINFO_UNAVAIL:
+ return LKA_TEMPFAIL;
+ default:
+ return LKA_PERMFAIL;
+ }
+}
+#endif
+
+#ifdef HAVE_GETSPNAM
+int
+parent_auth_getspnam(const char *username, const char *password)
+{
+ struct spwd *pw;
+ char *ep;
+
+ errno = 0;
+ do {
+ pw = getspnam(username);
+ } while (pw == NULL && errno == EINTR);
+
+ if (pw == NULL) {
+ if (errno)
+ return LKA_TEMPFAIL;
+ return LKA_PERMFAIL;
+ }
+
+ if ((ep = crypt(password, pw->sp_pwdp)) == NULL)
+ return LKA_PERMFAIL;
+
+ if (strcmp(pw->sp_pwdp, ep) == 0)
+ return LKA_OK;
+
+ return LKA_PERMFAIL;
+}
+#endif
+
+int
+parent_auth_pwd(const char *username, const char *password)
+{
+ struct passwd *pw;
+ char *ep;
+
+ errno = 0;
+ do {
+ pw = getpwnam(username);
+ } while (pw == NULL && errno == EINTR);
+
+ if (pw == NULL) {
+ if (errno)
+ return LKA_TEMPFAIL;
+ return LKA_PERMFAIL;
+ }
+
+ if ((ep = crypt(password, pw->pw_passwd)) == NULL)
+ return LKA_PERMFAIL;
+
+ if (strcmp(pw->pw_passwd, ep) == 0)
+ return LKA_OK;
+
+ return LKA_PERMFAIL;
+}
+
+int
+parent_auth_user(const char *username, const char *password)
+{
+#if defined(BSD_AUTH)
+ return (parent_auth_bsd(username, password));
+#elif defined(USE_PAM)
+ return (parent_auth_pam(username, password));
+#elif defined(HAVE_GETSPNAM)
+ return (parent_auth_getspnam(username, password));
+#else
+ return (parent_auth_pwd(username, password));
+#endif
+}
diff --git a/smtpd/smtpd.conf b/smtpd/smtpd.conf
new file mode 100644
index 00000000..efecf2a6
--- /dev/null
+++ b/smtpd/smtpd.conf
@@ -0,0 +1,19 @@
+# $OpenBSD: smtpd.conf,v 1.10 2018/05/24 11:40:17 gilles Exp $
+
+# This is the smtpd server system-wide configuration file.
+# See smtpd.conf(5) for more information.
+
+table aliases file:/etc/mail/aliases
+
+# To accept external mail, replace with: listen on all
+#
+listen on localhost
+
+action "local" mbox alias <aliases>
+action "relay" relay
+
+# Uncomment the following to accept external mail for domain "example.org"
+#
+# match from any for domain "example.org" action "local"
+match for local action "local"
+match from local for any action "relay"
diff --git a/smtpd/smtpd.h b/smtpd/smtpd.h
index bcafee60..a5c704bf 100644
--- a/smtpd/smtpd.h
+++ b/smtpd/smtpd.h
@@ -18,6 +18,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <event.h>
+
+#include <imsg.h>
+
+#include "openbsd-compat.h"
+
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
@@ -37,9 +43,14 @@
(expected_sz), (imsg)->hdr.len - IMSG_HEADER_SIZE); \
} while (0)
-#define CONF_FILE "/etc/mail/smtpd.conf"
-#define MAILNAME_FILE "/etc/mail/mailname"
-#define CA_FILE "/etc/ssl/cert.pem"
+#ifndef SMTPD_CONFDIR
+#define SMTPD_CONFDIR "/etc"
+#endif
+#define CONF_FILE SMTPD_CONFDIR "/smtpd.conf"
+#define MAILNAME_FILE SMTPD_CONFDIR "/mailname"
+#ifndef CA_FILE
+#define CA_FILE "/etc/ssl/cert.pem"
+#endif
#define PROC_COUNT 7
@@ -49,19 +60,34 @@
#define EXPAND_BUFFER 1024
#define SMTPD_QUEUE_EXPIRY (4 * 24 * 60 * 60)
-#define SMTPD_SOCKET "/var/run/smtpd.sock"
+#ifndef SMTPD_USER
+#define SMTPD_USER "_smtpd"
+#endif
+#ifndef SMTPD_QUEUE_USER
+#define SMTPD_QUEUE_USER "_smtpq"
+#endif
+#ifndef SMTPD_SOCKDIR
+#define SMTPD_SOCKDIR "/var/run"
+#endif
+#define SMTPD_SOCKET SMTPD_SOCKDIR "/smtpd.sock"
+#ifndef SMTPD_NAME
#define SMTPD_NAME "OpenSMTPD"
-#define SMTPD_VERSION "6.4.0"
+#endif
+#define SMTPD_VERSION "6.4.0-portable"
#define SMTPD_SESSION_TIMEOUT 300
#define SMTPD_BACKLOG 5
+#ifndef PATH_SMTPCTL
#define PATH_SMTPCTL "/usr/sbin/smtpctl"
+#endif
#define PATH_OFFLINE "/offline"
#define PATH_PURGE "/purge"
#define PATH_TEMPORARY "/temporary"
+#ifndef PATH_LIBEXEC
#define PATH_LIBEXEC "/usr/local/libexec/smtpd"
+#endif
/*
@@ -1715,7 +1741,7 @@ int session_socket_error(int);
int getmailname(char *, size_t);
int base64_encode(unsigned char const *, size_t, char *, size_t);
int base64_decode(char const *, unsigned char *, size_t);
-
+void xclosefrom(int);
void log_trace_verbose(int);
void log_trace(int, const char *, ...)
__attribute__((format (printf, 2, 3)));
diff --git a/smtpd/spfwalk.c b/smtpd/spfwalk.c
index 22b05796..8188c620 100644
--- a/smtpd/spfwalk.c
+++ b/smtpd/spfwalk.c
@@ -14,10 +14,15 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/tree.h>
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+#include <arpa/nameser_compat.h>
+#endif
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netinet/in.h>
@@ -34,7 +39,6 @@
#include <strings.h>
#include <unistd.h>
-#define LINE_MAX 1024
#include "smtpd-defines.h"
#include "smtpd-api.h"
#include "unpack_dns.h"
diff --git a/smtpd/ssl.c b/smtpd/ssl.c
index 7cbee563..74932247 100644
--- a/smtpd/ssl.c
+++ b/smtpd/ssl.c
@@ -18,6 +18,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -85,7 +87,7 @@ ssl_setup(SSL_CTX **ctxp, struct pki *pki,
if (sni_cb)
SSL_CTX_set_tlsext_servername_callback(ctx, sni_cb);
- SSL_CTX_set_dh_auto(ctx, pki->pki_dhe);
+ SSL_CTX_set_dh_auto(ctx, 0);
SSL_CTX_set_ecdh_auto(ctx, 1);
diff --git a/smtpd/ssl.h b/smtpd/ssl.h
index dfa6994c..b7c8351f 100644
--- a/smtpd/ssl.h
+++ b/smtpd/ssl.h
@@ -65,3 +65,4 @@ int ssl_ctx_fake_private_key(SSL_CTX *, const void *, size_t,
/* ssl_privsep.c */
int ssl_by_mem_ctrl(X509_LOOKUP *, int, const char *, long, char **);
+int SSL_CTX_use_certificate_chain_mem(SSL_CTX *, void *, int);
diff --git a/smtpd/ssl_smtpd.c b/smtpd/ssl_smtpd.c
index 1f1e62d2..4e5b7e75 100644
--- a/smtpd/ssl_smtpd.c
+++ b/smtpd/ssl_smtpd.c
@@ -18,6 +18,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/stat_backend.c b/smtpd/stat_backend.c
index 28e0ea24..b510ab91 100644
--- a/smtpd/stat_backend.c
+++ b/smtpd/stat_backend.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>
diff --git a/smtpd/stat_ramstat.c b/smtpd/stat_ramstat.c
index ede2e130..bbf1541a 100644
--- a/smtpd/stat_ramstat.c
+++ b/smtpd/stat_ramstat.c
@@ -15,6 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
#include <sys/types.h>
#include <sys/socket.h>
diff --git a/smtpd/table.c b/smtpd/table.c
index 187cb0ed..37249abd 100644
--- a/smtpd/table.c
+++ b/smtpd/table.c
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -46,7 +48,9 @@
struct table_backend *table_backend_lookup(const char *);
extern struct table_backend table_backend_static;
+#ifdef HAVE_DB_API
extern struct table_backend table_backend_db;
+#endif
extern struct table_backend table_backend_getpwnam;
extern struct table_backend table_backend_proc;
@@ -62,8 +66,10 @@ table_backend_lookup(const char *backend)
{
if (!strcmp(backend, "static") || !strcmp(backend, "file"))
return &table_backend_static;
+#ifdef HAVE_DB_API
if (!strcmp(backend, "db"))
return &table_backend_db;
+#endif
if (!strcmp(backend, "getpwnam"))
return &table_backend_getpwnam;
if (!strcmp(backend, "proc"))
@@ -76,8 +82,10 @@ table_backend_name(struct table_backend *backend)
{
if (backend == &table_backend_static)
return "static";
+#ifdef HAVE_DB_API
if (backend == &table_backend_db)
return "db";
+#endif
if (backend == &table_backend_getpwnam)
return "getpwnam";
if (backend == &table_backend_proc)
@@ -395,7 +403,7 @@ table_netaddr_match(const char *s1, const char *s2)
return 0;
if (n1.ss.ss_family != n2.ss.ss_family)
return 0;
- if (n1.ss.ss_len != n2.ss.ss_len)
+ if (SS_LEN(&n1.ss) != SS_LEN(&n2.ss))
return 0;
return table_match_mask(&n1.ss, &n2);
}
@@ -657,8 +665,9 @@ table_parse_lookup(enum table_service service, const char *key,
static const char *
table_dump_lookup(enum table_service s, union lookup *lk)
{
- static char buf[LINE_MAX];
- int ret;
+ static char buf[LINE_MAX];
+ struct maddrnode *mn;
+ int ret;
switch (s) {
case K_NONE:
@@ -714,6 +723,23 @@ table_dump_lookup(enum table_service s, union lookup *lk)
goto err;
break;
+ case K_MAILADDRMAP:
+ buf[0] = '\0';
+ TAILQ_FOREACH(mn, &lk->maddrmap->queue, entries) {
+ (void)strlcat(buf, mn->mailaddr.user, sizeof(buf));
+ (void)strlcat(buf, "@", sizeof(buf));
+ ret = strlcat(buf, mn->mailaddr.domain, sizeof(buf));
+
+ if (mn != TAILQ_LAST(&lk->maddrmap->queue, xmaddr))
+ ret = strlcat(buf, ", ", sizeof(buf));
+
+ if (ret >= sizeof(buf)) {
+ strlcpy(buf + sizeof(buf) - 4, "...", 4);
+ break;
+ }
+ }
+ break;
+
case K_ADDRNAME:
ret = snprintf(buf, sizeof(buf), "%s",
lk->addrname.name);
@@ -760,7 +786,9 @@ parse_sockaddr(struct sockaddr *sa, int family, const char *str)
sin = (struct sockaddr_in *)sa;
memset(sin, 0, sizeof *sin);
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
sin->sin_len = sizeof(struct sockaddr_in);
+#endif
sin->sin_family = PF_INET;
sin->sin_addr.s_addr = ina.s_addr;
return (0);
@@ -785,7 +813,9 @@ parse_sockaddr(struct sockaddr *sa, int family, const char *str)
sin6 = (struct sockaddr_in6 *)sa;
memset(sin6, 0, sizeof *sin6);
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
sin6->sin6_len = sizeof(struct sockaddr_in6);
+#endif
sin6->sin6_family = PF_INET6;
sin6->sin6_addr = in6a;
@@ -794,7 +824,7 @@ parse_sockaddr(struct sockaddr *sa, int family, const char *str)
if (IN6_IS_ADDR_LINKLOCAL(&in6a) ||
IN6_IS_ADDR_MC_LINKLOCAL(&in6a) ||
- IN6_IS_ADDR_MC_INTFACELOCAL(&in6a))
+ IN6_IS_ADDR_MC_NODELOCAL(&in6a))
if ((sin6->sin6_scope_id = if_nametoindex(cp)))
return (0);
diff --git a/smtpd/table_api.c b/smtpd/table_api.c
index 2eac4860..4c3a51a8 100644
--- a/smtpd/table_api.c
+++ b/smtpd/table_api.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -29,6 +31,7 @@
#include <fcntl.h>
#include <imsg.h>
#include <pwd.h>
+#include <grp.h> /* needed for setgroups */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/smtpd/table_db.c b/smtpd/table_db.c
index aeeed209..4ef23f71 100644
--- a/smtpd/table_db.c
+++ b/smtpd/table_db.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/queue.h>
@@ -24,8 +26,13 @@
#include <netinet/in.h>
#include <arpa/inet.h>
-
+#ifdef HAVE_DB_H
#include <db.h>
+#elif defined(HAVE_DB1_DB_H)
+#include <db1/db.h>
+#elif defined(HAVE_DB_185_H)
+#include <db_185.h>
+#endif
#include <ctype.h>
#include <err.h>
#include <event.h>
diff --git a/smtpd/table_getpwnam.c b/smtpd/table_getpwnam.c
index 83cbf797..87b0a54c 100644
--- a/smtpd/table_getpwnam.c
+++ b/smtpd/table_getpwnam.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/table_proc.c b/smtpd/table_proc.c
index 27abbfe0..fcf4ffcb 100644
--- a/smtpd/table_proc.c
+++ b/smtpd/table_proc.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -26,7 +28,9 @@
#include <event.h>
#include <fcntl.h>
#include <imsg.h>
+#ifdef HAVE_PATHS_H
#include <paths.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/smtpd/table_static.c b/smtpd/table_static.c
index 7be9cf21..3a19e7e2 100644
--- a/smtpd/table_static.c
+++ b/smtpd/table_static.c
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
diff --git a/smtpd/to.c b/smtpd/to.c
index f4e1149a..bef539b1 100644
--- a/smtpd/to.c
+++ b/smtpd/to.c
@@ -18,6 +18,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -57,12 +59,14 @@ static int alias_is_filename(struct expandnode *, const char *, size_t);
static int alias_is_include(struct expandnode *, const char *, size_t);
static int alias_is_error(struct expandnode *, const char *, size_t);
+static int broken_inet_net_pton_ipv6(const char *, void *, size_t);
+
const char *
sockaddr_to_text(struct sockaddr *sa)
{
static char buf[NI_MAXHOST];
- if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0,
+ if (getnameinfo(sa, SA_LEN(sa), buf, sizeof(buf), NULL, 0,
NI_NUMERICHOST))
return ("(unknown)");
else
@@ -76,7 +80,9 @@ in6addr_to_text(const struct in6_addr *addr)
uint16_t tmp16;
memset(&sa_in6, 0, sizeof(sa_in6));
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
sa_in6.sin6_len = sizeof(sa_in6);
+#endif
sa_in6.sin6_family = AF_INET6;
memcpy(&sa_in6.sin6_addr, addr, sizeof(sa_in6.sin6_addr));
@@ -193,15 +199,20 @@ time_to_text(time_t when)
char *day[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
char *month[] = {"Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec"};
- char *tz;
+ const char *tz;
long offset;
lt = localtime(&when);
if (lt == NULL || when == 0)
fatalx("time_to_text: localtime");
+#if HAVE_STRUCT_TM_TM_GMTOFF
offset = lt->tm_gmtoff;
tz = lt->tm_zone;
+#elif defined HAVE_DECL_ALTZONE && defined HAVE_DECL_TIMEZONE
+ offset = lt->tm_isdst > 0 ? altzone : timezone;
+ tz = lt->tm_isdst > 0 ? tzname[1] : tzname[0];
+#endif
/* We do not use strftime because it is subject to locale substitution*/
if (!bsnprintf(buf, sizeof(buf),
@@ -283,15 +294,25 @@ text_to_netaddr(struct netaddr *netaddr, const char *s)
if (bits != -1) {
ssin.sin_family = AF_INET;
memcpy(&ss, &ssin, sizeof(ssin));
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
ss.ss_len = sizeof(struct sockaddr_in);
+#endif
} else {
bits = inet_net_pton(AF_INET6, s, &ssin6.sin6_addr,
sizeof(struct in6_addr));
- if (bits == -1)
- return 0;
+ if (bits == -1) {
+ if (errno != EAFNOSUPPORT)
+ return 0;
+ bits = broken_inet_net_pton_ipv6(s, &ssin6.sin6_addr,
+ sizeof(struct in6_addr));
+ if (bits == -1)
+ return 0;
+ }
ssin6.sin6_family = AF_INET6;
memcpy(&ss, &ssin6, sizeof(ssin6));
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
ss.ss_len = sizeof(struct sockaddr_in6);
+#endif
}
netaddr->ss = ss;
@@ -810,3 +831,35 @@ alias_is_error(struct expandnode *alias, const char *line, size_t len)
alias->type = EXPAND_ERROR;
return 1;
}
+
+static int
+broken_inet_net_pton_ipv6(const char *src, void *dst, size_t size)
+{
+ int ret;
+ int bits;
+ char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255:255:255:255/128")];
+ char *sep;
+ const char *errstr;
+
+ if (strlcpy(buf, src, sizeof buf) >= sizeof buf) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+
+ sep = strchr(buf, '/');
+ if (sep != NULL)
+ *sep++ = '\0';
+
+ ret = inet_pton(AF_INET6, buf, dst);
+ if (ret != 1)
+ return (-1);
+
+ if (sep == NULL)
+ return 128;
+
+ bits = strtonum(sep, 0, 128, &errstr);
+ if (errstr)
+ return (-1);
+
+ return bits;
+}
diff --git a/smtpd/tree.c b/smtpd/tree.c
index 2022ebaf..03ba8d15 100644
--- a/smtpd/tree.c
+++ b/smtpd/tree.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/tree.h>
diff --git a/smtpd/unpack_dns.c b/smtpd/unpack_dns.c
index fe50b026..974d5727 100644
--- a/smtpd/unpack_dns.c
+++ b/smtpd/unpack_dns.c
@@ -16,6 +16,11 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+#include <arpa/nameser_compat.h>
+#endif
#include <arpa/inet.h>
#include <string.h>
diff --git a/smtpd/util.c b/smtpd/util.c
index df7fabad..dbcea86e 100644
--- a/smtpd/util.c
+++ b/smtpd/util.c
@@ -19,6 +19,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
@@ -832,3 +834,14 @@ log_trace_verbose(int v)
/* Set debug logging in log.c */
log_setverbose(v & TRACE_DEBUG ? 2 : foreground_log);
}
+
+void
+xclosefrom(int lowfd)
+{
+#if defined HAVE_CLOSEFROM_INT
+ if (closefrom(lowfd) == -1)
+ err(1, "closefrom");
+#else
+ closefrom(lowfd);
+#endif
+}
diff --git a/smtpd/waitq.c b/smtpd/waitq.c
index dc459372..082a1e51 100644
--- a/smtpd/waitq.c
+++ b/smtpd/waitq.c
@@ -16,6 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>