X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Ftransports%2Fsmtp.c;h=fd550efff32b7f073a4e8f162d88de7f1a56a69b;hb=9f01e50d7efc5c625614e4e055790ca4a92a52a8;hp=baf304405bbd44ed1044b2a4a2c20f988e325f7c;hpb=4e48d56c083d2f763a5978e1dbf515b12dc12f96;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index baf304405..fd550efff 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -8,6 +8,10 @@ #include "../exim.h" #include "smtp.h" +#if defined(SUPPORT_DANE) && defined(DISABLE_TLS) +# error TLS is required for DANE +#endif + /* Options specific to the smtp transport. This transport also supports LMTP over TCP/IP. The options must be in alphabetic order (note that "_" comes @@ -620,7 +624,7 @@ switch(*errno_value) return FALSE; case ERRNO_WRITEINCOMPLETE: /* failure to write a complete data block */ - *message = string_sprintf("failed to write a data block"); + *message = US"failed to write a data block"; return FALSE; #ifdef SUPPORT_I18N @@ -810,6 +814,10 @@ if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2', #ifdef EXPERIMENTAL_DSN_INFO sx->helo_response = string_copy(sx->buffer); #endif +#ifndef DISABLE_EVENT +(void) event_raise(sx->conn_args.tblock->event_action, + US"smtp:ehlo", sx->buffer); +#endif return TRUE; } @@ -1184,8 +1192,14 @@ while (count-- > 0) else if (errno != 0 || sx->buffer[0] == 0) { - string_format(big_buffer, big_buffer_size, "RCPT TO:<%s>", + gstring gs = { .size = big_buffer_size, .ptr = 0, .s = big_buffer }, * g = &gs; + + /* Use taint-unchecked routines for writing into big_buffer, trusting + that we'll never expand it. */ + + g = string_fmt_append_f(g, SVFMT_TAINT_NOCHK, "RCPT TO:<%s>", transport_rcpt_address(addr, sx->conn_args.tblock->rcpt_include_affixes)); + string_from_gstring(g); return -2; } @@ -1555,20 +1569,20 @@ Globals f.smtp_authenticated Return True on error, otherwise buffer has (possibly empty) terminated string */ -BOOL +static BOOL smtp_mail_auth_str(uschar *buffer, unsigned bufsize, address_item *addrlist, smtp_transport_options_block *ob) { -uschar *local_authenticated_sender = authenticated_sender; +uschar * local_authenticated_sender = authenticated_sender; #ifdef notdef debug_printf("smtp_mail_auth_str: as<%s> os<%s> SA<%s>\n", authenticated_sender, ob->authenticated_sender, f.smtp_authenticated?"Y":"N"); #endif -if (ob->authenticated_sender != NULL) +if (ob->authenticated_sender) { uschar *new = expand_string(ob->authenticated_sender); - if (new == NULL) + if (!new) { if (!f.expand_string_forcedfail) { @@ -1578,17 +1592,17 @@ if (ob->authenticated_sender != NULL) return TRUE; } } - else if (new[0] != 0) local_authenticated_sender = new; + else if (*new) local_authenticated_sender = new; } /* Add the authenticated sender address if present */ -if ((f.smtp_authenticated || ob->authenticated_sender_force) && - local_authenticated_sender != NULL) +if ( (f.smtp_authenticated || ob->authenticated_sender_force) + && local_authenticated_sender) { - string_format(buffer, bufsize, " AUTH=%s", + string_format_nt(buffer, bufsize, " AUTH=%s", auth_xtextencode(local_authenticated_sender, - Ustrlen(local_authenticated_sender))); + Ustrlen(local_authenticated_sender))); client_authenticated_sender = string_copy(local_authenticated_sender); } else @@ -1953,7 +1967,6 @@ smtp_transport_options_block * ob = sx->conn_args.tblock->options_block; BOOL pass_message = FALSE; uschar * message = NULL; int yield = OK; -int rc; #ifndef DISABLE_TLS uschar * tls_errstr; #endif @@ -2064,6 +2077,7 @@ if (!continue_hostname) if (sx->conn_args.host->dnssec == DS_YES) { + int rc; if( sx->dane_required || verify_check_given_host(CUSS &ob->hosts_try_dane, sx->conn_args.host) == OK ) @@ -3040,7 +3054,7 @@ if ( sx->peer_offered & OPTION_UTF8 && addrlist->prop.utf8_msg && !addrlist->prop.utf8_downcvt ) - Ustrcpy(p, " SMTPUTF8"), p += 9; + Ustrcpy(p, US" SMTPUTF8"), p += 9; #endif /* check if all addresses have DSN-lasthop flag; do not send RET and ENVID if so */ @@ -3061,9 +3075,9 @@ for (sx->dsn_all_lasthop = TRUE, addr = addrlist, address_count = 0; if (sx->peer_offered & OPTION_DSN && !sx->dsn_all_lasthop) { if (dsn_ret == dsn_ret_hdrs) - { Ustrcpy(p, " RET=HDRS"); p += 9; } + { Ustrcpy(p, US" RET=HDRS"); p += 9; } else if (dsn_ret == dsn_ret_full) - { Ustrcpy(p, " RET=FULL"); p += 9; } + { Ustrcpy(p, US" RET=FULL"); p += 9; } if (dsn_envid) { @@ -3100,7 +3114,7 @@ if (sx->peer_offered & OPTION_DSN && !(addr->dsn_flags & rf_dsnlasthop)) { BOOL first = TRUE; - Ustrcpy(p, " NOTIFY="); + Ustrcpy(p, US" NOTIFY="); while (*p) p++; for (int i = 0; i < nelem(rf_list); i++) if (addr->dsn_flags & rf_list[i]) { @@ -3307,6 +3321,8 @@ Arguments: bufsiz size of buffer pfd pipe filedescriptor array; [0] is comms to proxied process timeout per-read timeout, seconds + +Does not return. */ void @@ -3324,7 +3340,7 @@ if ((rc = fork())) _exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS); } -if (f.running_in_test_harness) millisleep(100); /* let parent debug out */ +testharness_pause_ms(100); /* let parent debug out */ set_process_info("proxying TLS connection for continued transport"); FD_ZERO(&rfds); FD_SET(tls_out.active.sock, &rfds); @@ -3398,7 +3414,7 @@ for (int fd_bits = 3; fd_bits; ) } done: - if (f.running_in_test_harness) millisleep(100); /* let logging complete */ + testharness_pause_ms(100); /* let logging complete */ exim_exit(0, US"TLS proxy"); } #endif @@ -3687,6 +3703,11 @@ else transport_count = 0; #ifndef DISABLE_DKIM + { +# ifdef MEASURE_TIMING + struct timeval t0; + gettimeofday(&t0, NULL); +# endif dkim_exim_sign_init(); # ifdef EXPERIMENTAL_ARC { @@ -3711,6 +3732,10 @@ else } } # endif +# ifdef MEASURE_TIMING + report_time_since(&t0, US"dkim_exim_sign_init (delta)"); +# endif + } sx.ok = dkim_transport_write_message(&tctx, &ob->dkim, CUSS &message); #else sx.ok = transport_write_message(&tctx, 0); @@ -4297,7 +4322,7 @@ propagate it from the initial int pid = fork(); if (pid == 0) /* child; fork again to disconnect totally */ { - if (f.running_in_test_harness) millisleep(100); /* let parent debug out */ + testharness_pause_ms(100); /* let parent debug out */ /* does not return */ smtp_proxy_tls(sx.cctx.tls_ctx, sx.buffer, sizeof(sx.buffer), pfd, ob->command_timeout); @@ -4378,7 +4403,8 @@ HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP(close)>>\n"); if (sx.send_quit) { shutdown(sx.cctx.sock, SHUT_WR); - millisleep(f.running_in_test_harness ? 200 : 20); + millisleep(20); + testharness_pause_ms(200); if (fcntl(sx.cctx.sock, F_SETFL, O_NONBLOCK) == 0) for (int i = 16; read(sx.cctx.sock, sx.inbuffer, sizeof(sx.inbuffer)) > 0 && i > 0;) i--; /* drain socket */ @@ -4596,6 +4622,17 @@ if (!hostlist || (ob->hosts_override && ob->hosts)) else if (ob->hosts_randomize) s = expanded_hosts = string_copy(s); + if (is_tainted(s)) + { + log_write(0, LOG_MAIN|LOG_PANIC, + "attempt to use tainted host list '%s' from '%s' in transport %s", + s, ob->hosts, tblock->name); + /* Avoid leaking info to an attacker */ + addrlist->message = US"internal configuration error"; + addrlist->transport_return = PANIC; + return FALSE; + } + host_build_hostlist(&hostlist, s, ob->hosts_randomize); /* Check that the expansion yielded something useful. */ @@ -5080,7 +5117,7 @@ retry_non_continued: if (expanded_hosts) { - thost = store_get(sizeof(host_item)); + thost = store_get(sizeof(host_item), FALSE); *thost = *host; thost->name = string_copy(host->name); thost->address = string_copy(host->address); @@ -5321,7 +5358,7 @@ retry_non_continued: ob->hosts_max_try_hardlimit); } - if (f.running_in_test_harness) millisleep(500); /* let server debug out */ + testharness_pause_ms(500); /* let server debug out */ } /* End of loop for trying multiple hosts. */ /* If we failed to find a matching host in the list, for an already-open