X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/2081aac24b67f3f3f34389aadc06354abcad0cad..4191cb150300d310ab5fa22ce2cfb02b6f6051b0:/src/src/transport.c diff --git a/src/src/transport.c b/src/src/transport.c index 39b8c411a..96a936503 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -3,7 +3,7 @@ *************************************************/ /* Copyright (c) University of Cambridge 1995 - 2018 */ -/* Copyright (c) The Exim Maintainers 2020 */ +/* Copyright (c) The Exim Maintainers 2020 - 2021 */ /* See the file NOTICE for conditions of use and distribution. */ /* General functions concerned with transportation, and generic options for all @@ -253,7 +253,6 @@ for (int i = 0; i < 100; i++) for(;;) { - fd_set fds; /* This code makes use of alarm() in order to implement the timeout. This isn't a very tidy way of doing things. Using non-blocking I/O with select() provides a neater approach. However, I don't know how to do this when TLS is @@ -281,8 +280,7 @@ for (int i = 0; i < 100; i++) if (rc >= 0 || errno != ENOTCONN || connretry <= 0) break; - FD_ZERO(&fds); FD_SET(fd, &fds); - select(fd+1, NULL, &fds, NULL, NULL); /* could set timout? */ + poll_one_fd(fd, POLLOUT, -1); /* could set timeout? retval check? */ connretry--; } @@ -653,7 +651,7 @@ so that we don't handle it again. */ for (ppp = *pdlist; ppp; ppp = ppp->next) if (p == ppp->ptr) return TRUE; -ppp = store_get(sizeof(struct aci), FALSE); +ppp = store_get(sizeof(struct aci), GET_UNTAINTED); ppp->next = *pdlist; *pdlist = ppp; ppp->ptr = p; @@ -677,7 +675,7 @@ if (ppp) return TRUE; /* Remember what we have output, and output it. */ -ppp = store_get(sizeof(struct aci), FALSE); +ppp = store_get(sizeof(struct aci), GET_UNTAINTED); ppp->next = *pplist; *pplist = ppp; ppp->ptr = pp; @@ -959,10 +957,10 @@ if (!(tctx->options & topt_no_headers)) if (tctx->options & topt_add_return_path) { - uschar buffer[ADDRESS_MAXLENGTH + 20]; - int n = sprintf(CS buffer, "Return-path: <%.*s>\n", ADDRESS_MAXLENGTH, - return_path); - if (!write_chunk(tctx, buffer, n)) goto bad; + int n; + uschar * s = string_sprintf("Return-path: <%.*s>\n%n", + EXIM_EMAILADDR_MAX, return_path, &n); + if (!write_chunk(tctx, s, n)) goto bad; } /* Add envelope-to: if requested */ @@ -1398,7 +1396,7 @@ if (write_pid > 0) yield = FALSE; } else if (!ok) - { + { /* Try to drain the pipe; read fails are don't care */ int dummy = read(pfd[pipe_read], (void *)&save_errno, sizeof(int)); dummy = read(pfd[pipe_read], (void *)&tctx->addr->more_errno, sizeof(int)); dummy = read(pfd[pipe_read], (void *)&tctx->addr->delivery_time, sizeof(struct timeval)); @@ -1523,7 +1521,7 @@ for (host_item * host = hostlist; host; host = host->next) if (!(host_record = dbfn_read(dbm_file, host->name))) { - host_record = store_get(sizeof(dbdata_wait) + MESSAGE_ID_LENGTH, FALSE); + host_record = store_get(sizeof(dbdata_wait) + MESSAGE_ID_LENGTH, GET_UNTAINTED); host_record->count = host_record->sequence = 0; } @@ -1587,7 +1585,7 @@ for (host_item * host = hostlist; host; host = host->next) else { dbdata_wait *newr = - store_get(sizeof(dbdata_wait) + host_length + MESSAGE_ID_LENGTH, FALSE); + store_get(sizeof(dbdata_wait) + host_length + MESSAGE_ID_LENGTH, GET_UNTAINTED); memcpy(newr, host_record, sizeof(dbdata_wait) + host_length); host_record = newr; } @@ -1721,7 +1719,7 @@ while (1) /* create an array to read entire message queue into memory for processing */ - msgq = store_get(sizeof(msgq_t) * host_record->count, FALSE); + msgq = store_get(sizeof(msgq_t) * host_record->count, GET_UNTAINTED); msgq_count = host_record->count; msgq_actual = msgq_count; @@ -1729,7 +1727,7 @@ while (1) { msgq[i].bKeep = TRUE; - Ustrncpy_nt(msgq[i].message_id, host_record->text + (i * MESSAGE_ID_LENGTH), + Ustrncpy_nt(msgq[i].message_id, host_record->text + (i * MESSAGE_ID_LENGTH), MESSAGE_ID_LENGTH); msgq[i].message_id[MESSAGE_ID_LENGTH] = 0; } @@ -1880,9 +1878,21 @@ void transport_do_pass_socket(const uschar *transport_name, const uschar *hostname, const uschar *hostaddress, uschar *id, int socket_fd) { -int i = 27; +int i = 13; const uschar **argv; +#ifndef DISABLE_TLS +if (smtp_peer_options & OPTION_TLS) i += 6; +#endif +#ifdef EXPERIMENTAL_ESMTP_LIMITS +if (continue_limit_mail || continue_limit_rcpt || continue_limit_rcptdom) + i += 4; +#endif +if (queue_run_pid != (pid_t)0) i += 3; +#ifdef SUPPORT_SOCKS +if (proxy_session) i += 5; +#endif + /* Set up the calling arguments; use the standard function for the basics, but we have a number of extras that may be added. */ @@ -1916,6 +1926,16 @@ if (smtp_peer_options & OPTION_TLS) argv[i++] = US"-MCT"; #endif +#ifdef EXPERIMENTAL_ESMTP_LIMITS +if (continue_limit_rcpt || continue_limit_rcptdom) + { + argv[i++] = US"-MCL"; + argv[i++] = string_sprintf("%u", continue_limit_mail); + argv[i++] = string_sprintf("%u", continue_limit_rcpt); + argv[i++] = string_sprintf("%u", continue_limit_rcptdom); + } +#endif + if (queue_run_pid != (pid_t)0) { argv[i++] = US"-MCQ"; @@ -1976,13 +1996,23 @@ Returns: FALSE if fork fails; TRUE otherwise BOOL transport_pass_socket(const uschar *transport_name, const uschar *hostname, - const uschar *hostaddress, uschar *id, int socket_fd) + const uschar *hostaddress, uschar *id, int socket_fd +#ifdef EXPERIMENTAL_ESMTP_LIMITS + , unsigned peer_limit_mail, unsigned peer_limit_rcpt, unsigned peer_limit_rcptdom +#endif + ) { pid_t pid; int status; DEBUG(D_transport) debug_printf("transport_pass_socket entered\n"); +#ifdef EXPERIMENTAL_ESMTP_LIMITS +continue_limit_mail = peer_limit_mail; +continue_limit_rcpt = peer_limit_rcpt; +continue_limit_rcptdom = peer_limit_rcptdom; +#endif + if ((pid = exim_fork(US"continued-transport-interproc")) == 0) { /* Disconnect entirely from the parent process. If we are running in the @@ -2061,7 +2091,7 @@ delivery batch option is set. */ for (address_item * ad = addr; ad; ad = ad->next) address_count++; max_args = address_count + 60; -*argvptr = argv = store_get((max_args+1)*sizeof(uschar *), FALSE); +*argvptr = argv = store_get((max_args+1)*sizeof(uschar *), GET_UNTAINTED); /* Split the command up into arguments terminated by white space. Lose trailing space at the start and end. Double-quoted arguments can contain \\ and @@ -2077,7 +2107,7 @@ for (; *s != 0 && argcount < max_args; argcount++) { ss = s + 1; while (*ss != 0 && *ss != '\'') ss++; - argv[argcount] = ss = store_get(ss - s++, is_tainted(cmd)); + argv[argcount] = ss = store_get(ss - s++, cmd); while (*s != 0 && *s != '\'') *ss++ = *s++; if (*s != 0) s++; *ss++ = 0; @@ -2177,7 +2207,6 @@ if (expand_arguments) int address_pipe_argcount = 0; int address_pipe_max_args; uschar **address_pipe_argv; - BOOL tainted; /* We can never have more then the argv we will be loading into */ address_pipe_max_args = max_args - argcount + 1; @@ -2186,13 +2215,12 @@ if (expand_arguments) debug_printf("address_pipe_max_args=%d\n", address_pipe_max_args); /* We allocate an additional for (uschar *)0 */ - address_pipe_argv = store_get((address_pipe_max_args+1)*sizeof(uschar *), FALSE); + address_pipe_argv = store_get((address_pipe_max_args+1)*sizeof(uschar *), GET_UNTAINTED); /* +1 because addr->local_part[0] == '|' since af_force_command is set */ s = expand_string(addr->local_part + 1); - tainted = is_tainted(s); - if (s == NULL || *s == '\0') + if (!s || *s == '\0') { addr->transport_return = FAIL; addr->message = string_sprintf("Expansion of \"%s\" " @@ -2203,15 +2231,16 @@ if (expand_arguments) while (isspace(*s)) s++; /* strip leading space */ - while (*s != 0 && address_pipe_argcount < address_pipe_max_args) + while (*s && address_pipe_argcount < address_pipe_max_args) { if (*s == '\'') { - ss = s + 1; - while (*ss != 0 && *ss != '\'') ss++; - address_pipe_argv[address_pipe_argcount++] = ss = store_get(ss - s++, tainted); - while (*s != 0 && *s != '\'') *ss++ = *s++; - if (*s != 0) s++; + int n; + for (ss = s + 1; *ss && *ss != '\''; ) ss++; + n = ss - s++; + address_pipe_argv[address_pipe_argcount++] = ss = store_get(n, s); + while (*s && *s != '\'') *ss++ = *s++; + if (*s) s++; *ss++ = 0; } else address_pipe_argv[address_pipe_argcount++] = @@ -2247,12 +2276,12 @@ if (expand_arguments) } /* If we are not just able to replace the slot that contained - * $address_pipe (address_pipe_argcount == 1) - * We have to move the existing argv by address_pipe_argcount - 1 - * Visually if address_pipe_argcount == 2: - * [argv 0][argv 1][argv 2($address_pipe)][argv 3][0] - * [argv 0][argv 1][ap_arg0][ap_arg1][old argv 3][0] - */ + $address_pipe (address_pipe_argcount == 1) + We have to move the existing argv by address_pipe_argcount - 1 + Visually if address_pipe_argcount == 2: + [argv 0][argv 1][argv 2($address_pipe)][argv 3][0] + [argv 0][argv 1][ap_arg0][ap_arg1][old argv 3][0] */ + if (address_pipe_argcount > 1) memmove( /* current position + additional args */ @@ -2264,15 +2293,12 @@ if (expand_arguments) ); /* Now we fill in the slots we just moved argv out of - * [argv 0][argv 1][argv 2=pipeargv[0]][argv 3=pipeargv[1]][old argv 3][0] - */ + [argv 0][argv 1][argv 2=pipeargv[0]][argv 3=pipeargv[1]][old argv 3][0] */ + for (int address_pipe_i = 0; address_pipe_argv[address_pipe_i] != US 0; - address_pipe_i++) - { + address_pipe_i++, argcount++) argv[i++] = address_pipe_argv[address_pipe_i]; - argcount++; - } /* Subtract one since we replace $address_pipe */ argcount--; @@ -2316,6 +2342,19 @@ if (expand_arguments) return TRUE; } + + +/* For error messages, a string describing the config location associated +with current processing. NULL if we are not in a transport. */ +/* Name only, for now */ + +uschar * +transport_current_name(void) +{ +if (!transport_name) return NULL; +return string_sprintf(" (transport %s, %s %d)", transport_name, driver_srcfile, driver_srcline); +} + #endif /*!MACRO_PREDEF*/ /* vi: aw ai sw=2 */