From dcd3e9553bf120cf570ec1d51e6c7121dbb7e2c3 Mon Sep 17 00:00:00 2001 From: Tom Kistner Date: Thu, 2 Dec 2004 09:15:11 +0000 Subject: [PATCH] more W.I.P --- src/exim_monitor/em_globals.c | 11 +- src/src/EDITME | 12 ++- src/src/config.h.defaults | 6 +- src/src/exim.c | 111 +++++++------------- src/src/expand.c | 39 ++++++- src/src/functions.h | 8 +- src/src/globals.c | 10 +- src/src/globals.h | 10 +- src/src/header.c | 15 ++- src/src/local_scan.h | 3 +- src/src/macros.h | 9 +- src/src/readconf.c | 11 +- src/src/receive.c | 187 ++++++++++++++++++++++++++++++++-- src/src/smtp_in.c | 13 ++- src/src/spool_in.c | 11 +- src/src/spool_out.c | 5 +- 16 files changed, 359 insertions(+), 102 deletions(-) diff --git a/src/exim_monitor/em_globals.c b/src/exim_monitor/em_globals.c index ae38e9f8a..a0b28136d 100644 --- a/src/exim_monitor/em_globals.c +++ b/src/exim_monitor/em_globals.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/exim_monitor/em_globals.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */ +/* $Cambridge: exim/src/exim_monitor/em_globals.c,v 1.1.2.1 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim Monitor * @@ -132,6 +132,10 @@ int deliver_frozen_at = 0; BOOL deliver_manual_thaw = FALSE; BOOL dont_deliver = FALSE; +#ifdef WITH_CONTENT_SCAN +BOOL fake_reject = FALSE; +#endif + header_line *header_last = NULL; header_line *header_list = NULL; @@ -142,6 +146,11 @@ int interface_port = 0; BOOL local_error_message = FALSE; uschar *local_scan_data = NULL; BOOL log_timezone = FALSE; + +#ifdef WITH_CONTENT_SCAN +uschar *spam_score_int = NULL; +#endif + int message_age = 0; uschar *message_id; uschar *message_id_external; diff --git a/src/src/EDITME b/src/src/EDITME index 0f213aa0a..b8c39d12e 100644 --- a/src/src/EDITME +++ b/src/src/EDITME @@ -1,4 +1,4 @@ -# $Cambridge: exim/src/src/EDITME,v 1.4.2.1 2004/11/25 15:33:54 tom Exp $ +# $Cambridge: exim/src/src/EDITME,v 1.4.2.2 2004/12/02 09:15:11 tom Exp $ ################################################## # The Exim mail transport agent # @@ -323,6 +323,16 @@ EXIM_MONITOR=eximon.bin #WITH_CONTENT_SCAN=yes +# If you want to use the deprecated "demime" condition in the DATA ACL, +# uncomment the line below. Doing so will also explicitly turn on the +# WITH_CONTENT_SCAN option. If possible, use the MIME ACL instead of +# the "demime" condition. + +#WITH_OLD_DEMIME=yes + + + + ############################################################################### # THESE ARE THINGS YOU MIGHT WANT TO SPECIFY # ############################################################################### diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults index 9e098b760..e5e9f08e6 100644 --- a/src/src/config.h.defaults +++ b/src/src/config.h.defaults @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/config.h.defaults,v 1.2.2.1 2004/11/30 15:18:58 tom Exp $ */ +/* $Cambridge: exim/src/src/config.h.defaults,v 1.2.2.2 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -53,7 +53,7 @@ in config.h unless some value is defined in Local/Makefile. */ #define HAVE_CRYPT16 #define HAVE_SA_LEN #define HEADERS_CHARSET "ISO-8859-1" -#define HEADER_ADD_BUFFER_SIZE 8192 +#define HEADER_ADD_BUFFER_SIZE (8192 * 4) #define HEADER_MAXSIZE (1024*1024) #define INPUT_DIRECTORY_MODE 0750 @@ -107,7 +107,7 @@ in config.h unless some value is defined in Local/Makefile. */ #define SPOOL_DIRECTORY #define SPOOL_DIRECTORY_MODE 0750 #define SPOOL_MODE 0640 -#define STRING_SPRINTF_BUFFER_SIZE 8192 +#define STRING_SPRINTF_BUFFER_SIZE (8192 * 4) #define SUPPORT_A6 #define SUPPORT_CRYPTEQ diff --git a/src/src/exim.c b/src/src/exim.c index 46dcd9100..80857a698 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/exim.c,v 1.10 2004/11/25 13:54:31 ph10 Exp $ */ +/* $Cambridge: exim/src/src/exim.c,v 1.9.2.1 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -839,6 +839,9 @@ fprintf(f, "Support for:"); fprintf(f, " OpenSSL"); #endif #endif +#ifdef WITH_CONTENT_SCAN + fprintf(f, " Content_Scanning"); +#endif fprintf(f, "\n"); fprintf(f, "Lookups:"); @@ -1169,8 +1172,7 @@ uschar **argv = USS cargv; int arg_receive_timeout = -1; int arg_smtp_receive_timeout = -1; int arg_error_handling = error_handling; -int filter_sfd = -1; -int filter_ufd = -1; +int filter_fd = -1; int group_count; int i; int list_queue_option = 0; @@ -1216,6 +1218,7 @@ uschar *ftest_prefix = NULL; uschar *ftest_suffix = NULL; uschar *real_sender_address; uschar *originator_home = US"/"; +BOOL ftest_system = FALSE; void *reset_point; struct passwd *pw; @@ -1581,32 +1584,20 @@ for (i = 1; i < argc; i++) else if (*argrest == 'e') expansion_test = checking = TRUE; - /* -bF: Run system filter test */ - - else if (*argrest == 'F') - { - filter_test |= FTEST_SYSTEM; - if (*(++argrest) != 0) { badarg = TRUE; break; } - if (++i < argc) filter_test_sfile = argv[i]; else - { - fprintf(stderr, "exim: file name expected after %s\n", argv[i-1]); - exit(EXIT_FAILURE); - } - } - - /* -bf: Run user filter test + /* -bf: Run in mail filter testing mode + -bF: Ditto, but for system filters -bfd: Set domain for filter testing -bfl: Set local part for filter testing -bfp: Set prefix for filter testing -bfs: Set suffix for filter testing */ - else if (*argrest == 'f') + else if (*argrest == 'f' || *argrest == 'F') { - if (*(++argrest) == 0) + ftest_system = *argrest++ == 'F'; + if (*argrest == 0) { - filter_test |= FTEST_USER; - if (++i < argc) filter_test_ufile = argv[i]; else + if(++i < argc) filter_test = argv[i]; else { fprintf(stderr, "exim: file name expected after %s\n", argv[i-1]); exit(EXIT_FAILURE); @@ -2773,7 +2764,7 @@ if (( (smtp_input || extract_recipients || recipients_arg < argc) && (daemon_listen || queue_interval >= 0 || bi_option || test_retry_arg >= 0 || test_rewrite_arg >= 0 || - filter_test != FTEST_NONE || (msg_action_arg > 0 && !one_msg_action)) + filter_test != NULL || (msg_action_arg > 0 && !one_msg_action)) ) || ( msg_action_arg > 0 && @@ -2791,19 +2782,19 @@ if (( ( list_options && (checking || smtp_input || extract_recipients || - filter_test != FTEST_NONE || bi_option) + filter_test != NULL || bi_option) ) || ( verify_address_mode && (address_test_mode || smtp_input || extract_recipients || - filter_test != FTEST_NONE || bi_option) + filter_test != NULL || bi_option) ) || ( address_test_mode && (smtp_input || extract_recipients || - filter_test != FTEST_NONE || bi_option) + filter_test != NULL || bi_option) ) || ( - smtp_input && (sender_address != NULL || filter_test != FTEST_NONE || + smtp_input && (sender_address != NULL || filter_test != NULL || extract_recipients) ) || ( @@ -2963,7 +2954,7 @@ if (( /* EITHER */ ) || /* OR */ expansion_test /* expansion testing */ || /* OR */ - filter_test != FTEST_NONE) /* Filter testing */ + filter_test != NULL) /* Filter testing */ { setgroups(group_count, group_list); exim_setugid(real_uid, real_gid, FALSE, @@ -2986,26 +2977,15 @@ privileged user. */ else exim_setugid(geteuid(), getegid(), FALSE, US"forcing real = effective"); -/* If testing a filter, open the file(s) now, before wasting time doing other +/* If testing a filter, open the file now, before wasting time doing other setups and reading the message. */ -if ((filter_test & FTEST_SYSTEM) != 0) +if (filter_test != NULL) { - filter_sfd = Uopen(filter_test_sfile, O_RDONLY, 0); - if (filter_sfd < 0) + filter_fd = Uopen(filter_test, O_RDONLY,0); + if (filter_fd < 0) { - fprintf(stderr, "exim: failed to open %s: %s\n", filter_test_sfile, - strerror(errno)); - return EXIT_FAILURE; - } - } - -if ((filter_test & FTEST_USER) != 0) - { - filter_ufd = Uopen(filter_test_ufile, O_RDONLY, 0); - if (filter_ufd < 0) - { - fprintf(stderr, "exim: failed to open %s: %s\n", filter_test_ufile, + fprintf(stderr, "exim: failed to open %s: %s\n", filter_test, strerror(errno)); return EXIT_FAILURE; } @@ -3400,11 +3380,11 @@ if (real_uid != root_uid && real_uid != exim_uid && } /* If the caller is not trusted, certain arguments are ignored when running for -real, but are permitted when checking things (-be, -bv, -bt, -bh, -bf, -bF). -Note that authority for performing certain actions on messages is tested in the +real, but are permitted when checking things (-be, -bv, -bt, -bh, -bf). Note +that authority for performing certain actions on messages is tested in the queue_action() function. */ -if (!trusted_caller && !checking && filter_test == FTEST_NONE) +if (!trusted_caller && !checking && filter_test == NULL) { sender_host_name = sender_host_address = interface_address = sender_ident = received_protocol = NULL; @@ -3801,7 +3781,7 @@ for (i = 0;;) if (originator_name == NULL) { if (sender_address == NULL || - (!trusted_caller && filter_test == FTEST_NONE)) + (!trusted_caller && filter_test == NULL)) { uschar *name = US pw->pw_gecos; uschar *amp = Ustrchr(name, '&'); @@ -3935,7 +3915,7 @@ unless a trusted caller supplies a sender address with -f, or is passing in the message via SMTP (inetd invocation or otherwise). */ if ((sender_address == NULL && !smtp_input) || - (!trusted_caller && filter_test == FTEST_NONE)) + (!trusted_caller && filter_test == NULL)) { sender_local = TRUE; @@ -3966,7 +3946,7 @@ if ((!smtp_input && sender_address == NULL) || || /* OR */ (sender_address[0] != 0 && /* Non-empty sender address, AND */ !checking && /* Not running tests, AND */ - filter_test == FTEST_NONE)) /* Not testing a filter */ + filter_test == NULL)) /* Not testing a filter */ { sender_address = originator_login; sender_address_forced = FALSE; @@ -4176,7 +4156,7 @@ if (recipients_arg >= argc && !extract_recipients && !smtp_input) printf("Configuration file is %s\n", config_main_filename); return EXIT_SUCCESS; } - if (filter_test == FTEST_NONE) + if (filter_test == NULL) { fprintf(stderr, "Exim is a Mail Transfer Agent. It is normally called by Mail User Agents,\n" @@ -4530,9 +4510,9 @@ while (more) } } - /* Read the data for the message. If filter_test is not FTEST_NONE, this - will just read the headers for the message, and not write anything onto the - spool. */ + /* Read the data for the message. If filter_test is true, this will + just read the headers for the message, and not write anything onto + the spool. */ message_ended = END_NOTENDED; more = receive_msg(extract_recipients); @@ -4551,7 +4531,7 @@ while (more) unless specified. The the return path is set to to the sender unless it has already been set from a return-path header in the message. */ - if (filter_test != FTEST_NONE) + if (filter_test != NULL) { deliver_domain = (ftest_domain != NULL)? ftest_domain : qualify_domain_recipient; @@ -4586,27 +4566,8 @@ while (more) if (ftest_suffix != NULL) printf("Suffix = %s\n", ftest_suffix); chdir("/"); /* Get away from wherever the user is running this from */ - - /* Now we run either a system filter test, or a user filter test, or both. - In the latter case, headers added by the system filter will persist and be - available to the user filter. We need to copy the filter variables - explicitly. */ - - if ((filter_test & FTEST_SYSTEM) != 0) - { - if (!filter_runtest(filter_sfd, filter_test_sfile, TRUE, more)) - exim_exit(EXIT_FAILURE); - } - - memcpy(filter_sn, filter_n, sizeof(filter_sn)); - - if ((filter_test & FTEST_USER) != 0) - { - if (!filter_runtest(filter_ufd, filter_test_ufile, FALSE, more)) - exim_exit(EXIT_FAILURE); - } - - exim_exit(EXIT_SUCCESS); + exim_exit(filter_runtest(filter_fd, ftest_system, more)? + EXIT_SUCCESS : EXIT_FAILURE); } /* Else act on the result of message reception. We should not get here unless diff --git a/src/src/expand.c b/src/src/expand.c index 1bdcd3760..6c7890861 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/expand.c,v 1.7 2004/11/18 11:17:33 ph10 Exp $ */ +/* $Cambridge: exim/src/src/expand.c,v 1.7.2.1 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -326,6 +326,10 @@ static var_entry var_table[] = { { "caller_uid", vtype_uid, &real_uid }, { "compile_date", vtype_stringptr, &version_date }, { "compile_number", vtype_stringptr, &version_cnumber }, +#ifdef WITH_OLD_DEMIME + { "demime_errorlevel", vtype_int, &demime_errorlevel }, + { "demime_reason", vtype_stringptr, &demime_reason }, +#endif { "dnslist_domain", vtype_stringptr, &dnslist_domain }, { "dnslist_text", vtype_stringptr, &dnslist_text }, { "dnslist_value", vtype_stringptr, &dnslist_value }, @@ -334,6 +338,9 @@ static var_entry var_table[] = { { "exim_gid", vtype_gid, &exim_gid }, { "exim_path", vtype_stringptr, &exim_path }, { "exim_uid", vtype_uid, &exim_uid }, +#ifdef WITH_OLD_DEMIME + { "found_extension", vtype_stringptr, &found_extension }, +#endif { "home", vtype_stringptr, &deliver_home }, { "host", vtype_stringptr, &deliver_host }, { "host_address", vtype_stringptr, &deliver_host_address }, @@ -357,6 +364,9 @@ static var_entry var_table[] = { { "log_inodes", vtype_pinodes, (void *)FALSE }, { "log_space", vtype_pspace, (void *)FALSE }, { "mailstore_basename", vtype_stringptr, &mailstore_basename }, +#ifdef WITH_CONTENT_SCAN + { "malware_name", vtype_stringptr, &malware_name }, +#endif { "message_age", vtype_int, &message_age }, { "message_body", vtype_msgbody, &message_body }, { "message_body_end", vtype_msgbody_end, &message_body_end }, @@ -364,6 +374,24 @@ static var_entry var_table[] = { { "message_headers", vtype_msgheaders, NULL }, { "message_id", vtype_stringptr, &message_id }, { "message_size", vtype_int, &message_size }, +#ifdef WITH_CONTENT_SCAN + { "mime_anomaly_level", vtype_int, &mime_anomaly_level }, + { "mime_anomaly_text", vtype_stringptr, &mime_anomaly_text }, + { "mime_boundary", vtype_stringptr, &mime_boundary }, + { "mime_charset", vtype_stringptr, &mime_charset }, + { "mime_content_description", vtype_stringptr, &mime_content_description }, + { "mime_content_disposition", vtype_stringptr, &mime_content_disposition }, + { "mime_content_id", vtype_stringptr, &mime_content_id }, + { "mime_content_size", vtype_int, &mime_content_size }, + { "mime_content_transfer_encoding",vtype_stringptr, &mime_content_transfer_encoding }, + { "mime_content_type", vtype_stringptr, &mime_content_type }, + { "mime_decoded_filename", vtype_stringptr, &mime_decoded_filename }, + { "mime_filename", vtype_stringptr, &mime_filename }, + { "mime_is_coverletter", vtype_int, &mime_is_coverletter }, + { "mime_is_multipart", vtype_int, &mime_is_multipart }, + { "mime_is_rfc822", vtype_int, &mime_is_rfc822 }, + { "mime_part_count", vtype_int, &mime_part_count }, +#endif { "n0", vtype_filter_int, &filter_n[0] }, { "n1", vtype_filter_int, &filter_n[1] }, { "n2", vtype_filter_int, &filter_n[2] }, @@ -394,6 +422,9 @@ static var_entry var_table[] = { { "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure }, { "recipients", vtype_recipients, NULL }, { "recipients_count", vtype_int, &recipients_count }, +#ifdef WITH_CONTENT_SCAN + { "regex_match_string", vtype_stringptr, ®ex_match_string }, +#endif { "reply_address", vtype_reply, NULL }, { "return_path", vtype_stringptr, &return_path }, { "return_size_limit", vtype_int, &bounce_return_size_limit }, @@ -424,6 +455,12 @@ static var_entry var_table[] = { { "sn7", vtype_filter_int, &filter_sn[7] }, { "sn8", vtype_filter_int, &filter_sn[8] }, { "sn9", vtype_filter_int, &filter_sn[9] }, +#ifdef WITH_CONTENT_SCAN + { "spam_bar", vtype_stringptr, &spam_bar }, + { "spam_report", vtype_stringptr, &spam_report }, + { "spam_score", vtype_stringptr, &spam_score }, + { "spam_score_int", vtype_stringptr, &spam_score_int }, +#endif { "spool_directory", vtype_stringptr, &spool_directory }, { "spool_inodes", vtype_pinodes, (void *)TRUE }, { "spool_space", vtype_pspace, (void *)TRUE }, diff --git a/src/src/functions.h b/src/src/functions.h index f1180b81f..5c1b0dab3 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/functions.h,v 1.5.2.1 2004/11/30 15:18:58 tom Exp $ */ +/* $Cambridge: exim/src/src/functions.h,v 1.5.2.2 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -68,6 +68,9 @@ extern void deliver_msglog(const char *, ...); extern void deliver_set_expansions(address_item *); extern int deliver_split_address(address_item *); extern void deliver_succeeded(address_item *); +#ifdef WITH_OLD_DEMIME +extern int demime(uschar **); +#endif extern BOOL directory_make(uschar *, uschar *, int, BOOL); extern dns_address *dns_address_from_rr(dns_answer *, dns_record *); extern void dns_build_reverse(uschar *, uschar *); @@ -173,6 +176,9 @@ extern void queue_count(void); extern void queue_run(uschar *, uschar *, BOOL); extern int random_number(int); +#ifdef WITH_CONTENT_SCAN +extern int recv_line(int, uschar *, int); +#endif extern int rda_interpret(redirect_block *, int, uschar *, uschar *, ugid_block *, address_item **, uschar **, error_block **, int *, uschar *); extern int rda_is_filter(const uschar *); diff --git a/src/src/globals.c b/src/src/globals.c index 1e5eb5659..da57ba5e2 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.c,v 1.6.2.2 2004/11/26 16:04:26 tom Exp $ */ +/* $Cambridge: exim/src/src/globals.c,v 1.6.2.3 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -447,6 +447,11 @@ uschar *deliver_selectstring = NULL; BOOL deliver_selectstring_regex = FALSE; uschar *deliver_selectstring_sender = NULL; BOOL deliver_selectstring_sender_regex = FALSE; +#ifdef WITH_OLD_DEMIME +int demime_errorlevel = 0; +int demime_ok = 0; +uschar *demime_reason = NULL; +#endif BOOL disable_logging = FALSE; uschar *dns_again_means_nonexist = NULL; @@ -494,6 +499,9 @@ int filter_sn[FILTER_VARIABLE_COUNT]; uschar *filter_test = NULL; uschar *filter_thisaddress = NULL; int finduser_retries = 0; +#ifdef WITH_OLD_DEMIME +uschar *found_extension = NULL; +#endif uid_t fixed_never_users[] = { FIXED_NEVER_USERS }; uschar *freeze_tell = NULL; uschar *fudged_queue_times = US""; diff --git a/src/src/globals.h b/src/src/globals.h index c63a56bc9..727be71c5 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.h,v 1.6.2.1 2004/11/26 16:04:26 tom Exp $ */ +/* $Cambridge: exim/src/src/globals.h,v 1.6.2.2 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -241,6 +241,11 @@ extern uschar *deliver_selectstring; /* For selecting by recipient */ extern BOOL deliver_selectstring_regex; /* String is regex */ extern uschar *deliver_selectstring_sender; /* For selecting by sender */ extern BOOL deliver_selectstring_sender_regex; /* String is regex */ +#ifdef WITH_OLD_DEMIME +extern int demime_errorlevel; /* Severity of MIME error */ +extern int demime_ok; /* Nonzero if message has been demimed */ +extern uschar *demime_reason; /* Reason for broken MIME container */ +#endif extern BOOL disable_logging; /* Disables log writing when TRUE */ extern uschar *dns_again_means_nonexist; /* Domains that are badly set up */ @@ -288,6 +293,9 @@ extern uschar *filter_test; /* Run as a filter tester on this file */ extern uschar *filter_thisaddress; /* For address looping */ extern int finduser_retries; /* Retry count for getpwnam() */ extern uid_t fixed_never_users[]; /* Can't be overridden */ +#ifdef WITH_OLD_DEMIME +extern uschar *found_extension; /* demime acl condition: file extension found */ +#endif extern uschar *freeze_tell; /* Message on (some) freezings */ extern uschar *fudged_queue_times; /* For use in test harness */ diff --git a/src/src/header.c b/src/src/header.c index 2cac551c6..9b464d25b 100644 --- a/src/src/header.c +++ b/src/src/header.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/header.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */ +/* $Cambridge: exim/src/src/header.c,v 1.1.2.1 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -40,6 +40,19 @@ while (*tt == ' ' || *tt == '\t') tt++; return *tt == ':'; } +/* This is a copy of the function above, only that it is possible to pass + only the beginning of a header name. It simply does a front-anchored + substring match. Arguments and Return codes are the same as for + header_testname() above. */ + +BOOL +header_testname_incomplete(header_line *h, uschar *name, int len, BOOL notdel) +{ +uschar *tt; +if (h->type == '*' && notdel) return FALSE; +if (h->text == NULL || strncmpic(h->text, name, len) != 0) return FALSE; +return TRUE; +} /************************************************* diff --git a/src/src/local_scan.h b/src/src/local_scan.h index 4e6f88a31..fd95643a5 100644 --- a/src/src/local_scan.h +++ b/src/src/local_scan.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/local_scan.h,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */ +/* $Cambridge: exim/src/src/local_scan.h,v 1.1.2.1 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -147,6 +147,7 @@ extern void header_add(int, char *, ...); extern void header_add_at_position(BOOL, uschar *, BOOL, int, char *, ...); extern void header_remove(int, uschar *); extern BOOL header_testname(header_line *, uschar *, int, BOOL); +extern BOOL header_testname_incomplete(header_line *, uschar *, int, BOOL); extern void log_write(unsigned int, int, char *format, ...); extern int lss_b64decode(uschar *, uschar **); extern uschar *lss_b64encode(uschar *, int); diff --git a/src/src/macros.h b/src/src/macros.h index d4e7b8a65..bff6706b4 100644 --- a/src/src/macros.h +++ b/src/src/macros.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/macros.h,v 1.2.2.2 2004/11/30 15:18:58 tom Exp $ */ +/* $Cambridge: exim/src/src/macros.h,v 1.2.2.3 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -131,12 +131,12 @@ enough to hold all the headers from a normal kind of message. */ into big_buffer_size and in some circumstances increased. It should be at least as long as the maximum path length. */ -#if defined PATH_MAX && PATH_MAX > 1024 +#if defined PATH_MAX && PATH_MAX > 16384 #define BIG_BUFFER_SIZE PATH_MAX -#elif defined MAXPATHLEN && MAXPATHLEN > 1024 +#elif defined MAXPATHLEN && MAXPATHLEN > 16384 #define BIG_BUFFER_SIZE MAXPATHLEN #else -#define BIG_BUFFER_SIZE 1024 +#define BIG_BUFFER_SIZE 16384 #endif /* This limits the length of data returned by local_scan(). Because it is @@ -545,6 +545,7 @@ to the header name, by calling header_checkname(). */ #define htype_add_top 'a' #define htype_add_rec 'r' #define htype_add_bot 'z' +#define htype_add_rfc 'f' /* Types of item in options lists. These are the bottom 8 bits of the "type" field, which is an int. The opt_void value is used for entries in tables that diff --git a/src/src/readconf.c b/src/src/readconf.c index caa78ee90..e1ca32ebc 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/readconf.c,v 1.2 2004/10/18 09:16:57 ph10 Exp $ */ +/* $Cambridge: exim/src/src/readconf.c,v 1.2.2.1 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -143,6 +143,9 @@ static optionlist optionlist_config[] = { { "acl_smtp_helo", opt_stringptr, &acl_smtp_helo }, { "acl_smtp_mail", opt_stringptr, &acl_smtp_mail }, { "acl_smtp_mailauth", opt_stringptr, &acl_smtp_mailauth }, +#ifdef WITH_CONTENT_SCAN + { "acl_smtp_mime", opt_stringptr, &acl_smtp_mime }, +#endif { "acl_smtp_predata", opt_stringptr, &acl_smtp_predata }, { "acl_smtp_quit", opt_stringptr, &acl_smtp_quit }, { "acl_smtp_rcpt", opt_stringptr, &acl_smtp_rcpt }, @@ -156,6 +159,9 @@ static optionlist optionlist_config[] = { { "allow_utf8_domains", opt_bool, &allow_utf8_domains }, { "auth_advertise_hosts", opt_stringptr, &auth_advertise_hosts }, { "auto_thaw", opt_time, &auto_thaw }, +#ifdef WITH_CONTENT_SCAN + { "av_scanner", opt_stringptr, &av_scanner }, +#endif { "bi_command", opt_stringptr, &bi_command }, { "bounce_message_file", opt_stringptr, &bounce_message_file }, { "bounce_message_text", opt_stringptr, &bounce_message_text }, @@ -318,6 +324,9 @@ static optionlist optionlist_config[] = { { "smtp_receive_timeout", opt_time, &smtp_receive_timeout }, { "smtp_reserve_hosts", opt_stringptr, &smtp_reserve_hosts }, { "smtp_return_error_details",opt_bool, &smtp_return_error_details }, +#ifdef WITH_CONTENT_SCAN + { "spamd_address", opt_stringptr, &spamd_address }, +#endif { "split_spool_directory", opt_bool, &split_spool_directory }, { "spool_directory", opt_stringptr, &spool_directory }, { "strip_excess_angle_brackets", opt_bool, &strip_excess_angle_brackets }, diff --git a/src/src/receive.c b/src/src/receive.c index 0ed05f1db..99a918981 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/receive.c,v 1.5 2004/11/25 13:54:31 ph10 Exp $ */ +/* $Cambridge: exim/src/src/receive.c,v 1.4.2.1 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -427,7 +427,7 @@ if (smtp_input) } else { - if (filter_test == FTEST_NONE) + if (filter_test == NULL) { fprintf(stderr, "\nexim: %s received - message abandoned\n", (sig == SIGTERM)? "SIGTERM" : "SIGINT"); @@ -918,6 +918,21 @@ for (h = acl_warn_headers; h != NULL; h = next) DEBUG(D_receive|D_acl) debug_printf(" (after Received:)"); break; + case htype_add_rfc: + /* add header before any header which is NOT Received: or Resent- */ + last_received = header_list; + while ( (last_received->next != NULL) && + ( (header_testname(last_received->next, US"Received", 8, FALSE)) || + (header_testname_incomplete(last_received->next, US"Resent-", 7, FALSE)) ) ) + last_received = last_received->next; + /* last_received now points to the last Received: or Resent-* header + in an uninterrupted chain of those header types (seen from the beginning + of all headers. Our current header must follow it. */ + h->next = last_received->next; + last_received->next = h; + DEBUG(D_receive|D_acl) debug_printf(" (before any non-Received: or Resent-*: header)"); + break; + default: h->next = NULL; header_last->next = h; @@ -1508,18 +1523,18 @@ for (;;) if (domain == 0 && newsender[0] != 0) newsender = rewrite_address_qualify(newsender, FALSE); - if (filter_test != FTEST_NONE || receive_check_set_sender(newsender)) + if (filter_test != NULL || receive_check_set_sender(newsender)) { sender_address = newsender; - if (trusted_caller || filter_test != FTEST_NONE) + if (trusted_caller || filter_test != NULL) { authenticated_sender = NULL; originator_name = US""; sender_local = FALSE; } - if (filter_test != FTEST_NONE) + if (filter_test != NULL) printf("Sender taken from \"From \" line\n"); } } @@ -1659,7 +1674,7 @@ if (smtp_input && (receive_feof)()) /* If this is a filter test run and no headers were read, output a warning in case there is a mistake in the test message. */ -if (filter_test != FTEST_NONE && header_list->next == NULL) +if (filter_test != NULL && header_list->next == NULL) printf("Warning: no message headers read\n"); @@ -1781,7 +1796,7 @@ for (h = header_list->next; h != NULL; h = h->next) otherwise set. However, remove any <> that surround the address because the variable doesn't have these. */ - if (filter_test != FTEST_NONE) + if (filter_test != NULL) { uschar *start = h->text + 12; uschar *end = start + Ustrlen(start); @@ -2378,7 +2393,7 @@ DEBUG(D_receive) testing mode, that is all this function does. Return TRUE if the message ended with a dot. */ -if (filter_test != FTEST_NONE) +if (filter_test != NULL) { process_info[process_info_len] = 0; return message_ended == END_DOT; @@ -2716,6 +2731,130 @@ 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 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: +#endif /* WITH_CONTENT_SCAN */ + + if (acl_smtp_data != NULL && recipients_count > 0) { uschar *user_msg, *log_msg; @@ -2729,6 +2868,9 @@ else else if (rc != OK) { Uunlink(spool_name); +#ifdef WITH_CONTENT_SCAN + unspool_mbox(); +#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_reply = US""; /* Indicate reply already sent */ @@ -2779,6 +2921,10 @@ else enable_dollar_recipients = FALSE; } +#ifdef WITH_CONTENT_SCAN +unspool_mbox(); +#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 @@ -3235,12 +3381,37 @@ if (smtp_input) { if (smtp_reply == NULL) { +#ifndef WITH_CONTENT_SCAN smtp_printf("250 OK id=%s\r\n", message_id); +#elif + if (fake_reject) + { + smtp_printf("550-FAKE_REJECT id=%s\r\n", message_id); + smtp_printf("550-Your message has been rejected but is being kept for evaluation.\r\n"); + smtp_printf("550 If it was a legit message, it may still be delivered to the target recipient(s).\r\n"); + } + else + smtp_printf("250 OK id=%s\r\n", message_id); +#endif if (host_checking) fprintf(stdout, "\n**** SMTP testing: that is not a real message id!\n\n"); } +#ifndef WITH_CONTENT_SCAN else if (smtp_reply[0] != 0) smtp_printf("%.1024s\r\n", smtp_reply); +#elif + else if (smtp_reply[0] != 0) + { + if (fake_reject && (smtp_reply[0] == '2')) + { + smtp_printf("550-FAKE_REJECT id=%s\r\n", message_id); + smtp_printf("550-Your message has been rejected but is being kept for evaluation.\r\n"); + smtp_printf("550 If it was a legit message, it may still be delivered to the target recipient(s).\r\n"); + } + else + smtp_printf("%.1024s\r\n", smtp_reply); + }; +#endif } /* For batched SMTP, generate an error message on failure, and do diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 9b25c2333..dd8747b92 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/smtp_in.c,v 1.5 2004/11/10 15:21:16 ph10 Exp $ */ +/* $Cambridge: exim/src/src/smtp_in.c,v 1.5.2.1 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -805,6 +805,10 @@ message_size = -1; acl_warn_headers = NULL; queue_only_policy = FALSE; deliver_freeze = FALSE; /* Can be set by ACL */ +#ifdef WITH_CONTENT_SCAN +fake_reject = FALSE; /* Can be set by ACL */ +no_mbox_unspool = FALSE; /* Can be set by ACL */ +#endif submission_mode = FALSE; /* Can be set by ACL */ active_local_from_check = local_from_check; /* Can be set by ACL */ active_local_sender_retain = local_sender_retain; /* Can be set by ACL */ @@ -1774,6 +1778,9 @@ BOOL drop = rc == FAIL_DROP; uschar *lognl; uschar *sender_info = US""; uschar *what = (where == ACL_WHERE_PREDATA)? US"DATA" : +#ifdef WITH_CONTENT_SCAN + (where == ACL_WHERE_MIME)? US"during MIME ACL checks" : +#endif (where == ACL_WHERE_DATA)? US"after DATA" : string_sprintf("%s %s", acl_wherenames[where], smtp_data); @@ -1785,7 +1792,11 @@ fixed, sender_address at this point became the rewritten address. I'm not sure this is what should be logged, so I've changed to logging the unrewritten address to retain backward compatibility. */ +#ifndef WITH_CONTENT_SCAN if (where == ACL_WHERE_RCPT || where == ACL_WHERE_DATA) +#elif +if (where == ACL_WHERE_RCPT || where == ACL_WHERE_DATA || where == ACL_WHERE_MIME) +#endif { sender_info = string_sprintf("F=<%s> ", (sender_address_unrewritten != NULL)? sender_address_unrewritten : sender_address); diff --git a/src/src/spool_in.c b/src/src/spool_in.c index f43556bfa..29996f697 100644 --- a/src/src/spool_in.c +++ b/src/src/spool_in.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/spool_in.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */ +/* $Cambridge: exim/src/src/spool_in.c,v 1.1.2.1 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -277,6 +277,11 @@ tls_cipher = NULL; tls_peerdn = NULL; #endif +#ifdef WITH_CONTENT_SCAN +fake_reject = FALSE; +spam_score_int = NULL; +#endif + /* Generate the full name and open the file. If message_subdir is already set, just look in the given directory. Otherwise, look in both the split and unsplit directories, as for the data file above. */ @@ -369,6 +374,10 @@ for (;;) local_error_message = TRUE; else if (Ustrncmp(big_buffer, "-local_scan ", 12) == 0) local_scan_data = string_copy(big_buffer + 12); +#ifdef WITH_CONTENT_SCAN + else if (Ustrncmp(big_buffer, "-spam_score_int ", 16) == 0) + spam_score_int = string_copy(big_buffer + 16); +#endif else if (Ustrcmp(big_buffer, "-host_lookup_failed") == 0) host_lookup_failed = TRUE; else if (Ustrncmp(big_buffer, "-body_linecount", 15) == 0) diff --git a/src/src/spool_out.c b/src/src/spool_out.c index af36f4169..8514edfd3 100644 --- a/src/src/spool_out.c +++ b/src/src/spool_out.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/spool_out.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */ +/* $Cambridge: exim/src/src/spool_out.c,v 1.1.2.1 2004/12/02 09:15:11 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -216,6 +216,9 @@ if (host_lookup_failed) fprintf(f, "-host_lookup_failed\n"); if (sender_local) fprintf(f, "-local\n"); if (local_error_message) fprintf(f, "-localerror\n"); if (local_scan_data != NULL) fprintf(f, "-local_scan %s\n", local_scan_data); +#ifdef WITH_CONTENT_SCAN +if (spam_score_int != NULL) fprintf(f,"-spam_score_int %s\n", spam_score_int); +#endif if (deliver_manual_thaw) fprintf(f, "-manual_thaw\n"); if (sender_set_untrusted) fprintf(f, "-sender_set_untrusted\n"); -- 2.30.2