X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/48c7f9e2e3b50cd5548447de62c77c7ddfe21519..41c7c167f4d3552804bfaf7278d72fc448b851ff:/src/src/transports/smtp.c diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index f9e56c2e1..cf09010cb 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/transports/smtp.c,v 1.29 2006/11/06 15:50:12 ph10 Exp $ */ +/* $Cambridge: exim/src/src/transports/smtp.c,v 1.33 2007/01/30 15:10:59 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2006 */ +/* Copyright (c) University of Cambridge 1995 - 2007 */ /* See the file NOTICE for conditions of use and distribution. */ #include "../exim.h" @@ -63,6 +63,14 @@ optionlist smtp_transport_options[] = { (void *)offsetof(smtp_transport_options_block, final_timeout) }, { "gethostbyname", opt_bool, (void *)offsetof(smtp_transport_options_block, gethostbyname) }, + #ifdef SUPPORT_TLS + { "gnutls_require_kx", opt_stringptr, + (void *)offsetof(smtp_transport_options_block, gnutls_require_kx) }, + { "gnutls_require_mac", opt_stringptr, + (void *)offsetof(smtp_transport_options_block, gnutls_require_mac) }, + { "gnutls_require_protocols", opt_stringptr, + (void *)offsetof(smtp_transport_options_block, gnutls_require_proto) }, + #endif { "helo_data", opt_stringptr, (void *)offsetof(smtp_transport_options_block, helo_data) }, { "hosts", opt_stringptr, @@ -178,6 +186,9 @@ smtp_transport_options_block smtp_transport_option_defaults = { NULL, /* tls_crl */ NULL, /* tls_privatekey */ NULL, /* tls_require_ciphers */ + NULL, /* gnutls_require_kx */ + NULL, /* gnutls_require_mac */ + NULL, /* gnutls_require_proto */ NULL, /* tls_verify_certificates */ TRUE /* tls_tempfail_tryclear */ #endif @@ -837,7 +848,7 @@ smtp_outblock outblock; int max_rcpt = tblock->max_addresses; uschar *igquotstr = US""; uschar *local_authenticated_sender = authenticated_sender; -uschar *helo_data; +uschar *helo_data = NULL; uschar *message = NULL; uschar new_message_id[MESSAGE_ID_LENGTH + 1]; uschar *p; @@ -866,17 +877,6 @@ outblock.ptr = outbuffer; outblock.cmd_count = 0; outblock.authenticating = FALSE; -/* Expand the greeting message */ - -helo_data = expand_string(ob->helo_data); -if (helo_data == NULL) - { - uschar *message = string_sprintf("failed to expand helo_data: %s", - expand_string_message); - set_errno(addrlist, 0, message, DEFER, FALSE); - return ERROR; - } - /* If an authenticated_sender override has been specified for this transport instance, expand it. If the expansion is forced to fail, and there was already an authenticated_sender for this message, the original value will be used. @@ -916,6 +916,12 @@ if (continue_hostname == NULL) return DEFER; } + /* Expand the greeting message while waiting for the initial response. (Makes + sense if helo_data contains ${lookup dnsdb ...} stuff). The expansion is + delayed till here so that $sending_interface and $sending_port are set. */ + + helo_data = expand_string(ob->helo_data); + /* The first thing is to wait for an initial OK response. The dreaded "goto" is nevertheless a reasonably clean way of programming this kind of logic, where you want to escape on any error. */ @@ -923,6 +929,18 @@ if (continue_hostname == NULL) if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2', ob->command_timeout)) goto RESPONSE_FAILED; + /* Now check if the helo_data expansion went well, and sign off cleanly if it + didn't. */ + + if (helo_data == NULL) + { + uschar *message = string_sprintf("failed to expand helo_data: %s", + expand_string_message); + set_errno(addrlist, 0, message, DEFER, FALSE); + yield = DEFER; + goto SEND_QUIT; + } + /** Debugging without sending a message addrlist->transport_return = DEFER; goto SEND_QUIT; @@ -1053,13 +1071,18 @@ if (tls_offered && !suppress_tls && else { - int rc = tls_client_start(inblock.sock, host, addrlist, + int rc = tls_client_start(inblock.sock, + host, + addrlist, NULL, /* No DH param */ ob->tls_certificate, ob->tls_privatekey, ob->tls_verify_certificates, ob->tls_crl, ob->tls_require_ciphers, + ob->gnutls_require_mac, + ob->gnutls_require_kx, + ob->gnutls_require_proto, ob->command_timeout); /* TLS negotiation failed; give an error. From outside, this function may @@ -1087,10 +1110,27 @@ if (tls_offered && !suppress_tls && } } -/* If we started TLS, redo the EHLO/LHLO exchange over the secure channel. */ +/* If we started TLS, redo the EHLO/LHLO exchange over the secure channel. If +helo_data is null, we are dealing with a connection that was passed from +another process, and so we won't have expanded helo_data above. We have to +expand it here. $sending_ip_address and $sending_port are set up right at the +start of the Exim process (in exim.c). */ if (tls_active >= 0) { + if (helo_data == NULL) + { + helo_data = expand_string(ob->helo_data); + if (helo_data == NULL) + { + uschar *message = string_sprintf("failed to expand helo_data: %s", + expand_string_message); + set_errno(addrlist, 0, message, DEFER, FALSE); + yield = DEFER; + goto SEND_QUIT; + } + } + if (smtp_write_command(&outblock, FALSE, "%s %s\r\n", lmtp? "LHLO" : "EHLO", helo_data) < 0) goto SEND_FAILED; @@ -1674,7 +1714,7 @@ if (!ok) ok = TRUE; else /* Ensure the journal file is pushed out to disk. */ - if (fsync(journal_fd) < 0) + if (EXIMfsync(journal_fd) < 0) log_write(0, LOG_MAIN|LOG_PANIC, "failed to fsync journal: %s", strerror(errno)); }