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
418static int conn_tmout = 30;
419static 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
427static const NAME_MASK lookup_masks[] = {
428    "dns", HOST_FLAG_DNS,
429    "native", HOST_FLAG_NATIVE,
430    0,
431};
432
433static 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
440typedef 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  */
457typedef 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
506static 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  */
513typedef 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
522static 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
551static 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
604static 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
618static 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
645static 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
679static 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
712static 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
736static 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
961static 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
1008static 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
1063static 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
1113static 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
1166static 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
1283static 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
1308static 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
1373static 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
1441static 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
1477static 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
1549static 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
1592static 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
1647static 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
1671static 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
1725static 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
1771static 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
1789static 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
1829static 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
1848static 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
1878static 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
1892static 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
2114static 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
2151static 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
2177int     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