diff options
-rw-r--r-- | usr.sbin/smtpd/enqueue.c | 12 | ||||
-rw-r--r-- | usr.sbin/smtpd/parse.y | 16 | ||||
-rw-r--r-- | usr.sbin/smtpd/rfc2822.c | 70 | ||||
-rw-r--r-- | usr.sbin/smtpd/rfc2822.h | 15 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtp_session.c | 24 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 4 |
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 { |