Silence compiler string format warning
[exim.git] / src / src / receive.c
index e0c1c73939325ad31668a735ced5eb0a8d259916..072fee9f1f27aaf4fe50541e1ee17e94d3f5ba69 100644 (file)
 extern int dcc_ok;
 #endif
 
+#ifdef EXPERIMENTAL_DMARC
+#include "dmarc.h"
+#endif /* EXPERIMENTAL_DMARC */
+
 /*************************************************
 *                Local static variables          *
 *************************************************/
@@ -286,32 +290,50 @@ Returns:     it doesn't
 void
 receive_bomb_out(uschar *reason, uschar *msg)
 {
+  static BOOL already_bombing_out;
+/* The smtp_notquit_exit() below can call ACLs which can trigger recursive
+timeouts, if someone has something slow in their quit ACL.  Since the only
+things we should be doing are to close down cleanly ASAP, on the second
+pass we also close down stuff that might be opened again, before bypassing
+the ACL call and exiting. */
+
 /* If spool_name is set, it contains the name of the data file that is being
 written. Unlink it before closing so that it cannot be picked up by a delivery
 process. Ensure that any header file is also removed. */
 
-if (spool_name[0] != 0)
+if (spool_name[0] != '\0')
   {
   Uunlink(spool_name);
   spool_name[Ustrlen(spool_name) - 1] = 'H';
   Uunlink(spool_name);
+  spool_name[0] = '\0';
   }
 
 /* Now close the file if it is open, either as a fd or a stream. */
 
-if (data_file != NULL) (void)fclose(data_file);
-  else if (data_fd >= 0) (void)close(data_fd);
+if (data_file != NULL)
+  {
+  (void)fclose(data_file);
+  data_file = NULL;
+} else if (data_fd >= 0) {
+  (void)close(data_fd);
+  data_fd = -1;
+  }
 
 /* Attempt to close down an SMTP connection tidily. For non-batched SMTP, call
 smtp_notquit_exit(), which runs the NOTQUIT ACL, if present, and handles the
 SMTP response. */
 
-if (smtp_input)
+if (!already_bombing_out)
   {
-  if (smtp_batched_input)
-    moan_smtp_batch(NULL, "421 %s - message abandoned", msg);  /* No return */
-  smtp_notquit_exit(reason, US"421", US"%s %s - closing connection.",
-    smtp_active_hostname, msg);
+  already_bombing_out = TRUE;
+  if (smtp_input)
+    {
+    if (smtp_batched_input)
+      moan_smtp_batch(NULL, "421 %s - message abandoned", msg);  /* No return */
+    smtp_notquit_exit(reason, US"421", US"%s %s - closing connection.",
+      smtp_active_hostname, msg);
+    }
   }
 
 /* Exit from the program (non-BSMTP cases) */
@@ -484,30 +506,32 @@ recipients_list[recipients_count++].errors_to = NULL;
 /*************************************************
 *        Send user response message              *
 *************************************************/
-        
+
 /* This function is passed a default response code and a user message. It calls
 smtp_message_code() to check and possibly modify the response code, and then
 calls smtp_respond() to transmit the response. I put this into a function
 just to avoid a lot of repetition.
-            
-Arguments:               
+
+Arguments:
   code         the response code
   user_msg     the user message
 
 Returns:       nothing
-*/        
-            
-static void 
+*/
+
+#ifdef EXPERIMENTAL_PRDR
+static void
 smtp_user_msg(uschar *code, uschar *user_msg)
-{           
+{
 int len = 3;
 smtp_message_code(&code, &len, &user_msg, NULL);
 smtp_respond(code, len, TRUE, user_msg);
-}           
-                        
-            
-          
-          
+}
+#endif
+
+
+
+
 
 /*************************************************
 *        Remove a recipient from the list        *
@@ -1253,9 +1277,10 @@ else if (rc != OK)
 #ifdef EXPERIMENTAL_DCC
   dcc_ok = 0;
 #endif
-  if (smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0)
+  if (smtp_input && smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0) {
     *smtp_yield_ptr = FALSE;    /* No more messsages after dropped connection */
-  *smtp_reply_ptr = US"";       /* Indicate reply already sent */
+    *smtp_reply_ptr = US"";     /* Indicate reply already sent */
+  }
   message_id[0] = 0;            /* Indicate no message accepted */
   return FALSE;                 /* Cause skip to end of receive function */
   }
@@ -1429,7 +1454,7 @@ BOOL resents_exist = FALSE;
 uschar *resent_prefix = US"";
 uschar *blackholed_by = NULL;
 uschar *blackhole_log_msg = US"";
-int  cutthrough_done = 0;
+enum {NOT_TRIED, TMP_REJ, PERM_REJ, ACCEPTED} cutthrough_done;
 
 flock_t lock_data;
 error_block *bad_addresses = NULL;
@@ -1460,6 +1485,10 @@ header_line *subject_header = NULL;
 header_line *msgid_header = NULL;
 header_line *received_header;
 
+#ifdef EXPERIMENTAL_DMARC
+int dmarc_up = 0;
+#endif /* EXPERIMENTAL_DMARC */
+
 /* Variables for use when building the Received: header. */
 
 uschar *timestamp;
