Testsuite: Ignore optional-config output change
[exim.git] / src / src / smtp_out.c
CommitLineData
059ec3d9
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
80fea873 5/* Copyright (c) University of Cambridge 1995 - 2016 */
059ec3d9
PH
6/* See the file NOTICE for conditions of use and distribution. */
7
8/* A number of functions for driving outgoing SMTP calls. */
9
10
11#include "exim.h"
7eb6c37c 12#include "transports/smtp.h"
059ec3d9
PH
13
14
15
16/*************************************************
17* Find an outgoing interface *
18*************************************************/
19
20/* This function is called from the smtp transport and also from the callout
21code in verify.c. Its job is to expand a string to get a list of interfaces,
22and choose a suitable one (IPv4 or IPv6) for the outgoing address.
23
24Arguments:
25 istring string interface setting, may be NULL, meaning "any", in
26 which case the function does nothing
27 host_af AF_INET or AF_INET6 for the outgoing IP address
28 addr the mail address being handled (for setting errors)
059ec3d9
PH
29 interface point this to the interface
30 msg to add to any error message
31
32Returns: TRUE on success, FALSE on failure, with error message
33 set in addr and transport_return set to PANIC
34*/
35
36BOOL
37smtp_get_interface(uschar *istring, int host_af, address_item *addr,
6f6dedcc 38 uschar **interface, uschar *msg)
059ec3d9 39{
55414b25 40const uschar * expint;
059ec3d9
PH
41uschar *iface;
42int sep = 0;
43
fb05276a 44if (!istring) return TRUE;
059ec3d9 45
fb05276a 46if (!(expint = expand_string(istring)))
059ec3d9
PH
47 {
48 if (expand_string_forcedfail) return TRUE;
49 addr->transport_return = PANIC;
50 addr->message = string_sprintf("failed to expand \"interface\" "
51 "option for %s: %s", msg, expand_string_message);
52 return FALSE;
53 }
54
059ec3d9
PH
55while (isspace(*expint)) expint++;
56if (*expint == 0) return TRUE;
57
58while ((iface = string_nextinlist(&expint, &sep, big_buffer,
fb05276a 59 big_buffer_size)))
059ec3d9
PH
60 {
61 if (string_is_ip_address(iface, NULL) == 0)
62 {
63 addr->transport_return = PANIC;
64 addr->message = string_sprintf("\"%s\" is not a valid IP "
65 "address for the \"interface\" option for %s",
66 iface, msg);
67 return FALSE;
68 }
69
70 if (((Ustrchr(iface, ':') == NULL)? AF_INET:AF_INET6) == host_af)
71 break;
72 }
73
fb05276a 74if (iface) *interface = string_copy(iface);
059ec3d9
PH
75return TRUE;
76}
77
78
79
80/*************************************************
81* Find an outgoing port *
82*************************************************/
83
84/* This function is called from the smtp transport and also from the callout
85code in verify.c. Its job is to find a port number. Note that getservbyname()
86produces the number in network byte order.
87
88Arguments:
89 rstring raw (unexpanded) string representation of the port
90 addr the mail address being handled (for setting errors)
91 port stick the port in here
92 msg for adding to error message
93
94Returns: TRUE on success, FALSE on failure, with error message set
95 in addr, and transport_return set to PANIC
96*/
97
98BOOL
99smtp_get_port(uschar *rstring, address_item *addr, int *port, uschar *msg)
100{
101uschar *pstring = expand_string(rstring);
102
00580051 103if (!pstring)
059ec3d9
PH
104 {
105 addr->transport_return = PANIC;
106 addr->message = string_sprintf("failed to expand \"%s\" (\"port\" option) "
107 "for %s: %s", rstring, msg, expand_string_message);
108 return FALSE;
109 }
110
111if (isdigit(*pstring))
112 {
113 uschar *end;
114 *port = Ustrtol(pstring, &end, 0);
115 if (end != pstring + Ustrlen(pstring))
116 {
117 addr->transport_return = PANIC;
118 addr->message = string_sprintf("invalid port number for %s: %s", msg,
119 pstring);
120 return FALSE;
121 }
122 }
123
124else
125 {
126 struct servent *smtp_service = getservbyname(CS pstring, "tcp");
00580051 127 if (!smtp_service)
059ec3d9
PH
128 {
129 addr->transport_return = PANIC;
130 addr->message = string_sprintf("TCP port \"%s\" is not defined for %s",
131 pstring, msg);
132 return FALSE;
133 }
134 *port = ntohs(smtp_service->s_port);
135 }
136
137return TRUE;
138}
139
140
141
142
0ab63f3d
JH
143/* Arguments as for smtp_connect(), plus
144 early_data if non-NULL, data to be sent - preferably in the TCP SYN segment
145
146Returns: connected socket number, or -1 with errno set
147*/
148
059ec3d9 149int
7eb6c37c 150smtp_sock_connect(host_item * host, int host_af, int port, uschar * interface,
0ab63f3d 151 transport_instance * tb, int timeout, const blob * early_data)
059ec3d9 152{
7eb6c37c
JH
153smtp_transport_options_block * ob =
154 (smtp_transport_options_block *)tb->options_block;
155const uschar * dscp = ob->dscp;
9e4f5962
PP
156int dscp_value;
157int dscp_level;
158int dscp_option;
059ec3d9 159int sock;
7eb6c37c 160int save_errno = 0;
059ec3d9 161
0cbf2b82 162#ifndef DISABLE_EVENT
7eb6c37c
JH
163deliver_host_address = host->address;
164deliver_host_port = port;
165if (event_raise(tb->event_action, US"tcp:connect", NULL)) return -1;
a7538db1
JH
166#endif
167
059ec3d9
PH
168if ((sock = ip_socket(SOCK_STREAM, host_af)) < 0) return -1;
169
170/* Set TCP_NODELAY; Exim does its own buffering. */
171
d4ff61d1
JH
172if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, US &on, sizeof(on)))
173 HDEBUG(D_transport|D_acl|D_v)
e1d04f48 174 debug_printf_indent("failed to set NODELAY: %s ", strerror(errno));
059ec3d9 175
9e4f5962
PP
176/* Set DSCP value, if we can. For now, if we fail to set the value, we don't
177bomb out, just log it and continue in default traffic class. */
178
179if (dscp && dscp_lookup(dscp, host_af, &dscp_level, &dscp_option, &dscp_value))
180 {
181 HDEBUG(D_transport|D_acl|D_v)
e1d04f48 182 debug_printf_indent("DSCP \"%s\"=%x ", dscp, dscp_value);
9e4f5962
PP
183 if (setsockopt(sock, dscp_level, dscp_option, &dscp_value, sizeof(dscp_value)) < 0)
184 HDEBUG(D_transport|D_acl|D_v)
e1d04f48 185 debug_printf_indent("failed to set DSCP: %s ", strerror(errno));
9e4f5962
PP
186 /* If the kernel supports IPv4 and IPv6 on an IPv6 socket, we need to set the
187 option for both; ignore failures here */
188 if (host_af == AF_INET6 &&
189 dscp_lookup(dscp, AF_INET, &dscp_level, &dscp_option, &dscp_value))
9e4f5962 190 (void) setsockopt(sock, dscp_level, dscp_option, &dscp_value, sizeof(dscp_value));
9e4f5962
PP
191 }
192
059ec3d9
PH
193/* Bind to a specific interface if requested. Caller must ensure the interface
194is the same type (IPv4 or IPv6) as the outgoing address. */
195
7eb6c37c 196if (interface && ip_bind(sock, host_af, interface, 0) < 0)
059ec3d9
PH
197 {
198 save_errno = errno;
199 HDEBUG(D_transport|D_acl|D_v)
e1d04f48 200 debug_printf_indent("unable to bind outgoing SMTP call to %s: %s", interface,
059ec3d9
PH
201 strerror(errno));
202 }
203
204/* Connect to the remote host, and add keepalive to the socket before returning
0ab63f3d
JH
205it, if requested. If the build supports TFO, request it - and if the caller
206requested some early-data then include that in the TFO request. */
059ec3d9 207
0ab63f3d
JH
208else
209 {
210 const blob * fastopen = NULL;
211
212#ifdef TCP_FASTOPEN
213 if (verify_check_given_host(&ob->hosts_try_fastopen, host) == OK)
214 fastopen = early_data ? early_data : &tcp_fastopen_nodata;
215#endif
216
217 if (ip_connect(sock, host_af, host->address, port, timeout, fastopen) < 0)
218 save_errno = errno;
219 else if (early_data && !fastopen && early_data->data && early_data->len)
220 if (send(sock, early_data->data, early_data->len, 0) < 0)
221 save_errno = errno;
222 }
059ec3d9
PH
223
224/* Either bind() or connect() failed */
225
226if (save_errno != 0)
227 {
8e669ac1 228 HDEBUG(D_transport|D_acl|D_v)
4deaf07d 229 {
e1d04f48 230 debug_printf_indent("failed: %s", CUstrerror(save_errno));
8e669ac1 231 if (save_errno == ETIMEDOUT)
4deaf07d 232 debug_printf(" (timeout=%s)", readconf_printtime(timeout));
8e669ac1
PH
233 debug_printf("\n");
234 }
f1e894f3 235 (void)close(sock);
059ec3d9
PH
236 errno = save_errno;
237 return -1;
238 }
239
240/* Both bind() and connect() succeeded */
241
242else
243 {
41c7c167
PH
244 union sockaddr_46 interface_sock;
245 EXIM_SOCKLEN_T size = sizeof(interface_sock);
e1d04f48 246 HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("connected\n");
41c7c167
PH
247 if (getsockname(sock, (struct sockaddr *)(&interface_sock), &size) == 0)
248 sending_ip_address = host_ntoa(-1, &interface_sock, NULL, &sending_port);
249 else
250 {
251 log_write(0, LOG_MAIN | ((errno == ECONNRESET)? 0 : LOG_PANIC),
252 "getsockname() failed: %s", strerror(errno));
253 close(sock);
254 return -1;
255 }
7eb6c37c 256 if (ob->keepalive) ip_keepalive(sock, host->address, TRUE);
059ec3d9
PH
257 return sock;
258 }
259}
260
58c30e47
JH
261
262
263
264
265void
266smtp_port_for_connect(host_item * host, int port)
267{
268if (host->port != PORT_NONE)
269 {
270 HDEBUG(D_transport|D_acl|D_v)
271 debug_printf_indent("Transport port=%d replaced by host-specific port=%d\n", port,
272 host->port);
273 port = host->port;
274 }
275else host->port = port; /* Set the port actually used */
276}
277
278
7eb6c37c
JH
279/*************************************************
280* Connect to remote host *
281*************************************************/
282
283/* Create a socket, and connect it to a remote host. IPv6 addresses are
284detected by checking for a colon in the address. AF_INET6 is defined even on
285non-IPv6 systems, to enable the code to be less messy. However, on such systems
286host->address will always be an IPv4 address.
287
7eb6c37c 288Arguments:
58c30e47 289 host host item containing name and address and port
7eb6c37c 290 host_af AF_INET or AF_INET6
7eb6c37c
JH
291 interface outgoing interface address or NULL
292 timeout timeout value or 0
293 tb transport
294
295Returns: connected socket number, or -1 with errno set
296*/
297
298int
58c30e47 299smtp_connect(host_item *host, int host_af, uschar *interface,
7eb6c37c
JH
300 int timeout, transport_instance * tb)
301{
58c30e47 302int port = host->port;
f0989ec0 303#ifdef SUPPORT_SOCKS
7eb6c37c
JH
304smtp_transport_options_block * ob =
305 (smtp_transport_options_block *)tb->options_block;
0539a19d 306#endif
7eb6c37c 307
055e2cb4
JH
308callout_address = string_sprintf("[%s]:%d", host->address, port);
309
7eb6c37c
JH
310HDEBUG(D_transport|D_acl|D_v)
311 {
312 uschar * s = US" ";
313 if (interface) s = string_sprintf(" from %s ", interface);
f0989ec0 314#ifdef SUPPORT_SOCKS
7eb6c37c
JH
315 if (ob->socks_proxy) s = string_sprintf("%svia proxy ", s);
316#endif
e1d04f48 317 debug_printf_indent("Connecting to %s %s%s... ", host->name, callout_address, s);
7eb6c37c
JH
318 }
319
320/* Create and connect the socket */
321
f0989ec0 322#ifdef SUPPORT_SOCKS
7eb6c37c
JH
323if (ob->socks_proxy)
324 return socks_sock_connect(host, host_af, port, interface, tb, timeout);
325#endif
326
0ab63f3d 327return smtp_sock_connect(host, host_af, port, interface, tb, timeout, NULL);
7eb6c37c
JH
328}
329
059ec3d9
PH
330
331/*************************************************
332* Flush outgoing command buffer *
333*************************************************/
334
335/* This function is called only from smtp_write_command() below. It flushes
336the buffer of outgoing commands. There is more than one in the buffer only when
337pipelining.
338
339Argument:
340 outblock the SMTP output block
925ac8e4 341 mode further data expected, or plain
059ec3d9
PH
342
343Returns: TRUE if OK, FALSE on error, with errno set
344*/
345
346static BOOL
4e910c01 347flush_buffer(smtp_outblock * outblock, int mode)
059ec3d9
PH
348{
349int rc;
58fc5fb2 350int n = outblock->ptr - outblock->buffer;
925ac8e4 351BOOL more = mode == SCMD_MORE;
059ec3d9 352
4e910c01 353HDEBUG(D_transport|D_acl) debug_printf_indent("cmd buf flush %d bytes%s\n", n,
925ac8e4 354 more ? " (more expected)" : "");
4e910c01 355
059ec3d9 356#ifdef SUPPORT_TLS
817d9f57 357if (tls_out.active == outblock->sock)
925ac8e4 358 rc = tls_write(FALSE, outblock->buffer, n, more);
059ec3d9
PH
359else
360#endif
4e910c01
JH
361 rc = send(outblock->sock, outblock->buffer, n,
362#ifdef MSG_MORE
925ac8e4 363 more ? MSG_MORE : 0
4e910c01
JH
364#else
365 0
366#endif
367 );
059ec3d9 368
059ec3d9
PH
369if (rc <= 0)
370 {
e1d04f48 371 HDEBUG(D_transport|D_acl) debug_printf_indent("send failed: %s\n", strerror(errno));
059ec3d9
PH
372 return FALSE;
373 }
374
375outblock->ptr = outblock->buffer;
376outblock->cmd_count = 0;
377return TRUE;
378}
379
380
381
382/*************************************************
383* Write SMTP command *
384*************************************************/
385
386/* The formatted command is left in big_buffer so that it can be reflected in
387any error message.
388
389Arguments:
390 outblock contains buffer for pipelining, and socket
4e910c01 391 mode buffer, write-with-more-likely, write
059ec3d9
PH
392 format a format, starting with one of
393 of HELO, MAIL FROM, RCPT TO, DATA, ".", or QUIT.
6d5c916c 394 If NULL, flush pipeline buffer only.
059ec3d9
PH
395 ... data for the format
396
397Returns: 0 if command added to pipelining buffer, with nothing transmitted
398 +n if n commands transmitted (may still have buffered the new one)
399 -1 on error, with errno set
400*/
401
402int
4e910c01 403smtp_write_command(smtp_outblock * outblock, int mode, const char *format, ...)
059ec3d9
PH
404{
405int count;
406int rc = 0;
407va_list ap;
408
6d5c916c 409if (format)
059ec3d9 410 {
6d5c916c
JH
411 va_start(ap, format);
412 if (!string_vformat(big_buffer, big_buffer_size, CS format, ap))
413 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing "
414 "SMTP");
415 va_end(ap);
416 count = Ustrlen(big_buffer);
417
418 if (count > outblock->buffersize)
419 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing "
420 "SMTP");
421
422 if (count > outblock->buffersize - (outblock->ptr - outblock->buffer))
423 {
424 rc = outblock->cmd_count; /* flush resets */
4e910c01 425 if (!flush_buffer(outblock, SCMD_FLUSH)) return -1;
6d5c916c 426 }
059ec3d9 427
6d5c916c
JH
428 Ustrncpy(CS outblock->ptr, big_buffer, count);
429 outblock->ptr += count;
430 outblock->cmd_count++;
431 count -= 2;
432 big_buffer[count] = 0; /* remove \r\n for error message */
059ec3d9 433
6d5c916c
JH
434 /* We want to hide the actual data sent in AUTH transactions from reflections
435 and logs. While authenticating, a flag is set in the outblock to enable this.
436 The AUTH command itself gets any data flattened. Other lines are flattened
437 completely. */
059ec3d9 438
6d5c916c 439 if (outblock->authenticating)
059ec3d9 440 {
6d5c916c
JH
441 uschar *p = big_buffer;
442 if (Ustrncmp(big_buffer, "AUTH ", 5) == 0)
443 {
444 p += 5;
445 while (isspace(*p)) p++;
446 while (!isspace(*p)) p++;
447 while (isspace(*p)) p++;
448 }
449 while (*p != 0) *p++ = '*';
059ec3d9 450 }
059ec3d9 451
e1d04f48 452 HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP>> %s\n", big_buffer);
6d5c916c 453 }
059ec3d9 454
4e910c01 455if (mode != SCMD_BUFFER)
059ec3d9
PH
456 {
457 rc += outblock->cmd_count; /* flush resets */
4e910c01 458 if (!flush_buffer(outblock, mode)) return -1;
059ec3d9
PH
459 }
460
461return rc;
462}
463
464
465
466/*************************************************
467* Read one line of SMTP response *
468*************************************************/
469
470/* This function reads one line of SMTP response from the server host. This may
471not be a complete response - it could be just part of a multiline response. We
472have to use a buffer for incoming packets, because when pipelining or using
473LMTP, there may well be more than one response in a single packet. This
474function is called only from the one that follows.
475
476Arguments:
477 inblock the SMTP input block (contains holding buffer, socket, etc.)
478 buffer where to put the line
479 size space available for the line
480 timeout the timeout to use when reading a packet
481
482Returns: length of a line that has been put in the buffer
483 -1 otherwise, with errno set
484*/
485
486static int
487read_response_line(smtp_inblock *inblock, uschar *buffer, int size, int timeout)
488{
489uschar *p = buffer;
490uschar *ptr = inblock->ptr;
491uschar *ptrend = inblock->ptrend;
492int sock = inblock->sock;
493
494/* Loop for reading multiple packets or reading another packet after emptying
495a previously-read one. */
496
497for (;;)
498 {
499 int rc;
500
501 /* If there is data in the input buffer left over from last time, copy
502 characters from it until the end of a line, at which point we can return,
503 having removed any whitespace (which will include CR) at the end of the line.
504 The rules for SMTP say that lines end in CRLF, but there are have been cases
505 of hosts using just LF, and other MTAs are reported to handle this, so we
506 just look for LF. If we run out of characters before the end of a line,
507 carry on to read the next incoming packet. */
508
509 while (ptr < ptrend)
510 {
511 int c = *ptr++;
512 if (c == '\n')
513 {
514 while (p > buffer && isspace(p[-1])) p--;
515 *p = 0;
516 inblock->ptr = ptr;
517 return p - buffer;
518 }
519 *p++ = c;
520 if (--size < 4)
521 {
522 *p = 0; /* Leave malformed line for error message */
523 errno = ERRNO_SMTPFORMAT;
524 return -1;
525 }
526 }
527
528 /* Need to read a new input packet. */
529
de6273b4
JH
530 if((rc = ip_recv(sock, inblock->buffer, inblock->buffersize, timeout)) <= 0)
531 {
170f4904
JH
532 DEBUG(D_deliver|D_transport|D_acl)
533 debug_printf_indent(errno ? " SMTP(%s)<<\n" : " SMTP(closed)<<\n",
534 strerror(errno));
de6273b4
JH
535 break;
536 }
059ec3d9
PH
537
538 /* Another block of data has been successfully read. Set up the pointers
539 and let the loop continue. */
540
541 ptrend = inblock->ptrend = inblock->buffer + rc;
542 ptr = inblock->buffer;
e1d04f48 543 DEBUG(D_transport|D_acl) debug_printf_indent("read response data: size=%d\n", rc);
059ec3d9
PH
544 }
545
546/* Get here if there has been some kind of recv() error; errno is set, but we
547ensure that the result buffer is empty before returning. */
548
549*buffer = 0;
550return -1;
551}
552
553
554
555
556
557/*************************************************
558* Read SMTP response *
559*************************************************/
560
561/* This function reads an SMTP response with a timeout, and returns the
562response in the given buffer, as a string. A multiline response will contain
563newline characters between the lines. The function also analyzes the first
564digit of the reply code and returns FALSE if it is not acceptable. FALSE is
565also returned after a reading error. In this case buffer[0] will be zero, and
566the error code will be in errno.
567
568Arguments:
569 inblock the SMTP input block (contains holding buffer, socket, etc.)
570 buffer where to put the response
571 size the size of the buffer
572 okdigit the expected first digit of the response
2760b518 573 timeout the timeout to use, in seconds
059ec3d9
PH
574
575Returns: TRUE if a valid, non-error response was received; else FALSE
576*/
577
578BOOL
579smtp_read_response(smtp_inblock *inblock, uschar *buffer, int size, int okdigit,
580 int timeout)
581{
582uschar *ptr = buffer;
583int count;
584
585errno = 0; /* Ensure errno starts out zero */
586
4c04137d 587/* This is a loop to read and concatenate the lines that make up a multi-line
059ec3d9
PH
588response. */
589
590for (;;)
591 {
592 if ((count = read_response_line(inblock, ptr, size, timeout)) < 0)
593 return FALSE;
594
595 HDEBUG(D_transport|D_acl|D_v)
e1d04f48 596 debug_printf_indent(" %s %s\n", (ptr == buffer)? "SMTP<<" : " ", ptr);
059ec3d9
PH
597
598 /* Check the format of the response: it must start with three digits; if
599 these are followed by a space or end of line, the response is complete. If
600 they are followed by '-' this is a multi-line response and we must look for
601 another line until the final line is reached. The only use made of multi-line
602 responses is to pass them back as error messages. We therefore just
603 concatenate them all within the buffer, which should be large enough to
604 accept any reasonable number of lines. */
605
606 if (count < 3 ||
607 !isdigit(ptr[0]) ||
608 !isdigit(ptr[1]) ||
609 !isdigit(ptr[2]) ||
610 (ptr[3] != '-' && ptr[3] != ' ' && ptr[3] != 0))
611 {
612 errno = ERRNO_SMTPFORMAT; /* format error */
613 return FALSE;
614 }
615
616 /* If the line we have just read is a terminal line, line, we are done.
617 Otherwise more data has to be read. */
618
619 if (ptr[3] != '-') break;
620
621 /* Move the reading pointer upwards in the buffer and insert \n between the
622 components of a multiline response. Space is left for this by read_response_
623 line(). */
624
625 ptr += count;
626 *ptr++ = '\n';
627 size -= count + 1;
628 }
629
630/* Return a value that depends on the SMTP return code. On some systems a
631non-zero value of errno has been seen at this point, so ensure it is zero,
632because the caller of this function looks at errno when FALSE is returned, to
633distinguish between an unexpected return code and other errors such as
634timeouts, lost connections, etc. */
635
636errno = 0;
637return buffer[0] == okdigit;
638}
639
640/* End of smtp_out.c */
7eb6c37c
JH
641/* vi: aw ai sw=2
642*/