X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/b8e078953178c757578f2e104d9d2c822ae0943c..4687a69c269ee3f2a7f0625e0147a503fd9d3d0b:/src/src/exim.c diff --git a/src/src/exim.c b/src/src/exim.c index 14c057f40..5c9e64021 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -49,6 +49,8 @@ optimize out the tail recursion and so not make them too expensive. */ static void * function_store_malloc(PCRE2_SIZE size, void * tag) { +if (size > INT_MAX) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "excessive memory alloc request"); return store_malloc((int)size); } @@ -63,12 +65,15 @@ if (block) store_free(block); static void * function_store_get(PCRE2_SIZE size, void * tag) { +if (size > INT_MAX) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "excessive memory alloc request"); return store_get((int)size, GET_UNTAINTED); /* loses track of taint */ } static void function_store_nullfree(void * block, void * tag) { +/* We cannot free memory allocated using store_get() */ } @@ -1100,6 +1105,9 @@ g = string_cat(g, US"Support for:"); #ifndef DISABLE_DNSSEC g = string_cat(g, US" DNSSEC"); #endif +#ifndef DISABLE_ESMTP_LIMITS + g = string_cat(g, US" ESMTP_Limits"); +#endif #ifndef DISABLE_EVENT g = string_cat(g, US" Event"); #endif @@ -1146,9 +1154,6 @@ g = string_cat(g, US"Support for:"); #ifdef EXPERIMENTAL_DSN_INFO g = string_cat(g, US" Experimental_DSN_info"); #endif -#ifdef EXPERIMENTAL_ESMTP_LIMITS - g = string_cat(g, US" Experimental_ESMTP_Limits"); -#endif #ifdef EXPERIMENTAL_QUEUEFILE g = string_cat(g, US" Experimental_QUEUEFILE"); #endif @@ -1379,17 +1384,15 @@ Argument: the local part Returns: the local part, quoted if necessary */ -uschar * -local_part_quote(uschar *lpart) +const uschar * +local_part_quote(const uschar * lpart) { BOOL needs_quote = FALSE; gstring * g; -for (uschar * t = lpart; !needs_quote && *t != 0; t++) - { +for (const uschar * t = lpart; !needs_quote && *t; t++) needs_quote = !isalnum(*t) && strchr("!#$%&'*+-/=?^_`{|}~", *t) == NULL && (*t != '.' || t == lpart || t[1] == 0); - } if (!needs_quote) return lpart; @@ -1397,8 +1400,8 @@ g = string_catn(NULL, US"\"", 1); for (;;) { - uschar *nq = US Ustrpbrk(lpart, "\\\""); - if (nq == NULL) + uschar * nq = US Ustrpbrk(lpart, "\\\""); + if (!nq) { g = string_cat(g, lpart); break; @@ -1701,8 +1704,10 @@ if (isupper(big_buffer[0])) if (macro_read_assignment(big_buffer)) printf("Defined macro '%s'\n", mlast->name); } +else if (Ustrncmp(big_buffer, "set,t ", 6) == 0) + printf("%s\n", acl_standalone_setvar(big_buffer+6, TRUE)); else if (Ustrncmp(big_buffer, "set ", 4) == 0) - printf("%s\n", acl_standalone_setvar(big_buffer+4)); + printf("%s\n", acl_standalone_setvar(big_buffer+4, FALSE)); else if ((s = expand_string(big_buffer))) printf("%s\n", CS s); else printf("Failed: %s\n", expand_string_message); @@ -1809,20 +1814,20 @@ BOOL verify_address_mode = FALSE; BOOL verify_as_sender = FALSE; BOOL rcpt_verify_quota = FALSE; BOOL version_printed = FALSE; -const uschar *alias_arg = NULL; -const uschar *called_as = US""; -const uschar *cmdline_syslog_name = NULL; -const uschar *start_queue_run_id = NULL; -const uschar *stop_queue_run_id = NULL; -const uschar *expansion_test_message = NULL; -const uschar *ftest_domain = NULL; -const uschar *ftest_localpart = NULL; -const uschar *ftest_prefix = NULL; -const uschar *ftest_suffix = NULL; -uschar *log_oneline = NULL; -const uschar *malware_test_file = NULL; -uschar *real_sender_address; -uschar *originator_home = US"/"; +const uschar * alias_arg = NULL; +const uschar * called_as = US""; +const uschar * cmdline_syslog_name = NULL; +const uschar * start_queue_run_id = NULL; +const uschar * stop_queue_run_id = NULL; +const uschar * expansion_test_message = NULL; +const uschar * ftest_domain = NULL; +const uschar * ftest_localpart = NULL; +const uschar * ftest_prefix = NULL; +const uschar * ftest_suffix = NULL; +uschar * log_oneline = NULL; +const uschar * malware_test_file = NULL; +const uschar * real_sender_address; +uschar * originator_home = US"/"; size_t sz; struct passwd *pw; @@ -2627,14 +2632,11 @@ on the second character (the one after '-'), to save some effort. */ reset_point = store_mark(); while (Ufgets(big_buffer, big_buffer_size, trust_list)) { - uschar *start = big_buffer, *nl; - while (*start && isspace(*start)) - start++; - if (*start != '/') + uschar * start = big_buffer, * nl; + if (Uskip_whitespace(&start) != '/') continue; - nl = Ustrchr(start, '\n'); - if (nl) - *nl = 0; + if ((nl = Ustrchr(start, '\n'))) + *nl = '\0'; trusted_configs[nr_configs++] = string_copy(start); if (nr_configs == nelem(trusted_configs)) break; @@ -2693,7 +2695,7 @@ on the second character (the one after '-'), to save some effort. */ const uschar * s = argrest; opt_D_used = TRUE; - while (isspace(*s)) s++; + Uskip_whitespace(&s); if (*s < 'A' || *s > 'Z') exim_fail("exim: macro name set by -D must start with " @@ -2706,11 +2708,10 @@ on the second character (the one after '-'), to save some effort. */ } name[ptr] = 0; if (ptr == 0) { badarg = TRUE; break; } - while (isspace(*s)) s++; - if (*s != 0) + if (Uskip_whitespace(&s)) { if (*s++ != '=') { badarg = TRUE; break; } - while (isspace(*s)) s++; + Uskip_whitespace(&s); } for (m = macros_user; m; m = m->next) @@ -2844,7 +2845,11 @@ on the second character (the one after '-'), to save some effort. */ if (i+1 < argc) argrest = argv[++i]; else { badarg = TRUE; break; } (void) exim_str_fail_toolong(argrest, EXIM_DISPLAYMAIL_MAX, "-f"); if (!*argrest) - *(sender_address = store_get(1, GET_UNTAINTED)) = '\0'; /* Ensure writeable memory */ + { + uschar * s = store_get(1, GET_UNTAINTED); /* Ensure writeable memory */ + *s = '\0'; + sender_address = s; + } else { const uschar * temp = argrest + Ustrlen(argrest) - 1; @@ -3012,7 +3017,7 @@ on the second character (the one after '-'), to save some effort. */ case 'K': smtp_peer_options |= OPTION_CHUNKING; break; -#ifdef EXPERIMENTAL_ESMTP_LIMITS +#ifndef DISABLE_ESMTP_LIMITS /* -MCL: peer used LIMITS RCPTMAX and/or RCPTDOMAINMAX */ case 'L': if (++i < argc) continue_limit_mail = Uatoi(argv[i]); else badarg = TRUE; @@ -3686,7 +3691,7 @@ on the second character (the one after '-'), to save some effort. */ in all cases provided there are no further characters in this argument. */ - alloc_onetime_qrunner(); + if (!qrunners) alloc_onetime_qrunner(); qrunners->queue_2stage = f.queue_2stage; if (*argrest) for (int i = 0; i < nelem(rsopts); i++) @@ -5056,6 +5061,8 @@ for (i = 0;;) /* If a pattern for matching the gecos field was supplied, apply it and then expand the name string. */ + GET_OPTION("gecos_pattern"); + GET_OPTION("gecos_name"); if (gecos_pattern && gecos_name) { const pcre2_code *re; @@ -5101,6 +5108,7 @@ any setting of unknown_login overrides the actual name. */ if (!originator_login || f.running_in_test_harness) { + GET_OPTION("unknown_login"); if (unknown_login) { originator_login = expand_string(unknown_login); @@ -5332,6 +5340,7 @@ if (expansion_test) else if (expansion_test_message) { + uschar * rme = expand_string(recipients_max); int save_stdin = dup(0); int fd = Uopen(expansion_test_message, O_RDONLY, 0); if (fd < 0) @@ -5340,6 +5349,7 @@ if (expansion_test) (void) dup2(fd, 0); filter_test = FTEST_USER; /* Fudge to make it look like filter test */ message_ended = END_NOTENDED; + recipients_max_expanded = atoi(CCS rme); read_message_body(receive_msg(extract_recipients)); message_linecount += body_linecount; (void)dup2(save_stdin, 0); @@ -5398,17 +5408,18 @@ for hosts that want to play several parts at once. We need to ensure that it is set for host checking, and for receiving messages. */ smtp_active_hostname = primary_hostname; -if (raw_active_hostname != NULL) +GET_OPTION("smtp_active_hostname"); +if (raw_active_hostname) { - uschar *nah = expand_string(raw_active_hostname); - if (nah == NULL) + uschar * nah = expand_string(raw_active_hostname); + if (!nah) { if (!f.expand_string_forcedfail) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to expand \"%s\" " "(smtp_active_hostname): %s", raw_active_hostname, expand_string_message); } - else if (nah[0] != 0) smtp_active_hostname = nah; + else if (nah[0]) smtp_active_hostname = nah; } /* Handle host checking: this facility mocks up an incoming SMTP call from a @@ -5666,6 +5677,7 @@ if (smtp_input) else { + GET_OPTION("message_size_limit"); thismessage_size_limit = expand_string_integer(message_size_limit, TRUE); if (expand_string_message) if (thismessage_size_limit == -1) @@ -5746,8 +5758,8 @@ for (BOOL more = TRUE; more; ) int rc; if ((rc = smtp_setup_msg()) > 0) { - if (real_sender_address != NULL && - !receive_check_set_sender(sender_address)) + if ( real_sender_address + && !receive_check_set_sender(sender_address)) { sender_address = raw_sender = real_sender_address; sender_address_unrewritten = NULL; @@ -5758,14 +5770,18 @@ for (BOOL more = TRUE; more; ) the very end. The result of the ACL is ignored (as for other non-SMTP messages). It is run for its potential side effects. */ - if (smtp_batched_input && acl_not_smtp_start != NULL) - { - uschar *user_msg, *log_msg; - f.enable_dollar_recipients = TRUE; - (void)acl_check(ACL_WHERE_NOTSMTP_START, NULL, acl_not_smtp_start, - &user_msg, &log_msg); - f.enable_dollar_recipients = FALSE; - } + if (smtp_batched_input) + { + GET_OPTION("acl_not_smtp_start"); + if (acl_not_smtp_start) + { + uschar * user_msg, * log_msg; + f.enable_dollar_recipients = TRUE; + (void)acl_check(ACL_WHERE_NOTSMTP_START, NULL, acl_not_smtp_start, + &user_msg, &log_msg); + f.enable_dollar_recipients = FALSE; + } + } /* Now get the data for the message */ @@ -5794,10 +5810,12 @@ for (BOOL more = TRUE; more; ) else { - int rcount = 0; - int count = argc - recipients_arg; + uschar * rme = expand_string(recipients_max); + int rcount = 0, count = argc - recipients_arg; const uschar ** list = argv + recipients_arg; + recipients_max_expanded = atoi(CCS rme); + /* These options cannot be changed dynamically for non-SMTP messages */ f.active_local_sender_retain = local_sender_retain; @@ -5824,15 +5842,19 @@ for (BOOL more = TRUE; more; ) while (*s) { BOOL finished = FALSE; - uschar *recipient; - uschar *ss = parse_find_address_end(s, FALSE); + uschar * recipient; + uschar * ss = parse_find_address_end(s, FALSE); if (*ss == ',') *ss = 0; else finished = TRUE; /* Check max recipients - if -t was used, these aren't recipients */ - if (recipients_max > 0 && ++rcount > recipients_max && - !extract_recipients) + if ( recipients_max_expanded > 0 && ++rcount > recipients_max_expanded + && !extract_recipients) + { + DEBUG(D_all) debug_printf("excess reipients (max %d)\n", + recipients_max_expanded); + if (error_handling == ERRORS_STDERR) { fprintf(stderr, "exim: too many recipients\n"); @@ -5842,6 +5864,7 @@ for (BOOL more = TRUE; more; ) return moan_to_sender(ERRMESS_TOOMANYRECIP, NULL, NULL, stdin, TRUE)? errors_sender_rc : EXIT_FAILURE; + } #ifdef SUPPORT_I18N { @@ -5866,6 +5889,10 @@ for (BOOL more = TRUE; more; ) } if (!recipient) + { + DEBUG(D_all) debug_printf("bad recipient address \"%s\": %s\n", + string_printing(list[i]), errmess); + if (error_handling == ERRORS_STDERR) { fprintf(stderr, "exim: bad recipient address \"%s\": %s\n", @@ -5882,11 +5909,12 @@ for (BOOL more = TRUE; more; ) moan_to_sender(ERRMESS_BADARGADDRESS, &eblock, NULL, stdin, TRUE)? errors_sender_rc : EXIT_FAILURE; } + } receive_add_recipient(string_copy_taint(recipient, GET_TAINTED), -1); s = ss; if (!finished) - while (*(++s) != 0 && (*s == ',' || isspace(*s))); + while (*++s && (*s == ',' || isspace(*s))); } } @@ -5907,9 +5935,10 @@ for (BOOL more = TRUE; more; ) ignored; rejecting here would just add complication, and it can just as well be done later. Allow $recipients to be visible in the ACL. */ + GET_OPTION("acl_not_smtp_start"); if (acl_not_smtp_start) { - uschar *user_msg, *log_msg; + uschar * user_msg, * log_msg; f.enable_dollar_recipients = TRUE; (void)acl_check(ACL_WHERE_NOTSMTP_START, NULL, acl_not_smtp_start, &user_msg, &log_msg);