94
99
/* Application-specific. */
97
#include "smtp_addr.h"
102
#include <smtp_addr.h>
103
#include <smtp_reuse.h>
105
#define STR(x) vstring_str(x)
107
/* smtp_salvage - salvage the server reply before disconnecting */
109
static VSTRING *smtp_salvage(VSTREAM *stream)
111
int len = vstream_peek(stream);
112
VSTRING *buf = vstring_alloc(len);
115
* We know the server replied with 4... or 5...; salvage whatever we have
116
* received in the VSTREAM buffer and sanitize any non-printable crud.
118
vstream_fread(stream, STR(buf), len);
119
VSTRING_AT_OFFSET(buf, len); /* XXX not public interface */
120
VSTRING_TERMINATE(buf);
121
translit(STR(buf), "\r\n", " ");
122
printable(STR(buf), '?');
99
126
/* smtp_connect_addr - connect to explicit address */
101
static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
128
static SMTP_SESSION *smtp_connect_addr(const char *dest, DNS_RR *addr,
129
unsigned port, VSTRING *why,
104
132
char *myname = "smtp_connect_addr";
105
struct sockaddr_in sin;
133
struct sockaddr_storage ss; /* remote */
134
struct sockaddr *sa = (struct sockaddr *) & ss;
135
SOCKADDR_SIZE salen = sizeof(ss);
136
MAI_HOSTADDR_STR hostaddr;
107
INET_ADDR_LIST *addr_list;
112
unsigned long inaddr;
114
145
smtp_errno = SMTP_ERR_NONE; /* Paranoia */
119
if (addr->data_len > sizeof(sin.sin_addr)) {
120
msg_warn("%s: skip address with length %d", myname, addr->data_len);
150
if (dns_rr_to_sa(addr, port, sa, &salen) != 0) {
151
msg_warn("%s: skip address type %s: %m",
152
myname, dns_strtype(addr->type));
121
153
smtp_errno = SMTP_ERR_RETRY;
128
memset((char *) &sin, 0, sizeof(sin));
129
sin.sin_family = AF_INET;
131
if ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0)
160
if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
132
161
msg_fatal("%s: socket: %m", myname);
135
164
* Allow the sysadmin to specify the source address, for example, as "-o
136
165
* smtp_bind_address=x.x.x.x" in the master.cf file.
138
if (*var_smtp_bind_addr) {
139
sin.sin_addr.s_addr = inet_addr(var_smtp_bind_addr);
140
if (sin.sin_addr.s_addr == INADDR_NONE)
141
msg_fatal("%s: bad %s parameter: %s",
142
myname, VAR_SMTP_BIND_ADDR, var_smtp_bind_addr);
143
if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
144
msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
146
msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
168
if (sa->sa_family == AF_INET6) {
169
bind_addr = var_smtp_bind_addr6;
170
bind_var = VAR_SMTP_BIND_ADDR6;
173
if (sa->sa_family == AF_INET) {
174
bind_addr = var_smtp_bind_addr;
175
bind_var = VAR_SMTP_BIND_ADDR;
177
bind_var = bind_addr = "";
180
struct addrinfo *res0;
182
if ((aierr = hostaddr_to_sockaddr(bind_addr, (char *) 0, 0, &res0)) != 0)
183
msg_fatal("%s: bad %s parameter: %s: %s",
184
myname, bind_var, bind_addr, MAI_STRERROR(aierr));
185
if (bind(sock, res0->ai_addr, res0->ai_addrlen) < 0)
186
msg_warn("%s: bind %s: %m", myname, bind_addr);
187
else if (msg_verbose)
188
msg_info("%s: bind %s", myname, bind_addr);
150
193
* When running as a virtual host, bind to the virtual interface so that
151
194
* the mail appears to come from the "right" machine address.
196
* XXX The IPv6 patch expands the null host (as client endpoint) and uses
197
* the result as the loopback address list.
153
else if ((addr_list = own_inet_addr_list())->used == 1) {
154
memcpy((char *) &sin.sin_addr, addr_list->addrs, sizeof(sin.sin_addr));
155
inaddr = ntohl(sin.sin_addr.s_addr);
156
if (!IN_CLASSA(inaddr)
157
|| !(((inaddr & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)) {
158
if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
159
msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
161
msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
201
struct sockaddr *own_addr = 0;
202
INET_ADDR_LIST *addr_list = own_inet_addr_list();
203
struct sockaddr_storage *s;
205
for (s = addr_list->addrs; s < addr_list->addrs + addr_list->used; s++) {
206
if (SOCK_ADDR_FAMILY(s) == sa->sa_family) {
209
own_addr = SOCK_ADDR_PTR(s);
212
if (count == 1 && !sock_addr_in_loopback(own_addr)) {
213
if (bind(sock, own_addr, SOCK_ADDR_LEN(own_addr)) < 0) {
214
SOCKADDR_TO_HOSTADDR(own_addr, SOCK_ADDR_LEN(own_addr),
215
&hostaddr, (MAI_SERVPORT_STR *) 0, 0);
216
msg_warn("%s: bind %s: %m", myname, hostaddr.buf);
217
} else if (msg_verbose) {
218
SOCKADDR_TO_HOSTADDR(own_addr, SOCK_ADDR_LEN(own_addr),
219
&hostaddr, (MAI_SERVPORT_STR *) 0, 0);
220
msg_info("%s: bind %s", myname, hostaddr.buf);
166
226
* Connect to the SMTP server.
169
memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr));
228
SOCKADDR_TO_HOSTADDR(sa, salen, &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
172
230
msg_info("%s: trying: %s[%s] port %d...",
173
myname, addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
231
myname, addr->name, hostaddr.buf, ntohs(port));
174
232
if (var_smtp_conn_tmout > 0) {
175
233
non_blocking(sock, NON_BLOCKING);
176
conn_stat = timed_connect(sock, (struct sockaddr *) & sin,
177
sizeof(sin), var_smtp_conn_tmout);
234
conn_stat = timed_connect(sock, sa, salen, var_smtp_conn_tmout);
178
235
saved_errno = errno;
179
236
non_blocking(sock, BLOCKING);
180
237
errno = saved_errno;
182
conn_stat = sane_connect(sock, (struct sockaddr *) & sin, sizeof(sin));
239
conn_stat = sane_connect(sock, sa, salen);
184
241
if (conn_stat < 0) {
185
242
vstring_sprintf(why, "connect to %s[%s]: %m",
186
addr->name, inet_ntoa(sin.sin_addr));
243
addr->name, hostaddr.buf);
187
244
smtp_errno = SMTP_ERR_RETRY;
206
263
stream = vstream_fdopen(sock, O_RDWR);
207
264
if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
208
265
vstring_sprintf(why, "connect to %s[%s]: server dropped connection without sending the initial SMTP greeting",
209
addr->name, inet_ntoa(sin.sin_addr));
266
addr->name, hostaddr.buf);
210
267
smtp_errno = SMTP_ERR_RETRY;
211
268
vstream_fclose(stream);
214
271
vstream_ungetc(stream, ch);
215
return (smtp_session_alloc(stream, addr->name, inet_ntoa(sin.sin_addr)));
274
* Skip this host if it sends a 4xx or 5xx greeting. This prevents us
275
* from counting it towards the MX session limit. Unfortunately, this
276
* also means that we have to salvage the server's response ourself so
277
* that it can be included in logging or in non-delivery reports. It does
278
* not hurt if we keep the test for a 4xx or 5xx greeting in smtp_helo().
280
if (ch == '4' || (ch == '5' && var_smtp_skip_5xx_greeting)) {
281
VSTRING *salvage_buf = smtp_salvage(stream);
283
vstring_sprintf(why, "connect to %s[%s]: server refused to talk to me: %s",
284
addr->name, hostaddr.buf, STR(salvage_buf));
285
vstring_free(salvage_buf);
286
smtp_errno = SMTP_ERR_RETRY;
287
vstream_fclose(stream);
290
return (smtp_session_alloc(stream, dest, addr->name,
291
hostaddr.buf, port, sess_flags));
218
294
/* smtp_parse_destination - parse destination */
331
/* smtp_cleanup_session - clean up after using a session */
333
static void smtp_cleanup_session(SMTP_STATE *state)
335
SMTP_SESSION *session = state->session;
338
* Inform the postmaster of trouble.
340
if (session->history != 0
341
&& (session->error_mask & name_mask(VAR_NOTIFY_CLASSES,
343
var_notify_classes)) != 0)
344
smtp_chat_notify(session);
347
* When session caching is enabled, cache the first good session for this
348
* delivery request under the next-hop destination, and cache all good
349
* sessions under their server network address (destroying the session in
352
* Caching under the next-hop destination name (rather than the fall-back
353
* destination) allows us to skip over non-responding primary or backup
354
* hosts. In fact, this is the only benefit of caching logical to
355
* physical bindings; caching a session under its own hostname provides
356
* no performance benefit, given the way smtp_connect() works.
358
* XXX Should not cache TLS sessions unless we are using a single-session,
359
* in-process, cache. And if we did, we should passivate VSTREAM objects
360
* in addition to passivating SMTP_SESSION objects.
362
* XXX Workaround. If this host spoke TLS, connection caching was already
363
* turned off for this session by smtp_tls_start(). However, this alone
364
* does not distinguish between "good TLS connection" and "bad
367
* In the case of "bad connection" to a primary host we want to store the
368
* first good alternate connection under the logical next-hop destination
369
* name name. In the case of a good primary TLS connection that would not
370
* make sense: the Postfix cache would prefer non-TLS secondary hosts
371
* over TLS-enabled primary hosts!
373
* The real fix is to have three-valued connection caching state: "do
374
* cache", "don't cache", and "bad connection", but that involves more
375
* change than is allowed in a stable release.
377
* To distinguish good TLS connections from bad connections we reset the
378
* logical next-hop state, so that we won't cache connections to
379
* less-preferred MX hosts under the logical next-hop destination.
381
if (session->reuse_count > 0) {
382
smtp_save_session(state);
383
if (HAVE_NEXTHOP_STATE(state))
384
FREE_NEXTHOP_STATE(state);
387
if (session->tls_context)
388
if (HAVE_NEXTHOP_STATE(state))
389
FREE_NEXTHOP_STATE(state);
391
smtp_session_free(session);
396
* Clean up the lists with todo and dropped recipients.
398
smtp_rcpt_cleanup(state);
401
/* smtp_scrub_address_list - delete all cached addresses from list */
403
static void smtp_scrub_addr_list(HTABLE *cached_addr, DNS_RR **addr_list)
405
MAI_HOSTADDR_STR hostaddr;
410
* XXX Extend the DNS_RR structure with fields for the printable address
411
* and/or binary sockaddr representations, so that we can avoid repeated
412
* binary->string transformations for the same address.
414
for (addr = *addr_list; addr; addr = next) {
416
if (dns_rr_to_pa(addr, &hostaddr) == 0) {
417
msg_warn("cannot convert type %s resource record to socket address",
418
dns_strtype(addr->type));
421
if (htable_locate(cached_addr, hostaddr.buf))
422
*addr_list = dns_rr_remove(*addr_list, addr);
426
/* smtp_update_addr_list - common address list update */
428
static void smtp_update_addr_list(DNS_RR **addr_list, const char *server_addr,
434
struct addrinfo *res0;
440
* Truncate the address list if we are not going to use it anyway.
442
if (session_count == var_smtp_mxsess_limit
443
|| session_count == var_smtp_mxaddr_limit) {
444
dns_rr_free(*addr_list);
450
* Convert server address to internal form, and look it up in the address
453
* XXX smtp_reuse_session() breaks if we remove two or more adjacent list
454
* elements but do not truncate the list to zero length.
456
* XXX Extend the SMTP_SESSION structure with sockaddr information so that
457
* we can avoid repeated string->binary transformations for the same
460
if ((aierr = hostaddr_to_sockaddr(server_addr, (char *) 0, 0, &res0)) != 0) {
461
msg_warn("hostaddr_to_sockaddr %s: %s",
462
server_addr, MAI_STRERROR(aierr));
464
for (addr = *addr_list; addr; addr = next) {
466
if (DNS_RR_EQ_SA(addr, (struct sockaddr *) res0->ai_addr)) {
467
*addr_list = dns_rr_remove(*addr_list, addr);
475
/* smtp_reuse_session - try to use existing connection, return session count */
477
static int smtp_reuse_session(SMTP_STATE *state, int lookup_mx,
478
const char *domain, unsigned port,
479
DNS_RR **addr_list, int domain_best_pref)
481
int session_count = 0;
484
int saved_final_server = state->final_server;
485
SMTP_SESSION *session;
488
* First, search the cache by logical destination. We truncate the server
489
* address list when all the sessions for this destination are used up,
490
* to reduce the number of variables that need to be checked later.
492
* Note: lookup by logical destination restores the "best MX" bit.
494
if (*addr_list && SMTP_RCPT_LEFT(state) > 0
495
&& (session = smtp_reuse_domain(state, lookup_mx, domain, port)) != 0) {
497
smtp_update_addr_list(addr_list, session->addr, session_count);
498
state->final_server = (saved_final_server && *addr_list == 0);
500
smtp_cleanup_session(state);
504
* Second, search the cache by primary MX address. Again, we use address
505
* list truncation so that we have to check fewer variables later.
507
* XXX This loop is safe because smtp_update_addr_list() either truncates
508
* the list to zero length, or removes at most one list element.
510
for (addr = *addr_list; SMTP_RCPT_LEFT(state) > 0 && addr; addr = next) {
511
if (addr->pref != domain_best_pref)
514
if ((session = smtp_reuse_addr(state, addr, port)) != 0) {
515
session->features |= SMTP_FEATURE_BEST_MX;
517
smtp_update_addr_list(addr_list, session->addr, session_count);
520
state->final_server = (saved_final_server && next == 0);
522
smtp_cleanup_session(state);
525
return (session_count);
253
528
/* smtp_connect - establish SMTP connection */
255
530
int smtp_connect(SMTP_STATE *state)
299
581
* then is to build this into the pre-existing SMTP client without
300
582
* getting lost in the complexity.
584
#define IS_FALLBACK_RELAY(cpp, sites, non_fallback_sites) \
585
(*(cpp) && (cpp) >= (sites)->argv + (non_fallback_sites))
302
587
for (cpp = sites->argv; SMTP_RCPT_LEFT(state) > 0 && (dest = *cpp) != 0; cpp++) {
303
state->final_server = (cpp[1] == 0);
306
590
* Parse the destination. Default is to use the SMTP port. Look up
307
591
* the address instead of the mail exchanger when a quoted host is
308
592
* specified, or when DNS lookups are disabled.
310
dest_buf = smtp_parse_destination(dest, def_service, &host, &port);
594
dest_buf = smtp_parse_destination(dest, def_service, &domain, &port);
313
597
* Resolve an SMTP server. Skip mail exchanger lookups when a quoted
314
598
* host is specified, or when DNS lookups are disabled.
317
msg_info("connecting to %s port %d", host, ntohs(port));
318
if (ntohs(port) != 25)
601
msg_info("connecting to %s port %d", domain, ntohs(port));
602
if (ntohs(port) != IPPORT_SMTP)
319
603
misc_flags &= ~SMTP_MISC_FLAG_LOOP_DETECT;
321
605
misc_flags |= SMTP_MISC_FLAG_LOOP_DETECT;
322
if (var_disable_dns || *dest == '[') {
323
addr_list = smtp_host_addr(host, misc_flags, why);
606
lookup_mx = (var_disable_dns == 0 && *dest != '[');
608
addr_list = smtp_host_addr(domain, misc_flags, why);
609
/* XXX We could be an MX host for this destination... */
325
addr_list = smtp_domain_addr(host, misc_flags, why);
611
addr_list = smtp_domain_addr(domain, misc_flags, why, &i_am_mx);
612
/* If we're MX host, don't connect to non-MX backups. */
614
argv_truncate(sites, cpp - sites->argv + 1);
616
state->final_server = (cpp[1] == 0);
619
* When session caching is enabled, store the first good session for
620
* this delivery request under the next-hop destination name. All
621
* good sessions will be stored under their specific server IP
624
* XXX Replace sites->argv by (lookup_mx, domain, port) triples so we
625
* don't have to make clumsy ad-hoc copies and keep track of who
626
* free()s the memory.
628
* XXX smtp_session_cache_destinations specifies domain names without
629
* :port, because : is already used for maptype:mapname. Because of
630
* this limitation we use the bare domain without the optional [] or
631
* non-default TCP port.
633
* Opportunistic (a.k.a. on-demand) session caching on request by the
634
* queue manager. This is turned temporarily when a destination has a
635
* high volume of mail in the active queue.
637
if (cpp == sites->argv
638
&& ((var_smtp_cache_demand && (request->flags & DEL_REQ_FLAG_SCACHE) != 0)
639
|| (smtp_cache_dest && string_list_match(smtp_cache_dest, domain)))) {
640
sess_flags |= SMTP_SESS_FLAG_CACHE;
641
SET_NEXTHOP_STATE(state, lookup_mx, domain, port);
330
645
* Don't try any backup host if mail loops to myself. That would just
331
646
* make the problem worse.
333
if (addr_list == 0 && smtp_errno == SMTP_ERR_LOOP)
648
if (addr_list == 0 && smtp_errno == SMTP_ERR_LOOP) {
654
* No early loop exit or we have a memory leak with dest_buf.
657
domain_best_pref = addr_list->pref;
660
* Delete visited cached hosts from the address list.
662
* Optionally search the connection cache by domain name or by primary
665
* Enforce the MX session and MX address counts per next-hop or
666
* fall-back destination. smtp_reuse_session() will truncate the
667
* address list when either limit is reached.
669
if (addr_list && (sess_flags & SMTP_SESS_FLAG_CACHE) != 0) {
670
if (state->cache_used->used > 0)
671
smtp_scrub_addr_list(state->cache_used, &addr_list);
672
sess_count = addr_count =
673
smtp_reuse_session(state, lookup_mx, domain, port,
674
&addr_list, domain_best_pref);
676
sess_count = addr_count = 0;
337
679
* Connect to an SMTP server.
342
684
* the end of an SMTP session, weed out the recipient list. Unmark
343
685
* any left-over recipients and try to deliver them to a backup mail
688
* Cache the first good session under the next-hop destination name.
689
* Cache all good sessions under their physical endpoint.
691
* Don't query the session cache for primary MX hosts. We already did
692
* that in smtp_reuse_session(), and if any were found in the cache,
693
* they were already deleted from the address list.
346
sess_count = addr_count = 0;
347
695
for (addr = addr_list; SMTP_RCPT_LEFT(state) > 0 && addr; addr = next) {
348
696
next = addr->next;
349
697
if (++addr_count == var_smtp_mxaddr_limit)
351
if ((state->session = smtp_connect_addr(addr, port, why)) != 0) {
352
state->features = 0; /* XXX should be SESSION info */
699
if ((sess_flags & SMTP_SESS_FLAG_CACHE) == 0
700
|| addr->pref == domain_best_pref
701
|| (session = smtp_reuse_addr(state, addr, port)) == 0)
702
session = smtp_connect_addr(dest, addr, port, why, sess_flags);
703
if ((state->session = session) != 0) {
353
704
if (++sess_count == var_smtp_mxsess_limit)
355
706
state->final_server = (cpp[1] == 0 && next == 0);
356
state->session->best = (addr->pref == addr_list->pref);
357
debug_peer_check(state->session->host, state->session->addr);
358
if (smtp_helo(state, misc_flags) == 0)
707
if (addr->pref == domain_best_pref)
708
session->features |= SMTP_FEATURE_BEST_MX;
709
if ((session->features & SMTP_FEATURE_FROM_CACHE) == 0
710
&& smtp_helo(state, misc_flags) != 0) {
711
if (vstream_ferror(session->stream) == 0
712
&& vstream_feof(session->stream) == 0)
359
715
smtp_xfer(state);
360
if (state->history != 0) {
361
if (state->error_mask & name_mask(VAR_NOTIFY_CLASSES,
362
mail_error_masks, var_notify_classes))
363
smtp_chat_notify(state);
364
smtp_chat_reset(state);
366
state->error_mask = 0;
367
state->size_limit = 0;
368
/* XXX smtp_xfer() may abort in the middle of DATA. */
369
smtp_session_free(state->session);
372
smtp_sasl_cleanup(state);
374
debug_peer_restore();
375
smtp_rcpt_cleanup(state);
716
smtp_cleanup_session(state);
377
718
msg_info("%s (port %d)", vstring_str(why), ntohs(port));
380
721
dns_rr_free(addr_list);