X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/f7572e5a358cd3d9581140b87e590d58b6c278f0..5eb690a173fdc71d5326c05a2a6a9d87d159187a:/src/src/receive.c diff --git a/src/src/receive.c b/src/src/receive.c index 62db50f96..3c307b07b 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/receive.c,v 1.42 2007/09/28 12:21:57 tom Exp $ */ +/* $Cambridge: exim/src/src/receive.c,v 1.50 2009/10/16 12:33:09 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -11,38 +11,10 @@ #include "exim.h" -#if (defined EXPERIMENTAL_DOMAINKEYS) && (defined EXPERIMENTAL_DKIM) - -#warning Chaining Domainkeys via DKIM receive functions -#define RECEIVE_GETC dkim_receive_getc -#define RECEIVE_UNGETC dkim_receive_ungetc - -#else - -#if (defined EXPERIMENTAL_DOMAINKEYS) || (defined EXPERIMENTAL_DKIM) - -#ifdef EXPERIMENTAL_DOMAINKEYS -#warning Using Domainkeys receive functions -#define RECEIVE_GETC dk_receive_getc -#define RECEIVE_UNGETC dk_receive_ungetc -#endif -#ifdef EXPERIMENTAL_DKIM -#warning Using DKIM receive functions -#define RECEIVE_GETC dkim_receive_getc -#define RECEIVE_UNGETC dkim_receive_ungetc -#endif - -#else - -/* Normal operation */ -#define RECEIVE_GETC receive_getc -#define RECEIVE_UNGETC receive_ungetc - +#ifdef EXPERIMENTAL_DCC +extern int dcc_ok; #endif -#endif - - /************************************************* * Local static variables * *************************************************/ @@ -596,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') @@ -638,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) @@ -754,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) @@ -1412,17 +1384,10 @@ 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 -#ifdef EXPERIMENTAL_DKIM -/* Call into DKIM to set up the context. Check if DKIM is to be run are carried out - inside dk_exim_verify_init(). */ -dkim_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 @@ -1472,7 +1437,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. */ @@ -1536,7 +1501,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; } @@ -1551,13 +1516,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 */ } } @@ -1585,7 +1550,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; @@ -1595,7 +1560,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 = ' '; @@ -1680,14 +1645,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 */ } @@ -1943,7 +1908,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. */ @@ -2372,8 +2337,9 @@ if (msgid_header == NULL && /* Add the header line */ - 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(FALSE, 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 @@ -2581,9 +2547,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); } } @@ -2642,7 +2609,8 @@ to be more confusing if Exim adds one to all remotely-originated messages. */ 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(FALSE, NULL, FALSE, htype_other, "%sDate: %s\n", + resent_prefix, tod_stamp(tod_full)); search_tidyup(); /* Free any cached resources */ @@ -3002,15 +2970,97 @@ else if (smtp_input && !smtp_batched_input) { -#ifdef EXPERIMENTAL_DOMAINKEYS - dk_exim_verify_finish(); -#endif -#ifdef EXPERIMENTAL_DKIM - dkim_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]; + 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 */ @@ -3110,6 +3160,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 @@ -3544,8 +3599,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 */