From: Philip Hazel Date: Mon, 4 Apr 2005 10:33:49 +0000 (+0000) Subject: Added acl_not_smtp_mime. This involved a bit of refactoring of the X-Git-Tag: exim-4_51~31 X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/54cdb463ab15d0a064cfe0a276b3e3974767c8c7 Added acl_not_smtp_mime. This involved a bit of refactoring of the content scanning code. Also, updated doc/OptionList.txt with all the content-scanning options (none had been added.) --- diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index cf31d4690..87e001f27 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.106 2005/03/29 15:53:12 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.107 2005/04/04 10:33:49 ph10 Exp $ Change log file for Exim from version 4.21 ------------------------------------------- @@ -117,6 +117,8 @@ PH/20 When checking for unexpected SMTP input at connect time (before writing There were reports of junk text (parts of files, etc) appearing after "input=". +PH/21 Added acl_not_smtp_mime to allow for MIME scanning for non-SMTP messages. + A note about Exim versions 4.44 and 4.50 ---------------------------------------- diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 51ac28c37..6f3ac86d1 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/NewStuff,v 1.31 2005/03/29 14:19:21 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/NewStuff,v 1.32 2005/04/04 10:33:49 ph10 Exp $ New Features in Exim -------------------- @@ -96,6 +96,10 @@ PH/03 There is a new value for RADIUS_LIB_TYPE that can be set in in use from radiusclient 0.4.0 onwards, be used. It does not appear to be possible to detect the different versions automatically. +PH/04 There is a new option called acl_not_smtp_mime that allows you to scan + MIME parts in non-SMTP messages. It operates in exactly the same way as + acl_smtp_mime + Version 4.50 ------------ diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt index 49b76b3d6..ba727b0bb 100644 --- a/doc/doc-txt/OptionLists.txt +++ b/doc/doc-txt/OptionLists.txt @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/OptionLists.txt,v 1.6 2005/03/03 08:54:59 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/OptionLists.txt,v 1.7 2005/04/04 10:33:49 ph10 Exp $ LISTS OF EXIM OPTIONS --------------------- @@ -52,6 +52,7 @@ in fact some of them were inherited from earlier versions. ----------------------------------------------------------------------------------------- accept_8bitmime boolean false main 1.60 acl_not_smtp string* unset main 4.11 +acl_not_smtp_mime string* unset main 4.51 with content scan acl_smtp_auth string* unset main 4.00 acl_smtp_connect string* unset main 4.11 acl_smtp_data string* unset main 4.00 @@ -60,6 +61,7 @@ acl_smtp_expn string* unset main acl_smtp_helo string* unset main 4.20 acl_smtp_mail string* unset main 4.11 acl_smtp_mailauth string* unset main 4.21 +acl_smtp_mime string* unset main 4.50 with content scan acl_smtp_predata string* unset main 4.43 acl_smtp_quit string* unset main 4.43 acl_smtp_rcpt string* unset main 4.00 @@ -83,6 +85,7 @@ auth_advertise_hosts host list "*" main authenticated_sender string* unset smtp 4.14 authenticate_hosts host list unset smtp 3.13 auto_thaw time 0s main +av_scanner string* + main 4.50 with content scan batch_id string unset appendfile 4.00 unset lmtp 4.00 unset pipe 4.00 @@ -466,6 +469,7 @@ smtp_receive_timeout time 5m main smtp_reserve_hosts host list unset main smtp_return_error_details boolean false main 4.11 socket string* unset lmtp 4.11 +spamd_address string + main 4.50 with content scan split_spool_directory boolean false main 1.70 spool_directory string ++ main srv_fail_domains domain list unset dnslookup 4.43 diff --git a/src/src/functions.h b/src/src/functions.h index 88bc53d74..1563a55c3 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/functions.h,v 1.12 2005/03/08 15:32:02 tom Exp $ */ +/* $Cambridge: exim/src/src/functions.h,v 1.13 2005/04/04 10:33:49 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -152,8 +152,8 @@ extern void md5_start(md5 *); extern void millisleep(int); #ifdef WITH_CONTENT_SCAN struct mime_boundary_context; -extern int mime_acl_check(FILE *f, struct mime_boundary_context *, - uschar **, uschar **); +extern int mime_acl_check(uschar *acl, FILE *f, + struct mime_boundary_context *, uschar **, uschar **); extern int mime_decode(uschar **); extern int mime_regex(uschar **); #endif diff --git a/src/src/globals.c b/src/src/globals.c index 2324e4072..5fe414b43 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.c,v 1.20 2005/03/22 14:11:54 ph10 Exp $ */ +/* $Cambridge: exim/src/src/globals.c,v 1.21 2005/04/04 10:33:49 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -160,6 +160,9 @@ int address_expansions_count = sizeof(address_expansions)/sizeof(uschar **); tree_node *acl_anchor = NULL; uschar *acl_not_smtp = NULL; +#ifdef WITH_CONTENT_SCAN +uschar *acl_not_smtp_mime = NULL; +#endif uschar *acl_smtp_auth = NULL; uschar *acl_smtp_connect = NULL; uschar *acl_smtp_data = NULL; diff --git a/src/src/globals.h b/src/src/globals.h index 404838126..37faa9d50 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.h,v 1.13 2005/03/22 14:11:54 ph10 Exp $ */ +/* $Cambridge: exim/src/src/globals.h,v 1.14 2005/04/04 10:33:49 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -102,6 +102,9 @@ extern uschar **address_expansions[ADDRESS_EXPANSIONS_COUNT]; extern BOOL accept_8bitmime; /* Allow *BITMIME incoming */ extern tree_node *acl_anchor; /* Tree of named ACLs */ extern uschar *acl_not_smtp; /* ACL run for non-SMTP messages */ +#ifdef WITH_CONTENT_SCAN +extern uschar *acl_not_smtp_mime; /* For MIME parts of ditto */ +#endif extern uschar *acl_smtp_auth; /* ACL run for AUTH */ extern uschar *acl_smtp_connect; /* ACL run on SMTP connection */ extern uschar *acl_smtp_data; /* ACL run after DATA received */ diff --git a/src/src/mime.c b/src/src/mime.c index f97d25abb..05b6e3e2a 100644 --- a/src/src/mime.c +++ b/src/src/mime.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/mime.c,v 1.6 2005/03/08 16:57:28 ph10 Exp $ */ +/* $Cambridge: exim/src/src/mime.c,v 1.7 2005/04/04 10:33:49 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -502,8 +502,8 @@ int mime_get_header(FILE *f, uschar *header) { } -int mime_acl_check(FILE *f, struct mime_boundary_context *context, uschar - **user_msgptr, uschar **log_msgptr) { +int mime_acl_check(uschar *acl, FILE *f, struct mime_boundary_context *context, + uschar **user_msgptr, uschar **log_msgptr) { int rc = OK; uschar *header = NULL; struct mime_boundary_context nested_context; @@ -512,7 +512,7 @@ int mime_acl_check(FILE *f, struct mime_boundary_context *context, uschar header = (uschar *)malloc(MIME_MAX_HEADER_SIZE+1); if (header == NULL) { log_write(0, LOG_PANIC, - "acl_smtp_mime: can't allocate %d bytes of memory.", MIME_MAX_HEADER_SIZE+1); + "MIME ACL: can't allocate %d bytes of memory.", MIME_MAX_HEADER_SIZE+1); return DEFER; }; @@ -659,7 +659,7 @@ int mime_acl_check(FILE *f, struct mime_boundary_context *context, uschar mime_is_coverletter = !(context && context->context == MBC_ATTACHMENT); /* call ACL handling function */ - rc = acl_check(ACL_WHERE_MIME, NULL, acl_smtp_mime, user_msgptr, log_msgptr); + rc = acl_check(ACL_WHERE_MIME, NULL, acl, user_msgptr, log_msgptr); mime_stream = NULL; mime_current_boundary = NULL; @@ -680,7 +680,7 @@ int mime_acl_check(FILE *f, struct mime_boundary_context *context, uschar else nested_context.context = MBC_COVERLETTER_ONESHOT; - rc = mime_acl_check(f, &nested_context, user_msgptr, log_msgptr); + rc = mime_acl_check(acl, f, &nested_context, user_msgptr, log_msgptr); if (rc != OK) break; } else if ( (mime_content_type != NULL) && diff --git a/src/src/readconf.c b/src/src/readconf.c index 302255ddf..0fe00cf6b 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/readconf.c,v 1.5 2005/02/17 11:58:26 ph10 Exp $ */ +/* $Cambridge: exim/src/src/readconf.c,v 1.6 2005/04/04 10:33:49 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -135,6 +135,9 @@ static optionlist optionlist_config[] = { { "*set_system_filter_user", opt_bool|opt_hidden, &system_filter_uid_set }, { "accept_8bitmime", opt_bool, &accept_8bitmime }, { "acl_not_smtp", opt_stringptr, &acl_not_smtp }, +#ifdef WITH_CONTENT_SCAN + { "acl_not_smtp_mime", opt_stringptr, &acl_not_smtp_mime }, +#endif { "acl_smtp_auth", opt_stringptr, &acl_smtp_auth }, { "acl_smtp_connect", opt_stringptr, &acl_smtp_connect }, { "acl_smtp_data", opt_stringptr, &acl_smtp_data }, diff --git a/src/src/receive.c b/src/src/receive.c index e4ce9cb23..325544643 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/receive.c,v 1.12 2005/03/08 15:32:02 tom Exp $ */ +/* $Cambridge: exim/src/src/receive.c,v 1.13 2005/04/04 10:33:49 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -510,7 +510,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; } } @@ -1008,6 +1008,146 @@ return s; +/************************************************* +* 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); +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_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; +} + + + /************************************************* * Receive message * *************************************************/ @@ -2754,127 +2894,13 @@ else #endif #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 */ - }; - } - - NO_MIME_ACL: + 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) { @@ -2906,39 +2932,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";