X-Git-Url: https://git.exim.org/users/jgh/exim.git/blobdiff_plain/98a90c36edb0fbe03e6db6bf4ad4fff0892f18bb..35e4802b4bdf92823c4813e61d9e6ddf5162f8ca:/src/src/exim.c diff --git a/src/src/exim.c b/src/src/exim.c index ff6b4dd86..1e4d6d646 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -57,7 +57,7 @@ store_free(block); *************************************************/ enum commandline_info { CMDINFO_NONE=0, - CMDINFO_HELP, CMDINFO_SIEVE }; + CMDINFO_HELP, CMDINFO_SIEVE, CMDINFO_DSCP }; @@ -222,7 +222,7 @@ to disrupt whatever is going on outside the signal handler. */ if (fd < 0) return; -(void)write(fd, process_info, process_info_len); +{int dummy = write(fd, process_info, process_info_len); dummy = dummy; } (void)close(fd); } @@ -526,7 +526,7 @@ close_unwanted(void) if (smtp_input) { #ifdef SUPPORT_TLS - tls_close(FALSE); /* Shut down the TLS library */ + tls_close(FALSE, FALSE); /* Shut down the TLS library */ #endif (void)close(fileno(smtp_in)); (void)close(fileno(smtp_out)); @@ -816,6 +816,18 @@ fprintf(f, "Support for:"); #ifdef EXPERIMENTAL_DCC fprintf(f, " Experimental_DCC"); #endif +#ifdef EXPERIMENTAL_DMARC + fprintf(f, " Experimental_DMARC"); +#endif +#ifdef EXPERIMENTAL_OCSP + fprintf(f, " Experimental_OCSP"); +#endif +#ifdef EXPERIMENTAL_PRDR + fprintf(f, " Experimental_PRDR"); +#endif +#ifdef EXPERIMENTAL_DBL + fprintf(f, " EXPERIMENTAL_DBL"); +#endif fprintf(f, "\n"); fprintf(f, "Lookups (built-in):"); @@ -1044,6 +1056,7 @@ switch(request) "If the string is not recognised, you'll get this help (on stderr).\n" "\n" " exim -bI:help this information\n" +" exim -bI:dscp dscp value keywords known\n" " exim -bI:sieve list of supported sieve extensions, one per line.\n" ); return; @@ -1051,7 +1064,9 @@ switch(request) for (pp = exim_sieve_extension_list; *pp; ++pp) fprintf(stream, "%s\n", *pp); return; - + case CMDINFO_DSCP: + dscp_list_to_stream(stream); + return; } } @@ -1431,6 +1446,8 @@ BOOL checking = FALSE; BOOL count_queue = FALSE; BOOL expansion_test = FALSE; BOOL extract_recipients = FALSE; +BOOL flag_G = FALSE; +BOOL flag_n = FALSE; BOOL forced_delivery = FALSE; BOOL f_end_dot = FALSE; BOOL deliver_give_up = FALSE; @@ -1451,6 +1468,7 @@ BOOL verify_as_sender = 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; @@ -1461,6 +1479,7 @@ uschar *ftest_suffix = NULL; uschar *malware_test_file = NULL; uschar *real_sender_address; uschar *originator_home = US"/"; +size_t sz; void *reset_point; struct passwd *pw; @@ -1871,6 +1890,26 @@ for (i = 1; i < argc; i++) switch(switchchar) { + + /* sendmail uses -Ac and -Am to control which .cf file is used; + we ignore them. */ + case 'A': + if (*argrest == '\0') { badarg = TRUE; break; } + else + { + BOOL ignore = FALSE; + switch (*argrest) + { + case 'c': + case 'm': + if (*(argrest + 1) == '\0') + ignore = TRUE; + break; + } + if (!ignore) { badarg = TRUE; break; } + } + break; + /* -Btype is a sendmail option for 7bit/8bit setting. Exim is 8-bit clean so has no need of it. */ @@ -1986,6 +2025,11 @@ for (i = 1; i < argc; i++) info_flag = CMDINFO_SIEVE; info_stdout = TRUE; } + else if (strcmpic(p, CUS"dscp") == 0) + { + info_flag = CMDINFO_DSCP; + info_stdout = TRUE; + } else if (strcmpic(p, CUS"help") == 0) { info_stdout = TRUE; @@ -2475,9 +2519,13 @@ for (i = 1; i < argc; i++) } break; - /* This is some Sendmail thing which can be ignored */ + /* -G: sendmail invocation to specify that it's a gateway submission and + sendmail may complain about problems instead of fixing them. + We make it equivalent to an ACL "control = suppress_local_fixups" and do + not at this time complain about problems. */ case 'G': + flag_G = TRUE; break; /* -h: Set the hop count for an incoming message. Exim does not currently @@ -2502,6 +2550,29 @@ for (i = 1; i < argc; i++) break; + /* -L: set the identifier used for syslog; equivalent to setting + syslog_processname in the config file, but needs to be an admin option. */ + + case 'L': + if (*argrest == '\0') + { + if(++i < argc) argrest = argv[i]; else + { badarg = TRUE; break; } + } + sz = Ustrlen(argrest); + if (sz > 32) + { + fprintf(stderr, "exim: the -L syslog name is too long: \"%s\"\n", argrest); + return EXIT_FAILURE; + } + if (sz < 1) + { + fprintf(stderr, "exim: the -L syslog name is too short\n"); + return EXIT_FAILURE; + } + cmdline_syslog_name = argrest; + break; + case 'M': receiving_message = FALSE; @@ -2764,10 +2835,12 @@ for (i = 1; i < argc; i++) break; - /* -n: This means "don't alias" in sendmail, apparently. Just ignore - it. */ + /* -n: This means "don't alias" in sendmail, apparently. + For normal invocations, it has no effect. + It may affect some other options. */ case 'n': + flag_n = TRUE; break; /* -O: Just ignore it. In sendmail, apparently -O option=value means set @@ -3215,7 +3288,7 @@ for (i = 1; i < argc; i++) /* -tls-on-connect: don't wait for STARTTLS (for old clients) */ #ifdef SUPPORT_TLS - else if (Ustrcmp(argrest, "ls-on-connect") == 0) tls_on_connect = TRUE; + else if (Ustrcmp(argrest, "ls-on-connect") == 0) tls_in.on_connect = TRUE; #endif else badarg = TRUE; @@ -3256,6 +3329,20 @@ for (i = 1; i < argc; i++) if (*argrest != 0) badarg = TRUE; break; + /* -X: in sendmail: takes one parameter, logfile, and sends debugging + logs to that file. We swallow the parameter and otherwise ignore it. */ + + case 'X': + if (*argrest == '\0') + { + if (++i >= argc) + { + fprintf(stderr, "exim: string expected after -X\n"); + exit(EXIT_FAILURE); + } + } + break; + /* All other initial characters are errors */ default: @@ -3560,6 +3647,66 @@ configuration data for delivery can be read if needed. */ readconf_main(); +/* If an action on specific messages is requested, or if a daemon or queue +runner is being started, we need to know if Exim was called by an admin user. +This is the case if the real user is root or exim, or if the real group is +exim, or if one of the supplementary groups is exim or a group listed in +admin_groups. We don't fail all message actions immediately if not admin_user, +since some actions can be performed by non-admin users. Instead, set admin_user +for later interrogation. */ + +if (real_uid == root_uid || real_uid == exim_uid || real_gid == exim_gid) + admin_user = TRUE; +else + { + int i, j; + for (i = 0; i < group_count; i++) + { + if (group_list[i] == exim_gid) admin_user = TRUE; + else if (admin_groups != NULL) + { + for (j = 1; j <= (int)(admin_groups[0]); j++) + if (admin_groups[j] == group_list[i]) + { admin_user = TRUE; break; } + } + if (admin_user) break; + } + } + +/* Another group of privileged users are the trusted users. These are root, +exim, and any caller matching trusted_users or trusted_groups. Trusted callers +are permitted to specify sender_addresses with -f on the command line, and +other message parameters as well. */ + +if (real_uid == root_uid || real_uid == exim_uid) + trusted_caller = TRUE; +else + { + int i, j; + + if (trusted_users != NULL) + { + for (i = 1; i <= (int)(trusted_users[0]); i++) + if (trusted_users[i] == real_uid) + { trusted_caller = TRUE; break; } + } + + if (!trusted_caller && trusted_groups != NULL) + { + for (i = 1; i <= (int)(trusted_groups[0]); i++) + { + if (trusted_groups[i] == real_gid) + trusted_caller = TRUE; + else for (j = 0; j < group_count; j++) + { + if (trusted_groups[i] == group_list[j]) + { trusted_caller = TRUE; break; } + } + if (trusted_caller) break; + } + } + } + /* Handle the decoding of logging options. */ decode_bits(&log_write_selector, &log_extra_selector, 0, 0, @@ -3591,6 +3738,24 @@ if (sender_address != NULL) } } +/* See if an admin user overrode our logging. */ + +if (cmdline_syslog_name != NULL) + { + if (admin_user) + { + syslog_processname = cmdline_syslog_name; + log_file_path = string_copy(CUS"syslog"); + } + else + { + /* not a panic, non-privileged users should not be able to spam paniclog */ + fprintf(stderr, + "exim: you lack sufficient privilege to specify syslog process name\n"); + return EXIT_FAILURE; + } + } + /* Paranoia check of maximum lengths of certain strings. There is a check on the length of the log file path in log.c, which will come into effect if there are any calls to write the log earlier than this. However, if we @@ -3752,8 +3917,9 @@ if (((debug_selector & D_any) != 0 || (log_extra_selector & LX_arguments) != 0) { int i; uschar *p = big_buffer; - Ustrcpy(p, "cwd="); - (void)getcwd(CS p+4, big_buffer_size - 4); + char * dummy; + Ustrcpy(p, "cwd= (failed)"); + dummy = /* quieten compiler */ getcwd(CS p+4, big_buffer_size - 4); while (*p) p++; (void)string_format(p, big_buffer_size - (p - big_buffer), " %d args:", argc); while (*p) p++; @@ -3796,8 +3962,9 @@ privilege by now. Before the chdir, we try to ensure that the directory exists. if (Uchdir(spool_directory) != 0) { + int dummy; (void)directory_make(spool_directory, US"", SPOOL_DIRECTORY_MODE, FALSE); - (void)Uchdir(spool_directory); + dummy = /* quieten compiler */ Uchdir(spool_directory); } /* Handle calls with the -bi option. This is a sendmail option to rebuild *the* @@ -3834,65 +4001,9 @@ if (bi_option) } } -/* If an action on specific messages is requested, or if a daemon or queue -runner is being started, we need to know if Exim was called by an admin user. -This is the case if the real user is root or exim, or if the real group is -exim, or if one of the supplementary groups is exim or a group listed in -admin_groups. We don't fail all message actions immediately if not admin_user, -since some actions can be performed by non-admin users. Instead, set admin_user -for later interrogation. */ - -if (real_uid == root_uid || real_uid == exim_uid || real_gid == exim_gid) - admin_user = TRUE; -else - { - int i, j; - for (i = 0; i < group_count; i++) - { - if (group_list[i] == exim_gid) admin_user = TRUE; - else if (admin_groups != NULL) - { - for (j = 1; j <= (int)(admin_groups[0]); j++) - if (admin_groups[j] == group_list[i]) - { admin_user = TRUE; break; } - } - if (admin_user) break; - } - } - -/* Another group of privileged users are the trusted users. These are root, -exim, and any caller matching trusted_users or trusted_groups. Trusted callers -are permitted to specify sender_addresses with -f on the command line, and -other message parameters as well. */ - -if (real_uid == root_uid || real_uid == exim_uid) - trusted_caller = TRUE; -else - { - int i, j; - - if (trusted_users != NULL) - { - for (i = 1; i <= (int)(trusted_users[0]); i++) - if (trusted_users[i] == real_uid) - { trusted_caller = TRUE; break; } - } - - if (!trusted_caller && trusted_groups != NULL) - { - for (i = 1; i <= (int)(trusted_groups[0]); i++) - { - if (trusted_groups[i] == real_gid) - trusted_caller = TRUE; - else for (j = 0; j < group_count; j++) - { - if (trusted_groups[i] == group_list[j]) - { trusted_caller = TRUE; break; } - } - if (trusted_caller) break; - } - } - } +/* We moved the admin/trusted check to be immediately after reading the +configuration file. We leave these prints here to ensure that syslog setup, +logfile setup, and so on has already happened. */ if (trusted_caller) DEBUG(D_any) debug_printf("trusted user\n"); if (admin_user) DEBUG(D_any) debug_printf("admin user\n"); @@ -3960,6 +4071,21 @@ else interface_port = check_port(interface_address); } +/* If the caller is trusted, then they can use -G to suppress_local_fixups. */ +if (flag_G) + { + if (trusted_caller) + { + suppress_local_fixups = suppress_local_fixups_default = TRUE; + DEBUG(D_acl) debug_printf("suppress_local_fixups forced on by -G\n"); + } + else + { + fprintf(stderr, "exim: permission denied (-G requires a trusted user)\n"); + return EXIT_FAILURE; + } + } + /* If an SMTP message is being received check to see if the standard input is a TCP/IP socket. If it is, we assume that Exim was called from inetd if the caller is root or the Exim user, or if the port is a privileged one. Otherwise, @@ -3981,7 +4107,7 @@ if (smtp_input) interface_address = host_ntoa(-1, &interface_sock, NULL, &interface_port); - if (host_is_tls_on_connect_port(interface_port)) tls_on_connect = TRUE; + if (host_is_tls_on_connect_port(interface_port)) tls_in.on_connect = TRUE; if (real_uid == root_uid || real_uid == exim_uid || interface_port < 1024) { @@ -4288,11 +4414,12 @@ if (test_retry_arg >= 0) } /* Handle a request to list one or more configuration options */ +/* If -n was set, we suppress some information */ if (list_options) { set_process_info("listing variables"); - if (recipients_arg >= argc) readconf_print(US"all", NULL); + if (recipients_arg >= argc) readconf_print(US"all", NULL, flag_n); else for (i = recipients_arg; i < argc; i++) { if (i < argc - 1 && @@ -4301,10 +4428,10 @@ if (list_options) Ustrcmp(argv[i], "authenticator") == 0 || Ustrcmp(argv[i], "macro") == 0)) { - readconf_print(argv[i+1], argv[i]); + readconf_print(argv[i+1], argv[i], flag_n); i++; } - else readconf_print(argv[i], NULL); + else readconf_print(argv[i], NULL, flag_n); } exim_exit(EXIT_SUCCESS); } @@ -5285,7 +5412,11 @@ while (more) if (ftest_prefix != NULL) printf("Prefix = %s\n", ftest_prefix); if (ftest_suffix != NULL) printf("Suffix = %s\n", ftest_suffix); - (void)chdir("/"); /* Get away from wherever the user is running this from */ + if (chdir("/")) /* Get away from wherever the user is running this from */ + { + DEBUG(D_receive) debug_printf("chdir(\"/\") failed\n"); + exim_exit(EXIT_FAILURE); + } /* 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