*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
#ifdef USE_OPENSSL
g = string_cat(g, US" OpenSSL");
#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
#ifndef DISABLE_DKIM
g = string_cat(g, US" DKIM");
#endif
+#ifdef SUPPORT_DMARC
+ g = string_cat(g, US" DMARC");
+#endif
#ifndef DISABLE_DNSSEC
g = string_cat(g, US" DNSSEC");
#endif
#ifdef SUPPORT_PROXY
g = string_cat(g, US" PROXY");
#endif
+#ifndef DISABLE_QUEUE_RAMP
+ g = string_cat(g, US" Experimental_Queue_Ramp");
+#endif
#ifdef SUPPORT_SOCKS
g = string_cat(g, US" SOCKS");
#endif
#ifdef SUPPORT_SPF
g = string_cat(g, US" SPF");
#endif
-#ifdef SUPPORT_DMARC
- g = string_cat(g, US" DMARC");
+#if defined(SUPPORT_SRS)
+ g = string_cat(g, US" SRS");
#endif
#ifdef TCP_FASTOPEN
tcp_init();
#ifdef EXPERIMENTAL_DSN_INFO
g = string_cat(g, US" Experimental_DSN_info");
#endif
-#ifdef EXPERIMENTAL_LMDB
- g = string_cat(g, US" Experimental_LMDB");
-#endif
-#ifdef EXPERIMENTAL_QUEUE_RAMP
- g = string_cat(g, US" Experimental_Queue_Ramp");
-#endif
#ifdef EXPERIMENTAL_QUEUEFILE
g = string_cat(g, US" Experimental_QUEUEFILE");
#endif
-#if defined(EXPERIMENTAL_SRS) || defined(EXPERIMENTAL_SRS_NATIVE)
+#if defined(EXPERIMENTAL_SRS_ALT)
g = string_cat(g, US" Experimental_SRS");
#endif
-#ifdef EXPERIMENTAL_TLS_RESUME
- g = string_cat(g, US" Experimental_TLS_resume");
-#endif
g = string_cat(g, US"\n");
g = string_cat(g, US"Lookups (built-in):");
#if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
g = string_cat(g, US" ldap ldapdn ldapm");
#endif
-#ifdef EXPERIMENTAL_LMDB
+#ifdef LOOKUP_LMDB
g = string_cat(g, US" lmdb");
#endif
#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
BOOL usage_wanted = FALSE;
BOOL verify_address_mode = FALSE;
BOOL verify_as_sender = FALSE;
+BOOL rcpt_verify_quota = FALSE;
BOOL version_printed = FALSE;
uschar *alias_arg = NULL;
uschar *called_as = US"";
concept of *the* alias file, but since Sun's YP make script calls
sendmail this way, some support must be provided. */
case 'i':
- if (!*++argrest) bi_option = TRUE;
+ if (!*argrest) bi_option = TRUE;
else badarg = TRUE;
break;
else badarg = TRUE;
break;
+ /* -MCq: do a quota check on the given recipient for the given size
+ of message. Separate from -MC. */
+ case 'q': rcpt_verify_quota = TRUE;
+ if (++i < argc) message_size = Uatoi(argv[i]);
+ else badarg = TRUE;
+ break;
+
/* -MCS: set the smtp_use_size flag; this is useful only when it
precedes -MC (see above) */
if (usage_wanted) exim_usage(called_as);
/* Arguments have been processed. Check for incompatibilities. */
-if ((
- (smtp_input || extract_recipients || recipients_arg < argc) &&
- (f.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))
- ) ||
- (
- msg_action_arg > 0 &&
- (f.daemon_listen || queue_interval > 0 || list_options ||
- (checking && msg_action != MSG_LOAD) ||
- bi_option || test_retry_arg >= 0 || test_rewrite_arg >= 0)
- ) ||
- (
- (f.daemon_listen || queue_interval > 0) &&
- (sender_address != NULL || list_options || list_queue || checking ||
- bi_option)
- ) ||
- (
- f.daemon_listen && queue_interval == 0
- ) ||
- (
- f.inetd_wait_mode && queue_interval >= 0
- ) ||
- (
- list_options &&
- (checking || smtp_input || extract_recipients ||
- filter_test != FTEST_NONE || bi_option)
- ) ||
- (
- verify_address_mode &&
- (f.address_test_mode || smtp_input || extract_recipients ||
- filter_test != FTEST_NONE || bi_option)
- ) ||
- (
- f.address_test_mode && (smtp_input || extract_recipients ||
- filter_test != FTEST_NONE || bi_option)
- ) ||
- (
- smtp_input && (sender_address != NULL || filter_test != FTEST_NONE ||
- extract_recipients)
- ) ||
- (
- deliver_selectstring != NULL && queue_interval < 0
- ) ||
- (
- msg_action == MSG_LOAD &&
- (!expansion_test || expansion_test_message != NULL)
- )
+if ( ( (smtp_input || extract_recipients || recipients_arg < argc)
+ && ( f.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
+ ) )
+ || ( msg_action_arg > 0
+ && ( f.daemon_listen || queue_interval > 0 || list_options
+ || checking && msg_action != MSG_LOAD
+ || bi_option || test_retry_arg >= 0 || test_rewrite_arg >= 0
+ ) )
+ || ( (f.daemon_listen || queue_interval > 0)
+ && ( sender_address || list_options || list_queue || checking
+ || bi_option
+ ) )
+ || f.daemon_listen && queue_interval == 0
+ || f.inetd_wait_mode && queue_interval >= 0
+ || ( list_options
+ && ( checking || smtp_input || extract_recipients
+ || filter_test != FTEST_NONE || bi_option
+ ) )
+ || ( verify_address_mode
+ && ( f.address_test_mode || smtp_input || extract_recipients
+ || filter_test != FTEST_NONE || bi_option
+ ) )
+ || ( f.address_test_mode
+ && ( smtp_input || extract_recipients || filter_test != FTEST_NONE
+ || bi_option
+ ) )
+ || ( smtp_input
+ && (sender_address || filter_test != FTEST_NONE || extract_recipients)
+ )
+ || deliver_selectstring && queue_interval < 0
+ || msg_action == MSG_LOAD && (!expansion_test || expansion_test_message)
)
exim_fail("exim: incompatible command-line options or arguments\n");
if (bi_option)
{
(void)fclose(config_file);
- if (bi_command)
+ if (bi_command && *bi_command)
{
int i = 0;
uschar *argv[3];
setgroups(group_count, group_list);
exim_setugid(real_uid, real_gid, FALSE, US"running bi_command");
- DEBUG(D_exec) debug_printf("exec %.256s %.256s\n", argv[0],
- argv[1] ? argv[1] : US"");
+ DEBUG(D_exec) debug_printf("exec '%.256s' %s%.256s%s\n", argv[0],
+ argv[1] ? "'" : "", argv[1] ? argv[1] : US"", argv[1] ? "'" : "");
execv(CS argv[0], (char *const *)argv);
- exim_fail("exim: exec failed: %s\n", strerror(errno));
+ exim_fail("exim: exec '%s' failed: %s\n", argv[0], strerror(errno));
}
else
{
|| 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\n", debugset ? " debugging" : "");
}
/* If the real user is not root or the exim uid, the argument for passing
one that supplied an input message, or we are using a patched exim for
regression testing. */
-if (real_uid != root_uid && real_uid != exim_uid &&
- (continue_hostname != NULL ||
- (f.dont_deliver &&
- (queue_interval >= 0 || f.daemon_listen || msg_action_arg > 0)
- )) && !f.running_in_test_harness)
+if ( real_uid != root_uid && real_uid != exim_uid
+ && ( continue_hostname
+ || ( f.dont_deliver
+ && (queue_interval >= 0 || f.daemon_listen || msg_action_arg > 0)
+ ) )
+ && !f.running_in_test_harness
+ )
exim_fail("exim: Permission denied\n");
/* If the caller is not trusted, certain arguments are ignored when running for
else
{
- if (sender_host_address != NULL)
+ if (sender_host_address)
sender_host_port = check_port(sender_host_address);
- if (interface_address != NULL)
+ if (interface_address)
interface_port = check_port(interface_address);
}
situation (controlled by the TRUE below), in order to be as close as possible
to the state Exim usually runs in. */
-if (!unprivileged && /* originally had root AND */
- !removed_privilege && /* still got root AND */
- !f.daemon_listen && /* not starting the daemon */
- queue_interval <= 0 && /* (either kind of daemon) */
- ( /* AND EITHER */
- deliver_drop_privilege || /* requested unprivileged */
- ( /* OR */
- queue_interval < 0 && /* not running the queue */
- (msg_action_arg < 0 || /* and */
- msg_action != MSG_DELIVER) && /* not delivering and */
- (!checking || !f.address_test_mode) /* not address checking */
- ) ) )
+if ( !unprivileged /* originally had root AND */
+ && !removed_privilege /* still got root AND */
+ && !f.daemon_listen /* not starting the daemon */
+ && queue_interval <= 0 /* (either kind of daemon) */
+ && ( /* AND EITHER */
+ deliver_drop_privilege /* requested unprivileged */
+ || ( /* OR */
+ queue_interval < 0 /* not running the queue */
+ && ( msg_action_arg < 0 /* and */
+ || msg_action != MSG_DELIVER /* not delivering */
+ ) /* and */
+ && (!checking || !f.address_test_mode) /* not address checking */
+ && !rcpt_verify_quota /* and not quota checking */
+ ) ) )
exim_setugid(exim_uid, exim_gid, TRUE, US"privilege not needed");
/* When we are retaining a privileged uid, we still change to the exim gid. */
if (!(unprivileged || removed_privilege))
exim_fail("exim: changing group failed: %s\n", strerror(errno));
else
+ {
DEBUG(D_any) debug_printf("changing group to %ld failed: %s\n",
(long int)exim_gid, strerror(errno));
+ }
}
/* Handle a request to scan a file for malware */
#ifdef WITH_CONTENT_SCAN
int result;
set_process_info("scanning file for malware");
- result = malware_in_file(malware_test_file);
- if (result == FAIL)
+ if ((result = malware_in_file(malware_test_file)) == FAIL)
{
printf("No malware found.\n");
exit(EXIT_SUCCESS);
#endif
}
+/* Handle a request to check quota */
+if (rcpt_verify_quota)
+ if (real_uid != root_uid && real_uid != exim_uid)
+ exim_fail("exim: Permission denied\n");
+ else if (recipients_arg >= argc)
+ exim_fail("exim: missing recipient for quota check\n");
+ else
+ {
+ verify_quota(argv[recipients_arg]);
+ exim_exit(EXIT_SUCCESS);
+ }
+
/* Handle the -brt option. This is for checking out retry configurations.
The next three arguments are a domain name or a complete address, and
optionally two error numbers. All it does is to call the function that
sender, or if a sender other than <> is set, override with the originator's
login (which will get qualified below), except when checking things. */
- if (sender_address == NULL /* No sender_address set */
- || /* OR */
+ if ( !sender_address /* No sender_address set */
+ || /* OR */
(sender_address[0] != 0 && /* Non-empty sender address, AND */
!checking)) /* Not running tests, including filter tests */
{
}
if (recipients_arg < argc)
- {
while (recipients_arg < argc)
{
/* Supplied addresses are tainted since they come from a user */
while (*++s == ',' || isspace(*s)) ;
}
}
- }
else for (;;)
{
deliver_localpart_orig = NULL;
deliver_domain_orig = NULL;
callout_address = sending_ip_address = NULL;
+ deliver_localpart_data = deliver_domain_data =
+ recipient_data = sender_data = NULL;
sender_rate = sender_rate_limit = sender_rate_period = NULL;
}
smtp_log_no_mail();
if (filter_test != FTEST_NONE)
{
- deliver_domain = (ftest_domain != NULL)?
- ftest_domain : qualify_domain_recipient;
+ deliver_domain = ftest_domain ? ftest_domain : qualify_domain_recipient;
deliver_domain_orig = deliver_domain;
- deliver_localpart = (ftest_localpart != NULL)?
- ftest_localpart : originator_login;
+ deliver_localpart = ftest_localpart ? ftest_localpart : originator_login;
deliver_localpart_orig = deliver_localpart;
deliver_localpart_prefix = ftest_prefix;
deliver_localpart_suffix = ftest_suffix;
deliver_home = originator_home;
- if (return_path == NULL)
+ if (!return_path)
{
printf("Return-path copied from sender\n");
return_path = string_copy(sender_address);
receive_add_recipient(
string_sprintf("%s%s%s@%s",
- (ftest_prefix == NULL)? US"" : ftest_prefix,
+ ftest_prefix ? ftest_prefix : US"",
deliver_localpart,
- (ftest_suffix == NULL)? US"" : ftest_suffix,
+ ftest_suffix ? ftest_suffix : US"",
deliver_domain), -1);
printf("Recipient = %s\n", recipients_list[0].address);
- if (ftest_prefix != NULL) printf("Prefix = %s\n", ftest_prefix);
- if (ftest_suffix != NULL) printf("Suffix = %s\n", ftest_suffix);
+ if (ftest_prefix) printf("Prefix = %s\n", ftest_prefix);
+ if (ftest_suffix) printf("Suffix = %s\n", ftest_suffix);
if (chdir("/")) /* Get away from wherever the user is running this from */
{
available to the user filter. We need to copy the filter variables
explicitly. */
- if ((filter_test & FTEST_SYSTEM) != 0)
+ if (filter_test & FTEST_SYSTEM)
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_test & FTEST_USER)
if (!filter_runtest(filter_ufd, filter_test_ufile, FALSE, more))
exim_exit(EXIT_FAILURE);
will be TRUE. If it is not, check on the number of messages received in this
connection. */
- if (!session_local_queue_only &&
- smtp_accept_queue_per_connection > 0 &&
- receive_messagecount > smtp_accept_queue_per_connection)
+ if ( !session_local_queue_only
+ && smtp_accept_queue_per_connection > 0
+ && receive_messagecount > smtp_accept_queue_per_connection)
{
session_local_queue_only = TRUE;
queue_only_reason = 2;
ones. However, there are odd cases where this is not wanted, so this can be
changed by setting queue_only_load_latch false. */
- local_queue_only = session_local_queue_only;
- if (!local_queue_only && queue_only_load >= 0)
- {
- local_queue_only = (load_average = OS_GETLOADAVG()) > queue_only_load;
- if (local_queue_only)
+ if (!(local_queue_only = session_local_queue_only) && queue_only_load >= 0)
+ if ((local_queue_only = (load_average = OS_GETLOADAVG()) > queue_only_load))
{
queue_only_reason = 3;
if (queue_only_load_latch) session_local_queue_only = TRUE;
}
- }
/* If running as an MUA wrapper, all queueing options and freezing options
are ignored. */
#endif
callout_address = NULL;
sending_ip_address = NULL;
+ deliver_localpart_data = deliver_domain_data =
+ recipient_data = sender_data = NULL;
acl_var_m = NULL;
for(int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL;