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, ¶m_name, ¶m_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