X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/6023a6ad2ac0294879b14127f62795095da573b5..803628d5b0b175dfa78f0b19b35213ace01207b1:/src/src/receive.c diff --git a/src/src/receive.c b/src/src/receive.c index 7c56f47ba..32154792e 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2014 */ +/* Copyright (c) University of Cambridge 1995 - 2016 */ /* See the file NOTICE for conditions of use and distribution. */ /* Code for receiving a message and setting up spool files. */ @@ -23,7 +23,7 @@ extern int dcc_ok; static FILE *data_file = NULL; static int data_fd = -1; -static uschar spool_name[256]; +static uschar *spool_name = US""; @@ -525,7 +525,7 @@ static void smtp_user_msg(uschar *code, uschar *user_msg) { int len = 3; -smtp_message_code(&code, &len, &user_msg, NULL); +smtp_message_code(&code, &len, &user_msg, NULL, TRUE); smtp_respond(code, len, TRUE, user_msg); } #endif @@ -682,7 +682,8 @@ while ((ch = (receive_getc)()) != EOF) case 1: /* After written "\n" */ if (ch == '.') { ch_state = 3; continue; } if (ch == '\r') { ch_state = 2; continue; } - if (ch != '\n') ch_state = 0; else linelength = -1; + if (ch == '\n') { body_linecount++; linelength = -1; } + else ch_state = 0; break; case 2: @@ -835,7 +836,15 @@ while ((ch = (receive_getc)()) != EOF) ch_state = 4; continue; } - ch_state = 1; /* The dot itself is removed */ + /* The dot was removed at state 3. For a doubled dot, here, reinstate + it to cutthrough. The current ch, dot or not, is passed both to cutthrough + and to file below. */ + if (ch == '.') + { + uschar c= ch; + (void) cutthrough_puts(&c, 1); + } + ch_state = 1; break; case 4: /* After [CR] LF . CR */ @@ -953,10 +962,12 @@ if (error_handling == ERRORS_SENDER) error_block eblock; eblock.next = NULL; eblock.text1 = text1; + eblock.text2 = US""; if (!moan_to_sender(errcode, &eblock, hptr, f, FALSE)) error_rc = EXIT_FAILURE; } -else fprintf(stderr, "exim: %s%s\n", text2, text1); /* Sic */ +else + fprintf(stderr, "exim: %s%s\n", text2, text1); /* Sic */ (void)fclose(f); exim_exit(error_rc); } @@ -1113,17 +1124,17 @@ Returns: the extended string */ static uschar * -add_host_info_for_log(uschar *s, int *sizeptr, int *ptrptr) +add_host_info_for_log(uschar * s, int * sizeptr, int * ptrptr) { -if (sender_fullhost != NULL) +if (sender_fullhost) { + if (LOGGING(dnssec) && sender_host_dnssec) /*XXX sender_helo_dnssec? */ + s = string_cat(s, sizeptr, ptrptr, US" DS"); s = string_append(s, sizeptr, ptrptr, 2, US" H=", sender_fullhost); - if ((log_extra_selector & LX_incoming_interface) != 0 && - interface_address != NULL) + if (LOGGING(incoming_interface) && interface_address != NULL) { - uschar *ss = string_sprintf(" I=[%s]:%d", interface_address, - interface_port); - s = string_cat(s, sizeptr, ptrptr, ss, Ustrlen(ss)); + s = string_cat(s, sizeptr, ptrptr, + string_sprintf(" I=[%s]:%d", interface_address, interface_port)); } } if (sender_ident != NULL) @@ -1280,10 +1291,12 @@ else if (rc != OK) #ifdef EXPERIMENTAL_DCC dcc_ok = 0; #endif - 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 */ + if ( smtp_input + && smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0) + { + *smtp_yield_ptr = FALSE; /* No more messages after dropped connection */ *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 */ } @@ -1307,7 +1320,7 @@ if (recipients_count == 1) received_for = recipients_list[0].address; received = expand_string(received_header_text); received_for = NULL; -if (received == NULL) +if (!received) { if(spool_name[0] != 0) Uunlink(spool_name); /* Lose the data file */ @@ -1531,7 +1544,7 @@ yet, initialize the size and warning count, and deal with no size limit. */ message_id[0] = 0; data_file = NULL; data_fd = -1; -spool_name[0] = 0; +spool_name = US""; message_size = 0; warning_count = 0; received_count = 1; /* For the one we will add */ @@ -2304,7 +2317,7 @@ if (extract_recip) for (p = s; p < ss; p++) if (*p != '\n') *pp++ = *p; *pp = 0; -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N { BOOL b = allow_utf8_domains; allow_utf8_domains = TRUE; @@ -2312,7 +2325,7 @@ if (extract_recip) recipient = parse_extract_address(recipient, &errmess, &start, &end, &domain, FALSE); -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N if (string_is_utf8(recipient)) message_smtputf8 = TRUE; else @@ -2460,7 +2473,7 @@ it will fit. */ to be the least significant base-62 digit of the time of arrival. Otherwise ensure that it is an empty string. */ -message_subdir[0] = split_spool_directory? message_id[5] : 0; +message_subdir[0] = split_spool_directory ? message_id[5] : 0; /* Now that we have the message-id, if there is no message-id: header, generate one, but only for local (without suppress_local_fixups) or submission mode @@ -2529,7 +2542,7 @@ if (msgid_header == NULL && rewriting. Must copy the count, because later ACLs and the local_scan() function may mess with the real recipients. */ -if ((log_extra_selector & LX_received_recipients) != 0) +if (LOGGING(received_recipients)) { raw_recipients = store_get(recipients_count * sizeof(uschar *)); for (i = 0; i < recipients_count; i++) @@ -2849,20 +2862,18 @@ if (cutthrough.fd >= 0) /* 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 -directory if it isn't there. Note re use of sprintf: spool_directory -is checked on input to be < 200 characters long. */ +directory if it isn't there. */ -sprintf(CS spool_name, "%s/input/%s/%s-D", spool_directory, message_subdir, - message_id); -data_fd = Uopen(spool_name, O_RDWR|O_CREAT|O_EXCL, SPOOL_MODE); -if (data_fd < 0) +spool_name = spool_fname(US"input", message_subdir, message_id, US"-D"); +DEBUG(D_receive) debug_printf("Data file name: %s\n", spool_name); + +if ((data_fd = Uopen(spool_name, O_RDWR|O_CREAT|O_EXCL, SPOOL_MODE)) < 0) { if (errno == ENOENT) { - uschar temp[16]; - sprintf(CS temp, "input/%s", message_subdir); - if (message_subdir[0] == 0) temp[5] = 0; - (void)directory_make(spool_directory, temp, INPUT_DIRECTORY_MODE, TRUE); + (void) directory_make(spool_directory, + spool_sname(US"input", message_subdir), + INPUT_DIRECTORY_MODE, TRUE); data_fd = Uopen(spool_name, O_RDWR|O_CREAT|O_EXCL, SPOOL_MODE); } if (data_fd < 0) @@ -3264,7 +3275,7 @@ else { Uunlink(spool_name); if (smtp_handle_acl_fail(ACL_WHERE_DKIM, rc, user_msg, log_msg) != 0) - smtp_yield = FALSE; /* No more messsages after dropped connection */ + smtp_yield = FALSE; /* No more messages after dropped connection */ smtp_reply = US""; /* Indicate reply already sent */ message_id[0] = 0; /* Indicate no message accepted */ goto TIDYUP; /* Skip to end of function */ @@ -3382,7 +3393,7 @@ else dcc_ok = 0; #endif if (smtp_handle_acl_fail(ACL_WHERE_DATA, rc, user_msg, log_msg) != 0) - smtp_yield = FALSE; /* No more messsages after dropped connection */ + smtp_yield = FALSE; /* No more messages after dropped connection */ smtp_reply = US""; /* Indicate reply already sent */ message_id[0] = 0; /* Indicate no message accepted */ goto TIDYUP; /* Skip to end of function */ @@ -3573,7 +3584,7 @@ else goto TEMPREJECT; case LOCAL_SCAN_REJECT_NOLOGHDR: - log_extra_selector &= ~LX_rejected_header; + BIT_CLEAR(log_selector, log_selector_size, Li_rejected_header); /* Fall through */ case LOCAL_SCAN_REJECT: @@ -3582,7 +3593,7 @@ else break; case LOCAL_SCAN_TEMPREJECT_NOLOGHDR: - log_extra_selector &= ~LX_rejected_header; + BIT_CLEAR(log_selector, log_selector_size, Li_rejected_header); /* Fall through */ case LOCAL_SCAN_TEMPREJECT: @@ -3638,11 +3649,11 @@ signal(SIGINT, SIG_IGN); deliver_firsttime = TRUE; #ifdef EXPERIMENTAL_BRIGHTMAIL -if (bmi_run == 1) { - /* rewind data file */ +if (bmi_run == 1) + { /* rewind data file */ lseek(data_fd, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET); bmi_verdicts = bmi_process_message(header_list, data_fd); -}; + } #endif /* Update the timstamp in our Received: header to account for any time taken by @@ -3680,7 +3691,6 @@ if (host_checking || blackholed_by != NULL) /* Write the -H file */ else - { if ((msg_size = spool_write_header(message_id, SW_RECEIVING, &errmsg)) < 0) { log_write(0, LOG_MAIN, "Message abandoned: %s", errmsg); @@ -3700,7 +3710,6 @@ else /* Does not return */ } } - } /* The message has now been successfully received. */ @@ -3739,23 +3748,24 @@ size = 256; sptr = 0; s = store_get(size); -s = string_append(s, &size, &sptr, 2, US"<= ", - (sender_address[0] == 0)? US"<>" : sender_address); -if (message_reference != NULL) +s = string_append(s, &size, &sptr, 2, + fake_response == FAIL ? US"(= " : US"<= ", + sender_address[0] == 0 ? US"<>" : sender_address); +if (message_reference) s = string_append(s, &size, &sptr, 2, US" R=", message_reference); s = add_host_info_for_log(s, &size, &sptr); #ifdef SUPPORT_TLS -if (log_extra_selector & LX_tls_cipher && tls_in.cipher) +if (LOGGING(tls_cipher) && tls_in.cipher) s = string_append(s, &size, &sptr, 2, US" X=", tls_in.cipher); -if (log_extra_selector & LX_tls_certificate_verified && tls_in.cipher) +if (LOGGING(tls_certificate_verified) && tls_in.cipher) s = string_append(s, &size, &sptr, 2, US" CV=", - tls_in.certificate_verified? "yes":"no"); -if (log_extra_selector & LX_tls_peerdn && tls_in.peerdn) + tls_in.certificate_verified ? "yes":"no"); +if (LOGGING(tls_peerdn) && tls_in.peerdn) s = string_append(s, &size, &sptr, 3, US" DN=\"", string_printing(tls_in.peerdn), US"\""); -if (log_extra_selector & LX_tls_sni && tls_in.sni) +if (LOGGING(tls_sni) && tls_in.sni) s = string_append(s, &size, &sptr, 3, US" SNI=\"", string_printing(tls_in.sni), US"\""); #endif @@ -3763,10 +3773,10 @@ if (log_extra_selector & LX_tls_sni && tls_in.sni) if (sender_host_authenticated) { s = string_append(s, &size, &sptr, 2, US" A=", sender_host_authenticated); - if (authenticated_id != NULL) + if (authenticated_id) { s = string_append(s, &size, &sptr, 2, US":", authenticated_id); - if (log_extra_selector & LX_smtp_mailauth && authenticated_sender != NULL) + if (LOGGING(smtp_mailauth) && authenticated_sender) s = string_append(s, &size, &sptr, 2, US":", authenticated_sender); } } @@ -3776,9 +3786,9 @@ if (prdr_requested) s = string_append(s, &size, &sptr, 1, US" PRDR"); #endif -#ifdef EXPERIMENTAL_PROXY -if (proxy_session && log_extra_selector & LX_proxy) - s = string_append(s, &size, &sptr, 2, US" PRX=", proxy_host_address); +#ifdef SUPPORT_PROXY +if (proxy_session && LOGGING(proxy)) + s = string_append(s, &size, &sptr, 2, US" PRX=", proxy_local_address); #endif sprintf(CS big_buffer, "%d", msg_size); @@ -3788,18 +3798,21 @@ s = string_append(s, &size, &sptr, 2, US" S=", big_buffer); 0 ... no BODY= used 7 ... 7BIT 8 ... 8BITMIME */ -if (log_extra_selector & LX_8bitmime) +if (LOGGING(8bitmime)) { sprintf(CS big_buffer, "%d", body_8bitmime); s = string_append(s, &size, &sptr, 2, US" M8S=", big_buffer); } +if (*queue_name) + s = string_append(s, &size, &sptr, 2, US" Q=", queue_name); + /* If an addr-spec in a message-id contains a quoted string, it can contain any characters except " \ and CR and so in particular it can contain NL! Therefore, make sure we use a printing-characters only version for the log. Also, allow for domain literals in the message id. */ -if (msgid_header != NULL) +if (msgid_header) { uschar *old_id; BOOL save_allow_domain_literals = allow_domain_literals; @@ -3814,7 +3827,7 @@ if (msgid_header != NULL) /* If subject logging is turned on, create suitable printing-character text. By expanding $h_subject: we make use of the MIME decoding. */ -if ((log_extra_selector & LX_subject) != 0 && subject_header != NULL) +if (LOGGING(subject) && subject_header != NULL) { int i; uschar *p = big_buffer; @@ -3848,16 +3861,15 @@ if (message_logs && blackholed_by == NULL) { int fd; - sprintf(CS spool_name, "%s/msglog/%s/%s", spool_directory, message_subdir, - message_id); - fd = Uopen(spool_name, O_WRONLY|O_APPEND|O_CREAT, SPOOL_MODE); - - if (fd < 0 && errno == ENOENT) + spool_name = spool_fname(US"msglog", message_subdir, message_id, US""); + + if ( (fd = Uopen(spool_name, O_WRONLY|O_APPEND|O_CREAT, SPOOL_MODE)) < 0 + && errno == ENOENT + ) { - uschar temp[16]; - sprintf(CS temp, "msglog/%s", message_subdir); - if (message_subdir[0] == 0) temp[6] = 0; - (void)directory_make(spool_directory, temp, MSGLOG_DIRECTORY_MODE, TRUE); + (void)directory_make(spool_directory, + spool_sname(US"msglog", message_subdir), + MSGLOG_DIRECTORY_MODE, TRUE); fd = Uopen(spool_name, O_WRONLY|O_APPEND|O_CREAT, SPOOL_MODE); } @@ -3883,7 +3895,9 @@ if (message_logs && blackholed_by == NULL) if (deliver_freeze) fprintf(message_log, "%s frozen by %s\n", now, frozen_by); if (queue_only_policy) fprintf(message_log, - "%s no immediate delivery: queued by %s\n", now, queued_by); + "%s no immediate delivery: queued%s%s by %s\n", now, + *queue_name ? " in " : "", *queue_name ? CS queue_name : "", + queued_by); (void)fclose(message_log); } } @@ -3935,24 +3949,16 @@ if (smtp_input && sender_host_address != NULL && !sender_host_notsocket && /* Re-use the log line workspace */ sptr = 0; - s = string_cat(s, &size, &sptr, msg, Ustrlen(msg)); + s = string_cat(s, &size, &sptr, msg); s = add_host_info_for_log(s, &size, &sptr); s[sptr] = 0; log_write(0, LOG_MAIN, "%s", s); /* Delete the files for this aborted message. */ - sprintf(CS spool_name, "%s/input/%s/%s-D", spool_directory, - message_subdir, message_id); - Uunlink(spool_name); - - sprintf(CS spool_name, "%s/input/%s/%s-H", spool_directory, - message_subdir, message_id); - Uunlink(spool_name); - - sprintf(CS spool_name, "%s/msglog/%s/%s", spool_directory, - message_subdir, message_id); - Uunlink(spool_name); + Uunlink(spool_fname(US"input", message_subdir, message_id, US"-D")); + Uunlink(spool_fname(US"input", message_subdir, message_id, US"-H")); + Uunlink(spool_fname(US"msglog", message_subdir, message_id, US"")); goto TIDYUP; } @@ -3976,7 +3982,7 @@ for this message. */ */ if(cutthrough.fd >= 0) { - uschar * msg= cutthrough_finaldot(); /* Ask the target system to accept the messsage */ + uschar * msg= cutthrough_finaldot(); /* Ask the target system to accept the message */ /* Logging was done in finaldot() */ switch(msg[0]) { @@ -4003,15 +4009,17 @@ if(!smtp_reply) #endif { log_write(0, LOG_MAIN | - (((log_extra_selector & LX_received_recipients) != 0)? LOG_RECIPIENTS : 0) | - (((log_extra_selector & LX_received_sender) != 0)? LOG_SENDER : 0), + (LOGGING(received_recipients)? LOG_RECIPIENTS : 0) | + (LOGGING(received_sender)? LOG_SENDER : 0), "%s", s); /* Log any control actions taken by an ACL or local_scan(). */ if (deliver_freeze) log_write(0, LOG_MAIN, "frozen by %s", frozen_by); if (queue_only_policy) log_write(L_delay_delivery, LOG_MAIN, - "no immediate delivery: queued by %s", queued_by); + "no immediate delivery: queued%s%s by %s", + *queue_name ? " in " : "", *queue_name ? CS queue_name : "", + queued_by); } receive_call_bombout = FALSE; @@ -4067,19 +4075,19 @@ if (smtp_input) if (!smtp_batched_input) { - if (smtp_reply == NULL) + if (!smtp_reply) { if (fake_response != OK) - smtp_respond((fake_response == DEFER)? US"450" : US"550", 3, TRUE, - fake_response_text); + smtp_respond(fake_response == DEFER ? US"450" : US"550", + 3, TRUE, fake_response_text); /* An OK response is required; use "message" text if present. */ - else if (user_msg != NULL) + else if (user_msg) { uschar *code = US"250"; int len = 3; - smtp_message_code(&code, &len, &user_msg, NULL); + smtp_message_code(&code, &len, &user_msg, NULL, TRUE); smtp_respond(code, len, TRUE, user_msg); } @@ -4106,16 +4114,11 @@ if (smtp_input) switch (cutthrough_done) { 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); - sprintf(CS spool_name, "%s/input/%s/%s-H", spool_directory, - message_subdir, message_id); - Uunlink(spool_name); - sprintf(CS spool_name, "%s/msglog/%s/%s", spool_directory, - message_subdir, message_id); - Uunlink(spool_name); + case PERM_REJ: + { /* Delete spool files */ + Uunlink(spool_fname(US"input", message_subdir, message_id, US"-D")); + Uunlink(spool_fname(US"input", message_subdir, message_id, US"-H")); + Uunlink(spool_fname(US"msglog", message_subdir, message_id, US"")); } case TMP_REJ: message_id[0] = 0; /* Prevent a delivery from starting */ default:break; @@ -4127,7 +4130,8 @@ if (smtp_input) nothing on success. The function moan_smtp_batch() does not return - it exits from the program with a non-zero return code. */ - else if (smtp_reply != NULL) moan_smtp_batch(NULL, "%s", smtp_reply); + else if (smtp_reply) + moan_smtp_batch(NULL, "%s", smtp_reply); } @@ -4136,7 +4140,7 @@ file has already been unlinked, and the header file was never written to disk. We must now indicate that nothing was received, to prevent a delivery from starting. */ -if (blackholed_by != NULL) +if (blackholed_by) { const uschar *detail = local_scan_data ? string_printing(local_scan_data)