X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Ftransport.c;h=b8a4636b60818fe2cc4220d5ff8de4ebb7ab2cec;hb=cf0812d57c63b531e2e73187508c7ae99156043c;hp=3987fad3e0b0319cf26f6f219569b504c33ff6fc;hpb=48f1c8532119577336c1aa1c91a50b57ebecdaf8;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/transport.c b/src/src/transport.c index 3987fad3e..b8a4636b6 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -108,10 +108,23 @@ optionlist optionlist_transports[] = { (void *)offsetof(transport_instance, uid) } }; -int optionlist_transports_size = - sizeof(optionlist_transports)/sizeof(optionlist); +int optionlist_transports_size = nelem(optionlist_transports); +void +readconf_options_transports(void) +{ +struct transport_info * ti; + +readconf_options_from_list(optionlist_transports, nelem(optionlist_transports), US"TRANSPORTS", NULL); + +for (ti = transports_available; ti->driver_name[0]; ti++) + { + macro_create(string_sprintf("_DRIVER_TRANSPORT_%T", ti->driver_name), US"y", FALSE, TRUE); + readconf_options_from_list(ti->options, (unsigned)*ti->options_count, US"TRANSPORT", ti->driver_name); + } +} + /************************************************* * Initialize transport list * *************************************************/ @@ -139,14 +152,11 @@ readconf_driver_init(US"transport", /* Now scan the configured transports and check inconsistencies. A shadow transport is permitted only for local transports. */ -for (t = transports; t != NULL; t = t->next) +for (t = transports; t; t = t->next) { - if (!t->info->local) - { - if (t->shadow != NULL) - log_write(0, LOG_PANIC_DIE|LOG_CONFIG, - "shadow transport not allowed on non-local transport %s", t->name); - } + if (!t->info->local && t->shadow) + log_write(0, LOG_PANIC_DIE|LOG_CONFIG, + "shadow transport not allowed on non-local transport %s", t->name); if (t->body_only && t->headers_only) log_write(0, LOG_PANIC_DIE|LOG_CONFIG, @@ -418,15 +428,22 @@ for (ptr = start; ptr < end; ptr++) if ((len = chunk_ptr - deliver_out_buffer) > mlen) { + DEBUG(D_transport) debug_printf("flushing headers buffer\n"); + /* If CHUNKING, prefix with BDAT (size) NON-LAST. Also, reap responses from previous SMTP commands. */ if (tctx && tctx->options & topt_use_bdat && tctx->chunk_cb) - if (tctx->chunk_cb(fd, tctx, (unsigned)len, tc_reap_prev|tc_reap_one) != OK) + { + if ( tctx->chunk_cb(fd, tctx, (unsigned)len, 0) != OK + || !transport_write_block(fd, deliver_out_buffer, len) + || tctx->chunk_cb(fd, tctx, 0, tc_reap_prev) != OK + ) + return FALSE; + } + else + if (!transport_write_block(fd, deliver_out_buffer, len)) return FALSE; - - if (!transport_write_block(fd, deliver_out_buffer, len)) - return FALSE; chunk_ptr = deliver_out_buffer; } @@ -607,7 +624,7 @@ return write_chunk(fd, tctx, pp->address, Ustrlen(pp->address)); -/* Add/remove/rewwrite headers, and send them plus the empty-line sparator. +/* Add/remove/rewrite headers, and send them plus the empty-line separator. Globals: header_list @@ -616,13 +633,8 @@ Arguments: addr (chain of) addresses (for extra headers), or NULL; only the first address is used fd file descriptor to write the message to + tctx transport context sendfn function for output (transport or verify) - wck_flags - use_crlf turn NL into CR LF - use_bdat callback before chunk flush - rewrite_rules chain of header rewriting rules - rewrite_existflags flags for the rewriting rules - chunk_cb transport callback function for data-chunk commands Returns: TRUE on success; FALSE on failure. */ @@ -826,12 +838,12 @@ Arguments: end_dot if TRUE, send a terminating "." line at the end no_headers if TRUE, omit the headers no_body if TRUE, omit the body - size_limit if > 0, this is a limit to the size of message written; + check_string a string to check for at the start of lines, or NULL + escape_string a string to insert in front of any check string + size_limit if > 0, this is a limit to the size of message written; it is used when returning messages to their senders, and is approximate rather than exact, owing to chunk buffering - check_string a string to check for at the start of lines, or NULL - escape_string a string to insert in front of any check string Returns: TRUE on success; FALSE (with errno) on failure. In addition, the global variable transport_count @@ -896,7 +908,7 @@ if (!(tctx->options & topt_no_headers)) /* Pick up from all the addresses. The plist and dlist variables are anchors for lists of addresses already handled; they have to be defined at - this level becuase write_env_to() calls itself recursively. */ + this level because write_env_to() calls itself recursively. */ for (p = tctx->addr; p; p = p->next) if (!write_env_to(p, &plist, &dlist, &first, fd, tctx)) @@ -927,11 +939,11 @@ if (!(tctx->options & topt_no_headers)) return FALSE; } -/* When doing RFC3030 CHUNKING output, work out how much data will be in the -last BDAT, consisting of the current write_chunk() output buffer fill +/* When doing RFC3030 CHUNKING output, work out how much data would be in a +last-BDAT, consisting of the current write_chunk() output buffer fill (optimally, all of the headers - but it does not matter if we already had to flush that buffer with non-last BDAT prependix) plus the amount of body data -(as expanded for CRLF lines). Then create and write the BDAT, and ensure +(as expanded for CRLF lines). Then create and write BDAT(s), and ensure that further use of write_chunk() will not prepend BDATs. The first BDAT written will also first flush any outstanding MAIL and RCPT commands which were buffered thans to PIPELINING. @@ -942,7 +954,7 @@ suboptimal. */ if (tctx->options & topt_use_bdat) { off_t fsize; - int hsize, size; + int hsize, size = 0; if ((hsize = chunk_ptr - deliver_out_buffer) < 0) hsize = 0; @@ -965,6 +977,8 @@ if (tctx->options & topt_use_bdat) if (size > DELIVER_OUT_BUFFER_SIZE && hsize > 0) { + DEBUG(D_transport) + debug_printf("sending small initial BDAT; hsize=%d\n", hsize); if ( tctx->chunk_cb(fd, tctx, hsize, 0) != OK || !transport_write_block(fd, deliver_out_buffer, hsize) || tctx->chunk_cb(fd, tctx, 0, tc_reap_prev) != OK @@ -1077,7 +1091,8 @@ if ((dkim_fd = Uopen(dkim_spool_name, O_RDWR|O_CREAT|O_TRUNC, SPOOL_MODE)) < 0) goto CLEANUP; } -/* Call original function to write the -K file; does the CRLF expansion */ +/* Call original function to write the -K file; does the CRLF expansion +(but, in the CHUNKING case, not dot-stuffing and dot-termination). */ options = tctx->options; tctx->options &= ~topt_use_bdat; @@ -1092,14 +1107,9 @@ if (!rc) } /* Rewind file and feed it to the goats^W DKIM lib */ +dkim->dot_stuffed = !!(options & topt_end_dot); lseek(dkim_fd, 0, SEEK_SET); -dkim_signature = dkim_exim_sign(dkim_fd, - dkim->dkim_private_key, - dkim->dkim_domain, - dkim->dkim_selector, - dkim->dkim_canon, - dkim->dkim_sign_headers); -if (dkim_signature) +if ((dkim_signature = dkim_exim_sign(dkim_fd, dkim))) siglen = Ustrlen(dkim_signature); else if (dkim->dkim_strict) { @@ -1175,17 +1185,17 @@ else /* Send file down the original fd */ while((sread = read(dkim_fd, deliver_out_buffer, DELIVER_OUT_BUFFER_SIZE)) >0) { - char *p = deliver_out_buffer; + uschar * p = deliver_out_buffer; /* write the chunk */ while (sread) { #ifdef SUPPORT_TLS wwritten = tls_out.active == out_fd - ? tls_write(FALSE, US p, sread) - : write(out_fd, p, sread); + ? tls_write(FALSE, p, sread) + : write(out_fd, CS p, sread); #else - wwritten = write(out_fd, p, sread); + wwritten = write(out_fd, CS p, sread); #endif if (wwritten == -1) goto err; @@ -1238,7 +1248,6 @@ Returns: TRUE on success; FALSE (with errno) for any failure BOOL transport_write_message(int fd, transport_ctx * tctx, int size_limit) { -unsigned wck_flags; BOOL last_filter_was_NL = TRUE; int rc, len, yield, fd_read, fd_write, save_errno; int pfd[2] = {-1, -1}; @@ -1262,7 +1271,6 @@ if ( !transport_filter_argv before being written to the incoming fd. First set up the special processing to be done during the copying. */ -wck_flags = tctx->options & topt_use_crlf; nl_partial_match = -1; if (tctx->check_string && tctx->escape_string) @@ -1286,10 +1294,13 @@ save_errno = 0; yield = FALSE; write_pid = (pid_t)(-1); -(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); -filter_pid = child_open(USS transport_filter_argv, NULL, 077, - &fd_write, &fd_read, FALSE); -(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) & ~FD_CLOEXEC); + { + int bits = fcntl(fd, F_GETFD); + (void)fcntl(fd, F_SETFD, bits | FD_CLOEXEC); + filter_pid = child_open(USS transport_filter_argv, NULL, 077, + &fd_write, &fd_read, FALSE); + (void)fcntl(fd, F_SETFD, bits & ~FD_CLOEXEC); + } if (filter_pid < 0) goto TIDY_UP; /* errno set */ DEBUG(D_transport) @@ -1428,14 +1439,19 @@ if (write_pid > 0) { rc = child_close(write_pid, 30); if (yield) - { if (rc == 0) { BOOL ok; - int dummy = read(pfd[pipe_read], (void *)&ok, sizeof(BOOL)); - if (!ok) + if (read(pfd[pipe_read], (void *)&ok, sizeof(BOOL)) != sizeof(BOOL)) + { + DEBUG(D_transport) + debug_printf("pipe read from writing process: %s\n", strerror(errno)); + save_errno = ERRNO_FILTER_FAIL; + yield = FALSE; + } + else if (!ok) { - dummy = read(pfd[pipe_read], (void *)&save_errno, sizeof(int)); + int dummy = read(pfd[pipe_read], (void *)&save_errno, sizeof(int)); dummy = read(pfd[pipe_read], (void *)&(tctx->addr->more_errno), sizeof(int)); yield = FALSE; } @@ -1447,7 +1463,6 @@ if (write_pid > 0) tctx->addr->more_errno = rc; DEBUG(D_transport) debug_printf("writing process returned %d\n", rc); } - } } (void)close(pfd[pipe_read]); @@ -1761,7 +1776,7 @@ while (1) /* create an array to read entire message queue into memory for processing */ - msgq = (msgq_t*) malloc(sizeof(msgq_t) * host_record->count); + msgq = store_malloc(sizeof(msgq_t) * host_record->count); msgq_count = host_record->count; msgq_actual = msgq_count; @@ -1869,7 +1884,7 @@ test but the code should work */ if (bFound) /* Usual exit from main loop */ { - free (msgq); + store_free (msgq); break; } @@ -1895,7 +1910,7 @@ test but the code should work */ return FALSE; } - free(msgq); + store_free(msgq); } /* we need to process a continuation record */ /* Control gets here when an existing message has been encountered; its @@ -1944,7 +1959,7 @@ DEBUG(D_transport) debug_printf("transport_pass_socket entered\n"); if ((pid = fork()) == 0) { - int i = 16; + int i = 17; const uschar **argv; /* Disconnect entirely from the parent process. If we are running in the @@ -1960,16 +1975,15 @@ if ((pid = fork()) == 0) argv = CUSS child_exec_exim(CEE_RETURN_ARGV, TRUE, &i, FALSE, 0); - if (smtp_use_dsn) argv[i++] = US"-MCD"; - if (smtp_authenticated) argv[i++] = US"-MCA"; - #ifdef SUPPORT_TLS - if (tls_offered) argv[i++] = US"-MCT"; - #endif - - if (smtp_use_size) argv[i++] = US"-MCS"; - if (smtp_use_pipelining) argv[i++] = US"-MCP"; + if (smtp_peer_options & PEER_OFFERED_CHUNKING) argv[i++] = US"-MCK"; + if (smtp_peer_options & PEER_OFFERED_DSN) argv[i++] = US"-MCD"; + if (smtp_peer_options & PEER_OFFERED_PIPE) argv[i++] = US"-MCP"; + if (smtp_peer_options & PEER_OFFERED_SIZE) argv[i++] = US"-MCS"; +#ifdef SUPPORT_TLS + if (smtp_peer_options & PEER_OFFERED_TLS) argv[i++] = US"-MCT"; +#endif if (queue_run_pid != (pid_t)0) { @@ -2258,7 +2272,7 @@ if (expand_arguments) */ if (address_pipe_argcount > 1) memmove( - /* current position + additonal args */ + /* current position + additional args */ argv + i + address_pipe_argcount, /* current position + 1 (for the (uschar *)0 at the end) */ argv + i + 1,