@@ -1516,6 +1545,11 @@ message_linecount = body_linecount = body_zerocount =
 if (smtp_input && !smtp_batched_input && !dkim_disable_verify) dkim_exim_verify_init();
 #endif
 
+#ifdef EXPERIMENTAL_DMARC
+/* initialize libopendmarc */
+dmarc_up = dmarc_init();
+#endif
+
 /* Remember the time of reception. Exim uses time+pid for uniqueness of message
 ids, and fractions of a second are required. See the comments that precede the
 message id creation below. */
@@ -2686,7 +2720,6 @@ if (from_header != NULL &&
     }
   }
 
-
 /* If there are any rewriting rules, apply them to the sender address, unless
 it has already been rewritten as part of verification for SMTP input. */
 
@@ -2796,7 +2829,7 @@ if (cutthrough_fd >= 0)
   add_acl_headers(US"MAIL or RCPT");
   (void) cutthrough_headers_send();
   }
+
 
 /* Open a new spool file for the data portion of the message. We need
 to access it both via a file descriptor and a stream. Try to make the
@@ -3159,7 +3192,7 @@ else
               uschar seen_item_buf[256];
               uschar *seen_items_list = seen_items;
               int seen_this_item = 0;
-              
+
               while ((seen_item = string_nextinlist(&seen_items_list, &sep,
                                                     seen_item_buf,
                                                     sizeof(seen_item_buf))) != NULL)
@@ -3168,7 +3201,7 @@ else
                     {
                       seen_this_item = 1;
                       break;
-                    } 
+                    }
                 }
 
               if (seen_this_item > 0)
@@ -3177,7 +3210,7 @@ else
                   debug_printf("acl_smtp_dkim: skipping signer %s, already seen\n", item);
                 continue;
                 }
-              
+
               seen_items = string_append(seen_items,&seen_items_size,&seen_items_offset,1,":");
               }
 
@@ -3227,6 +3260,10 @@ else
       goto TIDYUP;
 #endif /* WITH_CONTENT_SCAN */
 
+#ifdef EXPERIMENTAL_DMARC
+    dmarc_up = dmarc_store_data(from_header);
+#endif /* EXPERIMENTAL_DMARC */
+
 #ifdef EXPERIMENTAL_PRDR
     if (prdr_requested && recipients_count > 1 && acl_smtp_data_prdr != NULL )
       {
@@ -3275,7 +3312,7 @@ else
          }
        if (log_msg)       log_write(0, LOG_MAIN, "PRDR %s %s", addr, log_msg);
        else if (user_msg) log_write(0, LOG_MAIN, "PRDR %s %s", addr, user_msg);
-       else               log_write(0, LOG_MAIN, CS msg);
+       else               log_write(0, LOG_MAIN, "%s", CS msg);
 
        if (rc != OK) { receive_remove_recipient(addr); c--; }
         }
@@ -3912,7 +3949,7 @@ for this message. */
 
    XXX We do not handle queue-only, freezing, or blackholes.
 */
-cutthrough_done = 0;
+cutthrough_done = NOT_TRIED;
 if(cutthrough_fd >= 0)
   {
   uschar * msg= cutthrough_finaldot(); /* Ask the target system to accept the messsage */
@@ -3920,17 +3957,17 @@ if(cutthrough_fd >= 0)
   switch(msg[0])
     {
     case '2':  /* Accept. Do the same to the source; dump any spoolfiles.   */
-      cutthrough_done = 3;
+      cutthrough_done = ACCEPTED;
       break;                                   /* message_id needed for SMTP accept below */
-  
+
     default:   /* Unknown response, or error.  Treat as temp-reject.         */
     case '4':  /* Temp-reject. Keep spoolfiles and accept. */
-      cutthrough_done = 1;                     /* Avoid the usual immediate delivery attempt */
+      cutthrough_done = TMP_REJ;               /* Avoid the usual immediate delivery attempt */
       break;                                   /* message_id needed for SMTP accept below */
-  
+
     case '5':  /* Perm-reject.  Do the same to the source.  Dump any spoolfiles */
       smtp_reply= msg;         /* Pass on the exact error */
-      cutthrough_done = 2;
+      cutthrough_done = PERM_REJ;
       break;
     }
   }
@@ -4044,8 +4081,8 @@ if (smtp_input)
 
     switch (cutthrough_done)
       {
-      case 3: log_write(0, LOG_MAIN, "Completed");     /* Delivery was done */
-      case 2: {                                                /* Delete spool files */
+      case ACCEPTED: log_write(0, LOG_MAIN, "Completed");/* Delivery was done */
+      case PERM_REJ: {                                 /* Delete spool files */
              sprintf(CS spool_name, "%s/input/%s/%s-D", spool_directory,
                message_subdir, message_id);
              Uunlink(spool_name);
@@ -4056,7 +4093,7 @@ if (smtp_input)
                message_subdir, message_id);
              Uunlink(spool_name);
              }
-      case 1: message_id[0] = 0;                       /* Prevent a delivery from starting */
+      case TMP_REJ: message_id[0] = 0;   /* Prevent a delivery from starting */
       default:break;
       }
     cutthrough_delivery = FALSE;