X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/48ed62d9a68c4e44c9fbaa6e300f88401bb32d65..8544e77a6ed430f7063162906c449f1353d72e58:/src/src/receive.c diff --git a/src/src/receive.c b/src/src/receive.c index 651121956..c4fb31ea7 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -1,22 +1,18 @@ -/* $Cambridge: exim/src/src/receive.c,v 1.41 2007/08/22 14:20:28 ph10 Exp $ */ +/* $Cambridge: exim/src/src/receive.c,v 1.55 2010/06/05 11:13:30 pdp Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2007 */ +/* Copyright (c) University of Cambridge 1995 - 2009 */ /* See the file NOTICE for conditions of use and distribution. */ /* 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 +#ifdef EXPERIMENTAL_DCC +extern int dcc_ok; #endif /************************************************* @@ -572,7 +568,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') @@ -614,7 +610,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) @@ -730,7 +726,7 @@ int ch_state = 0; register int ch; register int linelength = 0; -while ((ch = (RECEIVE_GETC)()) != EOF) +while ((ch = (receive_getc)()) != EOF) { if (ch == 0) body_zerocount++; switch (ch_state) @@ -1071,7 +1067,7 @@ unsigned long mbox_size; header_line *my_headerlist; uschar *user_msg, *log_msg; int mime_part_count_buffer = -1; -int rc; +int rc = OK; memset(CS rfc822_file_path,0,2048); @@ -1098,7 +1094,7 @@ return TRUE; DO_MIME_ACL: /* make sure the eml mbox file is spooled up */ -mbox_file = spool_mbox(&mbox_size); +mbox_file = spool_mbox(&mbox_size, NULL); if (mbox_file == NULL) { /* error while spooling */ log_write(0, LOG_MAIN|LOG_PANIC, @@ -1289,7 +1285,8 @@ not. */ BOOL receive_msg(BOOL extract_recip) { -int i, rc; +int i; +int rc = FAIL; int msg_size = 0; int process_info_len = Ustrlen(process_info); int error_rc = (error_handling == ERRORS_SENDER)? @@ -1388,10 +1385,9 @@ if (thismessage_size_limit <= 0) thismessage_size_limit = INT_MAX; message_linecount = body_linecount = body_zerocount = max_received_linelength = 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(); +#ifndef DISABLE_DKIM +/* Call into DKIM to set up the context. */ +if (smtp_input && !smtp_batched_input && !dkim_disable_verify) dkim_exim_verify_init(); #endif /* Remember the time of reception. Exim uses time+pid for uniqueness of message @@ -1442,7 +1438,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. */ @@ -1506,7 +1502,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; } @@ -1521,13 +1517,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 */ } } @@ -1555,7 +1551,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; @@ -1565,7 +1561,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 = ' '; @@ -1650,14 +1646,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 */ } @@ -1913,7 +1909,7 @@ for (h = header_list->next; h != NULL; h = h->next) /* Record whether a Date: or Resent-Date: header exists, as appropriate. */ case htype_date: - date_header_exists = !resents_exist || is_resent; + if (!resents_exist || is_resent) date_header_exists = TRUE; break; /* Same comments as about Return-Path: below. */ @@ -2340,10 +2336,13 @@ if (msgid_header == NULL && } } - /* Add the header line */ + /* Add the header line + * Resent-* headers are prepended, per RFC 5322 3.6.6. Non-Resent-* are + * appended, to preserve classical expectations of header ordering. */ - header_add(htype_id, "%sMessage-Id: <%s%s%s@%s>\n", resent_prefix, - message_id_external, (*id_text == 0)? "" : ".", id_text, id_domain); + header_add_at_position(!resents_exist, NULL, FALSE, htype_id, + "%sMessage-Id: <%s%s%s@%s>\n", resent_prefix, message_id_external, + (*id_text == 0)? "" : ".", id_text, id_domain); } /* If we are to log recipients, keep a copy of the raw ones before any possible @@ -2551,9 +2550,10 @@ if (from_header != NULL && 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); + if (Ustrcmp(sender_address_unrewritten, generated_sender_address) != 0) + log_write(L_address_rewrite, LOG_MAIN, + "\"%s\" from env-from rewritten as \"%s\" by submission mode", + sender_address_unrewritten, generated_sender_address); } } @@ -2607,12 +2607,15 @@ changes in RFC 2822, this was dropped in November 2003. */ /* If there is no date header, generate one if the message originates locally (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. */ +to be more confusing if Exim adds one to all remotely-originated messages. +As per Message-Id, we prepend if resending, else append. +*/ 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)); + header_add_at_position(!resents_exist, NULL, FALSE, htype_other, + "%sDate: %s\n", resent_prefix, tod_stamp(tod_full)); search_tidyup(); /* Free any cached resources */ @@ -2972,12 +2975,99 @@ else if (smtp_input && !smtp_batched_input) { -#ifdef EXPERIMENTAL_DOMAINKEYS - dk_exim_verify_finish(); -#endif +#ifndef DISABLE_DKIM + if (!dkim_disable_verify) + { + /* Finish verification, this will log individual signature results to + the mainlog */ + dkim_exim_verify_finish(); + + /* Check if we must run the DKIM ACL */ + if ((acl_smtp_dkim != NULL) && + (dkim_verify_signers != NULL) && + (dkim_verify_signers[0] != '\0')) + { + uschar *dkim_verify_signers_expanded = + expand_string(dkim_verify_signers); + if (dkim_verify_signers_expanded == NULL) + { + log_write(0, LOG_MAIN|LOG_PANIC, + "expansion of dkim_verify_signers option failed: %s", + expand_string_message); + } + else + { + int sep = 0; + uschar *ptr = dkim_verify_signers_expanded; + uschar *item = NULL; + uschar *seen_items = NULL; + int seen_items_size = 0; + int seen_items_offset = 0; + uschar itembuf[256]; + /* Default to OK when no items are present */ + rc = OK; + while ((item = string_nextinlist(&ptr, &sep, + itembuf, + sizeof(itembuf))) != NULL) + { + /* Prevent running ACL for an empty item */ + if (!item || (item[0] == '\0')) continue; + /* Only run ACL once for each domain or identity, no matter how often it + appears in the expanded list. */ + if (seen_items != NULL) + { + uschar *seen_items_list = seen_items; + if (match_isinlist(item, + &seen_items_list,0,NULL,NULL,MCL_STRING,TRUE,NULL) == OK) + { + DEBUG(D_receive) + 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,":"); + } + + seen_items = string_append(seen_items,&seen_items_size,&seen_items_offset,1,item); + seen_items[seen_items_offset] = '\0'; + + DEBUG(D_receive) + debug_printf("calling acl_smtp_dkim for dkim_cur_signer=%s\n", item); + + dkim_exim_acl_setup(item); + rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, &user_msg, &log_msg); + + if (rc != OK) + { + DEBUG(D_receive) + debug_printf("acl_smtp_dkim: acl_check returned %d on %s, skipping remaining items\n", rc, item); + break; + } + } + add_acl_headers(US"DKIM"); + if (rc == DISCARD) + { + recipients_count = 0; + blackholed_by = US"DKIM ACL"; + if (log_msg != NULL) + blackhole_log_msg = string_sprintf(": %s", log_msg); + } + else if (rc != OK) + { + 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_reply = US""; /* Indicate reply already sent */ + message_id[0] = 0; /* Indicate no message accepted */ + goto TIDYUP; /* Skip to end of function */ + } + } + } + } +#endif /* DISABLE_DKIM */ #ifdef WITH_CONTENT_SCAN - if (acl_smtp_mime != NULL && + if (recipients_count > 0 && + acl_smtp_mime != NULL && !run_mime_acl(acl_smtp_mime, &smtp_yield, &smtp_reply, &blackholed_by)) goto TIDYUP; #endif /* WITH_CONTENT_SCAN */ @@ -3077,6 +3167,11 @@ else unspool_mbox(); #endif +#ifdef EXPERIMENTAL_DCC +dcc_ok = 0; +#endif + + /* The final check on the message is to run the scan_local() function. The version supplied with Exim always accepts, but this is a hook for sysadmins to supply their own checking code. The local_scan() function is run even when all @@ -3511,8 +3606,8 @@ if (smtp_input && sender_host_address != NULL && !sender_host_notsocket && if (select(fileno(smtp_in) + 1, &select_check, NULL, NULL, &tv) != 0) { - int c = (RECEIVE_GETC)(); - if (c != EOF) (RECEIVE_UNGETC)(c); else + int c = (receive_getc)(); + if (c != EOF) (receive_ungetc)(c); else { uschar *msg = US"SMTP connection lost after final dot"; smtp_reply = US""; /* No attempt to send a response */