X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/fd98a5c6771f3a5a686e54370b0525dcc3dca2f9..b784ce7fc69e626c9265eb1238d345263d607266:/src/src/receive.c diff --git a/src/src/receive.c b/src/src/receive.c index e0c1c7393..48c83db03 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -13,6 +13,10 @@ 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 * @@ -1429,7 +1453,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 +1484,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 +1544,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 +2719,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 +2828,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 +3191,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 +3200,7 @@ else { seen_this_item = 1; break; - } + } } if (seen_this_item > 0) @@ -3177,7 +3209,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 +3259,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 ) { @@ -3912,7 +3948,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 +3956,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 +4080,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 +4092,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;