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:

Reply via email to