CHUNKING: fix second message on conn when first rejected
[exim.git] / src / src / smtp_in.c
index 9efc816fa8e56b91fdc537ed2ba25df30aa43340..752e80dca4887cc97fe099046bfbece520420783 100644 (file)
@@ -2,8 +2,8 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim Maintainers 2020 - 2022 */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 - 2021 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions for handling an incoming SMTP call. */
@@ -342,7 +342,7 @@ if (!sender_address                         /* No transaction in progress */
 
 if (recipients_count > 0)
   {
-  raw_recipients = store_get(recipients_count * sizeof(uschar *), FALSE);
+  raw_recipients = store_get(recipients_count * sizeof(uschar *), GET_UNTAINTED);
   for (int i = 0; i < recipients_count; i++)
     raw_recipients[i] = recipients_list[i].address;
   raw_recipients_count = recipients_count;
@@ -840,12 +840,8 @@ while (chunking_data_left)
   }
 
 bdat_pop_receive_functions();
-
-if (chunking_state != CHUNKING_LAST)
-  {
-  chunking_state = CHUNKING_OFFERED;
-  DEBUG(D_receive) debug_printf("chunking state %d\n", (int)chunking_state);
-  }
+chunking_state = CHUNKING_OFFERED;
+DEBUG(D_receive) debug_printf("chunking state %d\n", (int)chunking_state);
 }
 
 
@@ -956,15 +952,12 @@ that we'll never expand it. */
 yield = !! string_vformat(&gs, SVFMT_TAINT_NOCHK, format, ap);
 string_from_gstring(&gs);
 
