X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/98913c8ea2be5188dd22ec652da1182017e8edb7..65e061b76867a9ea7aeeb535341b790b90ae6c21:/src/src/exim.c diff --git a/src/src/exim.c b/src/src/exim.c index fd08cc780..88e119778 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -2710,7 +2710,7 @@ for (i = 1; i < argc; i++) /* Set up $sending_ip_address and $sending_port, unless proxied */ - if (!continue_proxy) + if (!continue_proxy_cipher) if (getsockname(fileno(stdin), (struct sockaddr *)(&interface_sock), &size) == 0) sending_ip_address = host_ntoa(-1, &interface_sock, NULL, @@ -2774,13 +2774,15 @@ for (i = 1; i < argc; i++) #ifdef SUPPORT_TLS /* -MCt: similar to -MCT below but the connection is still open via a proxy proces which handles the TLS context and coding. - Require two arguments for the proxied local address and port. */ + Require three arguments for the proxied local address and port, + and the TLS cipher. */ - case 't': continue_proxy = TRUE; - if (++i < argc) sending_ip_address = argv[i]; + case 't': if (++i < argc) sending_ip_address = argv[i]; else badarg = TRUE; if (++i < argc) sending_port = (int)(Uatol(argv[i])); else badarg = TRUE; + if (++i < argc) continue_proxy_cipher = argv[i]; + else badarg = TRUE; /*FALLTHROUGH*/ /* -MCT: set the tls_offered flag; this is useful only when it @@ -3104,7 +3106,14 @@ for (i = 1; i < argc; i++) /* -oMr: Received protocol */ - else if (Ustrcmp(argrest, "Mr") == 0) received_protocol = argv[++i]; + else if (Ustrcmp(argrest, "Mr") == 0) + + if (received_protocol) + { + fprintf(stderr, "received_protocol is set already\n"); + exit(EXIT_FAILURE); + } + else received_protocol = argv[++i]; /* -oMs: Set sender host name */ @@ -3200,7 +3209,15 @@ for (i = 1; i < argc; i++) if (*argrest != 0) { - uschar *hn = Ustrchr(argrest, ':'); + uschar *hn; + + if (received_protocol) + { + fprintf(stderr, "received_protocol is set already\n"); + exit(EXIT_FAILURE); + } + + hn = Ustrchr(argrest, ':'); if (hn == NULL) { received_protocol = argrest; @@ -3809,6 +3826,10 @@ defined) */ readconf_main(checking || list_options); +if (builtin_macros_create_trigger) DEBUG(D_any) + debug_printf("Builtin macros created (expensive) due to config line '%.*s'\n", + Ustrlen(builtin_macros_create_trigger)-1, builtin_macros_create_trigger); + /* Now in directory "/" */ if (cleanup_environment() == FALSE) @@ -3828,17 +3849,13 @@ if (real_uid == root_uid || real_uid == exim_uid || real_gid == exim_gid) 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++) + for (i = 0; i < group_count && !admin_user; i++) + if (group_list[i] == exim_gid) + admin_user = TRUE; + else if (admin_groups) + for (j = 1; j <= (int)admin_groups[0] && !admin_user; j++) if (admin_groups[j] == group_list[i]) - { admin_user = TRUE; break; } - } - if (admin_user) break; - } + admin_user = TRUE; } /* Another group of privileged users are the trusted users. These are root, @@ -3852,29 +3869,28 @@ else { int i, j; - if (trusted_users != NULL) - { - for (i = 1; i <= (int)(trusted_users[0]); i++) + if (trusted_users) + for (i = 1; i <= (int)trusted_users[0] && !trusted_caller; i++) if (trusted_users[i] == real_uid) - { trusted_caller = TRUE; break; } - } + trusted_caller = TRUE; - if (!trusted_caller && trusted_groups != NULL) - { - for (i = 1; i <= (int)(trusted_groups[0]); i++) - { + if (trusted_groups) + for (i = 1; i <= (int)trusted_groups[0] && !trusted_caller; i++) if (trusted_groups[i] == real_gid) trusted_caller = TRUE; - else for (j = 0; j < group_count; j++) - { + else for (j = 0; j < group_count && !trusted_caller; j++) if (trusted_groups[i] == group_list[j]) - { trusted_caller = TRUE; break; } - } - if (trusted_caller) break; - } - } + trusted_caller = TRUE; } +/* At this point, we know if the user is privileged and some command-line +options become possibly imperssible, depending upon the configuration file. */ + +if (checking && commandline_checks_require_admin && !admin_user) { + fprintf(stderr, "exim: those command-line flags are set to require admin\n"); + exit(EXIT_FAILURE); +} + /* Handle the decoding of logging options. */ decode_bits(log_selector, log_selector_size, log_notall, @@ -4350,11 +4366,8 @@ if (!unprivileged && /* originally had root AND */ (msg_action_arg < 0 || /* and */ msg_action != MSG_DELIVER) && /* not delivering and */ (!checking || !address_test_mode) /* not address 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. */ @@ -4368,7 +4381,6 @@ else there's no security risk. For me, it's { exim -bV } on a just-built binary, no need to complain then. */ if (rv == -1) - { if (!(unprivileged || removed_privilege)) { fprintf(stderr, @@ -4378,7 +4390,6 @@ else 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 */ @@ -5327,15 +5338,13 @@ if (smtp_input) else { thismessage_size_limit = expand_string_integer(message_size_limit, TRUE); - if (expand_string_message != NULL) - { + if (expand_string_message) if (thismessage_size_limit == -1) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to expand " "message_size_limit: %s", expand_string_message); else log_write(0, LOG_MAIN|LOG_PANIC_DIE, "invalid value for " "message_size_limit: %s", expand_string_message); - } } /* Loop for several messages when reading SMTP input. If we fork any child @@ -5432,6 +5441,7 @@ while (more) more = receive_msg(extract_recipients); if (message_id[0] == 0) { + cancel_cutthrough_connection(TRUE, US"receive dropped"); if (more) goto moreloop; smtp_log_no_mail(); /* Log no mail if configured */ exim_exit(EXIT_FAILURE); @@ -5439,6 +5449,7 @@ while (more) } else { + cancel_cutthrough_connection(TRUE, US"message setup dropped"); smtp_log_no_mail(); /* Log no mail if configured */ exim_exit((rc == 0)? EXIT_SUCCESS : EXIT_FAILURE); } @@ -5714,21 +5725,28 @@ while (more) not if queue_only is set (case 0). Case 1 doesn't happen here (too many connections). */ - if (local_queue_only) switch(queue_only_reason) + if (local_queue_only) { - case 2: - log_write(L_delay_delivery, - LOG_MAIN, "no immediate delivery: more than %d messages " - "received in one connection", smtp_accept_queue_per_connection); - break; + cancel_cutthrough_connection(TRUE, US"no delivery; queueing"); + switch(queue_only_reason) + { + case 2: + log_write(L_delay_delivery, + LOG_MAIN, "no immediate delivery: more than %d messages " + "received in one connection", smtp_accept_queue_per_connection); + break; - case 3: - log_write(L_delay_delivery, - LOG_MAIN, "no immediate delivery: load average %.2f", - (double)load_average/1000.0); - break; + case 3: + log_write(L_delay_delivery, + LOG_MAIN, "no immediate delivery: load average %.2f", + (double)load_average/1000.0); + break; + } } + else if (queue_only_policy || deliver_freeze) + cancel_cutthrough_connection(TRUE, US"no delivery; queueing"); + /* Else do the delivery unless the ACL or local_scan() called for queue only or froze the message. Always deliver in a separate process. A fork failure is not a disaster, as the delivery will eventually happen on a subsequent queue @@ -5737,7 +5755,7 @@ while (more) thereby defer the delivery if it tries to use (for example) a cached ldap connection that the parent has called unbind on. */ - else if (!queue_only_policy && !deliver_freeze) + else { pid_t pid; search_tidyup(); @@ -5753,8 +5771,7 @@ while (more) if (geteuid() != root_uid && !deliver_drop_privilege && !unprivileged) { - (void)child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, - 2, US"-Mc", message_id); + delivery_re_exec(CEE_EXEC_EXIT); /* Control does not return here. */ } @@ -5768,22 +5785,27 @@ while (more) if (pid < 0) { + cancel_cutthrough_connection(TRUE, US"delivery fork failed"); log_write(0, LOG_MAIN|LOG_PANIC, "failed to fork automatic delivery " "process: %s", strerror(errno)); } + else + { + release_cutthrough_connection(US"msg passed for delivery"); - /* In the parent, wait if synchronous delivery is required. This will - always be the case in MUA wrapper mode. */ + /* In the parent, wait if synchronous delivery is required. This will + always be the case in MUA wrapper mode. */ - else if (synchronous_delivery) - { - int status; - while (wait(&status) != pid); - if ((status & 0x00ff) != 0) - log_write(0, LOG_MAIN|LOG_PANIC, - "process %d crashed with signal %d while delivering %s", - (int)pid, status & 0x00ff, message_id); - if (mua_wrapper && (status & 0xffff) != 0) exim_exit(EXIT_FAILURE); + if (synchronous_delivery) + { + int status; + while (wait(&status) != pid); + if ((status & 0x00ff) != 0) + log_write(0, LOG_MAIN|LOG_PANIC, + "process %d crashed with signal %d while delivering %s", + (int)pid, status & 0x00ff, message_id); + if (mua_wrapper && (status & 0xffff) != 0) exim_exit(EXIT_FAILURE); + } } }