* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) The Exim Maintainers 2020 - 2022 */
+/* Copyright (c) The Exim Maintainers 2020 - 2024 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
/* SPDX-License-Identifier: GPL-2.0-or-later */
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);
}
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() */
}
static void
term_handler(int sig)
{
-exit(1);
+exim_exit(EXIT_FAILURE);
}
/* fail if a length is too long */
static inline void
-exim_len_fail_toolong(int itemlen, int maxlen, const char *description)
+exim_len_fail_toolong(int itemlen, int maxlen, const char * description)
{
if (itemlen <= maxlen)
return;
/* only pass through the string item back to the caller if it's short enough */
static inline const uschar *
-exim_str_fail_toolong(const uschar *item, int maxlen, const char *description)
+exim_str_fail_toolong(const uschar * item, int maxlen, const char * description)
{
+if (!item)
+ exim_fail("exim: bad item for: %s\n", description);
exim_len_fail_toolong(Ustrlen(item), maxlen, description);
return item;
}
struct stat buf;
if (0 == (fd < 0 ? stat(name, &buf) : fstat(fd, &buf)))
-{
+ {
if (buf.st_uid == owner && buf.st_gid == group) return 0;
log_write(0, LOG_MAIN|LOG_PANIC, "Wrong ownership on %s", name);
-}
+ }
else log_write(0, LOG_MAIN|LOG_PANIC, "Stat failed on %s: %s", name, strerror(errno));
#endif
}
+/* Bump the index for argv, checking for overflow,
+and return the argument. */
+
+static const uschar *
+next_argv(const uschar ** argv, int * pi, int argc, const uschar * where)
+{
+int i = *pi;
+if (++i >= argc) exim_fail("exim: bad item for: %s\n", where);
+return argv[*pi = i];
+}
+
+
/*************************************************
* Extract port from host address *
*************************************************/
static gstring *
show_db_version(gstring * g)
{
+g = string_cat(g, US"Hints DB:\n");
#ifdef DB_VERSION_STRING
DEBUG(D_any)
{
- g = string_fmt_append(g, "Library version: BDB: Compile: %s\n", DB_VERSION_STRING);
- g = string_fmt_append(g, " Runtime: %s\n",
+ g = string_fmt_append(g, " Library version: BDB: Compile: %s\n", DB_VERSION_STRING);
+ g = string_fmt_append(g, " Runtime: %s\n",
db_version(NULL, NULL, NULL));
}
else
- g = string_fmt_append(g, "Berkeley DB: %s\n", DB_VERSION_STRING);
+ g = string_fmt_append(g, " Berkeley DB: %s\n", DB_VERSION_STRING);
#elif defined(BTREEVERSION) && defined(HASHVERSION)
# ifdef USE_DB
- g = string_cat(g, US"Probably Berkeley DB version 1.8x (native mode)\n");
+ g = string_cat(g, US" Probably Berkeley DB version 1.8x (native mode)\n");
# else
- g = string_cat(g, US"Probably Berkeley DB version 1.8x (compatibility mode)\n");
+ g = string_cat(g, US" Probably Berkeley DB version 1.8x (compatibility mode)\n");
# endif
#elif defined(_DBM_RDONLY) || defined(dbm_dirfno)
-g = string_cat(g, US"Probably ndbm\n");
+g = string_cat(g, US" Probably ndbm\n");
+#elif defined(USE_SQLITE)
+g = string_cat(g, US" Using sqlite3\n");
#elif defined(USE_TDB)
-g = string_cat(g, US"Using tdb\n");
+g = string_cat(g, US" Using tdb\n");
#else
# ifdef USE_GDBM
- g = string_cat(g, US"Probably GDBM (native mode)\n");
+g = string_cat(g, US" Probably GDBM (native mode)\n");
# else
- g = string_cat(g, US"Probably GDBM (compatibility mode)\n");
+g = string_cat(g, US" Probably GDBM (compatibility mode)\n");
# endif
#endif
return g;
DEBUG(D_any) {} else g = show_db_version(g);
g = string_cat(g, US"Support for:");
+#ifdef WITH_CONTENT_SCAN
+ g = string_cat(g, US" Content_Scanning");
+#endif
#ifdef SUPPORT_CRYPTEQ
g = string_cat(g, US" crypteq");
#endif
+#ifdef EXPAND_DLFUNC
+ g = string_cat(g, US" Expand_dlfunc");
+#endif
#if HAVE_ICONV
g = string_cat(g, US" iconv()");
#endif
#if HAVE_IPV6
g = string_cat(g, US" IPv6");
#endif
-#ifdef HAVE_SETCLASSRESOURCES
- g = string_cat(g, US" use_setclassresources");
-#endif
#ifdef SUPPORT_PAM
g = string_cat(g, US" PAM");
#endif
#ifdef EXIM_PERL
g = string_cat(g, US" Perl");
#endif
-#ifdef EXPAND_DLFUNC
- g = string_cat(g, US" Expand_dlfunc");
-#endif
-#ifdef USE_TCP_WRAPPERS
- g = string_cat(g, US" TCPwrappers");
-#endif
#ifdef USE_GNUTLS
g = string_cat(g, US" GnuTLS");
#endif
+#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
+ g = string_cat(g, US" move_frozen_messages");
+#endif
#ifdef USE_OPENSSL
g = string_cat(g, US" OpenSSL");
#endif
+#if defined(CYRUS_PWCHECK_SOCKET)
+ g = string_cat(g, US" pwcheck");
+#endif
+#if defined(RADIUS_CONFIG_FILE)
+ g = string_cat(g, US" radius");
+#endif
#ifndef DISABLE_TLS_RESUME
g = string_cat(g, US" TLS_resume");
#endif
#ifdef SUPPORT_TRANSLATE_IP_ADDRESS
g = string_cat(g, US" translate_ip_address");
#endif
-#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
- g = string_cat(g, US" move_frozen_messages");
+#ifdef USE_TCP_WRAPPERS
+ g = string_cat(g, US" TCPwrappers");
#endif
-#ifdef WITH_CONTENT_SCAN
- g = string_cat(g, US" Content_Scanning");
+#ifdef HAVE_SETCLASSRESOURCES
+ g = string_cat(g, US" use_setclassresources");
#endif
#ifdef SUPPORT_DANE
g = string_cat(g, US" DANE");
#ifndef DISABLE_DNSSEC
g = string_cat(g, US" DNSSEC");
#endif
+#ifndef DISABLE_ESMTP_LIMITS
+ g = string_cat(g, US" ESMTP_Limits");
+#endif
+#ifndef DISABLE_WELLKNOWN
+ g = string_cat(g, US" ESMTP_Wellknown");
+#endif
#ifndef DISABLE_EVENT
g = string_cat(g, US" Event");
#endif
#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
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;
for (;;)
{
- uschar *nq = US Ustrpbrk(lpart, "\\\"");
- if (nq == NULL)
+ uschar * nq = US Ustrpbrk(lpart, "\\\"");
+ if (!nq)
{
g = string_cat(g, lpart);
break;
*/
static void
-exim_usage(uschar *progname)
+exim_usage(const uschar * progname)
{
/* Handle specific program invocation variants */
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);
*/
int
-main(int argc, char **cargv)
+main(int argc, char ** cargv)
{
-uschar **argv = USS cargv;
+const uschar ** argv = CUSS cargv;
int arg_receive_timeout = -1;
int arg_smtp_receive_timeout = -1;
int arg_error_handling = error_handling;
BOOL verify_as_sender = FALSE;
BOOL rcpt_verify_quota = FALSE;
BOOL version_printed = FALSE;
-uschar *alias_arg = NULL;
-uschar *called_as = US"";
-uschar *cmdline_syslog_name = NULL;
-uschar *start_queue_run_id = NULL;
-uschar *stop_queue_run_id = NULL;
-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;
-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;
for (i = 1; i < argc; i++)
{
BOOL badarg = FALSE;
- uschar * arg = argv[i];
- uschar * argrest;
+ const uschar * arg = argv[i];
+ const uschar * argrest;
uschar switchchar;
/* An argument not starting with '-' is the start of a recipients list;
/* -bh: Host checking - an IP address must follow. */
case 'h':
- if (!*argrest || Ustrcmp(argrest, "c") == 0)
+ if ( (!*argrest || Ustrcmp(argrest, "c") == 0)
+ && ++i < argc)
{
- if (++i >= argc) { badarg = TRUE; break; }
sender_host_address = string_copy_taint(
exim_str_fail_toolong(argv[i], EXIM_IPADDR_MAX, "-bh"),
GET_TAINTED);
f.host_checking_callout = *argrest == 'c';
message_logs = FALSE;
}
- else badarg = TRUE;
+ else
+ badarg = TRUE;
break;
/* -bi: This option is used by sendmail to initialize *the* alias file,
case 'I':
if (Ustrlen(argrest) >= 1 && *argrest == ':')
{
- uschar *p = argrest+1;
+ const uschar * p = argrest+1;
info_flag = CMDINFO_HELP;
if (Ustrlen(p))
if (strcmpic(p, CUS"sieve") == 0)
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;
#else
{
int ptr = 0;
- macro_item *m;
+ macro_item * m;
uschar name[24];
- uschar *s = argrest;
+ 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 "
}
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)
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
{
- uschar * temp = argrest + Ustrlen(argrest) - 1;
+ const uschar * temp = argrest + Ustrlen(argrest) - 1;
while (temp >= argrest && isspace(*temp)) temp--;
if (temp >= argrest && *temp == '.') f_end_dot = TRUE;
allow_domain_literals = TRUE;
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;
{
msg_action = MSG_SETQUEUE;
queue_name_dest = string_copy_taint(
- exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-MG"),
+ exim_str_fail_toolong(next_argv(argv, &i, argc, arg),
+ EXIM_DRIVERNAME_MAX, "-MG"),
GET_TAINTED);
}
else if (Ustrcmp(argrest, "mad") == 0) msg_action = MSG_MARK_ALL_DELIVERED;
/* -oB: Set a connection message max value for remote deliveries */
case 'B':
{
- uschar * p = argrest;
+ const uschar * p = argrest;
if (!*p)
if (i+1 < argc && isdigit((argv[i+1][0])))
p = argv[++i];
if (Ustrcmp(argrest, "a") == 0)
sender_host_address = string_copy_taint(
- exim_str_fail_toolong(argv[++i], EXIM_IPADDR_MAX, "-oMa"),
- GET_TAINTED);
+ exim_str_fail_toolong(next_argv(argv, &i, argc, arg),
+ EXIM_IPADDR_MAX, "-oMa"), GET_TAINTED);
/* -oMaa: Set authenticator name */
else if (Ustrcmp(argrest, "aa") == 0)
sender_host_authenticated = string_copy_taint(
- exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-oMaa"),
- GET_TAINTED);
+ exim_str_fail_toolong(next_argv(argv, &i, argc, arg),
+ EXIM_DRIVERNAME_MAX, "-oMaa"), GET_TAINTED);
/* -oMas: setting authenticated sender */
else if (Ustrcmp(argrest, "as") == 0)
authenticated_sender = string_copy_taint(
- exim_str_fail_toolong(argv[++i], EXIM_EMAILADDR_MAX, "-oMas"),
- GET_TAINTED);
+ exim_str_fail_toolong(next_argv(argv, &i, argc, arg),
+ EXIM_EMAILADDR_MAX, "-oMas"), GET_TAINTED);
/* -oMai: setting authenticated id */
else if (Ustrcmp(argrest, "ai") == 0)
authenticated_id = string_copy_taint(
- exim_str_fail_toolong(argv[++i], EXIM_EMAILADDR_MAX, "-oMai"),
- GET_TAINTED);
+ exim_str_fail_toolong(next_argv(argv, &i, argc, arg),
+ EXIM_EMAILADDR_MAX, "-oMai"), GET_TAINTED);
/* -oMi: Set incoming interface address */
else if (Ustrcmp(argrest, "i") == 0)
interface_address = string_copy_taint(
- exim_str_fail_toolong(argv[++i], EXIM_IPADDR_MAX, "-oMi"),
- GET_TAINTED);
+ exim_str_fail_toolong(next_argv(argv, &i, argc, arg),
+ EXIM_IPADDR_MAX, "-oMi"), GET_TAINTED);
/* -oMm: Message reference */
exim_fail("-oMm must be a valid message ID\n");
if (!f.trusted_config)
exim_fail("-oMm must be called by a trusted user/config\n");
- message_reference = argv[++i];
+ message_reference = next_argv(argv, &i, argc, arg);
}
/* -oMr: Received protocol */
if (received_protocol)
exim_fail("received_protocol is set already\n");
else
- received_protocol = string_copy_taint(
- exim_str_fail_toolong(argv[++i], EXIM_DRIVERNAME_MAX, "-oMr"),
- GET_TAINTED);
+ if (++i >= argc) badarg = TRUE;
+ else
+ received_protocol = string_copy_taint(
+ exim_str_fail_toolong(argv[i], EXIM_DRIVERNAME_MAX, "-oMr"),
+ GET_TAINTED);
/* -oMs: Set sender host name */
else if (Ustrcmp(argrest, "s") == 0)
- sender_host_name = string_copy_taint(
- exim_str_fail_toolong(argv[++i], EXIM_HOSTNAME_MAX, "-oMs"),
- GET_TAINTED);
+ if (++i >= argc) badarg = TRUE;
+ else
+ sender_host_name = string_copy_taint(
+ exim_str_fail_toolong(argv[i], EXIM_HOSTNAME_MAX, "-oMs"),
+ GET_TAINTED);
/* -oMt: Set sender ident */
else if (Ustrcmp(argrest, "t") == 0)
- {
- sender_ident_set = TRUE;
- sender_ident = string_copy_taint(
- exim_str_fail_toolong(argv[++i], EXIM_IDENTUSER_MAX, "-oMt"),
- GET_TAINTED);
- }
+ if (++i >= argc) badarg = TRUE;
+ else
+ {
+ sender_ident_set = TRUE;
+ sender_ident = string_copy_taint(
+ exim_str_fail_toolong(argv[i], EXIM_IDENTUSER_MAX, "-oMt"),
+ GET_TAINTED);
+ }
/* Else a bad argument */
exim_fail("exim: only uid=%d or uid=%d can use -oP and -oPX "
"(uid=%d euid=%d | %d)\n",
root_uid, exim_uid, getuid(), geteuid(), real_uid);
- if (!*argrest) override_pid_file_path = argv[++i];
+ if (!*argrest)
+ if (++i < argc) override_pid_file_path = argv[i];
+ else badarg = TRUE;
else if (Ustrcmp(argrest, "X") == 0) delete_pid_file();
else badarg = TRUE;
break;
/* Limits: Is there a real limit we want here? 1024 is very arbitrary. */
case 'X':
- if (*argrest) badarg = TRUE;
+ if (*argrest || ++i >= argc) badarg = TRUE;
else override_local_interfaces = string_copy_taint(
- exim_str_fail_toolong(argv[++i], 1024, "-oX"),
- GET_TAINTED);
+ exim_str_fail_toolong(argv[i], 1024, "-oX"), GET_TAINTED);
break;
/* -oY: Override creation of daemon notifier socket */
which sets the host protocol and host name */
if (!*argrest)
- if (i+1 < argc) argrest = argv[++i]; else { badarg = TRUE; break; }
+ argrest = next_argv(argv, &i, argc, arg);
if (*argrest)
{
else
{
- int intvl = readconf_readtime(*argrest ? argrest : argv[++i], 0, FALSE);
- if (intvl <= 0)
+ int intvl;
+ const uschar * s;
+
+ if (*argrest) s = argrest;
+ else if (++i < argc) { badarg = TRUE; break; }
+ else s = argv[i];
+
+ if ((intvl = readconf_readtime(s, 0, FALSE)) <= 0)
exim_fail("exim: bad time value %s: abandoned\n", argv[i]);
for (qrunner * qq = qrunners; qq; qq = qq->next)
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++)
tested. Otherwise variability of clock ticks etc. cause problems. */
case 'T':
- if (f.running_in_test_harness && Ustrcmp(argrest, "qt") == 0)
- fudged_queue_times = string_copy_taint(argv[++i], GET_TAINTED);
+ if (f.running_in_test_harness && Ustrcmp(argrest, "qt") == 0 && ++i < argc)
+ fudged_queue_times = string_copy_taint(argv[i], GET_TAINTED);
else badarg = TRUE;
break;
if (bi_command && *bi_command)
{
int i = 0;
- uschar *argv[3];
+ const uschar * argv[3];
argv[i++] = bi_command; /* nonexpanded option so assume untainted */
if (alias_arg) argv[i++] = alias_arg;
argv[i++] = NULL;
|| queue_name_dest && prod_requires_admin
|| debugset && !f.running_in_test_harness
)
- exim_fail("exim:%s permission denied\n", debugset ? " debugging" : "");
+ exim_fail("exim:%s permission denied; not admin\n",
+ debugset ? " debugging" : "");
}
/* If the real user is not root or the exim uid, the argument for passing
) )
&& !f.running_in_test_harness
)
- exim_fail("exim: Permission denied\n");
+ exim_fail("exim: Permission denied; not exim user or root\n");
/* 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).
if ((result = malware_in_file(malware_test_file)) == FAIL)
{
printf("No malware found.\n");
- exit(EXIT_SUCCESS);
+ exim_exit(EXIT_SUCCESS);
}
if (result != OK)
{
printf("Malware lookup returned non-okay/fail: %d\n", result);
- exit(EXIT_FAILURE);
+ exim_exit(EXIT_FAILURE);
}
if (malware_name)
printf("Malware found: %s\n", malware_name);
#else
printf("Malware scanning not enabled at compile time.\n");
#endif
- exit(EXIT_FAILURE);
+ exim_exit(EXIT_FAILURE);
}
/* Handle a request to list the delivery queue */
{
set_process_info("listing the queue");
queue_list(list_queue_option, argv + recipients_arg, argc - recipients_arg);
- exit(EXIT_SUCCESS);
+ exim_exit(EXIT_SUCCESS);
}
/* Handle a request to count the delivery queue */
{
set_process_info("counting the queue");
fprintf(stdout, "%u\n", queue_count());
- exit(EXIT_SUCCESS);
+ exim_exit(EXIT_SUCCESS);
}
/* Handle actions on specific messages, except for the force delivery and
else if (!queue_action(argv[msg_action_arg], msg_action, argv, argc,
recipients_arg)) yield = EXIT_FAILURE;
- exit(yield);
+ exim_exit(yield);
}
/* We used to set up here to skip reading the ACL section, on
exim_fail("exim: missing recipient for quota check\n");
else
{
- verify_quota(argv[recipients_arg]);
+ verify_quota(US argv[recipients_arg]); /*XXX we lose track of const here */
exim_exit(EXIT_SUCCESS);
}
/* 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;
if (!originator_login || f.running_in_test_harness)
{
+ GET_OPTION("unknown_login");
if (unknown_login)
{
originator_login = expand_string(unknown_login);
(void)gettimeofday(&t0, NULL);
# endif
if (!tls_dropprivs_validate_require_cipher(FALSE))
- exit(1);
+ exim_exit(EXIT_FAILURE);
# ifdef MEASURE_TIMING
report_time_since(&t0, US"validate_ciphers (delta)");
# endif
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)
(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);
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
}
/* In case the given address is a non-canonical IPv6 address, canonicalize
- it. The code works for both IPv4 and IPv6, as it happens. */
+ it. Use the compressed form for IPv6. */
size = host_aton(sender_host_address, x);
sender_host_address = store_get(48, GET_UNTAINTED); /* large enough for full IPv6 */
- (void)host_nmtoa(size, x, -1, sender_host_address, ':');
+ if (size == 1)
+ (void) host_nmtoa(size, x, -1, sender_host_address, ':');
+ else
+ (void) ipv6_nmtoa(x, sender_host_address);
/* Now set up for testing */
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)
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;
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 */
else
{
- int rcount = 0;
- int count = argc - recipients_arg;
- uschar **list = argv + 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 */
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");
return
moan_to_sender(ERRMESS_TOOMANYRECIP, NULL, NULL, stdin, TRUE)?
errors_sender_rc : EXIT_FAILURE;
+ }
#ifdef SUPPORT_I18N
{
}
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",
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)));
}
}
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);
/* End of exim.c */
+/* vi: aw ai sw=2
+*/