X-Git-Url: https://vcs.fsf.org/?p=exim.git;a=blobdiff_plain;f=src%2Fsrc%2Freceive.c;h=3f7170b3ecbb5115ba15b572330e8d7b469527e8;hp=7f814e64a6c5ec482435c5f004683c0b628f48e5;hb=de3a88fb84d10cefa219ffa33effdf2af43015e4;hpb=8e669ac162fe3b1040297f1d021de10778dce9d9 diff --git a/src/src/receive.c b/src/src/receive.c index 7f814e64a..3f7170b3e 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/receive.c,v 1.11 2005/02/17 11:58:26 ph10 Exp $ */ +/* $Cambridge: exim/src/src/receive.c,v 1.24 2005/09/12 10:08:54 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -9,10 +9,15 @@ /* Code for receiving a message and setting up spool files. */ - #include "exim.h" - +#ifdef EXPERIMENTAL_DOMAINKEYS +#define RECEIVE_GETC dk_receive_getc +#define RECEIVE_UNGETC dk_receive_ungetc +#else +#define RECEIVE_GETC receive_getc +#define RECEIVE_UNGETC receive_ungetc +#endif /************************************************* * Local static variables * @@ -298,8 +303,8 @@ if (spool_name[0] != 0) /* Now close the file if it is open, either as a fd or a stream. */ -if (data_file != NULL) fclose(data_file); - else if (data_fd >= 0) close(data_fd); +if (data_file != NULL) (void)fclose(data_file); + else if (data_fd >= 0) (void)close(data_fd); /* Attempt to close down an SMTP connection tidily. */ @@ -346,8 +351,9 @@ if (smtp_input) msg = US"SMTP incoming data timeout"; log_write(L_lost_incoming_connection, LOG_MAIN, "SMTP data timeout (message abandoned) on connection " - "from %s", - (sender_fullhost != NULL)? sender_fullhost : US"local process"); + "from %s F=<%s>", + (sender_fullhost != NULL)? sender_fullhost : US"local process", + sender_address); } else { @@ -505,7 +511,7 @@ for (count = 0; count < recipients_count; count++) { if ((--recipients_count - count) > 0) memmove(recipients_list + count, recipients_list + count + 1, - (recipients_count - count)*sizeof(recipient_item)); + (recipients_count - count)*sizeof(recipient_item)); return TRUE; } } @@ -565,7 +571,7 @@ if (!dot_ends) { register int last_ch = '\n'; - for (; (ch = (receive_getc)()) != EOF; last_ch = ch) + for (; (ch = (RECEIVE_GETC)()) != EOF; last_ch = ch) { if (ch == 0) body_zerocount++; if (last_ch == '\r' && ch != '\n') @@ -595,7 +601,7 @@ if (!dot_ends) ch_state = 1; -while ((ch = (receive_getc)()) != EOF) +while ((ch = (RECEIVE_GETC)()) != EOF) { if (ch == 0) body_zerocount++; switch (ch_state) @@ -696,7 +702,7 @@ read_message_data_smtp(FILE *fout) int ch_state = 0; register int ch; -while ((ch = (receive_getc)()) != EOF) +while ((ch = (RECEIVE_GETC)()) != EOF) { if (ch == 0) body_zerocount++; switch (ch_state) @@ -859,7 +865,7 @@ if (error_handling == ERRORS_SENDER) error_rc = EXIT_FAILURE; } else fprintf(stderr, "exim: %s%s\n", text2, text1); /* Sic */ -fclose(f); +(void)fclose(f); exim_exit(error_rc); } @@ -1002,6 +1008,149 @@ return s; +#ifdef WITH_CONTENT_SCAN + +/************************************************* +* Run the MIME ACL on a message * +*************************************************/ + +/* This code is in a subroutine so that it can be used for both SMTP +and non-SMTP messages. It is called with a non-NULL ACL pointer. + +Arguments: + acl The ACL to run (acl_smtp_mime or acl_not_smtp_mime) + smtp_yield_ptr Set FALSE to kill messages after dropped connection + smtp_reply_ptr Where SMTP reply is being built + blackholed_by_ptr Where "blackholed by" message is being built + +Returns: TRUE to carry on; FALSE to abandon the message +*/ + +static BOOL +run_mime_acl(uschar *acl, BOOL *smtp_yield_ptr, uschar **smtp_reply_ptr, + uschar **blackholed_by_ptr) +{ +FILE *mbox_file; +uschar rfc822_file_path[2048]; +unsigned long mbox_size; +header_line *my_headerlist; +uschar *user_msg, *log_msg; +int mime_part_count_buffer = -1; +int rc; + +memset(CS rfc822_file_path,0,2048); + +/* check if it is a MIME message */ +my_headerlist = header_list; +while (my_headerlist != NULL) { + /* skip deleted headers */ + if (my_headerlist->type == '*') { + my_headerlist = my_headerlist->next; + continue; + }; + if (strncmpic(my_headerlist->text, US"Content-Type:", 13) == 0) { + DEBUG(D_receive) debug_printf("Found Content-Type: header - executing acl_smtp_mime.\n"); + goto DO_MIME_ACL; + }; + my_headerlist = my_headerlist->next; +}; + +DEBUG(D_receive) debug_printf("No Content-Type: header - presumably not a MIME message.\n"); +return TRUE; + +DO_MIME_ACL: +/* make sure the eml mbox file is spooled up */ +mbox_file = spool_mbox(&mbox_size); +if (mbox_file == NULL) { + /* error while spooling */ + log_write(0, LOG_MAIN|LOG_PANIC, + "acl_smtp_mime: error while creating mbox spool file, message temporarily rejected."); + Uunlink(spool_name); + unspool_mbox(); + smtp_respond(451, TRUE, US"temporary local problem"); + message_id[0] = 0; /* Indicate no message accepted */ + *smtp_reply_ptr = US""; /* Indicate reply already sent */ + return FALSE; /* Indicate skip to end of receive function */ +}; + +mime_is_rfc822 = 0; + +MIME_ACL_CHECK: +mime_part_count = -1; +rc = mime_acl_check(acl, mbox_file, NULL, &user_msg, &log_msg); +(void)fclose(mbox_file); + +if (Ustrlen(rfc822_file_path) > 0) { + mime_part_count = mime_part_count_buffer; + + if (unlink(CS rfc822_file_path) == -1) { + log_write(0, LOG_PANIC, + "acl_smtp_mime: can't unlink RFC822 spool file, skipping."); + goto END_MIME_ACL; + }; +}; + +/* check if we must check any message/rfc822 attachments */ +if (rc == OK) { + uschar temp_path[1024]; + int n; + struct dirent *entry; + DIR *tempdir; + + (void)string_format(temp_path, 1024, "%s/scan/%s", spool_directory, + message_id); + + tempdir = opendir(CS temp_path); + n = 0; + do { + entry = readdir(tempdir); + if (entry == NULL) break; + if (strncmpic(US entry->d_name,US"__rfc822_",9) == 0) { + (void)string_format(rfc822_file_path, 2048,"%s/scan/%s/%s", spool_directory, message_id, entry->d_name); + debug_printf("RFC822 attachment detected: running MIME ACL for '%s'\n", rfc822_file_path); + break; + }; + } while (1); + closedir(tempdir); + + if (entry != NULL) { + mbox_file = Ufopen(rfc822_file_path,"rb"); + if (mbox_file == NULL) { + log_write(0, LOG_PANIC, + "acl_smtp_mime: can't open RFC822 spool file, skipping."); + unlink(CS rfc822_file_path); + goto END_MIME_ACL; + }; + /* set RFC822 expansion variable */ + mime_is_rfc822 = 1; + mime_part_count_buffer = mime_part_count; + goto MIME_ACL_CHECK; + }; +}; + +END_MIME_ACL: +add_acl_headers(US"MIME"); +if (rc == DISCARD) + { + recipients_count = 0; + *blackholed_by_ptr = US"MIME ACL"; + } +else if (rc != OK) + { + Uunlink(spool_name); + unspool_mbox(); + if (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 */ + message_id[0] = 0; /* Indicate no message accepted */ + return FALSE; /* Cause skip to end of receive function */ + }; + +return TRUE; +} + +#endif /* WITH_CONTENT_SCAN */ + /************************************************* * Receive message * @@ -1011,9 +1160,10 @@ return s; Either a non-null list of recipients, or the extract flag will be true, or both. The flag sender_local is true for locally generated messages. The flag submission_mode is true if an ACL has obeyed "control = submission". The flag -smtp_input is true if the message is to be handled using SMTP conventions about -termination and lines starting with dots. For non-SMTP messages, dot_ends is -true for dot-terminated messages. +suppress_local_fixups is true if an ACL has obeyed "control = +suppress_local_fixups". The flag smtp_input is true if the message is to be +handled using SMTP conventions about termination and lines starting with dots. +For non-SMTP messages, dot_ends is true for dot-terminated messages. If a message was successfully read, message_id[0] will be non-zero. @@ -1191,11 +1341,15 @@ received_count = 1; /* For the one we will add */ if (thismessage_size_limit <= 0) thismessage_size_limit = INT_MAX; -/* While reading the message, body_linecount and body_zerocount is computed. -The full message_ linecount is set up only when the headers are read back in -from the spool for delivery. */ +/* While reading the message, the following counts are computed. */ + +message_linecount = body_linecount = body_zerocount = 0; -body_linecount = body_zerocount = 0; +#ifdef EXPERIMENTAL_DOMAINKEYS +/* Call into DK to set up the context. Check if DK is to be run are carried out + inside dk_exim_verify_init(). */ +dk_exim_verify_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 @@ -1245,7 +1399,7 @@ next->text. */ for (;;) { - int ch = (receive_getc)(); + int ch = (RECEIVE_GETC)(); /* If we hit EOF on a SMTP connection, it's an error, since incoming SMTP must have a correct "." terminator. */ @@ -1309,7 +1463,7 @@ for (;;) if (ch == '\n') { if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = FALSE; - else if (first_line_ended_crlf) receive_ungetc(' '); + else if (first_line_ended_crlf) RECEIVE_UNGETC(' '); goto EOL; } @@ -1324,13 +1478,13 @@ for (;;) if (ptr == 0 && ch == '.' && (smtp_input || dot_ends)) { - ch = (receive_getc)(); + ch = (RECEIVE_GETC)(); if (ch == '\r') { - ch = (receive_getc)(); + ch = (RECEIVE_GETC)(); if (ch != '\n') { - receive_ungetc(ch); + RECEIVE_UNGETC(ch); ch = '\r'; /* Revert to CR */ } } @@ -1358,7 +1512,7 @@ for (;;) if (ch == '\r') { - ch = (receive_getc)(); + ch = (RECEIVE_GETC)(); if (ch == '\n') { if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = TRUE; @@ -1368,7 +1522,7 @@ for (;;) /* Otherwise, put back the character after CR, and turn the bare CR into LF SP. */ - ch = (receive_ungetc)(ch); + ch = (RECEIVE_UNGETC)(ch); next->text[ptr++] = '\n'; message_size++; ch = ' '; @@ -1419,7 +1573,11 @@ for (;;) /* End of header line reached */ EOL: - receive_linecount++; /* For BSMTP errors */ + + /* Keep track of lines for BSMTP errors and overall message_linecount. */ + + receive_linecount++; + message_linecount++; /* Now put in the terminating newline. There is always space for at least two more characters. */ @@ -1443,14 +1601,14 @@ for (;;) if (ch != EOF) { - int nextch = (receive_getc)(); + int nextch = (RECEIVE_GETC)(); if (nextch == ' ' || nextch == '\t') { next->text[ptr++] = nextch; message_size++; continue; /* Iterate the loop */ } - else if (nextch != EOF) (receive_ungetc)(nextch); /* For next time */ + else if (nextch != EOF) (RECEIVE_UNGETC)(nextch); /* For next time */ else ch = EOF; /* Cause main loop to exit at end */ } @@ -1819,18 +1977,22 @@ for (h = header_list->next; h != NULL; h = h->next) break; /* If there is a "Sender:" header and the message is locally originated, - and from an untrusted caller, or if we are in submission mode for a remote - message, mark it "old" so that it will not be transmitted with the message, - unless active_local_sender_retain is set. (This can only be true if - active_local_from_check is false.) If there are any resent- headers in the - message, apply this rule to Resent-Sender: instead of Sender:. Messages - with multiple resent- header sets cannot be tidily handled. (For this - reason, at least one MUA - Pine - turns old resent- headers into X-resent- - headers when resending, leaving just one set.) */ + and from an untrusted caller and suppress_local_fixups is not set, or if we + are in submission mode for a remote message, mark it "old" so that it will + not be transmitted with the message, unless active_local_sender_retain is + set. (This can only be true if active_local_from_check is false.) If there + are any resent- headers in the message, apply this rule to Resent-Sender: + instead of Sender:. Messages with multiple resent- header sets cannot be + tidily handled. (For this reason, at least one MUA - Pine - turns old + resent- headers into X-resent- headers when resending, leaving just one + set.) */ case htype_sender: h->type = ((!active_local_sender_retain && - ((sender_local && !trusted_caller) || submission_mode) + ( + (sender_local && !trusted_caller && !suppress_local_fixups) + || submission_mode + ) ) && (!resents_exist||is_resent))? htype_old : htype_sender; @@ -2092,11 +2254,13 @@ ensure that it is an empty string. */ 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 or submission mode messages. This can be -user-configured if required, but we had better flatten any illegal characters -therein. */ +one, but only for local (without suppress_local_fixups) or submission mode +messages. This can be user-configured if required, but we had better flatten +any illegal characters therein. */ -if (msgid_header == NULL && (sender_host_address == NULL || submission_mode)) +if (msgid_header == NULL && + ((sender_host_address == NULL && !suppress_local_fixups) + || submission_mode)) { uschar *p; uschar *id_text = US""; @@ -2170,46 +2334,75 @@ for (i = 0; i < recipients_count; i++) rewrite_address(recipients_list[i].address, TRUE, TRUE, global_rewrite_rules, rewrite_existflags); -/* If there is no From: header, generate one for local or submission_mode -messages. If there is no sender address, but the sender is local or this is a -local delivery error, use the originator login. This shouldn't happen for -genuine bounces, but might happen for autoreplies. The addition of From: must -be done *before* checking for the possible addition of a Sender: header, -because untrusted_set_sender allows an untrusted user to set anything in the -envelope (which might then get info From:) but we still want to ensure a valid -Sender: if it is required. */ - -if (from_header == NULL && (sender_host_address == NULL || submission_mode)) +/* If there is no From: header, generate one for local (without +suppress_local_fixups) or submission_mode messages. If there is no sender +address, but the sender is local or this is a local delivery error, use the +originator login. This shouldn't happen for genuine bounces, but might happen +for autoreplies. The addition of From: must be done *before* checking for the +possible addition of a Sender: header, because untrusted_set_sender allows an +untrusted user to set anything in the envelope (which might then get info +From:) but we still want to ensure a valid Sender: if it is required. */ + +if (from_header == NULL && + ((sender_host_address == NULL && !suppress_local_fixups) + || submission_mode)) { + uschar *oname = US""; + + /* Use the originator_name if this is a locally submitted message and the + caller is not trusted. For trusted callers, use it only if -F was used to + force its value or if we have a non-SMTP message for which -f was not used + to set the sender. */ + + if (sender_host_address == NULL) + { + if (!trusted_caller || sender_name_forced || + (!smtp_input && !sender_address_forced)) + oname = originator_name; + } + + /* For non-locally submitted messages, the only time we use the originator + name is when it was forced by the /name= option on control=submission. */ + + else + { + if (submission_name != NULL) oname = submission_name; + } + /* Envelope sender is empty */ if (sender_address[0] == 0) { + uschar *fromstart, *fromend; + + fromstart = string_sprintf("%sFrom: %s%s", resent_prefix, + oname, (oname[0] == 0)? "" : " <"); + fromend = (oname[0] == 0)? US"" : US">"; + if (sender_local || local_error_message) { - header_add(htype_from, "%sFrom: %s%s%s@%s%s\n", resent_prefix, - originator_name, - (originator_name[0] == 0)? "" : " <", - local_part_quote(originator_login), - qualify_domain_sender, - (originator_name[0] == 0)? "" : ">"); + header_add(htype_from, "%s%s@%s%s\n", fromstart, + local_part_quote(originator_login), qualify_domain_sender, + fromend); } else if (submission_mode && authenticated_id != NULL) { if (submission_domain == NULL) { - header_add(htype_from, "%sFrom: %s@%s\n", resent_prefix, - local_part_quote(authenticated_id), qualify_domain_sender); + header_add(htype_from, "%s%s@%s%s\n", fromstart, + local_part_quote(authenticated_id), qualify_domain_sender, + fromend); } else if (submission_domain[0] == 0) /* empty => whole address set */ { - header_add(htype_from, "%sFrom: %s\n", resent_prefix, - authenticated_id); + header_add(htype_from, "%s%s%s\n", fromstart, authenticated_id, + fromend); } else { - header_add(htype_from, "%sFrom: %s@%s\n", resent_prefix, - local_part_quote(authenticated_id), submission_domain); + header_add(htype_from, "%s%s@%s%s\n", fromstart, + local_part_quote(authenticated_id), submission_domain, + fromend); } from_header = header_last; /* To get it checked for Sender: */ } @@ -2221,34 +2414,31 @@ if (from_header == NULL && (sender_host_address == NULL || submission_mode)) else { - if (!smtp_input || sender_local) - header_add(htype_from, "%sFrom: %s%s%s%s\n", - resent_prefix, originator_name, - (originator_name[0] == 0)? "" : " <", - (sender_address_unrewritten == NULL)? - sender_address : sender_address_unrewritten, - (originator_name[0] == 0)? "" : ">"); - else - header_add(htype_from, "%sFrom: %s\n", resent_prefix, sender_address); + header_add(htype_from, "%sFrom: %s%s%s%s\n", resent_prefix, + oname, + (oname[0] == 0)? "" : " <", + (sender_address_unrewritten == NULL)? + sender_address : sender_address_unrewritten, + (oname[0] == 0)? "" : ">"); from_header = header_last; /* To get it checked for Sender: */ } } -/* If the sender is local, or if we are in submission mode and there is an -authenticated_id, check that an existing From: is correct, and if not, generate -a Sender: header, unless disabled. Any previously-existing Sender: header was -removed above. Note that sender_local, as well as being TRUE if the caller of -exim is not trusted, is also true if a trusted caller did not supply a -f -argument for non-smtp input. To allow trusted callers to forge From: without -supplying -f, we have to test explicitly here. If the From: header contains -more than one address, then the call to parse_extract_address fails, and a -Sender: header is inserted, as required. */ +/* If the sender is local (without suppress_local_fixups), or if we are in +submission mode and there is an authenticated_id, check that an existing From: +is correct, and if not, generate a Sender: header, unless disabled. Any +previously-existing Sender: header was removed above. Note that sender_local, +as well as being TRUE if the caller of exim is not trusted, is also true if a +trusted caller did not supply a -f argument for non-smtp input. To allow +trusted callers to forge From: without supplying -f, we have to test explicitly +here. If the From: header contains more than one address, then the call to +parse_extract_address fails, and a Sender: header is inserted, as required. */ if (from_header != NULL && (active_local_from_check && - ((sender_local && !trusted_caller) || + ((sender_local && !trusted_caller && !suppress_local_fixups) || (submission_mode && authenticated_id != NULL)) )) { @@ -2310,12 +2500,27 @@ if (from_header != NULL && if (make_sender) { - if (submission_mode) + if (submission_mode && submission_name == NULL) header_add(htype_sender, "%sSender: %s\n", resent_prefix, generated_sender_address); else header_add(htype_sender, "%sSender: %s <%s>\n", - resent_prefix, originator_name, generated_sender_address); + resent_prefix, + submission_mode? submission_name : originator_name, + generated_sender_address); + } + + /* Ensure that a non-null envelope sender address corresponds to the + submission mode sender address. */ + + if (submission_mode && sender_address[0] != 0) + { + if (sender_address_unrewritten == NULL) + sender_address_unrewritten = sender_address; + sender_address = generated_sender_address; + log_write(L_address_rewrite, LOG_MAIN, + "\"%s\" from env-from rewritten as \"%s\" by submission mode", + sender_address_unrewritten, generated_sender_address); } } @@ -2375,11 +2580,13 @@ if (!to_or_cc_header_exists && !bcc_header_exists) ******/ /* If there is no date header, generate one if the message originates locally -(i.e. not over TCP/IP) or the submission mode flag is set. Messages without -Date: are not valid, but it seems to be more confusing if Exim adds one to -all remotely-originated messages. */ +(i.e. not over TCP/IP) and suppress_local_fixups is not set, or if the +submission mode flag is set. Messages without Date: are not valid, but it seems +to be more confusing if Exim adds one to all remotely-originated messages. */ -if (!date_header_exists && (sender_host_address == NULL || submission_mode)) +if (!date_header_exists && + ((sender_host_address == NULL && !suppress_local_fixups) + || submission_mode)) header_add(htype_other, "%sDate: %s\n", resent_prefix, tod_stamp(tod_full)); search_tidyup(); /* Free any cached resources */ @@ -2431,8 +2638,8 @@ if (data_fd < 0) /* Make sure the file's group is the Exim gid, and double-check the mode because the group setting doesn't always get set automatically. */ -fchown(data_fd, exim_uid, exim_gid); -fchmod(data_fd, SPOOL_MODE); +(void)fchown(data_fd, exim_uid, exim_gid); +(void)fchmod(data_fd, SPOOL_MODE); /* We now have data file open. Build a stream for it and lock it. We lock only the first line of the file (containing the message ID) because otherwise there @@ -2461,7 +2668,7 @@ if (next != NULL) { uschar *s = next->text; int len = next->slen; - fwrite(s, 1, len, data_file); + (void)fwrite(s, 1, len, data_file); body_linecount++; /* Assumes only 1 line */ } @@ -2479,6 +2686,7 @@ if (!ferror(data_file) && !(receive_feof)() && message_ended != END_DOT) else message_ended = read_message_data(data_file); receive_linecount += body_linecount; /* For BSMTP errors mainly */ + message_linecount += body_linecount; /* Handle premature termination of SMTP */ @@ -2651,7 +2859,7 @@ if (extract_recip && (bad_addresses != NULL || recipients_count == 0)) if (recipients_count == 0 || error_handling == ERRORS_STDERR) { Uunlink(spool_name); - fclose(data_file); + (void)fclose(data_file); exim_exit(error_rc); } } @@ -2738,128 +2946,18 @@ else if (smtp_input && !smtp_batched_input) { -#ifdef WITH_CONTENT_SCAN - /* MIME ACL hook */ - if (acl_smtp_mime != NULL && recipients_count > 0) - { - FILE *mbox_file; - uschar rfc822_file_path[2048]; - unsigned long mbox_size; - header_line *my_headerlist; - uschar *user_msg, *log_msg; - int mime_part_count_buffer = -1; - - memset(CS rfc822_file_path,0,2048); - - /* check if it is a MIME message */ - my_headerlist = header_list; - while (my_headerlist != NULL) { - /* skip deleted headers */ - if (my_headerlist->type == '*') { - my_headerlist = my_headerlist->next; - continue; - }; - if (strncmpic(my_headerlist->text, US"Content-Type:", 13) == 0) { - DEBUG(D_receive) debug_printf("Found Content-Type: header - executing acl_smtp_mime.\n"); - goto DO_MIME_ACL; - }; - my_headerlist = my_headerlist->next; - }; - - DEBUG(D_receive) debug_printf("No Content-Type: header - presumably not a MIME message.\n"); - goto NO_MIME_ACL; - - DO_MIME_ACL: - /* make sure the eml mbox file is spooled up */ - mbox_file = spool_mbox(&mbox_size); - if (mbox_file == NULL) { - /* error while spooling */ - log_write(0, LOG_MAIN|LOG_PANIC, - "acl_smtp_mime: error while creating mbox spool file, message temporarily rejected."); - Uunlink(spool_name); - unspool_mbox(); - smtp_respond(451, TRUE, US"temporary local problem"); - message_id[0] = 0; /* Indicate no message accepted */ - smtp_reply = US""; /* Indicate reply already sent */ - goto TIDYUP; /* Skip to end of function */ - }; - - mime_is_rfc822 = 0; - - MIME_ACL_CHECK: - mime_part_count = -1; - rc = mime_acl_check(mbox_file, NULL, &user_msg, &log_msg); - fclose(mbox_file); - - if (Ustrlen(rfc822_file_path) > 0) { - mime_part_count = mime_part_count_buffer; - - if (unlink(CS rfc822_file_path) == -1) { - log_write(0, LOG_PANIC, - "acl_smtp_mime: can't unlink RFC822 spool file, skipping."); - goto END_MIME_ACL; - }; - }; - - /* check if we must check any message/rfc822 attachments */ - if (rc == OK) { - uschar temp_path[1024]; - int n; - struct dirent *entry; - DIR *tempdir; - - snprintf(CS temp_path, 1024, "%s/scan/%s", spool_directory, message_id); - - tempdir = opendir(CS temp_path); - n = 0; - do { - entry = readdir(tempdir); - if (entry == NULL) break; - if (strncmpic(US entry->d_name,US"__rfc822_",9) == 0) { - snprintf(CS rfc822_file_path, 2048,"%s/scan/%s/%s", spool_directory, message_id, entry->d_name); - debug_printf("RFC822 attachment detected: running MIME ACL for '%s'\n", rfc822_file_path); - break; - }; - } while (1); - closedir(tempdir); - - if (entry != NULL) { - mbox_file = Ufopen(rfc822_file_path,"r"); - if (mbox_file == NULL) { - log_write(0, LOG_PANIC, - "acl_smtp_mime: can't open RFC822 spool file, skipping."); - unlink(CS rfc822_file_path); - goto END_MIME_ACL; - }; - /* set RFC822 expansion variable */ - mime_is_rfc822 = 1; - mime_part_count_buffer = mime_part_count; - goto MIME_ACL_CHECK; - }; - }; - - END_MIME_ACL: - add_acl_headers(US"MIME"); - if (rc == DISCARD) - { - recipients_count = 0; - blackholed_by = US"MIME ACL"; - } - else if (rc != OK) - { - Uunlink(spool_name); - unspool_mbox(); - if (smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0) - smtp_yield = FALSE; /* No more messsages 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 */ - }; - } +#ifdef EXPERIMENTAL_DOMAINKEYS + dk_exim_verify_finish(); +#endif - NO_MIME_ACL: +#ifdef WITH_CONTENT_SCAN + if (acl_smtp_mime != NULL && + !run_mime_acl(acl_smtp_mime, &smtp_yield, &smtp_reply, &blackholed_by)) + goto TIDYUP; #endif /* WITH_CONTENT_SCAN */ + /* Check the recipients count again, as the MIME ACL might have changed + them. */ if (acl_smtp_data != NULL && recipients_count > 0) { @@ -2891,39 +2989,56 @@ else /* Handle non-SMTP and batch SMTP (i.e. non-interactive) messages. Note that we cannot take different actions for permanent and temporary rejections. */ - else if (acl_not_smtp != NULL) + else { - uschar *user_msg, *log_msg; - rc = acl_check(ACL_WHERE_NOTSMTP, NULL, acl_not_smtp, &user_msg, &log_msg); - if (rc == DISCARD) - { - recipients_count = 0; - blackholed_by = US"non-SMTP ACL"; - if (log_msg != NULL) blackhole_log_msg = string_sprintf(": %s", log_msg); - } - else if (rc != OK) + +#ifdef WITH_CONTENT_SCAN + if (acl_not_smtp_mime != NULL && + !run_mime_acl(acl_not_smtp_mime, &smtp_yield, &smtp_reply, + &blackholed_by)) + goto TIDYUP; +#endif /* WITH_CONTENT_SCAN */ + + if (acl_not_smtp != NULL) { - Uunlink(spool_name); - log_write(0, LOG_MAIN|LOG_REJECT, "F=<%s> rejected by non-SMTP ACL: %s", - sender_address, log_msg); - if (user_msg == NULL) user_msg = US"local configuration problem"; - if (smtp_batched_input) + uschar *user_msg, *log_msg; + rc = acl_check(ACL_WHERE_NOTSMTP, NULL, acl_not_smtp, &user_msg, &log_msg); + if (rc == DISCARD) { - moan_smtp_batch(NULL, "%d %s", 550, user_msg); - /* Does not return */ + recipients_count = 0; + blackholed_by = US"non-SMTP ACL"; + if (log_msg != NULL) + blackhole_log_msg = string_sprintf(": %s", log_msg); } - else + else if (rc != OK) { - fseek(data_file, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET); - give_local_error(ERRMESS_LOCAL_ACL, user_msg, - US"message rejected by non-SMTP ACL: ", error_rc, data_file, - header_list); - /* Does not return */ + Uunlink(spool_name); +#ifdef WITH_CONTENT_SCAN + unspool_mbox(); +#endif + log_write(0, LOG_MAIN|LOG_REJECT, "F=<%s> rejected by non-SMTP ACL: %s", + sender_address, log_msg); + if (user_msg == NULL) user_msg = US"local configuration problem"; + if (smtp_batched_input) + { + moan_smtp_batch(NULL, "%d %s", 550, user_msg); + /* Does not return */ + } + else + { + fseek(data_file, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET); + give_local_error(ERRMESS_LOCAL_ACL, user_msg, + US"message rejected by non-SMTP ACL: ", error_rc, data_file, + header_list); + /* Does not return */ + } } + add_acl_headers(US"non-SMTP"); } - add_acl_headers(US"non-SMTP"); } + /* The applicable ACLs have been run */ + if (deliver_freeze) frozen_by = US"ACL"; /* for later logging */ if (queue_only_policy) queued_by = US"ACL"; @@ -3330,7 +3445,7 @@ if (message_logs && blackholed_by == NULL) { log_write(0, LOG_MAIN|LOG_PANIC, "Couldn't fdopen message log %s: %s", spool_name, strerror(errno)); - close(fd); + (void)close(fd); } else { @@ -3340,7 +3455,7 @@ if (message_logs && blackholed_by == NULL) frozen_by); if (queue_only_policy) fprintf(message_log, "%s no immediate delivery: queued by %s\n", now, queued_by); - fclose(message_log); + (void)fclose(message_log); } } } @@ -3372,8 +3487,8 @@ possible for fclose() to fail - but what to do? What has happened to the lock if this happens? */ TIDYUP: -process_info[process_info_len] = 0; /* Remove message id */ -if (data_file != NULL) fclose(data_file); /* Frees the lock */ +process_info[process_info_len] = 0; /* Remove message id */ +if (data_file != NULL) (void)fclose(data_file); /* Frees the lock */ /* Now reset signal handlers to their defaults */ @@ -3398,8 +3513,9 @@ if (smtp_input) { if (smtp_reply == NULL) { - if (fake_reject) - smtp_respond(550,TRUE,fake_reject_text); + if (fake_response != OK) + smtp_respond(fake_response == DEFER ? 450 : 550, + TRUE, fake_response_text); else smtp_printf("250 OK id=%s\r\n", message_id); if (host_checking) @@ -3408,8 +3524,9 @@ if (smtp_input) } else if (smtp_reply[0] != 0) { - if (fake_reject && (smtp_reply[0] == '2')) - smtp_respond(550,TRUE,fake_reject_text); + if (fake_response != OK && (smtp_reply[0] == '2')) + smtp_respond(fake_response == DEFER ? 450 : 550, + TRUE, fake_response_text); else smtp_printf("%.1024s\r\n", smtp_reply); }