-DEBUG(D_receive)
-  {
-  uschar *msg_copy, *cr, *end;
-  msg_copy = string_copy(gs.s);
-  end = msg_copy + gs.ptr;
-  while ((cr = Ustrchr(msg_copy, '\r')) != NULL)   /* lose CRs */
-    memmove(cr, cr + 1, (end--) - cr);
-  debug_printf("SMTP>> %s", msg_copy);
-  }
+DEBUG(D_receive) for (const uschar * t, * s = gs.s;
+                     s && (t = Ustrchr(s, '\r'));
+                     s = t + 2)                                /* \r\n */
+    debug_printf("%s %.*s\n",
+                 s == gs.s ? "SMTP>>" : "      ",
+                 (int)(t - s), s);
 
 if (!yield)
   {
@@ -981,7 +974,7 @@ which sometimes uses smtp_printf() and sometimes smtp_respond(). */
 
 if (fl.rcpt_in_progress)
   {
-  if (rcpt_smtp_response == NULL)
+  if (!rcpt_smtp_response)
     rcpt_smtp_response = string_copy(big_buffer);
   else if (fl.rcpt_smtp_response_same &&
            Ustrcmp(rcpt_smtp_response, big_buffer) != 0)
@@ -2572,7 +2565,7 @@ acl_var_c = NULL;
 
 /* Allow for trailing 0 in the command and data buffers.  Tainted. */
 
-smtp_cmd_buffer = store_get_perm(2*SMTP_CMD_BUFFER_SIZE + 2, TRUE);
+smtp_cmd_buffer = store_get_perm(2*SMTP_CMD_BUFFER_SIZE + 2, GET_TAINTED);
 
 smtp_cmd_buffer[0] = 0;
 smtp_data_buffer = smtp_cmd_buffer + SMTP_CMD_BUFFER_SIZE + 1;
@@ -2682,7 +2675,7 @@ if (!f.sender_host_unknown)
     {
     #if OPTSTYLE == 1
     EXIM_SOCKLEN_T optlen = sizeof(struct ip_options) + MAX_IPOPTLEN;
-    struct ip_options *ipopt = store_get(optlen, FALSE);
+    struct ip_options *ipopt = store_get(optlen, GET_UNTAINTED);
     #elif OPTSTYLE == 2
     struct ip_opts ipoptblock;
     struct ip_opts *ipopt = &ipoptblock;
@@ -3777,6 +3770,12 @@ smtp_in_auth(auth_instance *au, uschar ** s, uschar ** ss)
 const uschar *set_id = NULL;
 int rc;
 
+/* Set up globals for error messages */
+
+authenticator_name = au->name;
+driver_srcfile = au->srcfile;
+driver_srcline = au->srcline;
+
 /* Run the checking code, passing the remainder of the command line as
 data. Initials the $auth<n> variables as empty. Initialize $0 empty and set
 it as the only set numerical variable. The authenticator may set $auth<n>
@@ -3797,6 +3796,7 @@ rc = (au->info->servercode)(au, smtp_cmd_data);
 if (au->set_id) set_id = expand_string(au->set_id);
 expand_nmax = -1;        /* Reset numeric variables */
 for (int i = 0; i < AUTH_VARS; i++) auth_vars[i] = NULL;   /* Reset $auth<n> */
+driver_srcfile = authenticator_name = NULL; driver_srcline = 0;
 
 /* The value of authenticated_id is stored in the spool file and printed in
 log lines. It must not contain binary zeros or newline characters. In
@@ -4369,7 +4369,7 @@ while (done <= 0)
       if (!user_msg)
        {
        /* sender_host_name below will be tainted, so save on copy when we hit it */
-       g = string_get_tainted(24, TRUE);
+       g = string_get_tainted(24, GET_TAINTED);
        g = string_fmt_append(g, "%.3s %s Hello %s%s%s",
          smtp_code,
          smtp_active_hostname,
@@ -4615,15 +4615,12 @@ while (done <= 0)
 #endif
        (void) fwrite(g->s, 1, g->ptr, smtp_out);
 
-      DEBUG(D_receive)
-       {
-       uschar *cr;
-
-       (void) string_from_gstring(g);
-       while ((cr = Ustrchr(g->s, '\r')) != NULL)   /* lose CRs */
-         memmove(cr, cr + 1, (g->ptr--) - (cr - g->s));
-       debug_printf("SMTP>> %s", g->s);
-       }
+      DEBUG(D_receive) for (const uschar * t, * s = string_from_gstring(g);
+                           s && (t = Ustrchr(s, '\r'));
+                           s = t + 2)                          /* \r\n */
+         debug_printf("%s %.*s\n",
+                       s == g->s ? "SMTP>>" : "      ",
+                       (int)(t - s), s);
       fl.helo_seen = TRUE;
 
       /* Reset the protocol and the state, abandoning any previous message. */
@@ -5080,7 +5077,7 @@ while (done <= 0)
       count this as a protocol error. Reset was_rej_mail so that further RCPTs
       get the same treatment. */
 
-      if (sender_address == NULL)
+      if (!sender_address)
        {
        if (f.smtp_in_pipelining_advertised && last_was_rej_mail)
          {
@@ -5099,7 +5096,7 @@ while (done <= 0)
 
       /* Check for an operand */
 
-      if (smtp_cmd_data[0] == 0)
+      if (!smtp_cmd_data[0])
        {
        done = synprot_error(L_smtp_syntax_error, 501, NULL,
          US"RCPT must have an address operand");
@@ -5827,7 +5824,7 @@ while (done <= 0)
        etrn_command = smtp_etrn_command;
        deliver_domain = smtp_cmd_data;
        rc = transport_set_up_command(&argv, smtp_etrn_command, TRUE, 0, NULL,
-         US"ETRN processing", &error);
+         FALSE, US"ETRN processing", &error);
        deliver_domain = NULL;
        if (!rc)
          {
@@ -5904,6 +5901,7 @@ while (done <= 0)
          {
          DEBUG(D_exec) debug_print_argv(argv);
          exim_nullstd();                   /* Ensure std{in,out,err} exist */
+         /* argv[0] should be untainted, from child_exec_exim() */
          execv(CS argv[0], (char *const *)argv);
          log_write(0, LOG_MAIN|LOG_PANIC_DIE, "exec of \"%s\" (ETRN) failed: %s",
            etrn_command, strerror(errno));