diff options
author | Emmanuel Vadot <elbarto@bocal.org> | 2014-10-22 09:53:44 +0200 |
---|---|---|
committer | Emmanuel Vadot <elbarto@bocal.org> | 2014-10-22 09:53:44 +0200 |
commit | ecee83f41db3c7dc105632f7622d0a621e6afeb2 (patch) | |
tree | ffed70912416e4b2e995e5f50446c66d77b42f99 | |
parent | Merge branch 'master' into portable (diff) | |
download | OpenSMTPD-ecee83f41db3c7dc105632f7622d0a621e6afeb2.tar.xz OpenSMTPD-ecee83f41db3c7dc105632f7622d0a621e6afeb2.zip |
- Add support for mail addresses and name on a multiline.
-rw-r--r-- | openbsd-compat/entropy.c | 2 | ||||
-rw-r--r-- | smtpd/rfc822.c | 101 | ||||
-rw-r--r-- | smtpd/rfc822.h | 3 | ||||
-rw-r--r-- | smtpd/smtp_session.c | 2 |
4 files changed, 73 insertions, 35 deletions
diff --git a/openbsd-compat/entropy.c b/openbsd-compat/entropy.c index 09ffe145..2005eff0 100644 --- a/openbsd-compat/entropy.c +++ b/openbsd-compat/entropy.c @@ -48,7 +48,7 @@ //#include "xmalloc.h" //#include "atomicio.h" //#include "pathnames.h" -#include "log.h" +#include "smtpd/log.h" //#include "buffer.h" void diff --git a/smtpd/rfc822.c b/smtpd/rfc822.c index f8e90d23..c9fc8ff7 100644 --- a/smtpd/rfc822.c +++ b/smtpd/rfc822.c @@ -31,12 +31,54 @@ #include "rfc822.h" +#include "log.h" + +static int +parse_addresses_finish(struct rfc822_parser *rp) +{ + char *wptr; + + /* some flags still set, malformed header */ + if (rp->escape || rp->comment || rp->quote || rp->bracket) { + free(rp->ra); + return 0; + } + + /* no value, malformed header */ + if (rp->ra->name[0] == '\0' && rp->ra->address[0] == '\0') { + free(rp->ra); + return 0; + } + + /* no <>, use name as address */ + if (rp->ra->address[0] == '\0') { + memcpy(rp->ra->address, rp->ra->name, sizeof rp->ra->address); + memset(rp->ra->name, 0, sizeof rp->ra->name); + } + + /* strip first trailing whitespace from name */ + wptr = &rp->ra->name[0] + strlen(rp->ra->name); + while (wptr != &rp->ra->name[0]) { + if (*wptr && ! isspace(*wptr)) + break; + *wptr-- = '\0'; + } + + log_debug("rfc822: address: %s", rp->ra->address); + log_debug("rfc822: name: %s", rp->ra->name); + + TAILQ_INSERT_TAIL(&rp->addresses, rp->ra, next); + rp->count++; + rp->ra = NULL; + + return 1; +} + static int parse_addresses(struct rfc822_parser *rp, const char *buffer, size_t len) { const char *s; char *wptr; - struct rfc822_address *ra; s = buffer; @@ -48,11 +90,16 @@ parse_addresses(struct rfc822_parser *rp, const char *buffer, size_t len) if (*s == '\0') return 0; - ra = calloc(1, sizeof *ra); - if (ra == NULL) - return -1; + if (rp->ra == NULL) { + rp->ra = calloc(1, sizeof *(rp->ra)); + if (rp->ra == NULL) + return -1; + } + else { + log_debug("rfc822: reuse: addr = '%s' name = '%s'", rp->ra->address, rp->ra->name); + } - wptr = ra->name; + wptr = rp->ra->name; for (; len; s++, len--) { if (*s == '(' && !rp->escape && !rp->quote) rp->comment++; @@ -60,16 +107,16 @@ parse_addresses(struct rfc822_parser *rp, const char *buffer, size_t len) rp->quote = !rp->quote; if (!rp->comment && !rp->quote && !rp->escape) { if (*s == '<' && rp->bracket) { - free(ra); + free(rp->ra); return 0; } if (*s == '>' && !rp->bracket) { - free(ra); + free(rp->ra); return 0; } if (*s == '<') { - wptr = ra->address; + wptr = rp->ra->address; rp->bracket++; continue; } @@ -89,34 +136,11 @@ parse_addresses(struct rfc822_parser *rp, const char *buffer, size_t len) *wptr++ = *s; } - /* some flags still set, malformed header */ - if (rp->escape || rp->comment || rp->quote || rp->bracket) { - free(ra); - return 0; - } + if (*s == '\0') + return 1; - /* no value, malformed header */ - if (ra->name[0] == '\0' && ra->address[0] == '\0') { - free(ra); + if (!parse_addresses_finish(rp)) return 0; - } - - /* no <>, use name as address */ - if (ra->address[0] == '\0') { - memcpy(ra->address, ra->name, sizeof ra->address); - memset(ra->name, 0, sizeof ra->name); - } - - /* strip first trailing whitespace from name */ - wptr = &ra->name[0] + strlen(ra->name); - while (wptr != &ra->name[0]) { - if (*wptr && ! isspace(*wptr)) - break; - *wptr-- = '\0'; - } - - TAILQ_INSERT_TAIL(&rp->addresses, ra, next); - rp->count++; /* do we have more to process ? */ for (; *s; ++s, --len) @@ -156,6 +180,15 @@ rfc822_parser_reset(struct rfc822_parser *rp) memset(rp, 0, sizeof *rp); } +void +rfc822_parser_finish(struct rfc822_parser *rp) +{ + if (!rp->ra) + return; + + parse_addresses_finish(rp); +} + int rfc822_parser_feed(struct rfc822_parser *rp, const char *line) { diff --git a/smtpd/rfc822.h b/smtpd/rfc822.h index aafb3770..3102f9be 100644 --- a/smtpd/rfc822.h +++ b/smtpd/rfc822.h @@ -32,6 +32,8 @@ struct rfc822_parser { size_t count; TAILQ_HEAD(addresses, rfc822_address) addresses; + struct rfc822_address *ra; + uint8_t quote; uint8_t comment; uint8_t escape; @@ -40,6 +42,7 @@ struct rfc822_parser { void rfc822_parser_init(struct rfc822_parser *); void rfc822_parser_reset(struct rfc822_parser *); +void rfc822_parser_finish(struct rfc822_parser *); int rfc822_parser_feed(struct rfc822_parser *, const char *); #endif diff --git a/smtpd/smtp_session.c b/smtpd/smtp_session.c index 14ffd134..43c38b40 100644 --- a/smtpd/smtp_session.c +++ b/smtpd/smtp_session.c @@ -301,6 +301,8 @@ header_masquerade_callback(const struct rfc2822_header *hdr, void *arg) if (! rfc822_parser_feed(&rp, l->buffer)) goto fail; + rfc822_parser_finish(&rp); + len = strlen(hdr->name) + 1; if (iobuf_fqueue(&s->obuf, "%s:", hdr->name) != (int)len) { s->msgflags |= MF_ERROR_IO; |