X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fexim.c;h=1b7529c73b493d643a78342cd2aac6cc3e089633;hb=5dc522966ae58ac845dc280495af651c9858f152;hp=dd3a17f14f5199e3aa964428ff494759cbd9b0c6;hpb=c9bce82e3064126be34d85280d0a7fbf65b3abec;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/exim.c b/src/src/exim.c index dd3a17f14..1b7529c73 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -496,7 +496,7 @@ while (exim_tvcmp(&now_tv, tgt_tv) <= 0) /* Be prapared to go around if the kernel does not implement subtick granularity (GNU Hurd) */ - (void)gettimeofday(&now_tv, NULL); + exim_gettime(&now_tv); now_true_usec = now_tv.tv_usec; now_tv.tv_usec = (now_true_usec/resolution) * resolution; } @@ -564,7 +564,7 @@ for (int i = 0; i <= 2; i++) { if (devnull < 0) devnull = open("/dev/null", O_RDWR); if (devnull < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s", - string_open_failed(errno, "/dev/null", NULL)); + string_open_failed("/dev/null", NULL)); if (devnull != i) (void)dup2(devnull, i); } } @@ -760,6 +760,25 @@ vfprintf(stderr, fmt, ap); exit(EXIT_FAILURE); } +/* fail if a length is too long */ +static void +exim_len_fail_toolong(int itemlen, int maxlen, const char *description) +{ +if (itemlen <= maxlen) + return; +fprintf(stderr, "exim: length limit exceeded (%d > %d) for: %s\n", + len, maxlen, description) +exit(EXIT_FAILURE); +} + +/* only pass through the string item back to the caller if it's short enough */ +static const uschar * +exim_str_fail_toolong(const uschar *item, int maxlen, const char *description) +{ +exim_len_fail_toolong(Ustrlen(item), maxlen, description); +return item; +} + /* exim_chown_failure() called from exim_chown()/exim_fchown() on failure of chown()/fchown(). See src/functions.h for more explanation */ int @@ -1010,6 +1029,9 @@ g = string_cat(NULL, 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 @@ -1135,6 +1157,9 @@ show_db_version(fp); #ifdef SUPPORT_I18N utf8_version_report(fp); #endif +#ifdef SUPPORT_DMARC + dmarc_version_report(fp); +#endif #ifdef SUPPORT_SPF spf_lib_version_report(fp); #endif @@ -1669,6 +1694,8 @@ extern char **environ; (void)gettimeofday(×tamp_startup, NULL); #endif +store_init(); /* Initialise the memory allocation susbsystem */ + /* If the Exim user and/or group and/or the configuration file owner/group were defined by ref:name at build time, we must now find the actual uid/gid values. This is a feature to make the lives of binary distributors easier. */ @@ -1731,6 +1758,9 @@ f.running_in_test_harness = if (f.running_in_test_harness) debug_store = TRUE; +/* Protect against abusive argv[0] */ +exim_len_fail_toolong(argv[0], PATH_MAX, "argv[0]"); + /* The C standard says that the equivalent of setlocale(LC_ALL, "C") is obeyed at the start of a program; however, it seems that some environments do not follow this. A "strange" locale can affect the formatting of timestamps, so we @@ -2132,10 +2162,10 @@ on the second character (the one after '-'), to save some effort. */ { if (++i >= argc) exim_fail("exim: string expected after %s\n", arg); - if (Ustrcmp(argrest, "d") == 0) ftest_domain = argv[i]; - else if (Ustrcmp(argrest, "l") == 0) ftest_localpart = argv[i]; - else if (Ustrcmp(argrest, "p") == 0) ftest_prefix = argv[i]; - else if (Ustrcmp(argrest, "s") == 0) ftest_suffix = argv[i]; + if (Ustrcmp(argrest, "d") == 0) ftest_domain = exim_str_fail_toolong(argv[i], EXIM_DOMAINNAME_MAX, "-bfd"); + else if (Ustrcmp(argrest, "l") == 0) ftest_localpart = exim_str_fail_toolong(argv[i], EXIM_LOCALPART_MAX, "-bfl"); + else if (Ustrcmp(argrest, "p") == 0) ftest_prefix = exim_str_fail_toolong(argv[i], EXIM_LOCALPART_MAX, "-bfp"); + else if (Ustrcmp(argrest, "s") == 0) ftest_suffix = exim_str_fail_toolong(argv[i], EXIM_LOCALPART_MAX, "-bfs"); else badarg = TRUE; } break; @@ -2145,7 +2175,7 @@ on the second character (the one after '-'), to save some effort. */ if (!*argrest || Ustrcmp(argrest, "c") == 0) { if (++i >= argc) { badarg = TRUE; break; } - sender_host_address = string_copy_taint(argv[i], TRUE); + sender_host_address = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_IPADDR_MAX, "-bh"), TRUE); host_checking = checking = f.log_testing_mode = TRUE; f.host_checking_callout = *argrest == 'c'; message_logs = FALSE; @@ -2255,7 +2285,7 @@ on the second character (the one after '-'), to save some effort. */ case 'P': /* -bP config: we need to setup here, because later, - * when list_options is checked, the config is read already */ + when list_options is checked, the config is read already */ if (*argrest) badarg = TRUE; else if (argv[i+1] && Ustrcmp(argv[i+1], "config") == 0) @@ -2373,6 +2403,7 @@ on the second character (the one after '-'), to save some effort. */ int len = Ustrlen(ALT_CONFIG_PREFIX); const uschar *list = argrest; uschar *filename; + /* The argv is untainted, so big_buffer (also untainted) is ok to use */ while((filename = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))) if ( ( Ustrlen(filename) < len @@ -2602,7 +2633,7 @@ on the second character (the one after '-'), to save some effort. */ case 'F': if (!*argrest) if (++i < argc) argrest = argv[i]; else { badarg = TRUE; break; } - originator_name = string_copy_taint(argrest, TRUE); + originator_name = string_copy_taint(exim_str_fail_toolong(argrest, EXIM_HUMANNAME_MAX, "-F"), TRUE); f.sender_name_forced = TRUE; break; @@ -2628,6 +2659,7 @@ on the second character (the one after '-'), to save some effort. */ uschar *errmess; if (!*argrest) 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, FALSE)) = '\0'; /* Ensure writeable memory */ else @@ -2724,9 +2756,9 @@ on the second character (the one after '-'), to save some effort. */ if (msg_action_arg >= 0) exim_fail("exim: incompatible arguments\n"); - continue_transport = string_copy_taint(argv[++i], TRUE); - continue_hostname = string_copy_taint(argv[++i], TRUE); - continue_host_address = string_copy_taint(argv[++i], TRUE); + continue_transport = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-C internal transport"), TRUE); + continue_hostname = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_HOSTNAME_MAX, "-C internal hostname"), TRUE); + continue_host_address = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IPADDR_MAX, "-C internal hostaddr"), TRUE); continue_sequence = Uatoi(argv[++i]); msg_action = MSG_DELIVER; msg_action_arg = ++i; @@ -2771,13 +2803,15 @@ on the second character (the one after '-'), to save some effort. */ /* -MCd: for debug, set a process-purpose string */ case 'd': if (++i < argc) - process_purpose = string_copy_taint(argv[i], TRUE); + process_purpose = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_DRIVERNAME_MAX, "-MCd"), TRUE); else badarg = TRUE; break; - /* -MCG: set the queue name, to a non-default value */ + /* -MCG: set the queue name, to a non-default value. Arguably, anything + from the commandline should be tainted - but we will need an untainted + value for the spoolfile when doing a -odi delivery process. */ - case 'G': if (++i < argc) queue_name = string_copy_taint(argv[i], TRUE); + case 'G': if (++i < argc) queue_name = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_DRIVERNAME_MAX, "-MCG"), FALSE); else badarg = TRUE; break; @@ -2785,11 +2819,42 @@ on the second character (the one after '-'), to save some effort. */ case 'K': smtp_peer_options |= OPTION_CHUNKING; break; +#ifdef EXPERIMENTAL_ESMTP_LIMITS + /* -MCL: peer used LIMITS RCPTMAX and/or RCPTDOMAINMAX */ + case 'L': if (++i < argc) continue_limit_mail = Uatoi(argv[i]); + else badarg = TRUE; + if (++i < argc) continue_limit_rcpt = Uatoi(argv[i]); + else badarg = TRUE; + if (++i < argc) continue_limit_rcptdom = Uatoi(argv[i]); + else badarg = TRUE; + break; +#endif + /* -MCP: set the smtp_use_pipelining flag; this is useful only when it preceded -MC (see above) */ case 'P': smtp_peer_options |= OPTION_PIPE; break; +#ifdef SUPPORT_SOCKS + /* -MCp: Socks proxy in use; nearside IP, port, external IP, port */ + case 'p': proxy_session = TRUE; + if (++i < argc) + { + proxy_local_address = string_copy_taint(argv[i], TRUE); + if (++i < argc) + { + proxy_local_port = Uatoi(argv[i]); + if (++i < argc) + { + proxy_external_address = string_copy_taint(argv[i], TRUE); + if (++i < argc) + { + proxy_external_port = Uatoi(argv[i]); + break; + } } } } + badarg = TRUE; + break; +#endif /* -MCQ: pass on the pid of the queue-running process that started this chain of deliveries and the fd of its synchronizing pipe; this is useful only when it precedes -MC (see above) */ @@ -2813,19 +2878,31 @@ on the second character (the one after '-'), to save some effort. */ case 'S': smtp_peer_options |= OPTION_SIZE; break; #ifndef DISABLE_TLS + /* -MCs: used with -MCt; SNI was sent */ + /* -MCr: ditto, DANE */ + + case 'r': + case 's': if (++i < argc) + { + continue_proxy_sni = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_HOSTNAME_MAX, "-MCr/-MCs"), TRUE); + if (argrest[1] == 'r') continue_proxy_dane = TRUE; + } + else badarg = TRUE; + break; + /* -MCt: similar to -MCT below but the connection is still open via a proxy process which handles the TLS context and coding. Require three arguments for the proxied local address and port, - and the TLS cipher. */ + and the TLS cipher. */ case 't': if (++i < argc) - sending_ip_address = string_copy_taint(argv[i], TRUE); + sending_ip_address = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_IPADDR_MAX, "-MCt IP"), TRUE); else badarg = TRUE; if (++i < argc) sending_port = (int)(Uatol(argv[i])); else badarg = TRUE; if (++i < argc) - continue_proxy_cipher = string_copy_taint(argv[i], TRUE); + continue_proxy_cipher = string_copy_taint(exim_str_fail_toolong(argv[i], EXIM_CIPHERNAME_MAX, "-MCt cipher"), TRUE); else badarg = TRUE; /*FALLTHROUGH*/ @@ -2852,6 +2929,7 @@ on the second character (the one after '-'), to save some effort. */ following options which are followed by a single message id, and which act on that message. Some of them use the "recipient" addresses as well. -Mar add recipient(s) + -MG move to a different queue -Mmad mark all recipients delivered -Mmd mark recipients(s) delivered -Mes edit sender @@ -2887,7 +2965,7 @@ on the second character (the one after '-'), to save some effort. */ else if (Ustrcmp(argrest, "G") == 0) { msg_action = MSG_SETQUEUE; - queue_name_dest = string_copy_taint(argv[++i], TRUE); + queue_name_dest = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-MG"), TRUE); } else if (Ustrcmp(argrest, "mad") == 0) { @@ -3100,27 +3178,27 @@ on the second character (the one after '-'), to save some effort. */ /* -oMa: Set sender host address */ if (Ustrcmp(argrest, "a") == 0) - sender_host_address = string_copy_taint(argv[++i], TRUE); + sender_host_address = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IPADDR_MAX, "-oMa"), TRUE); /* -oMaa: Set authenticator name */ else if (Ustrcmp(argrest, "aa") == 0) - sender_host_authenticated = string_copy_taint(argv[++i], TRUE); + sender_host_authenticated = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-oMaa"), TRUE); /* -oMas: setting authenticated sender */ else if (Ustrcmp(argrest, "as") == 0) - authenticated_sender = string_copy_taint(argv[++i], TRUE); + authenticated_sender = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_EMAILADDR_MAX, "-oMas"), TRUE); /* -oMai: setting authenticated id */ else if (Ustrcmp(argrest, "ai") == 0) - authenticated_id = string_copy_taint(argv[++i], TRUE); + authenticated_id = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_EMAILADDR_MAX, "-oMas"), TRUE); /* -oMi: Set incoming interface address */ else if (Ustrcmp(argrest, "i") == 0) - interface_address = string_copy_taint(argv[++i], TRUE); + interface_address = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IPADDR_MAX, "-oMi"), TRUE); /* -oMm: Message reference */ @@ -3140,19 +3218,19 @@ on the second character (the one after '-'), to save some effort. */ if (received_protocol) exim_fail("received_protocol is set already\n"); else - received_protocol = string_copy_taint(argv[++i], TRUE); + received_protocol = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-oMr"), TRUE); /* -oMs: Set sender host name */ else if (Ustrcmp(argrest, "s") == 0) - sender_host_name = string_copy_taint(argv[++i], TRUE); + sender_host_name = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_HOSTNAME_MAX, "-oMs"), TRUE); /* -oMt: Set sender ident */ else if (Ustrcmp(argrest, "t") == 0) { sender_ident_set = TRUE; - sender_ident = string_copy_taint(argv[++i], TRUE); + sender_ident = string_copy_taint(exim_str_fail_toolong(argv[++i], EXIM_IDENTUSER_MAX, "-oMt"), TRUE); } /* Else a bad argument */ @@ -3202,10 +3280,18 @@ on the second character (the one after '-'), to save some effort. */ break; /* -oX : Override local_interfaces and/or default daemon ports */ + /* Limits: Is there a real limit we want here? 1024 is very arbitrary. */ case 'X': if (*argrest) badarg = TRUE; - else override_local_interfaces = string_copy_taint(argv[++i], TRUE); + else override_local_interfaces = string_copy_taint(exim_str_fail_toolong(argv[++i], 1024, "-oX", TRUE); + break; + + /* -oY: Override creation of daemon notifier socket */ + + case 'Y': + if (*argrest) badarg = TRUE; + else notifier_socket = NULL; break; /* Unknown -o argument */ @@ -3246,9 +3332,10 @@ on the second character (the one after '-'), to save some effort. */ exim_fail("received_protocol is set already\n"); if (!hn) - received_protocol = string_copy_taint(argrest, TRUE); + received_protocol = string_copy_taint(exim_str_fail_toolong(argrest, EXIM_DRIVERNAME_MAX, "-p"), TRUE); else { + (void) exim_str_fail_toolong(argrest, (EXIM_DRIVERNAME_MAX+1+EXIM_HOSTNAME_MAX), "-p:"); received_protocol = string_copyn_taint(argrest, hn - argrest, TRUE); sender_host_name = string_copy_taint(hn + 1, TRUE); } @@ -3304,6 +3391,7 @@ on the second character (the one after '-'), to save some effort. */ { int i; for (argrest++, i = 0; argrest[i] && argrest[i] != '/'; ) i++; + exim_len_fail_toolong(i, EXIM_DRIVERNAME_MAX, "-q*G"); queue_name = string_copyn(argrest, i); argrest += i; if (*argrest == '/') argrest++; @@ -3357,15 +3445,18 @@ on the second character (the one after '-'), to save some effort. */ /* -R: Set string to match in addresses for forced queue run to pick out particular messages. */ + /* Avoid attacks from people providing very long strings, and do so before + we make copies. */ + const char *tainted_selectstr; if (*argrest) - deliver_selectstring = string_copy_taint(argrest, TRUE); + tainted_selectstr = argrest; else if (i+1 < argc) - deliver_selectstring = string_copy_taint(argv[++i], TRUE); + tainted_selectstr = argv[++i]; else exim_fail("exim: string expected after -R\n"); + deliver_selectstring = string_copy_taint(exim_str_fail_toolong(tainted_selectstr, EXIM_EMAILADDR_MAX, "-R"), TRUE); break; - /* -r: an obsolete synonym for -f (see above) */ @@ -3396,12 +3487,14 @@ on the second character (the one after '-'), to save some effort. */ /* -S: Set string to match in addresses for forced queue run to pick out particular messages. */ + const char *tainted_selectstr; if (*argrest) - deliver_selectstring_sender = string_copy_taint(argrest, TRUE); + tainted_selectstr = argrest; else if (i+1 < argc) - deliver_selectstring_sender = string_copy_taint(argv[++i], TRUE); + tainted_selectstr = argv[++i]; else exim_fail("exim: string expected after -S\n"); + deliver_selectstring_sender = string_copy_taint(exim_str_fail_toolong(tainted_selectstr, EXIM_EMAILADDR_MAX, "-S"), TRUE); break; /* -Tqt is an option that is exclusively for use by the testing suite. @@ -3483,10 +3576,12 @@ on the second character (the one after '-'), to save some effort. */ exim_fail("exim: string expected after -X\n"); break; + /* -z: a line of text to log */ + case 'z': if (!*argrest) if (++i < argc) - log_oneline = string_copy_taint(argv[i], TRUE); + log_oneline = string_copy_taint(exim_str_fail_toolong(argv[i], 2048, "-z logtext"), TRUE); else exim_fail("exim: file name expected after %s\n", argv[i-1]); break; @@ -3775,7 +3870,13 @@ during readconf_main() some expansion takes place already. */ /* Store the initial cwd before we change directories. Can be NULL if the dir has already been unlinked. */ +errno = 0; initial_cwd = os_getcwd(NULL, 0); +if (!initial_cwd && errno) + exim_fail("exim: getting initial cwd failed: %s\n", strerror(errno)); + +if (initial_cwd && (strlen(CCS initial_cwd) >= BIG_BUFFER_SIZE)) + exim_fail("exim: initial cwd is far too long (%d)\n", Ustrlen(CCS initial_cwd)); /* checking: -be[m] expansion test - @@ -4461,7 +4562,7 @@ if (test_retry_arg >= 0) printf("-brt needs a domain or address argument\n"); exim_exit(EXIT_FAILURE); } - s1 = argv[test_retry_arg++]; + s1 = exim_str_fail_toolong(argv[test_retry_arg++], EXIM_EMAILADDR_MAX, "-brt"); s2 = NULL; /* If the first argument contains no @ and no . it might be a local user @@ -4477,13 +4578,13 @@ if (test_retry_arg >= 0) /* There may be an optional second domain arg. */ if (test_retry_arg < argc && Ustrchr(argv[test_retry_arg], '.') != NULL) - s2 = argv[test_retry_arg++]; + s2 = exim_str_fail_toolong(argv[test_retry_arg++], EXIM_DOMAINNAME_MAX, "-brt 2nd"); /* The final arg is an error name */ if (test_retry_arg < argc) { - uschar *ss = argv[test_retry_arg]; + uschar *ss = exim_str_fail_toolong(argv[test_retry_arg], EXIM_DRIVERNAME_MAX, "-brt 3rd"); uschar *error = readconf_retry_error(ss, ss + Ustrlen(ss), &basic_errno, &more_errno); if (error != NULL) @@ -4585,11 +4686,11 @@ if (list_options) Ustrcmp(argv[i], "macro") == 0 || Ustrcmp(argv[i], "environment") == 0)) { - fail |= !readconf_print(argv[i+1], argv[i], flag_n); + fail |= !readconf_print(exim_str_fail_toolong(argv[i+1], EXIM_DRIVERNAME_MAX, "-bP name"), argv[i], flag_n); i++; } else - fail = !readconf_print(argv[i], NULL, flag_n); + fail = !readconf_print(exim_str_fail_toolong(argv[i], EXIM_DRIVERNAME_MAX, "-bP item"), NULL, flag_n); } exim_exit(fail ? EXIT_FAILURE : EXIT_SUCCESS); } @@ -4634,6 +4735,7 @@ if (msg_action_arg > 0 && msg_action != MSG_LOAD) pid_t pid; /*XXX This use of argv[i] for msg_id should really be tainted, but doing that runs into a later copy into the untainted global message_id[] */ + /*XXX Do we need a length limit check here? */ if (i == argc - 1) (void)deliver_message(argv[i], forced_delivery, deliver_give_up); else if ((pid = exim_fork(US"cmdline-delivery")) == 0) @@ -4758,16 +4860,16 @@ for (i = 0;;) configuration specifies something to use. When running in the test harness, any setting of unknown_login overrides the actual name. */ -if (originator_login == NULL || f.running_in_test_harness) +if (!originator_login || f.running_in_test_harness) { - if (unknown_login != NULL) + if (unknown_login) { originator_login = expand_string(unknown_login); - if (originator_name == NULL && unknown_username != NULL) + if (!originator_name && unknown_username) originator_name = expand_string(unknown_username); - if (originator_name == NULL) originator_name = US""; + if (!originator_name) originator_name = US""; } - if (originator_login == NULL) + if (!originator_login) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Failed to get user name for uid %d", (int)real_uid); } @@ -4775,8 +4877,7 @@ if (originator_login == NULL || f.running_in_test_harness) /* Ensure that the user name is in a suitable form for use as a "phrase" in an RFC822 address.*/ -originator_name = string_copy(parse_fix_phrase(originator_name, - Ustrlen(originator_name), big_buffer, big_buffer_size)); +originator_name = US parse_fix_phrase(originator_name, Ustrlen(originator_name)); /* If a message is created by this call of Exim, the uid/gid of its originator are those of the caller. These values are overridden if an existing message is @@ -4840,7 +4941,7 @@ if (test_rewrite_arg >= 0) printf("-brw needs an address argument\n"); exim_exit(EXIT_FAILURE); } - rewrite_test(argv[test_rewrite_arg]); + rewrite_test(exim_str_fail_toolong(argv[test_rewrite_arg], EXIM_EMAILADDR_MAX, "-brw")); exim_exit(EXIT_SUCCESS); } @@ -4933,7 +5034,7 @@ if (verify_address_mode || f.address_test_mode) while (recipients_arg < argc) { /* Supplied addresses are tainted since they come from a user */ - uschar * s = string_copy_taint(argv[recipients_arg++], TRUE); + uschar * s = string_copy_taint(exim_str_fail_toolong(argv[recipients_arg++], EXIM_DISPLAYMAIL_MAX, "address verification"), TRUE); while (*s) { BOOL finished = FALSE; @@ -4950,7 +5051,7 @@ if (verify_address_mode || f.address_test_mode) { uschar * s = get_stdinput(NULL, NULL); if (!s) break; - test_address(string_copy_taint(s, TRUE), flags, &exit_value); + test_address(string_copy_taint(exim_str_fail_toolong(s, EXIM_DISPLAYMAIL_MAX, "address verification (stdin)"), TRUE), flags, &exit_value); } route_tidyup(); @@ -4967,10 +5068,10 @@ if (expansion_test) dns_init(FALSE, FALSE, FALSE); if (msg_action_arg > 0 && msg_action == MSG_LOAD) { - uschar spoolname[256]; /* Not big_buffer; used in spool_read_header() */ + uschar spoolname[SPOOL_NAME_LENGTH]; /* Not big_buffer; used in spool_read_header() */ if (!f.admin_user) exim_fail("exim: permission denied\n"); - message_id = argv[msg_action_arg]; + message_id = exim_str_fail_toolong(argv[msg_action_arg], MESSAGE_ID_LENGTH, "message-id"); (void)string_format(spoolname, sizeof(spoolname), "%s-H", message_id); if ((deliver_datafile = spool_open_datafile(message_id)) < 0) printf ("Failed to load message datafile %s\n", message_id); @@ -5010,7 +5111,7 @@ if (expansion_test) if (recipients_arg < argc) while (recipients_arg < argc) - expansion_test_line(argv[recipients_arg++]); + expansion_test_line(exim_str_fail_toolong(argv[recipients_arg++], EXIM_EMAILADDR_MAX, "recipient")); /* Read stdin */ @@ -5453,7 +5554,9 @@ while (more) { int start, end, domain; uschar * errmess; - uschar * s = string_copy_taint(list[i], TRUE); + /* There can be multiple addresses, so EXIM_DISPLAYMAIL_MAX (tuned for 1) is too short. + * We'll still want to cap it to something, just in case. */ + uschar * s = string_copy_taint(exim_str_fail_toolong(list[i], BIG_BUFFER_SIZE, "address argument"), TRUE); /* Loop for each comma-separated address */