]> Pileus Git - ~andy/fetchmail/blobdiff - transact.c
Stefan Esser's security patch.
[~andy/fetchmail] / transact.c
index 19beb8cf60a0d03bd8042d79d5ee73bfc18bd477..c0f79253bdeea17b287fc6b8394d1fd07bae760f 100644 (file)
@@ -40,7 +40,7 @@ extern char *strstr();        /* needed on sysV68 R3V7.1. */
 
 int mytimeout;         /* value of nonreponse timeout */
 int suppress_tags;     /* emit tags? */
-char shroud[PASSWORDLEN];      /* string to shroud in debug output */
+char shroud[PASSWORDLEN*2+1];  /* string to shroud in debug output */
 struct msgblk msgblk;
 
 char tag[TAGLEN];
@@ -92,6 +92,13 @@ static void find_server_names(const char *hdr,
        {
            char        *atsign;
 
+           /* 
+            * Handle empty address from a To: header containing only 
+            * a comment.
+            */
+           if (!*cp)
+               continue;
+
            /*
             * If the name of the user begins with a qmail virtual
             * domain prefix, ignore the prefix.  Doing this here
@@ -181,6 +188,8 @@ static char *parse_received(struct query *ctl, char *bufp)
     char *base, *ok = (char *)NULL;
     static char rbuf[HOSTLEN + USERNAMELEN + 4]; 
 
+#define RBUF_WRITE(value) if (tp < rbuf+sizeof(rbuf)-1) *tp++=value
+
     /*
      * Try to extract the real envelope addressee.  We look here
      * specifically for the mailserver's Received line.
@@ -208,7 +217,7 @@ static char *parse_received(struct query *ctl, char *bufp)
                continue;
            tp = rbuf;
            for (; !isspace(*sp); sp++)
-               *tp++ = *sp;
+               RBUF_WRITE(*sp);
            *tp = '\0';
 
            /* look for valid address */
@@ -256,7 +265,7 @@ static char *parse_received(struct query *ctl, char *bufp)
                    continue;
                tp = rbuf;
                for (; !isspace(*sp); sp++)
-                   *tp++ = *sp;
+                   RBUF_WRITE(*sp);
                *tp = '\0';
 
                if (strchr(rbuf, '@'))
@@ -274,8 +283,8 @@ static char *parse_received(struct query *ctl, char *bufp)
            for (sp = ok + 4; isspace(*sp); sp++)
                continue;
            tp = rbuf;
-           *tp++ = ':';        /* Here is the hack.  This is to be friends */
-           *tp++ = ' ';        /* with nxtaddr()... */
+           RBUF_WRITE(':');    /* Here is the hack.  This is to be friends */
+           RBUF_WRITE(' ');    /* with nxtaddr()... */
            if (*sp == '<')
            {
                want_gt = TRUE;
@@ -288,14 +297,17 @@ static char *parse_received(struct query *ctl, char *bufp)
                    && (want_gt ? (*sp != '>') : !isspace(*sp))
                    && *sp != ';')
                if (!isspace(*sp))
-                   *tp++ = *sp++;
+               {
+                   RBUF_WRITE(*sp);
+                   sp++;
+               }    
                else
                {
                    /* uh oh -- whitespace here can't be right! */
                    ok = (char *)NULL;
                    break;
                }
-           *tp++ = '\n';
+           RBUF_WRITE('\n');
            *tp = '\0';
            if (strlen(rbuf) <= 3)      /* apparently nothing has been found */
                ok = NULL;
@@ -474,6 +486,7 @@ int readheaders(int sock,
             */
            if (protocol->delimited && line[0] == '.' && EMPTYLINE(line+1))
            {
+               headers_ok = FALSE;
                has_nuls = (linelen != strlen(line));
                free(line);
                goto process_headers;
@@ -652,7 +665,8 @@ int readheaders(int sock,
         */
        if (!strncasecmp("Return-Path:", line, 12) && (cp = nxtaddr(line)))
        {
-           strcpy(msgblk.return_path, cp);
+           strncpy(msgblk.return_path, cp, sizeof(msgblk.return_path));
+           msgblk.return_path[sizeof(msgblk.return_path)-1] = '\0';
            if (!ctl->mda) {
                free(line);
                continue;
@@ -903,8 +917,10 @@ int readheaders(int sock,
        else if (reply_to_offs >= 0 && (ap = nxtaddr(msgblk.headers + reply_to_offs)));
        else if (app_from_offs >= 0 && (ap = nxtaddr(msgblk.headers + app_from_offs)));
        /* multi-line MAIL FROM addresses confuse SMTP terribly */
-       if (ap && !strchr(ap, '\n')) 
-           strcpy(msgblk.return_path, ap);
+       if (ap && !strchr(ap, '\n')) {
+           strncpy(msgblk.return_path, ap, sizeof(msgblk.return_path));
+           msgblk.return_path[sizeof(msgblk.return_path)-1] = '\0';
+       }
     }
 
     /* cons up a list of local recipients */
@@ -1089,33 +1105,20 @@ int readheaders(int sock,
 #else
                    sprintf(buf+1,
 #endif /* HAVE_SNPRINTF */
-                           "for %s@%s (by default); ",
-                           user, ctl->destaddr);
+                           "for %s (by default); ",
+                           rcpt_address (ctl, run.postmaster, 0));
                }
                else if (good_addresses == 1)
                {
                    for (idp = msgblk.recipients; idp; idp = idp->next)
                        if (idp->val.status.mark == XMIT_ACCEPT)
                            break;      /* only report first address */
-                   if (strchr(idp->id, '@'))
 #ifdef HAVE_SNPRINTF
                    snprintf(buf+1, sizeof(buf)-1,
 #else                       
                    sprintf(buf+1,
 #endif /* HAVE_SNPRINTF */
-                           "for %s", idp->id);
-                   else
-                       /*
-                        * This could be a bit misleading, as destaddr is
-                        * the forwarding host rather than the actual 
-                        * destination.  Most of the time they coincide.
-                        */
-#ifdef HAVE_SNPRINTF
-                       snprintf(buf+1, sizeof(buf)-1,
-#else                       
-                       sprintf(buf+1,
-#endif /* HAVE_SNPRINTF */
-                               "for %s@%s", idp->id, ctl->destaddr);
+                           "for %s", rcpt_address (ctl, idp->id, 1));
                    sprintf(buf+strlen(buf), " (%s); ",
                            MULTIDROP(ctl) ? "multi-drop" : "single-drop");
                }
@@ -1166,22 +1169,39 @@ int readheaders(int sock,
                for (idp = msgblk.recipients; idp; idp = idp->next)
                    if (idp->val.status.mark == XMIT_REJECT)
                        break;
-               sprintf(errhd+strlen(errhd), GT_("recipient address %s didn't match any local name"), idp->id);
+#ifdef HAVE_SNPRINTF
+               snprintf(errhd+strlen(errhd), sizeof(errhd)-strlen(errhd),
+#else
+               sprintf(errhd+strlen(errhd),
+#endif /* HAVE_SNPRINTF */
+                       GT_("recipient address %s didn't match any local name"), idp->id);
            }
        }
 
        if (has_nuls)
        {
            if (errhd[sizeof("X-Fetchmail-Warning: ")])
+#ifdef HAVE_SNPRINTF
+               snprintf(errhd+strlen(errhd), sizeof(errhd)-strlen(errhd), "; ");
+           snprintf(errhd+strlen(errhd), sizeof(errhd)-strlen(errhd),
+#else
                strcat(errhd, "; ");
-           strcat(errhd, GT_("message has embedded NULs"));
+           strcat(errhd,
+#endif /* HAVE_SNPRINTF */
+                       GT_("message has embedded NULs"));
        }
 
        if (bad_addresses)
        {
            if (errhd[sizeof("X-Fetchmail-Warning: ")])
+#ifdef HAVE_SNPRINTF
+               snprintf(errhd+strlen(errhd), sizeof(errhd)-strlen(errhd), "; ");
+           snprintf(errhd+strlen(errhd), sizeof(errhd)-strlen(errhd),
+#else
                strcat(errhd, "; ");
-           strcat(errhd, GT_("SMTP listener rejected local recipient addresses: "));
+           strcat(errhd,
+#endif /* HAVE_SNPRINTF */
+                       GT_("SMTP listener rejected local recipient addresses: "));
            errlen = strlen(errhd);
            for (idp = msgblk.recipients; idp; idp = idp->next)
                if (idp->val.status.mark == XMIT_RCPTBAD)
@@ -1333,6 +1353,23 @@ void init_transact(const struct method *proto)
     protocol = (struct method *)proto;
 }
 
+static void enshroud(char *buf)
+/* shroud a password in the given buffer */
+{
+    char *cp;
+
+    if (shroud[0] && (cp = strstr(buf, shroud)))
+    {
+       char    *sp;
+
+       sp = cp + strlen(shroud);
+       *cp = '*';
+       while (*sp)
+           *cp++ = *sp++;
+       *cp = '\0';
+    }
+}
+
 #if defined(HAVE_STDARG_H)
 void gen_send(int sock, const char *fmt, ... )
 #else
@@ -1372,18 +1409,7 @@ va_dcl
 
     if (outlevel >= O_MONITOR)
     {
-       char *cp;
-
-       if (shroud[0] && (cp = strstr(buf, shroud)))
-       {
-           char        *sp;
-
-           sp = cp + strlen(shroud);
-           *cp++ = '*';
-           while (*sp)
-               *cp++ = *sp++;
-           *cp = '\0';
-       }
+       enshroud(buf);
        buf[strlen(buf)-2] = '\0';
        report(stdout, "%s> %s\n", protocol->name, buf);
     }
@@ -1462,19 +1488,8 @@ va_dcl
 
     if (outlevel >= O_MONITOR)
     {
-       char *cp;
-
-       if (shroud && shroud[0] && (cp = strstr(buf, shroud)))
-       {
-           char        *sp;
-
-           sp = cp + strlen(shroud);
-           *cp++ = '*';
-           while (*sp)
-               *cp++ = *sp++;
-           *cp = '\0';
-       }
-       buf[strlen(buf)-1] = '\0';
+       enshroud(buf);
+       buf[strlen(buf)-2] = '\0';
        report(stdout, "%s> %s\n", protocol->name, buf);
     }