Hi. The smtp message parser uses the header_domain_append_callback() and header_masquerade_callback() functions to add missing domains in header fields, and rewrite the sender in the From field if required. The two functions are basically the same, except that the latter also rewrites the sender after appending the missing domain. It is also conditionnally hooked to the parser, replacing the former callback. This is a bit confusing.
Instead of having two instances of the same complex code, keep only one function that handles everything. It simplifies the code-path and it makes it clear what conditions leads to rewriting the sender. As a bonus, it also fixes a bug (actually not triggerable) in the removed code ("!= 1" should be "== -1"). Please test, especially if you are using the "masquerade" option. Eric. Index: smtp_session.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/smtp_session.c,v retrieving revision 1.314 diff -u -p -r1.314 smtp_session.c --- smtp_session.c 20 Oct 2017 12:23:36 -0000 1.314 +++ smtp_session.c 10 Nov 2017 13:37:56 -0000 @@ -325,88 +325,6 @@ header_append_domain_buffer(char *buffer } static void -header_domain_append_callback(const struct rfc2822_header *hdr, void *arg) -{ - struct smtp_session *s = arg; - struct rfc2822_line *l; - size_t i, j; - int escape, quote, comment, skip; - char buffer[APPEND_DOMAIN_BUFFER_SIZE]; - - if (smtp_message_printf(s, "%s:", hdr->name) == -1) - return; - - i = j = 0; - escape = quote = comment = skip = 0; - memset(buffer, 0, sizeof buffer); - - TAILQ_FOREACH(l, &hdr->lines, next) { - for (i = 0; i < strlen(l->buffer); ++i) { - if (l->buffer[i] == '(' && !escape && !quote) - comment++; - if (l->buffer[i] == '"' && !escape && !comment) - quote = !quote; - if (l->buffer[i] == ')' && !escape && !quote && comment) - comment--; - if (l->buffer[i] == '\\' && !escape && !comment && !quote) - escape = 1; - else - escape = 0; - - /* found a separator, buffer contains a full address */ - if (l->buffer[i] == ',' && !escape && !quote && !comment) { - if (!skip && j + strlen(s->listener->hostname) + 1 < sizeof buffer) - header_append_domain_buffer(buffer, s->listener->hostname, sizeof buffer); - if (smtp_message_printf(s, "%s,", buffer) == -1) - return; - j = 0; - skip = 0; - memset(buffer, 0, sizeof buffer); - } - else { - if (skip) { - if (smtp_message_printf(s, "%c", - l->buffer[i]) == -1) - return; - } - else { - buffer[j++] = l->buffer[i]; - if (j == sizeof (buffer) - 1) { - if (smtp_message_printf(s, "%s", - buffer) != -1) - return; - skip = 1; - j = 0; - memset(buffer, 0, sizeof buffer); - } - } - } - } - if (skip) { - if (smtp_message_printf(s, "\n") == -1) - return; - } - else { - buffer[j++] = '\n'; - if (j == sizeof (buffer) - 1) { - if (smtp_message_printf(s, "%s", buffer) == -1) - return; - skip = 1; - j = 0; - memset(buffer, 0, sizeof buffer); - } - } - } - - /* end of header, if buffer is not empty we'll process it */ - if (buffer[0]) { - if (j + strlen(s->listener->hostname) + 1 < sizeof buffer) - header_append_domain_buffer(buffer, s->listener->hostname, sizeof buffer); - smtp_message_printf(s, "%s", buffer); - } -} - -static void header_address_rewrite_buffer(char *buffer, const char *address, size_t len) { size_t i; @@ -487,7 +405,7 @@ header_address_rewrite_buffer(char *buff } static void -header_masquerade_callback(const struct rfc2822_header *hdr, void *arg) +header_domain_append_callback(const struct rfc2822_header *hdr, void *arg) { struct smtp_session *s = arg; struct rfc2822_line *l; @@ -519,8 +437,12 @@ header_masquerade_callback(const struct if (l->buffer[i] == ',' && !escape && !quote && !comment) { if (!skip && j + strlen(s->listener->hostname) + 1 < sizeof buffer) { header_append_domain_buffer(buffer, s->listener->hostname, sizeof buffer); - header_address_rewrite_buffer(buffer, mailaddr_to_text(&s->tx->evp.sender), - sizeof buffer); + if (s->flags & SF_AUTHENTICATED && + s->listener->sendertable[0] && + s->listener->flags & F_MASQUERADE && + !(strcasecmp(hdr->name, "From"))) + header_address_rewrite_buffer(buffer, mailaddr_to_text(&s->tx->evp.sender), + sizeof buffer); } if (smtp_message_printf(s, "%s,", buffer) == -1) return; @@ -565,8 +487,12 @@ header_masquerade_callback(const struct if (buffer[0]) { if (j + strlen(s->listener->hostname) + 1 < sizeof buffer) { header_append_domain_buffer(buffer, s->listener->hostname, sizeof buffer); - header_address_rewrite_buffer(buffer, mailaddr_to_text(&s->tx->evp.sender), - sizeof buffer); + if (s->flags & SF_AUTHENTICATED && + s->listener->sendertable[0] && + s->listener->flags & F_MASQUERADE && + !(strcasecmp(hdr->name, "From"))) + header_address_rewrite_buffer(buffer, mailaddr_to_text(&s->tx->evp.sender), + sizeof buffer); } smtp_message_printf(s, "%s", buffer); } @@ -698,11 +624,6 @@ smtp_session_imsg(struct mproc *p, struc switch (status) { case LKA_OK: smtp_queue_create_message(s); - - /* sender check passed, override From callback if masquerading */ - if (s->listener->flags & F_MASQUERADE) - rfc2822_header_callback(&s->tx->rfc2822_parser, "from", - header_masquerade_callback, s); break; case LKA_PERMFAIL: