xref: /netbsd-src/external/ibm-public/postfix/dist/src/posttls-finger/posttls-finger.c (revision c48c605c14fd8622b523d1d6a3f0c0bad133ea89)
1 /*	$NetBSD: posttls-finger.c,v 1.5 2023/12/23 20:30:45 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	posttls-finger 1
6 /* SUMMARY
7 /*	Probe the TLS properties of an ESMTP or LMTP server.
8 /* SYNOPSIS
9 /*	\fBposttls-finger\fR [\fIoptions\fR] [\fBinet:\fR]\fIdomain\fR[:\fIport\fR] [\fImatch ...\fR]
10 /* .br
11 /*	\fBposttls-finger\fR -S [\fIoptions\fR] \fBunix:\fIpathname\fR [\fImatch ...\fR]
12 /* DESCRIPTION
13 /*	\fBposttls-finger\fR(1) connects to the specified destination
14 /*	and reports TLS-related information about the server. With SMTP, the
15 /*	destination is a domainname; with LMTP it is either a domainname
16 /*	prefixed with \fBinet:\fR or a pathname prefixed with \fBunix:\fR.  If
17 /*	Postfix is built without TLS support, the resulting \fBposttls-finger\fR(1)
18 /*	program has very limited functionality, and only the \fB-a\fR, \fB-c\fR,
19 /*	\fB-h\fR, \fB-o\fR, \fB-S\fR, \fB-t\fR, \fB-T\fR and \fB-v\fR options
20 /*	are available.
21 /*
22 /*	Note: this is an unsupported test program. No attempt is made
23 /*	to maintain compatibility between successive versions.
24 /*
25 /*	For SMTP servers that don't support ESMTP, only the greeting banner
26 /*	and the negative EHLO response are reported. Otherwise, the reported
27 /*	EHLO response details further server capabilities.
28 /*
29 /*	If TLS support is enabled when \fBposttls-finger\fR(1) is compiled, and
30 /*	the server supports \fBSTARTTLS\fR, a TLS handshake is attempted.
31 /*
32 /*	If DNSSEC support is available, the connection TLS security level
33 /*	(\fB-l\fR option) defaults to \fBdane\fR; see TLS_README for
34 /*	details. Otherwise, it defaults to \fBsecure\fR.  This setting
35 /*	determines the certificate matching policy.
36 /*
37 /*	If TLS negotiation succeeds, the TLS protocol and cipher details are
38 /*	reported. The server certificate is then verified in accordance with
39 /*	the policy at the chosen (or default) security level.  With public
40 /*	CA-based trust, when the \fB-L\fR option includes \fBcertmatch\fR,
41 /*	(true by default) name matching is performed even if the certificate
42 /*	chain is not trusted.  This logs the names found in the remote SMTP
43 /*	server certificate and which if any would match, were the certificate
44 /*	chain trusted.
45 /*
46 /*	Note: \fBposttls-finger\fR(1) does not perform any table lookups, so
47 /*	the TLS policy table and obsolete per-site tables are not consulted.
48 /*	It does not communicate with the \fBtlsmgr\fR(8) daemon (or any other
49 /*	Postfix daemons); its TLS session cache is held in private memory, and
50 /*	disappears when the process exits.
51 /*
52 /*	With the \fB-r \fIdelay\fR option, if the server assigns a TLS
53 /*	session id, the TLS session is cached. The connection is then closed
54 /*	and re-opened after the specified delay, and \fBposttls-finger\fR(1)
55 /*	then reports whether the cached TLS session was re-used.
56 /*
57 /*	When the destination is a load balancer, it may be distributing
58 /*	load between multiple server caches. Typically, each server returns
59 /*	its unique name in its EHLO response. If, upon reconnecting with
60 /*	\fB-r\fR, a new server name is detected, another session is cached
61 /*	for the new server, and the reconnect is repeated up to a maximum
62 /*	number of times (default 5) that can be specified via the \fB-m\fR
63 /*	option.
64 /*
65 /*	The choice of SMTP or LMTP (\fB-S\fR option) determines the syntax of
66 /*	the destination argument. With SMTP, one can specify a service on a
67 /*	non-default port as \fIhost\fR:\fIservice\fR, and disable MX (mail
68 /*	exchanger) DNS lookups with [\fIhost\fR] or [\fIhost\fR]:\fIport\fR.
69 /*	The [] form is required when you specify an IP address instead of a
70 /*	hostname.  An IPv6 address takes the form [\fBipv6:\fIaddress\fR].
71 /*	The default port for SMTP is taken from the \fBsmtp/tcp\fR entry in
72 /*	/etc/services, defaulting to 25 if the entry is not found.
73 /*
74 /*	With LMTP, specify \fBunix:\fIpathname\fR to connect to a local server
75 /*	listening on a unix-domain socket bound to the specified pathname;
76 /*	otherwise, specify an optional \fBinet:\fR prefix followed by a
77 /*	\fIdomain\fR and an optional port, with the same syntax as for
78 /*	SMTP. The default TCP port for LMTP is 24.
79 /*
80 /*	Arguments:
81 /* .IP "\fB-a\fR \fIfamily\fR (default: \fBany\fR)"
82 /*	Address family preference: \fBipv4\fR, \fBipv6\fR or \fBany\fR.  When
83 /*	using \fBany\fR, \fBposttls-finger\fR(1) will randomly select one of
84 /*	the two as the more preferred, and exhaust all MX preferences for the
85 /*	first address family before trying any addresses for the other.
86 /* .IP "\fB-A\fR \fItrust-anchor.pem\fR (default: none)"
87 /*	A list of PEM trust-anchor files that overrides CAfile and CApath
88 /*	trust chain verification.  Specify the option multiple times to
89 /*	specify multiple files.  See the main.cf documentation for
90 /*	smtp_tls_trust_anchor_file for details.
91 /* .IP "\fB-c\fR"
92 /*	Disable SMTP chat logging; only TLS-related information is logged.
93 /* .IP "\fB-C\fR"
94 /*	Print the remote SMTP server certificate trust chain in PEM format.
95 /*	The issuer DN, subject DN, certificate and public key fingerprints
96 /*	(see \fB-d \fImdalg\fR option below) are printed above each PEM
97 /*	certificate block.  If you specify \fB-F \fICAfile\fR or
98 /*	\fB-P \fICApath\fR, the OpenSSL library may augment the chain with
99 /*	missing issuer certificates.  To see the actual chain sent by the
100 /*	remote SMTP server leave \fICAfile\fR and \fICApath\fR unset.
101 /* .IP "\fB-d \fImdalg\fR (default: \fB$smtp_tls_fingerprint_digest\fR)"
102 /*	The message digest algorithm to use for reporting remote SMTP server
103 /*	fingerprints and matching against user provided certificate
104 /*	fingerprints (with DANE TLSA records the algorithm is specified
105 /*	in the DNS).  In Postfix versions prior to 3.6, the default value
106 /*	was "md5".
107 /* .IP "\fB-f\fR"
108 /*	Lookup the associated DANE TLSA RRset even when a hostname is not an
109 /*	alias and its address records lie in an unsigned zone.  See
110 /*	smtp_tls_force_insecure_host_tlsa_lookup for details.
111 /* .IP "\fB-F \fICAfile.pem\fR (default: none)"
112 /*	The PEM formatted CAfile for remote SMTP server certificate
113 /*	verification.  By default no CAfile is used and no public CAs
114 /*	are trusted.
115 /* .IP "\fB-g \fIgrade\fR (default: medium)"
116 /*	The minimum TLS cipher grade used by \fBposttls-finger\fR(1).
117 /*	See smtp_tls_mandatory_ciphers for details.
118 /* .IP "\fB-h \fIhost_lookup\fR (default: \fBdns\fR)"
119 /*	The hostname lookup methods used for the connection.  See the
120 /*	documentation of smtp_host_lookup for syntax and semantics.
121 /* .IP "\fB-H \fIchainfiles\fR (default: \fInone\fR)\fR"
122 /*	List of files with a sequence PEM-encoded TLS client certificate
123 /*	chains.  The list can be built-up incrementally, by specifying
124 /*	the option multiple times, or all at once via a comma or
125 /*	whitespace separated list of filenames.  Each chain starts with
126 /*	a private key, which is followed immediately by the
127 /*	corresponding certificate, and optionally by additional issuer
128 /*	certificates. Each new key begins a new chain for the
129 /*	corresponding algorithm.  This option is mutually exclusive with
130 /*	the below \fB-k\fR and \fB-K\fR options.
131 /* .IP "\fB-k \fIcertfile\fR (default: \fIkeyfile\fR)\fR"
132 /*	File with PEM-encoded TLS client certificate chain. This
133 /*	defaults to \fIkeyfile\fR if one is specified.
134 /* .IP "\fB-K \fIkeyfile\fR (default: \fIcertfile\fR)"
135 /*	File with PEM-encoded TLS client private key.
136 /*	This defaults to \fIcertfile\fR if one is specified.
137 /* .IP "\fB-l \fIlevel\fR (default: \fBdane\fR or \fBsecure\fR)"
138 /*	The security level for the connection, default \fBdane\fR or
139 /*	\fBsecure\fR depending on whether DNSSEC is available.  For syntax
140 /*	and semantics, see the documentation of smtp_tls_security_level.
141 /*	When \fBdane\fR or \fBdane-only\fR is supported and selected, if no
142 /*	TLSA records are found, or all the records found are unusable, the
143 /*	\fIsecure\fR level will be used instead.  The \fBfingerprint\fR
144 /*	security level allows you to test certificate or public-key
145 /*	fingerprint matches before you deploy them in the policy table.
146 /* .IP
147 /*	Note, since \fBposttls-finger\fR(1) does not actually deliver any email,
148 /*	the \fBnone\fR, \fBmay\fR and \fBencrypt\fR security levels are not
149 /*	very useful.  Since \fBmay\fR and \fBencrypt\fR don't require peer
150 /*	certificates, they will often negotiate anonymous TLS ciphersuites,
151 /*	so you won't learn much about the remote SMTP server's certificates
152 /*	at these levels if it also supports anonymous TLS (though you may
153 /*	learn that the server supports anonymous TLS).
154 /* .IP "\fB-L \fIlogopts\fR (default: \fBroutine,certmatch\fR)"
155 /*	Fine-grained TLS logging options. To tune the TLS features logged
156 /*	during the TLS handshake, specify one or more of:
157 /* .RS
158 /* .IP "\fB0, none\fR"
159 /*	These yield no TLS logging; you'll generally want more, but this
160 /*	is handy if you just want the trust chain:
161 /* .RS
162 /* .ad
163 /* .nf
164 /*	$ posttls-finger -cC -L none destination
165 /* .fi
166 /* .RE
167 /* .IP "\fB1, routine, summary\fR"
168 /*	These synonymous values yield a normal one-line summary of the TLS
169 /*	connection.
170 /* .IP "\fB2, debug\fR"
171 /*	These synonymous values combine routine, ssl-debug, cache and verbose.
172 /* .IP "\fB3, ssl-expert\fR"
173 /*	These synonymous values combine debug with ssl-handshake-packet-dump.
174 /*	For experts only.
175 /* .IP "\fB4, ssl-developer\fR"
176 /*	These synonymous values combine ssl-expert with ssl-session-packet-dump.
177 /*	For experts only, and in most cases, use wireshark instead.
178 /* .IP "\fBssl-debug\fR"
179 /*	Turn on OpenSSL logging of the progress of the SSL handshake.
180 /* .IP "\fBssl-handshake-packet-dump\fR"
181 /*	Log hexadecimal packet dumps of the SSL handshake; for experts only.
182 /* .IP "\fBssl-session-packet-dump\fR"
183 /*	Log hexadecimal packet dumps of the entire SSL session; only useful
184 /*	to those who can debug SSL protocol problems from hex dumps.
185 /* .IP "\fBuntrusted\fR"
186 /*	Logs trust chain verification problems.  This is turned on
187 /*	automatically at security levels that use peer names signed
188 /*	by Certification Authorities to validate certificates.  So while
189 /*	this setting is recognized, you should never need to set it
190 /*	explicitly.
191 /* .IP "\fBpeercert\fR"
192 /*	This logs a one line summary of the remote SMTP server certificate
193 /*	subject, issuer, and fingerprints.
194 /* .IP "\fBcertmatch\fR"
195 /*	This logs remote SMTP server certificate matching, showing the CN
196 /*	and each subjectAltName and which name matched.  With DANE, logs
197 /*	matching of TLSA record trust-anchor and end-entity certificates.
198 /* .IP "\fBcache\fR"
199 /*	This logs session cache operations, showing whether session caching
200 /*	is effective with the remote SMTP server.  Automatically used when
201 /*	reconnecting with the \fB-r\fR option; rarely needs to be set
202 /*	explicitly.
203 /* .IP "\fBverbose\fR"
204 /*	Enables verbose logging in the Postfix TLS driver; includes all of
205 /*	peercert..cache and more.
206 /* .RE
207 /* .IP
208 /*	The default is \fBroutine,certmatch\fR. After a reconnect,
209 /*	\fBpeercert\fR, \fBcertmatch\fR and \fBverbose\fR are automatically
210 /*	disabled while \fBcache\fR and \fBsummary\fR are enabled.
211 /* .IP "\fB-m \fIcount\fR (default: \fB5\fR)"
212 /*	When the \fB-r \fIdelay\fR option is specified, the \fB-m\fR option
213 /*	determines the maximum number of reconnect attempts to use with
214 /*	a server behind a load balancer, to see whether connection caching
215 /*	is likely to be effective for this destination.  Some MTAs
216 /*	don't expose the underlying server identity in their EHLO
217 /*	response; with these servers there will never be more than
218 /*	1 reconnection attempt.
219 /* .IP "\fB-M \fIinsecure_mx_policy\fR (default: \fBdane\fR)"
220 /*	The TLS policy for MX hosts with "secure" TLSA records when the
221 /*	nexthop destination security level is \fBdane\fR, but the MX
222 /*	record was found via an "insecure" MX lookup.  See the main.cf
223 /*	documentation for smtp_tls_dane_insecure_mx_policy for details.
224 /* .IP "\fB-o \fIname=value\fR"
225 /*	Specify zero or more times to override the value of the main.cf
226 /*	parameter \fIname\fR with \fIvalue\fR.  Possible use-cases include
227 /*	overriding the values of TLS library parameters, or "myhostname" to
228 /*	configure the SMTP EHLO name sent to the remote server.
229 /* .IP "\fB-p \fIprotocols\fR (default: >=TLSv1)"
230 /*	TLS protocols that \fBposttls-finger\fR(1) will exclude or include.  See
231 /*	smtp_tls_mandatory_protocols for details.
232 /* .IP "\fB-P \fICApath/\fR (default: none)"
233 /*	The OpenSSL CApath/ directory (indexed via c_rehash(1)) for remote
234 /*	SMTP server certificate verification.  By default no CApath is used
235 /*	and no public CAs are trusted.
236 /* .IP "\fB-r \fIdelay\fR"
237 /*	With a cacheable TLS session, disconnect and reconnect after \fIdelay\fR
238 /*	seconds. Report whether the session is re-used. Retry if a new server
239 /*	is encountered, up to 5 times or as specified with the \fB-m\fR option.
240 /*	By default reconnection is disabled, specify a positive delay to
241 /*	enable this behavior.
242 /* .IP "\fB-R\fR"
243 /*	Use SRV lookup instead of MX.
244 /* .IP "\fB-s \fIservername\fR"
245 /*	The server name to send with the TLS Server Name Indication (SNI)
246 /*	extension.  When the server has DANE TLSA records, this parameter
247 /*	is ignored and the TLSA base domain is used instead.  Otherwise, SNI is
248 /*	not used by default, but can be enabled by specifying the desired value
249 /*	with this option.
250 /* .IP "\fB-S\fR"
251 /*	Disable SMTP; that is, connect to an LMTP server. The default port for
252 /*	LMTP over TCP is 24.  Alternative ports can specified by appending
253 /*	"\fI:servicename\fR" or ":\fIportnumber\fR" to the destination
254 /*	argument.
255 /* .IP "\fB-t \fItimeout\fR (default: \fB30\fR)"
256 /*	The TCP connection timeout to use.  This is also the timeout for
257 /*	reading the remote server's 220 banner.
258 /* .IP "\fB-T \fItimeout\fR (default: \fB30\fR)"
259 /*	The SMTP/LMTP command timeout for EHLO/LHLO, STARTTLS and QUIT.
260 /* .IP "\fB-v\fR"
261 /*	Enable verbose Postfix logging.  Specify more than once to increase
262 /*	the level of verbose logging.
263 /* .IP "\fB-w\fR"
264 /*	Enable outgoing TLS wrapper mode, or SUBMISSIONS/SMTPS support.  This
265 /*	is typically provided on port 465 by servers that are compatible with
266 /*	the SMTP-in-SSL protocol, rather than the STARTTLS protocol.
267 /*	The destination \fIdomain\fR:\fIport\fR must of course provide such
268 /*	a service.
269 /* .IP "\fB-X\fR"
270 /*	Enable \fBtlsproxy\fR(8) mode. This is an unsupported mode,
271 /*	for program development only.
272 /* .IP "[\fBinet:\fR]\fIdomain\fR[:\fIport\fR]"
273 /*	Connect via TCP to domain \fIdomain\fR, port \fIport\fR. The default
274 /*	port is \fBsmtp\fR (or 24 with LMTP).  With SMTP an MX lookup is
275 /*	performed to resolve the domain to a host, unless the domain is
276 /*	enclosed in \fB[]\fR.  If you want to connect to a specific MX host,
277 /*	for instance \fImx1.example.com\fR, specify [\fImx1.example.com\fR]
278 /*	as the destination and \fIexample.com\fR as a \fBmatch\fR argument.
279 /*	When using DNS, the destination domain is assumed fully qualified
280 /*	and no default domain or search suffixes are applied; you must use
281 /*	fully-qualified names or also enable \fBnative\fR host lookups
282 /*	(these don't support \fBdane\fR or \fBdane-only\fR as no DNSSEC
283 /*	validation information is available via \fBnative\fR lookups).
284 /* .IP "\fBunix:\fIpathname\fR"
285 /*	Connect to the UNIX-domain socket at \fIpathname\fR. LMTP only.
286 /* .IP "\fBmatch ...\fR"
287 /*	With no match arguments specified, certificate peername matching uses
288 /*	the compiled-in default strategies for each security level.  If you
289 /*	specify one or more arguments, these will be used as the list of
290 /*	certificate or public-key digests to match for the \fBfingerprint\fR
291 /*	level, or as the list of DNS names to match in the certificate at the
292 /*	\fBverify\fR and \fBsecure\fR levels.  If the security level is
293 /*	\fBdane\fR, or \fBdane-only\fR the match names are ignored, and
294 /*	\fBhostname, nexthop\fR strategies are used.
295 /* .ad
296 /* .fi
297 /* ENVIRONMENT
298 /* .ad
299 /* .fi
300 /* .IP \fBMAIL_CONFIG\fR
301 /*	Read configuration parameters from a non-default location.
302 /* .IP \fBMAIL_VERBOSE\fR
303 /*	Same as \fB-v\fR option.
304 /* SEE ALSO
305 /*	smtp-source(1), SMTP/LMTP message source
306 /*	smtp-sink(1), SMTP/LMTP message dump
307 /*
308 /* README FILES
309 /* .ad
310 /* .fi
311 /*	Use "\fBpostconf readme_directory\fR" or "\fBpostconf
312 /*	html_directory\fR" to locate this information.
313 /* .na
314 /* .nf
315 /*	TLS_README, Postfix STARTTLS howto
316 /* LICENSE
317 /* .ad
318 /* .fi
319 /*	The Secure Mailer license must be distributed with this software.
320 /* AUTHOR(S)
321 /*	Wietse Venema
322 /*	IBM T.J. Watson Research
323 /*	P.O. Box 704
324 /*	Yorktown Heights, NY 10598, USA
325 /*
326 /*	Wietse Venema
327 /*	Google, Inc.
328 /*	111 8th Avenue
329 /*	New York, NY 10011, USA
330 /*
331 /*	Viktor Dukhovni
332 /*--*/
333 
334  /*
335   * System library.
336   */
337 #include <sys_defs.h>
338 #include <stdarg.h>
339 #include <string.h>
340 #include <ctype.h>
341 #include <stdio.h>
342 #include <stdlib.h>
343 #include <unistd.h>
344 #include <signal.h>
345 #include <fcntl.h>
346 #include <errno.h>
347 #include <sys/socket.h>
348 #include <sys/un.h>
349 #include <netinet/in.h>
350 #include <arpa/inet.h>
351 
352 #ifdef STRCASECMP_IN_STRINGS_H
353 #include <strings.h>
354 #endif
355 
356  /*
357   * Utility library.
358   */
359 #include <msg.h>
360 #include <msg_vstream.h>
361 #include <vstring.h>
362 #include <vstream.h>
363 #include <vstring_vstream.h>
364 #include <mymalloc.h>
365 #include <stringops.h>
366 #include <argv.h>
367 #include <name_mask.h>
368 #include <name_code.h>
369 #include <chroot_uid.h>
370 #include <host_port.h>
371 #include <inet_proto.h>
372 #include <iostuff.h>
373 #include <timed_connect.h>
374 #include <sane_connect.h>
375 #include <myaddrinfo.h>
376 #include <sock_addr.h>
377 #include <midna_domain.h>
378 #include <clean_env.h>
379 #include <known_tcp_ports.h>
380 
381 #define STR(x)		vstring_str(x)
382 
383  /*
384   * Global library.
385   */
386 #include <mail_params.h>
387 #include <mail_conf.h>
388 #include <smtp_stream.h>
389 #include <dsn_buf.h>
390 #include <mail_parm_split.h>
391 #include <mail_proto.h>
392 
393 /* DNS library. */
394 
395 #include <dns.h>
396 
397  /*
398   * master library
399   */
400 #include <mail_server.h>
401 
402  /*
403   * TLS Library
404   */
405 #define TLS_INTERNAL
406 #include <tls.h>
407 
408 #ifdef USE_TLS
409 #include <tls_proxy.h>
410 #include <openssl/engine.h>
411 #endif
412 
413  /*
414   * Application specific
415   */
416 #include "tlsmgrmem.h"
417 
418 static int conn_tmout = 30;
419 static int smtp_tmout = 30;
420 
421 #define HOST_FLAG_DNS		(1<<0)
422 #define HOST_FLAG_NATIVE	(1<<1)
423 
424 #define MISC_FLAG_PREF_IPV6	(1<<0)
425 #define MISC_FLAG_PREF_IPV4	(1<<1)
426 
427 static const NAME_MASK lookup_masks[] = {
428     "dns", HOST_FLAG_DNS,
429     "native", HOST_FLAG_NATIVE,
430     0,
431 };
432 
433 static const NAME_CODE addr_pref_map[] = {
434     INET_PROTO_NAME_IPV6, MISC_FLAG_PREF_IPV6,
435     INET_PROTO_NAME_IPV4, MISC_FLAG_PREF_IPV4,
436     INET_PROTO_NAME_ANY, 0,
437     0, -1,
438 };
439 
440 typedef struct OPTIONS {
441     char   *logopts;
442     char   *level;
443     ARGV   *tas;
444     char   *host_lookup;
445     char   *addr_pref;
446 } OPTIONS;
447 
448  /*
449   * Per-session data structure with state.
450   *
451   * This software can maintain multiple parallel connections to the same SMTP
452   * server. However, it makes no more than one connection request at a time
453   * to avoid overwhelming the server with SYN packets and having to back off.
454   * Back-off would screw up the benchmark. Pending connection requests are
455   * kept in a linear list.
456   */
457 typedef struct STATE {
458     int     smtp;			/* SMTP or LMTP? */
459     int     host_lookup;		/* dns|native|dns,native */
460     int     addr_pref;			/* v4, v6, both */
461     int     log_mask;			/* via tls_log_mask() */
462     int     reconnect;			/* -r option */
463     int     max_reconnect;		/* -m option */
464     int     force_tlsa;			/* -f option */
465     unsigned port;			/* TCP port */
466     char   *dest;			/* Full destination spec */
467     char   *paddr;			/* XXX printable addr for proxy */
468     char   *addrport;			/* [addr]:port */
469     char   *namaddrport;		/* name[addr]:port */
470     char   *nexthop;			/* Nexthop domain for verification */
471     char   *hostname;			/* Hostname for verification */
472     DNS_RR *addr;			/* IPv[46] Address to (re)connect to */
473     DNS_RR *mx;				/* MX RRset qname, rname, valid */
474     int     pass;			/* Pass number, 2 for reconnect */
475     int     nochat;			/* disable chat logging */
476     int     dosrv;			/* look up SRV records instead of MX */
477     char   *helo;			/* Server name from EHLO reply */
478     DSN_BUF *why;			/* SMTP-style error message */
479     VSTRING *buffer;			/* Response buffer */
480     VSTREAM *stream;			/* Open connection */
481     int     level;			/* TLS security level */
482     int     wrapper_mode;		/* SMTPS support */
483 #ifdef USE_TLS
484     char   *mdalg;			/* fingerprint digest algorithm */
485     char   *CAfile;			/* Trusted public CAs */
486     char   *CApath;			/* Trusted public CAs */
487     char   *chains;			/* TLS client certificate chain files */
488     char   *certfile;			/* TLS client certificate file */
489     char   *keyfile;			/* TLS client key file */
490     char   *sni;			/* Server SNI name */
491     ARGV   *match;			/* match arguments */
492     int     print_trust;		/* -C option */
493     BIO    *tls_bio;			/* BIO wrapper for stdout */
494     TLS_APPL_STATE *tls_ctx;		/* Application TLS context */
495     TLS_SESS_STATE *tls_context;	/* Session TLS context */
496     TLS_DANE *dane;			/* DANE TLSA validation structure */
497     TLS_DANE *ddane;			/* DANE TLSA from DNS */
498     char   *grade;			/* Minimum cipher grade */
499     char   *protocols;			/* Protocol inclusion/exclusion */
500     int     mxinsec_level;		/* DANE for insecure MX RRs? */
501     int     tlsproxy_mode;
502 #endif
503     OPTIONS options;			/* JCL */
504 } STATE;
505 
506 static DNS_RR *host_addr(STATE *, const char *);
507 
508 #define HNAME(addr) (addr->qname)
509 
510  /*
511   * Structure with broken-up SMTP server response.
512   */
513 typedef struct {			/* server response */
514     int     code;			/* status */
515     char   *str;			/* text */
516     VSTRING *buf;			/* origin of text */
517 } RESPONSE;
518 
519 
520 /* command - send an SMTP command */
521 
command(STATE * state,int verbose,char * fmt,...)522 static void PRINTFLIKE(3, 4) command(STATE *state, int verbose, char *fmt,...)
523 {
524     VSTREAM *stream = state->stream;
525     VSTRING *buf;
526     va_list ap;
527     char   *line;
528 
529     buf = vstring_alloc(100);
530     va_start(ap, fmt);
531     vstring_vsprintf(buf, fmt, ap);
532     va_end(ap);
533     line = vstring_str(buf);
534 
535     while (line && *line) {
536 	char   *nextline = strchr(line, '\n');
537 
538 	if (nextline)
539 	    *nextline++ = '\0';
540 	if (verbose && !state->nochat)
541 	    msg_info("> %s", line);
542 	smtp_printf(stream, "%s", line);
543 	line = nextline;
544     }
545 
546     vstring_free(buf);
547 }
548 
549 /* response - read and process SMTP server response */
550 
response(STATE * state,int verbose)551 static RESPONSE *response(STATE *state, int verbose)
552 {
553     VSTREAM *stream = state->stream;
554     VSTRING *buf = state->buffer;
555     static RESPONSE rdata;
556     int     more;
557     char   *cp;
558 
559     /*
560      * Initialize the response data buffer. smtp_get() defends against a
561      * denial of service attack by limiting the amount of single-line text,
562      * and the loop below limits the amount of multi-line text that we are
563      * willing to store.
564      */
565     if (rdata.buf == 0)
566 	rdata.buf = vstring_alloc(100);
567 
568     /*
569      * Censor out non-printable characters in server responses. Concatenate
570      * multi-line server responses. Separate the status code from the text.
571      * Leave further parsing up to the application.
572      */
573 #define BUF ((char *) vstring_str(buf))
574     VSTRING_RESET(rdata.buf);
575     for (;;) {
576 	smtp_get(buf, stream, var_line_limit, SMTP_GET_FLAG_SKIP);
577 	for (cp = BUF; *cp != 0; cp++)
578 	    if (!ISPRINT(*cp) && !ISSPACE(*cp))
579 		*cp = '?';
580 	cp = BUF;
581 	if (verbose && !state->nochat)
582 	    msg_info("< %s", cp);
583 	while (ISDIGIT(*cp))
584 	    cp++;
585 	rdata.code = (cp - BUF == 3 ? atoi(BUF) : 0);
586 	if ((more = (*cp == '-')) != 0)
587 	    cp++;
588 	while (ISSPACE(*cp))
589 	    cp++;
590 	if (VSTRING_LEN(rdata.buf) < var_line_limit)
591 	    vstring_strcat(rdata.buf, cp);
592 	if (more == 0)
593 	    break;
594 	if (VSTRING_LEN(rdata.buf) < var_line_limit)
595 	    VSTRING_ADDCH(rdata.buf, '\n');
596     }
597     VSTRING_TERMINATE(rdata.buf);
598     rdata.str = vstring_str(rdata.buf);
599     return (&rdata);
600 }
601 
602 /* exception_text - translate exceptions from the smtp_stream module */
603 
exception_text(int except)604 static char *exception_text(int except)
605 {
606     switch (except) {
607 	case SMTP_ERR_EOF:
608 	return ("lost connection");
609     case SMTP_ERR_TIME:
610 	return ("timeout");
611     default:
612 	msg_panic("exception_text: unknown exception %d", except);
613     }
614 }
615 
616 /* greeting - read server's 220 greeting */
617 
greeting(STATE * state)618 static int greeting(STATE *state)
619 {
620     VSTREAM *stream = state->stream;
621     int     except;
622     RESPONSE *resp;
623 
624     /*
625      * Prepare for disaster.
626      */
627     smtp_stream_setup(stream, conn_tmout, /* deadline */ 1, /* minrate */ 0);
628     if ((except = vstream_setjmp(stream)) != 0) {
629 	msg_info("%s while reading server greeting", exception_text(except));
630 	return (1);
631     }
632 
633     /*
634      * Read and parse the server's SMTP greeting banner.
635      */
636     if (((resp = response(state, 1))->code / 100) != 2) {
637 	msg_info("SMTP service not available: %d %s", resp->code, resp->str);
638 	return (1);
639     }
640     return (0);
641 }
642 
643 /* ehlo - send EHLO/LHLO */
644 
ehlo(STATE * state)645 static RESPONSE *ehlo(STATE *state)
646 {
647     int     except;
648     int     verbose;
649     volatile char *ehlo = state->smtp ? "EHLO" : "LHLO";
650     VSTREAM *stream = state->stream;
651     RESPONSE *resp;
652 
653 #ifdef USE_TLS
654     verbose = (state->pass == 1 && state->nochat == 0);
655 #else
656     verbose = 1;
657 #endif
658 
659     /*
660      * Send the standard greeting with our hostname
661      */
662     smtp_stream_setup(stream, smtp_tmout, /* deadline */ 1, /* minrate */ 0);
663     if ((except = vstream_setjmp(stream)) != 0) {
664 	msg_info("%s while sending %s", exception_text(except), ehlo);
665 	return (0);
666     }
667     command(state, verbose, "%s %s", ehlo, var_myhostname);
668 
669     resp = response(state, verbose);
670     if (resp->code / 100 != 2) {
671 	msg_info("%s rejected: %d %s", ehlo, resp->code, resp->str);
672 	return (0);
673     }
674     return resp;
675 }
676 
677 #ifdef USE_TLS
678 
print_stack(STATE * state,x509_stack_t * sk,int trustout)679 static void print_stack(STATE *state, x509_stack_t *sk, int trustout)
680 {
681     int     i;
682 
683     for (i = 0; i < sk_X509_num(sk); i++) {
684 	X509   *cert = sk_X509_value(sk, i);
685 	char    buf[CCERT_BUFSIZ];
686 	X509_NAME *xn;
687 	char   *digest;
688 
689 	if ((xn = X509_get_subject_name(cert)) != 0) {
690 	    X509_NAME_oneline(xn, buf, sizeof buf);
691 	    BIO_printf(state->tls_bio, "%2d subject: %s\n", i, buf);
692 	}
693 	if ((xn = X509_get_issuer_name(cert)) != 0) {
694 	    X509_NAME_oneline(xn, buf, sizeof buf);
695 	    BIO_printf(state->tls_bio, "    issuer: %s\n", buf);
696 	}
697 	digest = tls_cert_fprint(cert, state->mdalg);
698 	BIO_printf(state->tls_bio, "   cert digest=%s\n", digest);
699 	myfree(digest);
700 
701 	digest = tls_pkey_fprint(cert, state->mdalg);
702 	BIO_printf(state->tls_bio, "   pkey digest=%s\n", digest);
703 	myfree(digest);
704 
705 	if (trustout)
706 	    PEM_write_bio_X509_AUX(state->tls_bio, cert);
707 	else
708 	    PEM_write_bio_X509(state->tls_bio, cert);
709     }
710 }
711 
print_trust_info(STATE * state)712 static void print_trust_info(STATE *state)
713 {
714     x509_stack_t *sk = SSL_get_peer_cert_chain(state->tls_context->con);
715 
716     if (sk != 0) {
717 	BIO_printf(state->tls_bio, "\n---\nCertificate chain\n");
718 	print_stack(state, sk, 0);
719     }
720 #ifdef dane_verify_debug
721     /* print internally constructed untrusted chain */
722     if ((sk = state->tls_context->untrusted) != 0) {
723 	BIO_printf(state->tls_bio, "\n---\nUntrusted chain\n");
724 	print_stack(state, sk, 0);
725     }
726     /* print associated root CA */
727     if ((sk = state->tls_context->trusted) != 0) {
728 	BIO_printf(state->tls_bio, "\n---\nTrusted chain\n");
729 	print_stack(state, sk, 1);
730     }
731 #endif
732 }
733 
734 /* starttls - SMTP STARTTLS handshake */
735 
starttls(STATE * state)736 static int starttls(STATE *state)
737 {
738     VSTRING *cipher_exclusions;
739     int     except;
740     RESPONSE *resp;
741     VSTREAM *stream = state->stream;
742     TLS_CLIENT_START_PROPS start_props;
743     TLS_CLIENT_INIT_PROPS init_props;
744     VSTREAM *tlsproxy;
745     VSTRING *port_buf;
746     int     cwd_fd;
747 
748     if (state->wrapper_mode == 0) {
749 	/* SMTP stream with deadline timeouts */
750 	smtp_stream_setup(stream, smtp_tmout, /* deadline */ 1, /* minrate */ 0);
751 	if ((except = vstream_setjmp(stream)) != 0) {
752 	    msg_fatal("%s while sending STARTTLS", exception_text(except));
753 	    return (1);
754 	}
755 	command(state, state->pass == 1, "STARTTLS");
756 
757 	resp = response(state, state->pass == 1);
758 	if (resp->code / 100 != 2) {
759 	    msg_info("STARTTLS rejected: %d %s", resp->code, resp->str);
760 	    return (1);
761 	}
762 
763 	/*
764 	 * Discard any plain-text data that may be piggybacked after the
765 	 * server's 220 STARTTLS reply. Should we abort the session instead?
766 	 */
767 	vstream_fpurge(stream, VSTREAM_PURGE_READ);
768     }
769 #define ADD_EXCLUDE(vstr, str) \
770     do { \
771 	if (*(str)) \
772 	    vstring_sprintf_append((vstr), "%s%s", \
773 				   VSTRING_LEN(vstr) ? " " : "", (str)); \
774     } while (0)
775 
776     cipher_exclusions = vstring_alloc(10);
777     ADD_EXCLUDE(cipher_exclusions, DEF_SMTP_TLS_EXCL_CIPH);
778     if (TLS_REQUIRED(state->level))
779 	ADD_EXCLUDE(cipher_exclusions, DEF_SMTP_TLS_MAND_EXCL);
780 
781     /*
782      * If we're authenticating suppress anonymous ciphersuites, otherwise at
783      * least encrypt, not much point in doing neither.
784      */
785     if (TLS_MUST_MATCH(state->level))
786 	ADD_EXCLUDE(cipher_exclusions, "aNULL");
787     else
788 	ADD_EXCLUDE(cipher_exclusions, "eNULL");
789 
790     smtp_stream_setup(stream, smtp_tmout, /* deadline */ 1, /* minrate */ 0);
791     if (state->tlsproxy_mode) {
792 	TLS_CLIENT_PARAMS tls_params;
793 
794 	/*
795 	 * Send all our wishes in one big request.
796 	 */
797 	TLS_PROXY_CLIENT_INIT_PROPS(&init_props,
798 				    log_param = "-L option",
799 				    log_level = state->options.logopts,
800 				    verifydepth = DEF_SMTP_TLS_SCERT_VD,
801 				    cache_type = TLS_MGR_SCACHE_SMTP,
802 				    chain_files = state->chains,
803 				    cert_file = state->certfile,
804 				    key_file = state->keyfile,
805 				    dcert_file = "",
806 				    dkey_file = "",
807 				    eccert_file = "",
808 				    eckey_file = "",
809 				    CAfile = state->CAfile,
810 				    CApath = state->CApath,
811 				    mdalg = state->mdalg);
812 	TLS_PROXY_CLIENT_START_PROPS(&start_props,
813 				     timeout = smtp_tmout,
814 				     tls_level = state->level,
815 				     nexthop = state->nexthop,
816 				     host = state->hostname,
817 				     namaddr = state->namaddrport,
818 				     sni = state->sni,
819 				     serverid = state->addrport,
820 				     helo = state->helo ? state->helo : "",
821 				     protocols = state->protocols,
822 				     cipher_grade = state->grade,
823 				     cipher_exclusions
824 				     = vstring_str(cipher_exclusions),
825 				     matchargv = state->match,
826 				     mdalg = state->mdalg,
827 				     dane = state->ddane ?
828 				     state->ddane : state->dane);
829 
830 #define PROXY_OPEN_FLAGS \
831         (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_SEND_CONTEXT)
832 #define var_tlsproxy_service
833 
834 	if ((cwd_fd = open(".", O_RDONLY)) < 0)
835 	    msg_fatal("open(\".\", O_RDONLY): %m");
836 	if (chdir(var_queue_dir) < 0)
837 	    msg_fatal("chdir(%s): %m", var_queue_dir);
838 	port_buf = vstring_alloc(100);
839 	vstring_sprintf(port_buf, "%d", ntohs(state->port));
840 	tlsproxy =
841 	    tls_proxy_open(DEF_TLSPROXY_SERVICE /* TODO */ , PROXY_OPEN_FLAGS,
842 			   state->stream, state->paddr, STR(port_buf),
843 			   smtp_tmout, smtp_tmout, state->addrport,
844 			   tls_proxy_client_param_from_config(&tls_params),
845 			   &init_props, &start_props);
846 	vstring_free(port_buf);
847 	if (fchdir(cwd_fd) < 0)
848 	    msg_fatal("fchdir: %m");
849 	(void) close(cwd_fd);
850 
851 	/*
852 	 * To insert tlsproxy(8) between this process and the remote SMTP
853 	 * server, we swap the file descriptors between the tlsproxy and
854 	 * session->stream VSTREAMS, so that we don't lose all the
855 	 * user-configurable session->stream attributes (such as longjump
856 	 * buffers or timeouts).
857 	 *
858 	 * TODO: the tlsproxy RPCs should return more error detail than a "NO"
859 	 * result.
860 	 */
861 	if (tlsproxy == 0) {
862 	    state->tls_context = 0;
863 	} else {
864 	    vstream_control(tlsproxy,
865 			    CA_VSTREAM_CTL_DOUBLE,
866 			    CA_VSTREAM_CTL_END);
867 	    vstream_control(state->stream,
868 			    CA_VSTREAM_CTL_SWAP_FD(tlsproxy),
869 			    CA_VSTREAM_CTL_END);
870 	    (void) vstream_fclose(tlsproxy);	/* direct-to-server stream! */
871 
872 	    /*
873 	     * There must not be any pending data in the stream buffers
874 	     * before we read the TLS context attributes.
875 	     */
876 	    vstream_fpurge(state->stream, VSTREAM_PURGE_BOTH);
877 
878 	    /*
879 	     * After plumbing the plaintext stream, receive the TLS context
880 	     * object. For this we use the same VSTREAM buffer that we also
881 	     * use to receive subsequent SMTP commands, therefore we must be
882 	     * prepared for the possibility that the remote SMTP server
883 	     * starts talking immediately. The tlsproxy implementation sends
884 	     * the TLS context before remote content. The attribute protocol
885 	     * is robust enough that an adversary cannot insert their own TLS
886 	     * context attributes.
887 	     */
888 	    state->tls_context = tls_proxy_context_receive(state->stream);
889 	    if (state->tls_context) {
890 		if (state->log_mask &
891 		    (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT))
892 		    msg_info("%s: subject_CN=%s, issuer_CN=%s, "
893 			     "fingerprint=%s, pkey_fingerprint=%s",
894 			     state->namaddrport, state->tls_context->peer_CN,
895 			     state->tls_context->issuer_CN,
896 			     state->tls_context->peer_cert_fprint,
897 			     state->tls_context->peer_pkey_fprint);
898 		tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_NEW,
899 				state->tls_context);
900 	    } else {
901 		msg_warn("error receiving TLS proxy context");
902 	    }
903 	}
904     } else {					/* tls_proxy_mode */
905 	state->tls_context =
906 	    TLS_CLIENT_START(&start_props,
907 			     ctx = state->tls_ctx,
908 			     stream = stream,
909 			     fd = -1,
910 			     timeout = smtp_tmout,
911 			     tls_level = state->level,
912 			     nexthop = state->nexthop,
913 			     host = state->hostname,
914 			     namaddr = state->namaddrport,
915 			     sni = state->sni,
916 			     serverid = state->addrport,
917 			     helo = state->helo ? state->helo : "",
918 			     protocols = state->protocols,
919 			     cipher_grade = state->grade,
920 			     cipher_exclusions
921 			     = vstring_str(cipher_exclusions),
922 			     matchargv = state->match,
923 			     mdalg = state->mdalg,
924 			  dane = state->ddane ? state->ddane : state->dane);
925     }						/* tlsproxy_mode */
926     vstring_free(cipher_exclusions);
927     if (state->helo) {
928 	myfree(state->helo);
929 	state->helo = 0;
930     }
931     if (state->tls_context == 0) {
932 	/* We must avoid further I/O, the peer is in an undefined state. */
933 	(void) vstream_fpurge(stream, VSTREAM_PURGE_BOTH);
934 	(void) vstream_fclose(stream);
935 	state->stream = 0;
936 	return (1);
937     }
938     if (state->wrapper_mode && greeting(state) != 0)
939 	return (1);
940 
941     if (state->pass == 1) {
942 	ehlo(state);
943 	if (!TLS_CERT_IS_PRESENT(state->tls_context))
944 	    msg_info("Server is anonymous");
945 	else if (state->tlsproxy_mode == 0) {
946 	    if (state->print_trust)
947 		print_trust_info(state);
948 	    state->log_mask &= ~(TLS_LOG_CERTMATCH | TLS_LOG_PEERCERT |
949 				 TLS_LOG_VERBOSE | TLS_LOG_UNTRUSTED);
950 	}
951 	state->log_mask |= TLS_LOG_CACHE | TLS_LOG_SUMMARY;
952 	tls_update_app_logmask(state->tls_ctx, state->log_mask);
953     }
954     return (0);
955 }
956 
957 #endif
958 
959 /* doproto - do SMTP handshake */
960 
doproto(STATE * state)961 static int doproto(STATE *state)
962 {
963     VSTREAM *stream = state->stream;
964     RESPONSE *resp;
965     int     except;
966     int     n;
967     char   *lines;
968     char   *words = 0;
969     char   *word;
970 
971     if (!state->wrapper_mode) {
972 	if (greeting(state) != 0)
973 	    return (1);
974 	if ((resp = ehlo(state)) == 0)
975 	    return (1);
976 
977 	lines = resp->str;
978 	for (n = 0; (words = mystrtok(&lines, "\n")) != 0; ++n) {
979 	    if ((word = mystrtok(&words, " \t=")) != 0) {
980 		if (n == 0)
981 		    state->helo = mystrdup(word);
982 		if (strcasecmp(word, "STARTTLS") == 0)
983 		    break;
984 	    }
985 	}
986     }
987 #ifdef USE_TLS
988     if ((state->wrapper_mode || words) && state->tls_ctx)
989 	if (starttls(state))
990 	    return (1);
991 #endif
992 
993     /*
994      * Prepare for disaster.
995      */
996     smtp_stream_setup(stream, smtp_tmout, /* deadline */ 1, /* minrate */ 0);
997     if ((except = vstream_setjmp(stream)) != 0) {
998 	msg_warn("%s while sending QUIT command", exception_text(except));
999 	return (0);
1000     }
1001     command(state, 1, "QUIT");
1002     (void) response(state, 1);
1003     return (0);
1004 }
1005 
1006 /* connect_sock - connect a socket over some transport */
1007 
connect_sock(int sock,struct sockaddr * sa,int salen,const char * name,const char * addr,STATE * state)1008 static VSTREAM *connect_sock(int sock, struct sockaddr *sa, int salen,
1009 		           const char *name, const char *addr, STATE *state)
1010 {
1011     DSN_BUF *why = state->why;
1012     int     conn_stat;
1013     int     saved_errno;
1014     VSTREAM *stream;
1015 
1016     if (conn_tmout > 0) {
1017 	non_blocking(sock, NON_BLOCKING);
1018 	conn_stat = timed_connect(sock, sa, salen, conn_tmout);
1019 	saved_errno = errno;
1020 	non_blocking(sock, BLOCKING);
1021 	errno = saved_errno;
1022     } else {
1023 	conn_stat = sane_connect(sock, sa, salen);
1024     }
1025     if (conn_stat < 0) {
1026 	if (state->port)
1027 	    dsb_simple(why, "4.4.1", "connect to %s[%s]:%d: %m",
1028 		       name, addr, ntohs(state->port));
1029 	else
1030 	    dsb_simple(why, "4.4.1", "connect to %s[%s]: %m", name, addr);
1031 	close(sock);
1032 	return (0);
1033     }
1034     stream = vstream_fdopen(sock, O_RDWR);
1035     state->namaddrport =
1036 	vstring_export(state->port == 0 ?
1037 		  vstring_sprintf(vstring_alloc(10), "%s[%s]", name, addr) :
1038 		       vstring_sprintf(vstring_alloc(10), "%s[%s]:%u",
1039 				       name, addr, ntohs(state->port)));
1040     state->addrport =
1041 	vstring_export(state->port == 0 ?
1042 		       vstring_sprintf(vstring_alloc(10), "%s", addr) :
1043 		       vstring_sprintf(vstring_alloc(10), "[%s]:%u",
1044 				       addr, ntohs(state->port)));
1045 
1046     state->paddr = mystrdup(addr);		/* XXX for tlsproxy */
1047 
1048     /*
1049      * Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE.
1050      */
1051     if (sa->sa_family == AF_INET
1052 #ifdef AF_INET6
1053 	|| sa->sa_family == AF_INET6
1054 #endif
1055 	)
1056 	vstream_tweak_tcp(stream);
1057 
1058     return (stream);
1059 }
1060 
1061 /* connect_unix - connect to a unix-domain socket */
1062 
connect_unix(STATE * state,const char * path)1063 static VSTREAM *connect_unix(STATE *state, const char *path)
1064 {
1065     static const char *myname = "connect_unix";
1066     DSN_BUF *why = state->why;
1067     struct sockaddr_un sock_un;
1068     int     len = strlen(path);
1069     int     sock;
1070 
1071     if (!state->nexthop)
1072 	state->nexthop = mystrdup(var_myhostname);
1073     state->hostname = mystrdup(var_myhostname);
1074 
1075     dsb_reset(why);				/* Paranoia */
1076 
1077     /*
1078      * Sanity checks.
1079      */
1080     if (len >= (int) sizeof(sock_un.sun_path)) {
1081 	dsb_simple(why, "4.3.5", "unix-domain name too long: %s", path);
1082 	return (0);
1083     }
1084 
1085     /*
1086      * Initialize.
1087      */
1088     memset((void *) &sock_un, 0, sizeof(sock_un));
1089     sock_un.sun_family = AF_UNIX;
1090 #ifdef HAS_SUN_LEN
1091     sock_un.sun_len = len + 1;
1092 #endif
1093     memcpy(sock_un.sun_path, path, len + 1);
1094 
1095     /*
1096      * Create a client socket.
1097      */
1098     if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
1099 	msg_fatal("%s: socket: %m", myname);
1100 
1101     /*
1102      * Connect to the server.
1103      */
1104     if (msg_verbose)
1105 	msg_info("%s: trying: %s...", myname, path);
1106 
1107     return (connect_sock(sock, (struct sockaddr *) &sock_un, sizeof(sock_un),
1108 			 var_myhostname, path, state));
1109 }
1110 
1111 /* connect_addr - connect to explicit address */
1112 
connect_addr(STATE * state,DNS_RR * addr)1113 static VSTREAM *connect_addr(STATE *state, DNS_RR *addr)
1114 {
1115     static const char *myname = "connect_addr";
1116     DSN_BUF *why = state->why;
1117     struct sockaddr_storage ss;		/* remote */
1118     struct sockaddr *sa = (struct sockaddr *) &ss;
1119     SOCKADDR_SIZE salen = sizeof(ss);
1120     MAI_HOSTADDR_STR hostaddr;
1121     int     sock;
1122 
1123     dsb_reset(why);				/* Paranoia */
1124 
1125     /*
1126      * Sanity checks.
1127      */
1128     if (dns_rr_to_sa(addr, state->port, sa, &salen) != 0) {
1129 	msg_warn("%s: skip address type %s: %m",
1130 		 myname, dns_strtype(addr->type));
1131 	dsb_simple(why, "4.4.0", "network address conversion failed: %m");
1132 	return (0);
1133     }
1134 
1135     /*
1136      * Initialize.
1137      */
1138     if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
1139 	msg_fatal("%s: socket: %m", myname);
1140 
1141     if (inet_windowsize > 0)
1142 	set_inet_windowsize(sock, inet_windowsize);
1143 
1144     /*
1145      * Connect to the server.
1146      */
1147     SOCKADDR_TO_HOSTADDR(sa, salen, &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
1148     if (msg_verbose)
1149 	msg_info("%s: trying: %s[%s] port %d...",
1150 		 myname, HNAME(addr), hostaddr.buf, ntohs(state->port));
1151 
1152     return (connect_sock(sock, sa, salen, HNAME(addr), hostaddr.buf, state));
1153 }
1154 
1155 #define HAS_DSN(why)		(STR((why)->status)[0] != 0)
1156 #define HAS_SOFT_DSN(why)	(STR((why)->status)[0] == '4')
1157 #define HAS_HARD_DSN(why)	(STR((why)->status)[0] == '5')
1158 #define HAS_LOOP_DSN(why) \
1159     (HAS_DSN(why) && strcmp(STR((why)->status) + 1, ".4.6") == 0)
1160 
1161 #define SET_SOFT_DSN(why)	(STR((why)->status)[0] = '4')
1162 #define SET_HARD_DSN(why)	(STR((why)->status)[0] = '5')
1163 
1164 /* addr_one - address lookup for one host name */
1165 
addr_one(STATE * state,DNS_RR * addr_list,const char * host,int res_opt,unsigned pref,unsigned port)1166 static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host,
1167 			        int res_opt, unsigned pref, unsigned port)
1168 {
1169     static const char *myname = "addr_one";
1170     DSN_BUF *why = state->why;
1171     DNS_RR *addr = 0;
1172     DNS_RR *rr;
1173     int     aierr;
1174     struct addrinfo *res0;
1175     struct addrinfo *res;
1176     const INET_PROTO_INFO *proto_info = inet_proto_info();
1177     int     found;
1178 
1179     if (msg_verbose)
1180 	msg_info("%s: host %s", myname, host);
1181 
1182     /*
1183      * Interpret a numerical name as an address.
1184      */
1185     if (hostaddr_to_sockaddr(host, (char *) 0, 0, &res0) == 0
1186      && strchr((char *) proto_info->sa_family_list, res0->ai_family) != 0) {
1187 	if ((addr = dns_sa_to_rr(host, pref, res0->ai_addr)) == 0)
1188 	    msg_fatal("host %s: conversion error for address family %d: %m",
1189 		    host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
1190 	addr->pref = pref;
1191 	addr->port = port;
1192 	addr_list = dns_rr_append(addr_list, addr);
1193 	freeaddrinfo(res0);
1194 	return (addr_list);
1195     }
1196 
1197     /*
1198      * Use DNS lookup, but keep the option open to use native name service.
1199      *
1200      * XXX A soft error dominates past and future hard errors. Therefore we
1201      * should not clobber a soft error text and status code.
1202      */
1203     if (state->host_lookup & HOST_FLAG_DNS) {
1204 	switch (dns_lookup_v(host, res_opt, &addr, (VSTRING *) 0,
1205 			     why->reason, DNS_REQ_FLAG_NONE,
1206 			     proto_info->dns_atype_list)) {
1207 	case DNS_OK:
1208 	    for (rr = addr; rr; rr = rr->next) {
1209 		rr->pref = pref;
1210 		rr->port = port;
1211 	    }
1212 	    addr_list = dns_rr_append(addr_list, addr);
1213 	    return (addr_list);
1214 	default:
1215 	    dsb_status(why, "4.4.3");
1216 	    return (addr_list);
1217 	case DNS_FAIL:
1218 	    dsb_status(why, HAS_SOFT_DSN(why) ? "4.4.3" : "5.4.3");
1219 	    return (addr_list);
1220 	case DNS_INVAL:
1221 	    dsb_status(why, HAS_SOFT_DSN(why) ? "4.4.4" : "5.4.4");
1222 	    return (addr_list);
1223 	case DNS_NOTFOUND:
1224 	    dsb_status(why, HAS_SOFT_DSN(why) ? "4.4.4" : "5.4.4");
1225 	    /* maybe native naming service will succeed */
1226 	    break;
1227 	}
1228     }
1229 
1230     /*
1231      * Use the native name service which also looks in /etc/hosts.
1232      *
1233      * XXX A soft error dominates past and future hard errors. Therefore we
1234      * should not clobber a soft error text and status code.
1235      */
1236 #define RETRY_AI_ERROR(e) \
1237         ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
1238 #ifdef EAI_NODATA
1239 #define DSN_NOHOST(e) \
1240 	((e) == EAI_AGAIN || (e) == EAI_NODATA || (e) == EAI_NONAME)
1241 #else
1242 #define DSN_NOHOST(e) \
1243 	((e) == EAI_AGAIN || (e) == EAI_NONAME)
1244 #endif
1245 
1246     if (state->host_lookup & HOST_FLAG_NATIVE) {
1247 	if ((aierr = hostname_to_sockaddr(host, (char *) 0, 0, &res0)) != 0) {
1248 	    dsb_simple(why, (HAS_SOFT_DSN(why) || RETRY_AI_ERROR(aierr)) ?
1249 		       (DSN_NOHOST(aierr) ? "4.4.4" : "4.3.0") :
1250 		       (DSN_NOHOST(aierr) ? "5.4.4" : "5.3.0"),
1251 		       "unable to look up host %s: %s",
1252 		       host, MAI_STRERROR(aierr));
1253 	} else {
1254 	    for (found = 0, res = res0; res != 0; res = res->ai_next) {
1255 		if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
1256 		    msg_info("skipping address family %d for host %s",
1257 			     res->ai_family, host);
1258 		    continue;
1259 		}
1260 		found++;
1261 		if ((addr = dns_sa_to_rr(host, pref, res->ai_addr)) == 0)
1262 		    msg_fatal("host %s: conversion error for address family %d: %m",
1263 		    host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
1264 		addr_list = dns_rr_append(addr_list, addr);
1265 	    }
1266 	    freeaddrinfo(res0);
1267 	    if (found == 0) {
1268 		dsb_simple(why, HAS_SOFT_DSN(why) ? "4.4.4" : "5.4.4",
1269 			   "%s: host not found", host);
1270 	    }
1271 	    return (addr_list);
1272 	}
1273     }
1274 
1275     /*
1276      * No further alternatives for host lookup.
1277      */
1278     return (addr_list);
1279 }
1280 
1281 /* mx_addr_list - address lookup for a list of mail exchangers */
1282 
mx_addr_list(STATE * state,DNS_RR * mx_names)1283 static DNS_RR *mx_addr_list(STATE *state, DNS_RR *mx_names)
1284 {
1285     static const char *myname = "mx_addr_list";
1286     DNS_RR *addr_list = 0;
1287     DNS_RR *rr;
1288     int     res_opt = 0;
1289 
1290     if (mx_names->dnssec_valid)
1291 	res_opt = RES_USE_DNSSEC;
1292 #ifdef USE_TLS
1293     else if (state->mxinsec_level > TLS_LEV_MAY)
1294 	res_opt = RES_USE_DNSSEC;
1295 #endif
1296 
1297     for (rr = mx_names; rr; rr = rr->next) {
1298 	if (rr->type != T_MX && rr->type != T_SRV)
1299 	    msg_panic("%s: bad resource type: %d", myname, rr->type);
1300 	addr_list = addr_one(state, addr_list, (char *) rr->data, res_opt,
1301 			     rr->pref, rr->port);
1302     }
1303     return (addr_list);
1304 }
1305 
1306 /* domain_addr - mail exchanger address lookup */
1307 
domain_addr(STATE * state,char * domain)1308 static DNS_RR *domain_addr(STATE *state, char *domain)
1309 {
1310     DNS_RR *mx_names;
1311     DNS_RR *addr_list = 0;
1312     int     r = 0;			/* Resolver flags */
1313     const char *aname;
1314 
1315     dsb_reset(state->why);
1316 
1317 #if (RES_USE_DNSSEC != 0) && (RES_USE_EDNS0 != 0)
1318     r |= RES_USE_DNSSEC;
1319 #endif
1320 
1321     /*
1322      * IDNA support.
1323      */
1324 #ifndef NO_EAI
1325     if (!allascii(domain) && (aname = midna_domain_to_ascii(domain)) != 0) {
1326 	msg_info("%s asciified to %s", domain, aname);
1327     } else
1328 #endif
1329 	aname = domain;
1330 
1331     switch (dns_lookup(aname, T_MX, r, &mx_names, (VSTRING *) 0,
1332 		       state->why->reason)) {
1333     default:
1334 	dsb_status(state->why, "4.4.3");
1335 	break;
1336     case DNS_INVAL:
1337 	dsb_status(state->why, "5.4.4");
1338 	break;
1339     case DNS_NULLMX:
1340 	dsb_status(state->why, "5.1.0");
1341 	break;
1342     case DNS_FAIL:
1343 	dsb_status(state->why, "5.4.3");
1344 	break;
1345     case DNS_OK:
1346 	mx_names = dns_rr_sort(mx_names, dns_rr_compare_pref_any);
1347 	addr_list = mx_addr_list(state, mx_names);
1348 	state->mx = dns_rr_copy(mx_names);
1349 	dns_rr_free(mx_names);
1350 	if (addr_list == 0) {
1351 	    msg_warn("no MX host for %s has a valid address record", domain);
1352 	    break;
1353 	}
1354 #define COMPARE_ADDR(flags) \
1355 	((flags & MISC_FLAG_PREF_IPV6) ? dns_rr_compare_pref_ipv6 : \
1356 	 (flags & MISC_FLAG_PREF_IPV4) ? dns_rr_compare_pref_ipv4 : \
1357 	 dns_rr_compare_pref_any)
1358 	if (addr_list && addr_list->next) {
1359 	    addr_list = dns_rr_shuffle(addr_list);
1360 	    addr_list = dns_rr_sort(addr_list, COMPARE_ADDR(state->addr_pref));
1361 	}
1362 	break;
1363     case DNS_NOTFOUND:
1364 	addr_list = host_addr(state, domain);
1365 	break;
1366     }
1367 
1368     return (addr_list);
1369 }
1370 
1371 /* service_addr - mail exchanger address lookup */
1372 
service_addr(STATE * state,const char * domain,const char * service)1373 static DNS_RR *service_addr(STATE *state, const char *domain,
1374 			            const char *service)
1375 {
1376     VSTRING *srv_qname = vstring_alloc(100);
1377     char   *str_srv_qname;
1378     DNS_RR *srv_names;
1379     DNS_RR *addr_list = 0;
1380     int     r = 0;			/* Resolver flags */
1381     const char *aname;
1382 
1383     dsb_reset(state->why);
1384 
1385 #if (RES_USE_DNSSEC != 0) && (RES_USE_EDNS0 != 0)
1386     r |= RES_USE_DNSSEC;
1387 #endif
1388 
1389     vstring_sprintf(srv_qname, "_%s._tcp.%s", service, domain);
1390     str_srv_qname = STR(srv_qname);
1391 
1392     /*
1393      * IDNA support.
1394      */
1395 #ifndef NO_EAI
1396     if (!allascii(str_srv_qname)
1397 	&& (aname = midna_domain_to_ascii(str_srv_qname)) != 0) {
1398 	msg_info("%s asciified to %s", str_srv_qname, aname);
1399     } else
1400 #endif
1401 	aname = str_srv_qname;
1402 
1403     switch (dns_lookup(aname, T_SRV, r, &srv_names, (VSTRING *) 0,
1404 		       state->why->reason)) {
1405     default:
1406 	dsb_status(state->why, "4.4.3");
1407 	break;
1408     case DNS_INVAL:
1409 	dsb_status(state->why, "5.4.4");
1410 	break;
1411     case DNS_NULLMX:
1412 	dsb_status(state->why, "5.1.0");
1413 	break;
1414     case DNS_FAIL:
1415 	dsb_status(state->why, "5.4.3");
1416 	break;
1417     case DNS_OK:
1418 	/* Shuffle then sort the SRV rr records by priority and weight. */
1419 	srv_names = dns_srv_rr_sort(srv_names);
1420 	addr_list = mx_addr_list(state, srv_names);
1421 	state->mx = dns_rr_copy(srv_names);
1422 	dns_rr_free(srv_names);
1423 	if (addr_list == 0) {
1424 	    msg_warn("no SRV host for %s has a valid address record",
1425 		     str_srv_qname);
1426 	    break;
1427 	}
1428 	/* TODO: sort by priority, weight, and address family preference. */
1429 	break;
1430     case DNS_NOTFOUND:
1431 	dsb_status(state->why, "5.4.4");
1432 	break;
1433     }
1434 
1435     vstring_free(srv_qname);
1436     return (addr_list);
1437 }
1438 
1439 /* host_addr - direct host lookup */
1440 
host_addr(STATE * state,const char * host)1441 static DNS_RR *host_addr(STATE *state, const char *host)
1442 {
1443     DSN_BUF *why = state->why;
1444     DNS_RR *addr_list;
1445     int     res_opt = 0;
1446     const char *ahost;
1447 
1448     dsb_reset(why);				/* Paranoia */
1449 
1450 #if (RES_USE_DNSSEC != 0) && (RES_USE_EDNS0 != 0)
1451     res_opt |= RES_USE_DNSSEC;
1452 #endif
1453 
1454     /*
1455      * IDNA support.
1456      */
1457 #ifndef NO_EAI
1458     if (!allascii(host) && (ahost = midna_domain_to_ascii(host)) != 0) {
1459 	msg_info("%s asciified to %s", host, ahost);
1460     } else
1461 #endif
1462 	ahost = host;
1463 
1464 #define PREF0	0
1465 #define NOPORT	0
1466     addr_list = addr_one(state, (DNS_RR *) 0, ahost, res_opt, PREF0, NOPORT);
1467     if (addr_list && addr_list->next) {
1468 	addr_list = dns_rr_shuffle(addr_list);
1469 	if (inet_proto_info()->ai_family_list[1] != 0)
1470 	    addr_list = dns_rr_sort(addr_list, COMPARE_ADDR(state->addr_pref));
1471     }
1472     return (addr_list);
1473 }
1474 
1475 /* dane_host_level - candidate host "dane" or degraded security level */
1476 
dane_host_level(STATE * state,DNS_RR * addr)1477 static int dane_host_level(STATE *state, DNS_RR *addr)
1478 {
1479     int     level = state->level;
1480 
1481 #ifdef USE_TLS
1482     if (TLS_DANE_BASED(level)) {
1483 	if (state->mx == 0 || state->mx->dnssec_valid ||
1484 	    state->mxinsec_level > TLS_LEV_MAY) {
1485 
1486 	    /* See addr loop in connect_remote() */
1487 	    if (state->ddane)
1488 		tls_dane_free(state->ddane);
1489 
1490 	    /*
1491 	     * When TLSA lookups fail, next host.  If unusable or not found,
1492 	     * fallback to "secure"
1493 	     */
1494 	    state->ddane = tls_dane_resolve(state->port, "tcp", addr,
1495 					    state->force_tlsa);
1496 	    if (!state->ddane) {
1497 		dsb_simple(state->why, "4.7.5",
1498 			   "TLSA lookup error for %s:%u",
1499 			   HNAME(addr), ntohs(state->port));
1500 		level = TLS_LEV_INVALID;
1501 	    } else if (tls_dane_notfound(state->ddane)
1502 		       || tls_dane_unusable(state->ddane)) {
1503 		if (msg_verbose || level == TLS_LEV_DANE_ONLY)
1504 		    msg_info("no %sTLSA records found, "
1505 			     "resorting to \"secure\"",
1506 			     tls_dane_unusable(state->ddane) ?
1507 			     "usable " : "");
1508 		level = TLS_LEV_SECURE;
1509 	    } else if (state->ddane->tlsa == 0) {
1510 		msg_panic("DANE activated with no TLSA records to match");
1511 	    } else if (state->mx && !state->mx->dnssec_valid &&
1512 		       state->mxinsec_level == TLS_LEV_ENCRYPT) {
1513 		msg_info("TLSA RRs found, MX RRset insecure: just encrypt");
1514 		tls_dane_free(state->ddane);
1515 		state->ddane = 0;
1516 		level = TLS_LEV_ENCRYPT;
1517 	    } else {
1518 		if (state->match)
1519 		    argv_free(state->match);
1520 		argv_add(state->match = argv_alloc(2),
1521 			 state->ddane->base_domain, ARGV_END);
1522 		if (state->mx) {
1523 		    if (!state->mx->dnssec_valid) {
1524 			msg_info("MX RRset insecure: log verified as trusted");
1525 			level = TLS_LEV_HALF_DANE;
1526 		    }
1527 		    if (strcmp(state->mx->qname, state->mx->rname) == 0)
1528 			argv_add(state->match, state->mx->qname, ARGV_END);
1529 		    else
1530 			argv_add(state->match, state->mx->rname,
1531 				 state->mx->qname, ARGV_END);
1532 		}
1533 	    }
1534 	} else if (state->mx && !state->mx->dnssec_valid &&
1535 		   state->mxinsec_level == TLS_LEV_MAY) {
1536 	    msg_info("MX RRset is insecure: try to encrypt");
1537 	    level = TLS_LEV_MAY;
1538 	} else {
1539 	    level = TLS_LEV_SECURE;
1540 	}
1541     }
1542 #endif
1543 
1544     return (level);
1545 }
1546 
1547 /* parse_destination - parse host/port destination */
1548 
parse_destination(char * destination,char * def_service,char ** hostp,char ** servicep,unsigned * portp)1549 static char *parse_destination(char *destination, char *def_service,
1550 			               char **hostp, char **servicep,
1551 			               unsigned *portp)
1552 {
1553     char   *buf = mystrdup(destination);
1554     char   *service;
1555     struct servent *sp;
1556     char   *protocol = "tcp";
1557     unsigned port;
1558     const char *err;
1559 
1560     if (msg_verbose)
1561 	msg_info("parse_destination: %s %s", destination, def_service);
1562 
1563     /*
1564      * Parse the host/port information. We're working with a copy of the
1565      * destination argument so the parsing can be destructive.
1566      */
1567     if ((err = host_port(buf, hostp, (char *) 0, servicep, def_service)) != 0)
1568 	msg_fatal("%s in server description: %s", err, destination);
1569 
1570     /*
1571      * Convert service to port number, network byte order.
1572      */
1573     service = (char *) filter_known_tcp_port(*servicep);
1574     if (alldig(service)) {
1575 	if ((port = atoi(service)) >= 65536 || port == 0)
1576 	    msg_fatal("bad network port: %s for destination: %s",
1577 		      service, destination);
1578 	*portp = htons(port);
1579     } else {
1580 	if ((sp = getservbyname(service, protocol)) != 0)
1581 	    *portp = sp->s_port;
1582 	else if (strcmp(service, "smtp") == 0)
1583 	    *portp = htons(25);
1584 	else
1585 	    msg_fatal("unknown service: %s/%s", service, protocol);
1586     }
1587     return (buf);
1588 }
1589 
1590 /* connect_remote - connect to TCP destination or log an error */
1591 
connect_remote(STATE * state,char * dest)1592 static void connect_remote(STATE *state, char *dest)
1593 {
1594     DNS_RR *addr;
1595 
1596     /* When reconnecting use IP address of previous session */
1597     if (state->addr == 0) {
1598 	char   *buf;
1599 	char   *domain;
1600 	char   *service;
1601 
1602 	buf = parse_destination(dest, state->smtp ? "smtp" : "24",
1603 				&domain, &service, &state->port);
1604 	if (!state->nexthop)
1605 	    state->nexthop = mystrdup(domain);
1606 	if (state->smtp == 0 || *dest == '[')
1607 	    state->addr = host_addr(state, domain);
1608 	else if (state->dosrv)
1609 	    state->addr = service_addr(state, domain, service);
1610 	else
1611 	    state->addr = domain_addr(state, domain);
1612 	myfree(buf);
1613 
1614 	if (state->addr == 0) {
1615 	    msg_info("Destination address lookup failed: %s",
1616 		     vstring_str(state->why->reason));
1617 	    return;
1618 	}
1619     }
1620     for (addr = state->addr; addr; addr = addr->next) {
1621 	int     level = dane_host_level(state, addr);
1622 
1623 	if (addr->port)				/* SRV port override */
1624 	    state->port = htons(addr->port);
1625 
1626 	if (level == TLS_LEV_INVALID
1627 	    || (state->stream = connect_addr(state, addr)) == 0) {
1628 	    msg_info("Failed to establish session to %s via %s:%u: %s",
1629 		     dest, HNAME(addr), addr->port,
1630 		     vstring_str(state->why->reason));
1631 	    continue;
1632 	}
1633 	/* We have a connection */
1634 	state->level = level;
1635 	state->hostname = mystrdup(HNAME(addr));
1636 
1637 	/* We use the same address when reconnecting, so flush the rest. */
1638 	addr = dns_rr_copy(addr);
1639 	dns_rr_free(state->addr);
1640 	state->addr = addr;
1641 	break;
1642     }
1643 }
1644 
1645 /* connect_dest - connect to given inet: or unix: destination */
1646 
connect_dest(STATE * state)1647 static int connect_dest(STATE *state)
1648 {
1649     char   *dest = state->dest;
1650 
1651     /*
1652      * With LMTP we have direct-to-host delivery only. The destination may
1653      * have multiple IP addresses.
1654      */
1655     if (state->smtp == 0) {
1656 	if (strncmp(dest, "unix:", 5) == 0) {
1657 	    state->stream = connect_unix(state, dest + 5);
1658 	    if (!state->stream)
1659 		msg_info("Failed to establish session to %s: %s",
1660 			 dest, vstring_str(state->why->reason));
1661 	    return (1);
1662 	}
1663 	if (strncmp(dest, "inet:", 5) == 0)
1664 	    dest += 5;
1665     }
1666     connect_remote(state, dest);
1667 
1668     return (state->stream == 0);
1669 }
1670 
disconnect_dest(STATE * state)1671 static void disconnect_dest(STATE *state)
1672 {
1673 #ifdef USE_TLS
1674     if (state->tls_context) {
1675 	if (state->tlsproxy_mode) {
1676 	    tls_proxy_context_free(state->tls_context);
1677 	} else {
1678 	    tls_client_stop(state->tls_ctx, state->stream,
1679 			    smtp_tmout, 0, state->tls_context);
1680 	}
1681     }
1682     state->tls_context = 0;
1683     if (state->ddane)
1684 	tls_dane_free(state->ddane);
1685     state->ddane = 0;
1686 #endif
1687 
1688     if (state->stream)
1689 	vstream_fclose(state->stream);
1690     state->stream = 0;
1691 
1692     if (state->namaddrport)
1693 	myfree(state->namaddrport);
1694     state->namaddrport = 0;
1695 
1696     if (state->addrport)
1697 	myfree(state->addrport);
1698     state->addrport = 0;
1699 
1700     if (state->paddr)
1701 	myfree(state->paddr);
1702     state->paddr = 0;
1703 
1704     /* Reused on reconnect */
1705     if (state->reconnect <= 0) {
1706 	if (state->addr)
1707 	    dns_rr_free(state->addr);
1708 	state->addr = 0;
1709 	if (state->mx)
1710 	    dns_rr_free(state->mx);
1711 	state->mx = 0;
1712 
1713 	if (state->nexthop)
1714 	    myfree(state->nexthop);
1715 	state->nexthop = 0;
1716     }
1717     if (state->hostname)
1718 	myfree(state->hostname);
1719     state->hostname = 0;
1720 
1721     dsb_free(state->why);
1722     vstring_free(state->buffer);
1723 }
1724 
finger(STATE * state)1725 static int finger(STATE *state)
1726 {
1727     int     err;
1728 
1729     /*
1730      * smtp_get() makes sure the SMTP server cannot run us out of memory by
1731      * sending never-ending lines of text.
1732      */
1733     state->buffer = vstring_alloc(100);
1734     state->why = dsb_create();
1735 
1736     if (!(err = connect_dest(state))) {
1737 	if (state->pass == 1 && !state->nochat)
1738 	    msg_info("Connected to %s", state->namaddrport);
1739 	err = doproto(state);
1740     }
1741     disconnect_dest(state);
1742 
1743     if (err != 0)
1744 	return (1);
1745 
1746 #ifdef USE_TLS
1747     if (state->tlsproxy_mode == 0 && state->reconnect > 0) {
1748 	int     cache_enabled;
1749 	int     cache_count;
1750 	int     cache_hits;
1751 
1752 	tlsmgrmem_status(&cache_enabled, &cache_count, &cache_hits);
1753 	if (cache_enabled && cache_count == 0) {
1754 	    msg_info("Server declined session caching. Done reconnecting.");
1755 	    state->reconnect = 0;
1756 	} else if (cache_hits > 0 && (state->log_mask & TLS_LOG_CACHE) != 0) {
1757 	    msg_info("Found a previously used server.  Done reconnecting.");
1758 	    state->reconnect = 0;
1759 	} else if (state->max_reconnect-- <= 0) {
1760 	    msg_info("Maximum reconnect count reached.");
1761 	    state->reconnect = 0;
1762 	}
1763     }
1764 #endif
1765 
1766     return (0);
1767 }
1768 
1769 /* run - do what we were asked to do. */
1770 
run(STATE * state)1771 static int run(STATE *state)
1772 {
1773 
1774     while (1) {
1775 	if (finger(state) != 0)
1776 	    break;
1777 	if (state->reconnect <= 0)
1778 	    break;
1779 	msg_info("Reconnecting after %d seconds", state->reconnect);
1780 	++state->pass;
1781 	sleep(state->reconnect);
1782     }
1783 
1784     return (0);
1785 }
1786 
1787 /* cleanup - free memory allocated in main */
1788 
cleanup(STATE * state)1789 static void cleanup(STATE *state)
1790 {
1791 #ifdef USE_TLS
1792     if (state->tls_ctx != 0)
1793 	tls_free_app_context(state->tls_ctx);
1794     if (state->tls_bio)
1795 	(void) BIO_free(state->tls_bio);
1796     state->tls_bio = 0;
1797 
1798     myfree(state->mdalg);
1799     myfree(state->CApath);
1800     myfree(state->CAfile);
1801     myfree(state->certfile);
1802     myfree(state->keyfile);
1803     myfree(state->sni);
1804     if (state->options.level)
1805 	myfree(state->options.level);
1806     myfree(state->options.logopts);
1807     if (state->match)
1808 	argv_free(state->match);
1809     if (state->options.tas)
1810 	argv_free(state->options.tas);
1811     if (state->dane)
1812 	tls_dane_free(state->dane);
1813 
1814     /* Flush and free DANE TLSA cache */
1815     tls_dane_flush();
1816     /* Flush and free memory tlsmgr cache */
1817     tlsmgrmem_flush();
1818     myfree(state->grade);
1819     myfree(state->protocols);
1820 #endif
1821     myfree(state->options.host_lookup);
1822     myfree(state->dest);
1823 
1824     mail_conf_flush();
1825 }
1826 
1827 /* usage - explain */
1828 
usage(void)1829 static void usage(void)
1830 {
1831 #ifdef USE_TLS
1832     fprintf(stderr, "usage: %s %s \\\n\t%s \\\n\t%s \\\n\t%s \\\n\t%s"
1833 	    " destination [match ...]\n", var_procname,
1834 	    "[-acCfSvw] [-t conn_tmout] [-T cmd_tmout] [-L logopts]",
1835 	 "[-h host_lookup] [-l level] [-d mdalg] [-g grade] [-p protocols]",
1836 	    "[-A tafile] [-F CAfile.pem] [-P CApath/] [-s servername]",
1837 	    "[ [-H chainfiles] | [-k certfile [-K keyfile]] ]",
1838 	    "[-m count] [-r delay] [-o name=value]");
1839 #else
1840     fprintf(stderr, "usage: %s [-acStTv] [-h host_lookup] [-o name=value] destination\n",
1841 	    var_procname);
1842 #endif
1843     exit(1);
1844 }
1845 
1846 /* tls_init - initialize application TLS library context */
1847 
tls_init(STATE * state)1848 static void tls_init(STATE *state)
1849 {
1850 #ifdef USE_TLS
1851     TLS_CLIENT_INIT_PROPS props;
1852 
1853     if (state->level <= TLS_LEV_NONE)
1854 	return;
1855 
1856     /* Needed for tls_dane_avail() and other DANE-related processing. */
1857     state->tls_ctx =
1858 	TLS_CLIENT_INIT(&props,
1859 			log_param = "-L option",
1860 			log_level = state->options.logopts,
1861 			verifydepth = DEF_SMTP_TLS_SCERT_VD,
1862 			cache_type = "memory",
1863 			chain_files = state->chains,
1864 			cert_file = state->certfile,
1865 			key_file = state->keyfile,
1866 			dcert_file = "",
1867 			dkey_file = "",
1868 			eccert_file = "",
1869 			eckey_file = "",
1870 			CAfile = state->CAfile,
1871 			CApath = state->CApath,
1872 			mdalg = state->mdalg);
1873 #endif
1874 }
1875 
1876 /* override - update main.cf parameter */
1877 
override(const char * nameval)1878 static void override(const char *nameval)
1879 {
1880     char   *param_name;
1881     char   *param_value;
1882     char   *save = mystrdup(nameval);
1883 
1884     if (split_nameval(save, &param_name, &param_value) != 0)
1885 	usage();
1886     mail_conf_update(param_name, param_value);
1887     myfree(save);
1888 }
1889 
1890 /* parse_options - (argc, argv) -> state */
1891 
parse_options(STATE * state,int argc,char * argv[])1892 static void parse_options(STATE *state, int argc, char *argv[])
1893 {
1894     int     c;
1895 
1896     state->smtp = 1;
1897     state->pass = 1;
1898     state->dosrv = 0;
1899     state->reconnect = -1;
1900     state->max_reconnect = 5;
1901     state->wrapper_mode = 0;
1902 #ifdef USE_TLS
1903     state->protocols = mystrdup(">=TLSv1");
1904     state->grade = mystrdup("medium");
1905 #endif
1906     memset((void *) &state->options, 0, sizeof(state->options));
1907     state->options.host_lookup = mystrdup("dns");
1908 
1909 #define OPTS "a:ch:o:RSt:T:v"
1910 #ifdef USE_TLS
1911 #define TLSOPTS "A:Cd:fF:g:H:k:K:l:L:m:M:p:P:r:s:wX"
1912 
1913     state->mdalg = 0;
1914     state->CApath = mystrdup("");
1915     state->CAfile = mystrdup("");
1916     state->chains = mystrdup("");
1917     state->certfile = mystrdup("");
1918     state->keyfile = mystrdup("");
1919     state->sni = mystrdup("");
1920     state->options.tas = argv_alloc(1);
1921     state->options.logopts = 0;
1922     state->level = TLS_LEV_DANE;
1923     state->mxinsec_level = TLS_LEV_DANE;
1924     state->tlsproxy_mode = 0;
1925 #else
1926 #define TLSOPTS ""
1927     state->level = TLS_LEV_NONE;
1928 #endif
1929 
1930     while ((c = GETOPT(argc, argv, OPTS TLSOPTS)) > 0) {
1931 	switch (c) {
1932 	default:
1933 	    usage();
1934 	    break;
1935 	case 'a':
1936 	    state->options.addr_pref = mystrdup(optarg);
1937 	    break;
1938 	case 'c':
1939 	    state->nochat = 1;
1940 	    break;
1941 	case 'h':
1942 	    myfree(state->options.host_lookup);
1943 	    state->options.host_lookup = mystrdup(optarg);
1944 	    break;
1945 	case 'o':
1946 	    override(optarg);
1947 	    break;
1948 	case 'R':
1949 	    state->dosrv = 1;
1950 	    break;
1951 	case 'S':
1952 	    state->smtp = 0;
1953 	    break;
1954 	case 't':
1955 	    conn_tmout = atoi(optarg);
1956 	    break;
1957 	case 'T':
1958 	    smtp_tmout = atoi(optarg);
1959 	    break;
1960 	case 'v':
1961 	    msg_verbose++;
1962 	    break;
1963 #ifdef USE_TLS
1964 	case 'A':
1965 	    argv_add(state->options.tas, optarg, ARGV_END);
1966 	    break;
1967 	case 'C':
1968 	    state->print_trust = 1;
1969 	    break;
1970 	case 'd':
1971 	    if (state->mdalg)
1972 		myfree(state->mdalg);
1973 	    state->mdalg = mystrdup(optarg);
1974 	    break;
1975 	case 'f':
1976 	    state->force_tlsa = 1;
1977 	    break;
1978 	case 'F':
1979 	    myfree(state->CAfile);
1980 	    state->CAfile = mystrdup(optarg);
1981 	    break;
1982 	case 'g':
1983 	    myfree(state->grade);
1984 	    state->grade = mystrdup(optarg);
1985 	    break;
1986 	case 'H':
1987 	    {
1988 		char   *tmp;
1989 
1990 		if (*state->chains)
1991 		    tmp = concatenate(state->chains, ", ", optarg, (char *) 0);
1992 		else
1993 		    tmp = mystrdup(optarg);
1994 		myfree(state->chains);
1995 		state->chains = tmp;
1996 	    }
1997 	    break;
1998 	case 'k':
1999 	    myfree(state->certfile);
2000 	    state->certfile = mystrdup(optarg);
2001 	    if (!*state->keyfile) {
2002 		myfree(state->keyfile);
2003 		state->keyfile = mystrdup(optarg);
2004 	    }
2005 	    break;
2006 	case 'K':
2007 	    myfree(state->keyfile);
2008 	    state->keyfile = mystrdup(optarg);
2009 	    if (!*state->certfile) {
2010 		myfree(state->certfile);
2011 		state->certfile = mystrdup(optarg);
2012 	    }
2013 	    break;
2014 	case 'l':
2015 	    if (state->options.level)
2016 		myfree(state->options.level);
2017 	    state->options.level = mystrdup(optarg);
2018 	    break;
2019 	case 'L':
2020 	    if (state->options.logopts)
2021 		myfree(state->options.logopts);
2022 	    state->options.logopts = mystrdup(optarg);
2023 	    break;
2024 	case 'm':
2025 	    state->max_reconnect = atoi(optarg);
2026 	    break;
2027 	case 'M':
2028 	    switch (state->mxinsec_level = tls_level_lookup(optarg)) {
2029 	    case TLS_LEV_MAY:
2030 	    case TLS_LEV_ENCRYPT:
2031 	    case TLS_LEV_DANE:
2032 		break;
2033 	    default:
2034 		msg_fatal("bad '-M' option value: %s", optarg);
2035 	    }
2036 	    break;
2037 	case 'p':
2038 	    myfree(state->protocols);
2039 	    state->protocols = mystrdup(optarg);
2040 	    break;
2041 	case 'P':
2042 	    myfree(state->CApath);
2043 	    state->CApath = mystrdup(optarg);
2044 	    break;
2045 	case 'r':
2046 	    state->reconnect = atoi(optarg);
2047 	    break;
2048 	case 's':
2049 	    myfree(state->sni);
2050 	    state->sni = mystrdup(optarg);
2051 	    break;
2052 	case 'w':
2053 	    state->wrapper_mode = 1;
2054 	    break;
2055 	case 'X':
2056 	    state->tlsproxy_mode = 1;
2057 	    break;
2058 #endif
2059 	}
2060     }
2061 
2062     /*
2063      * Address family preference.
2064      */
2065     state->addr_pref =
2066 	name_code(addr_pref_map, NAME_CODE_FLAG_NONE, state->options.addr_pref ?
2067 		  state->options.addr_pref : "any");
2068     if (state->addr_pref < 0)
2069 	msg_fatal("bad '-a' option value: %s", state->options.addr_pref);
2070 
2071 #ifdef USE_TLS
2072     if (state->tlsproxy_mode && state->reconnect >= 0)
2073 	msg_fatal("The -X and -r options are mutually exclusive");
2074 #endif
2075 
2076     /*
2077      * Select hostname lookup mechanisms.
2078      */
2079     state->host_lookup =
2080 	name_mask("-h option", lookup_masks, state->options.host_lookup ?
2081 		  state->options.host_lookup : "dns");
2082 
2083 #ifdef USE_TLS
2084 
2085     if (*state->chains && *state->certfile)
2086 	msg_fatal("When the '-H' option is used, neither the '-k',"
2087 		  " nor the '-K' options may be used");
2088 
2089     if (state->reconnect < 0)
2090 	tlsmgrmem_disable();
2091 
2092     if (state->options.logopts == 0)
2093 	state->options.logopts = mystrdup("routine,certmatch");
2094     state->log_mask = tls_log_mask("-L option", state->options.logopts);
2095     tls_dane_loglevel("-L option", state->options.logopts);
2096 
2097     if (state->options.level) {
2098 	state->level = tls_level_lookup(state->options.level);
2099 
2100 	switch (state->level) {
2101 	case TLS_LEV_NONE:
2102 	    if (state->wrapper_mode)
2103 		msg_fatal("SSL wrapper mode requires that TLS not be disabled");
2104 	    return;
2105 	case TLS_LEV_INVALID:
2106 	    msg_fatal("Invalid TLS level \"%s\"", state->options.level);
2107 	}
2108     }
2109 #endif
2110 }
2111 
2112 /* parse_match - process match arguments */
2113 
parse_match(STATE * state,int argc,char * argv[])2114 static void parse_match(STATE *state, int argc, char *argv[])
2115 {
2116 #ifdef USE_TLS
2117     int     smtp_mode = 1;
2118 
2119     switch (state->level) {
2120     case TLS_LEV_SECURE:
2121 	state->match = argv_alloc(2);
2122 	while (*argv)
2123 	    argv_add(state->match, *argv++, ARGV_END);
2124 	if (state->match->argc == 0)
2125 	    argv_add(state->match, "nexthop", "dot-nexthop", ARGV_END);
2126 	break;
2127     case TLS_LEV_VERIFY:
2128 	state->match = argv_alloc(1);
2129 	while (*argv)
2130 	    argv_add(state->match, *argv++, ARGV_END);
2131 	if (state->match->argc == 0)
2132 	    argv_add(state->match, "hostname", ARGV_END);
2133 	break;
2134     case TLS_LEV_FPRINT:
2135 	state->dane = tls_dane_alloc();
2136 	while (*argv)
2137 	    tls_dane_add_fpt_digests((TLS_DANE *) state->dane, *argv++, "",
2138 				     smtp_mode);
2139 	break;
2140     case TLS_LEV_DANE:
2141     case TLS_LEV_DANE_ONLY:
2142 	state->match = argv_alloc(2);
2143 	argv_add(state->match, "nexthop", "hostname", ARGV_END);
2144 	break;
2145     }
2146 #endif
2147 }
2148 
2149 /* parse_tas - process '-A' trust anchor file option */
2150 
parse_tas(STATE * state)2151 static void parse_tas(STATE *state)
2152 {
2153 #ifdef USE_TLS
2154     char  **file;
2155 
2156     if (!state->options.tas->argc)
2157 	return;
2158 
2159     switch (state->level) {
2160     default:
2161 	return;
2162     case TLS_LEV_SECURE:
2163     case TLS_LEV_VERIFY:
2164 	state->dane = tls_dane_alloc();
2165 	for (file = state->options.tas->argv; *file; ++file) {
2166 	    if (!tls_dane_load_trustfile((TLS_DANE *) state->dane, *file))
2167 		break;
2168 	}
2169 	if (*file)
2170 	    msg_fatal("Failed to load trust anchor file: %s", *file);
2171 	break;
2172     }
2173 #endif
2174 }
2175 
2176 
main(int argc,char * argv[])2177 int     main(int argc, char *argv[])
2178 {
2179     static STATE state;
2180     char   *loopenv = getenv("VALGRINDLOOP");
2181     int     loop = loopenv ? atoi(loopenv) : 1;
2182     ARGV   *import_env;
2183     static char *var_smtp_tls_fpt_dgst;
2184     static const CONFIG_STR_TABLE smtp_str_table[] = {
2185 #ifdef USE_TLS
2186 	VAR_SMTP_TLS_FPT_DGST, DEF_SMTP_TLS_FPT_DGST, &var_smtp_tls_fpt_dgst, 1, 0,
2187 #endif
2188 	0,
2189     };
2190 
2191     /* Don't die when a peer goes away unexpectedly. */
2192     signal(SIGPIPE, SIG_IGN);
2193 
2194     /* We're a diagnostic utility, so diagnostic messages go to stdout. */
2195     var_procname = mystrdup(basename(argv[0]));
2196     set_mail_conf_str(VAR_PROCNAME, var_procname);
2197     msg_vstream_init(var_procname, VSTREAM_OUT);
2198 
2199     /*
2200      * Load main.cf, parse command-line options, then process main.cf
2201      * settings plus any command-line "-o" overrides.
2202      */
2203     mail_conf_suck();
2204     parse_options(&state, argc, argv);
2205     mail_params_init();
2206     get_mail_conf_str_table(smtp_str_table);
2207     parse_tas(&state);
2208 
2209 #ifdef USE_TLS
2210     /* Less surprising to default to the same fingerprint digest as smtp(8) */
2211     if (state.mdalg)
2212 	warn_compat_break_smtp_tls_fpt_dgst = 0;
2213     else
2214 	state.mdalg = mystrdup(var_smtp_tls_fpt_dgst);
2215 
2216     /*
2217      * We first call tls_init(), which ultimately calls SSL_library_init(),
2218      * since otherwise we can't tell whether we have the message digests
2219      * required for DANE support.
2220      */
2221     tls_init(&state);
2222     if (TLS_DANE_BASED(state.level) && !tls_dane_avail()) {
2223 	msg_warn("DANE TLS support is not available, resorting to \"secure\"");
2224 	state.level = TLS_LEV_SECURE;
2225     }
2226     state.tls_bio = 0;
2227     if (state.print_trust)
2228 	state.tls_bio = BIO_new_fp(stdout, BIO_NOCLOSE);
2229 #endif
2230 
2231     /* Enforce consistent operation of different Postfix parts. */
2232     import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ);
2233     update_env(import_env->argv);
2234     argv_free(import_env);
2235 
2236     argc -= optind;
2237     argv += optind;
2238 
2239     /* The first non-option argument is the destination. */
2240     if (!argc)
2241 	usage();
2242 
2243     state.dest = mystrdup(argv[0]);
2244     parse_match(&state, --argc, ++argv);
2245 
2246     /* Don't talk to remote systems as root */
2247     if (!geteuid())
2248 	chroot_uid(0, var_mail_owner);
2249 
2250     while (loop-- > 0)
2251 	run(&state);
2252 
2253     /* Be valgrind friendly and clean-up */
2254     cleanup(&state);
2255 
2256     return (0);
2257 }
2258