summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/smtpd/enqueue.c12
-rw-r--r--usr.sbin/smtpd/parse.y16
-rw-r--r--usr.sbin/smtpd/rfc2822.c70
-rw-r--r--usr.sbin/smtpd/rfc2822.h15
-rw-r--r--usr.sbin/smtpd/smtp_session.c24
-rw-r--r--usr.sbin/smtpd/smtpd.h4
6 files changed, 117 insertions, 24 deletions
diff --git a/usr.sbin/smtpd/enqueue.c b/usr.sbin/smtpd/enqueue.c
index c7dd6c9224e..5a2696f0d10 100644
--- a/usr.sbin/smtpd/enqueue.c
+++ b/usr.sbin/smtpd/enqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: enqueue.c,v 1.94 2015/05/13 07:34:49 gilles Exp $ */
+/* $OpenBSD: enqueue.c,v 1.95 2015/09/07 15:36:53 gilles Exp $ */
/*
* Copyright (c) 2005 Henning Brauer <henning@bulabula.org>
@@ -345,11 +345,6 @@ enqueue(int argc, char *argv[])
if (!msg.saw_date)
send_line(fout, 0, "Date: %s\n", time_to_text(timestamp));
- /* add Message-Id */
- if (!msg.saw_msgid)
- send_line(fout, 0, "Message-Id: <%"PRIu64".enqueue@%s>\n",
- generate_uid(), host);
-
if (msg.need_linesplit) {
/* we will always need to mime encode for long lines */
if (!msg.saw_mime_version)
@@ -893,11 +888,6 @@ savedeadletter(struct passwd *pw, FILE *in)
if (!msg.saw_date)
fprintf(fp, "Date: %s\n", time_to_text(timestamp));
- /* add Message-Id */
- if (!msg.saw_msgid)
- fprintf(fp, "Message-Id: <%"PRIu64".enqueue@%s>\n",
- generate_uid(), host);
-
if (msg.need_linesplit) {
/* we will always need to mime encode for long lines */
if (!msg.saw_mime_version)
diff --git a/usr.sbin/smtpd/parse.y b/usr.sbin/smtpd/parse.y
index e65dc4d71a0..19c2ba79a31 100644
--- a/usr.sbin/smtpd/parse.y
+++ b/usr.sbin/smtpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.153 2015/08/19 16:14:54 deraadt Exp $ */
+/* $OpenBSD: parse.y,v 1.154 2015/09/07 15:36:53 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -1967,6 +1967,9 @@ host_v4(const char *s, in_port_t port)
sain->sin_addr.s_addr = ina.s_addr;
sain->sin_port = port;
+ if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
+ h->local = 1;
+
return (h);
}
@@ -1988,6 +1991,9 @@ host_v6(const char *s, in_port_t port)
sin6->sin6_port = port;
memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6));
+ if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
+ h->local = 1;
+
return (h);
}
@@ -2026,12 +2032,16 @@ host_dns(struct listenerlist *al, struct listen_opts *lo)
sain->sin_addr.s_addr = ((struct sockaddr_in *)
res->ai_addr)->sin_addr.s_addr;
sain->sin_port = lo->port;
+ if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
+ h->local = 1;
} else {
sin6 = (struct sockaddr_in6 *)&h->ss;
sin6->sin6_len = sizeof(struct sockaddr_in6);
memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
sin6->sin6_port = lo->port;
+ if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
+ h->local = 1;
}
config_listener(h, lo);
@@ -2093,6 +2103,8 @@ interface(struct listenerlist *al, struct listen_opts *lo)
*sain = *(struct sockaddr_in *)p->ifa_addr;
sain->sin_len = sizeof(struct sockaddr_in);
sain->sin_port = lo->port;
+ if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
+ h->local = 1;
break;
case AF_INET6:
@@ -2100,6 +2112,8 @@ interface(struct listenerlist *al, struct listen_opts *lo)
*sin6 = *(struct sockaddr_in6 *)p->ifa_addr;
sin6->sin6_len = sizeof(struct sockaddr_in6);
sin6->sin6_port = lo->port;
+ if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
+ h->local = 1;
break;
default:
diff --git a/usr.sbin/smtpd/rfc2822.c b/usr.sbin/smtpd/rfc2822.c
index afc5737a7c2..044a4686f60 100644
--- a/usr.sbin/smtpd/rfc2822.c
+++ b/usr.sbin/smtpd/rfc2822.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rfc2822.c,v 1.3 2014/11/23 21:27:53 gilles Exp $ */
+/* $OpenBSD: rfc2822.c,v 1.4 2015/09/07 15:36:53 gilles Exp $ */
/*
* Copyright (c) 2014 Gilles Chehade <gilles@poolp.org>
@@ -47,23 +47,40 @@ header_reset(struct rfc2822_header *hdr)
static void
header_callback(struct rfc2822_parser *rp)
{
- struct rfc2822_hdr_cb *hdr_cb;
+ struct rfc2822_hdr_cb *hdr_cb;
+ struct rfc2822_hdr_miss_cb *hdr_miss_cb;
TAILQ_FOREACH(hdr_cb, &rp->hdr_cb, next)
if (strcasecmp(hdr_cb->name, rp->header.name) == 0) {
hdr_cb->func(&rp->header, hdr_cb->arg);
- header_reset(&rp->header);
- rp->in_hdr = 0;
- return;
+ goto end;
}
-
rp->hdr_dflt_cb.func(&rp->header, rp->hdr_dflt_cb.arg);
+
+end:
+ TAILQ_FOREACH(hdr_miss_cb, &rp->hdr_miss_cb, next)
+ if (strcasecmp(hdr_miss_cb->name, rp->header.name) == 0)
+ break;
+ if (hdr_miss_cb)
+ TAILQ_REMOVE(&rp->hdr_miss_cb, hdr_miss_cb, next);
header_reset(&rp->header);
rp->in_hdr = 0;
return;
}
static void
+missing_headers_callback(struct rfc2822_parser *rp)
+{
+ struct rfc2822_hdr_miss_cb *hdr_miss_cb;
+
+ while ((hdr_miss_cb = TAILQ_FIRST(&rp->hdr_miss_cb))) {
+ hdr_miss_cb->func(hdr_miss_cb->name, hdr_miss_cb->arg);
+ TAILQ_REMOVE(&rp->hdr_miss_cb, hdr_miss_cb, next);
+ free(hdr_miss_cb);
+ }
+}
+
+static void
body_callback(struct rfc2822_parser *rp, const char *line)
{
rp->body_line_cb.func(line, rp->body_line_cb.arg);
@@ -116,6 +133,7 @@ rfc2822_parser_init(struct rfc2822_parser *rp)
{
memset(rp, 0, sizeof *rp);
TAILQ_INIT(&rp->hdr_cb);
+ TAILQ_INIT(&rp->hdr_miss_cb);
TAILQ_INIT(&rp->header.lines);
rfc2822_header_default_callback(rp, hdr_dflt_cb, NULL);
rfc2822_body_callback(rp, body_dflt_cb, NULL);
@@ -131,13 +149,18 @@ rfc2822_parser_reset(struct rfc2822_parser *rp)
void
rfc2822_parser_release(struct rfc2822_parser *rp)
{
- struct rfc2822_hdr_cb *cb;
+ struct rfc2822_hdr_cb *cb;
+ struct rfc2822_hdr_miss_cb *mcb;
rfc2822_parser_reset(rp);
while ((cb = TAILQ_FIRST(&rp->hdr_cb))) {
TAILQ_REMOVE(&rp->hdr_cb, cb, next);
free(cb);
}
+ while ((mcb = TAILQ_FIRST(&rp->hdr_miss_cb))) {
+ TAILQ_REMOVE(&rp->hdr_miss_cb, mcb, next);
+ free(mcb);
+ }
}
int
@@ -150,8 +173,11 @@ rfc2822_parser_feed(struct rfc2822_parser *rp, const char *line)
header_callback(rp);
/* no longer in headers */
- if (*line == '\0')
+ if (*line == '\0') {
+ if (rp->in_hdrs)
+ missing_headers_callback(rp);
rp->in_hdrs = 0;
+ }
if (rp->in_hdrs) {
/* line exceeds RFC maximum size requirement */
@@ -192,6 +218,34 @@ rfc2822_header_callback(struct rfc2822_parser *rp, const char *header,
return 1;
}
+int
+rfc2822_missing_header_callback(struct rfc2822_parser *rp, const char *header,
+ void (*func)(const char *, void *), void *arg)
+{
+ struct rfc2822_hdr_miss_cb *cb;
+ struct rfc2822_hdr_miss_cb *cb_tmp;
+ char buffer[RFC2822_MAX_LINE_SIZE+1];
+
+ /* line exceeds RFC maximum size requirement */
+ if (strlcpy(buffer, header, sizeof buffer) >= sizeof buffer)
+ return 0;
+
+ TAILQ_FOREACH_SAFE(cb, &rp->hdr_miss_cb, next, cb_tmp) {
+ if (strcasecmp(cb->name, buffer) == 0) {
+ TAILQ_REMOVE(&rp->hdr_miss_cb, cb, next);
+ free(cb);
+ }
+ }
+
+ if ((cb = calloc(1, sizeof *cb)) == NULL)
+ return -1;
+ (void)strlcpy(cb->name, buffer, sizeof cb->name);
+ cb->func = func;
+ cb->arg = arg;
+ TAILQ_INSERT_TAIL(&rp->hdr_miss_cb, cb, next);
+ return 1;
+}
+
void
rfc2822_header_default_callback(struct rfc2822_parser *rp,
void (*func)(const struct rfc2822_header *, void *), void *arg)
diff --git a/usr.sbin/smtpd/rfc2822.h b/usr.sbin/smtpd/rfc2822.h
index 211d1b0a519..c78392d726a 100644
--- a/usr.sbin/smtpd/rfc2822.h
+++ b/usr.sbin/smtpd/rfc2822.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rfc2822.h,v 1.2 2015/08/15 16:49:23 gilles Exp $ */
+/* $OpenBSD: rfc2822.h,v 1.3 2015/09/07 15:36:53 gilles Exp $ */
/*
* Copyright (c) 2014 Gilles Chehade <gilles@poolp.org>
@@ -39,6 +39,14 @@ struct rfc2822_hdr_cb {
void *arg;
};
+struct rfc2822_hdr_miss_cb {
+ TAILQ_ENTRY(rfc2822_hdr_miss_cb) next;
+
+ char name[RFC2822_MAX_LINE_SIZE+1];
+ void (*func)(const char *, void *);
+ void *arg;
+};
+
struct rfc2822_line_cb {
void (*func)(const char *, void *);
void *arg;
@@ -47,7 +55,8 @@ struct rfc2822_line_cb {
struct rfc2822_parser {
uint8_t in_hdrs; /* in headers */
- TAILQ_HEAD(hdr_cb, rfc2822_hdr_cb) hdr_cb;
+ TAILQ_HEAD(hdr_cb, rfc2822_hdr_cb) hdr_cb;
+ TAILQ_HEAD(hdr_miss_cb, rfc2822_hdr_miss_cb) hdr_miss_cb;
uint8_t in_hdr; /* in specific header */
struct rfc2822_header header;
@@ -63,6 +72,8 @@ void rfc2822_parser_reset(struct rfc2822_parser *);
void rfc2822_parser_release(struct rfc2822_parser *);
int rfc2822_header_callback(struct rfc2822_parser *, const char *,
void (*)(const struct rfc2822_header *, void *), void *);
+int rfc2822_missing_header_callback(struct rfc2822_parser *, const char *,
+ void (*)(const char *, void *), void *);
void rfc2822_header_default_callback(struct rfc2822_parser *,
void (*)(const struct rfc2822_header *, void *), void *);
void rfc2822_body_callback(struct rfc2822_parser *,
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c
index b1efa639c63..ff30ad06695 100644
--- a/usr.sbin/smtpd/smtp_session.c
+++ b/usr.sbin/smtpd/smtp_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp_session.c,v 1.232 2015/09/03 05:10:19 gilles Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.233 2015/09/07 15:36:53 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -457,6 +457,23 @@ ioerror:
}
static void
+header_missing_callback(const char *header, void *arg)
+{
+ struct smtp_session *s = arg;
+ int len;
+
+ if (strcasecmp(header, "message-id") == 0) {
+ len = fprintf(s->ofile, "Message-Id: <%016"PRIx64"@%s>\n",
+ generate_uid(), s->listener->hostname);
+ if (len == -1) {
+ s->msgflags |= MF_ERROR_IO;
+ return;
+ }
+ s->datalen += len;
+ }
+}
+
+static void
smtp_session_init(void)
{
static int init = 0;
@@ -521,6 +538,11 @@ smtp_session(struct listener *listener, int sock,
rfc2822_body_callback(&s->rfc2822_parser,
dataline_callback, s);
+ if (hostname || listener->local) {
+ rfc2822_missing_header_callback(&s->rfc2822_parser, "message-id",
+ header_missing_callback, s);
+ }
+
/* For local enqueueing, the hostname is already set */
if (hostname) {
s->flags |= SF_AUTHENTICATED;
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index 0385bd4d1ed..30c192c8d2d 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.474 2015/04/19 20:29:12 gilles Exp $ */
+/* $OpenBSD: smtpd.h,v 1.475 2015/09/07 15:36:53 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -529,6 +529,8 @@ struct listener {
char hostname[HOST_NAME_MAX+1];
char hostnametable[PATH_MAX];
TAILQ_ENTRY(listener) entry;
+
+ int local; /* there must be a better way */
};
struct smtpd {