5
/* Probe the TLS properties of an ESMTP or LMTP server.
7
/* \fBposttls-finger\fR [\fIoptions\fR] [\fBinet:\fR]\fIdomain\fR[:\fIport\fR] [\fImatch ...\fR]
9
/* \fBposttls-finger\fR -S [\fIoptions\fR] \fBunix:\fIpathname\fR [\fImatch ...\fR]
11
/* \fBposttls-finger\fR(1) connects to the specified destination
12
/* and reports TLS-related information about the server. With SMTP, the
13
/* destination is a domainname; with LMTP it is either a domainname
14
/* prefixed with \fBinet:\fR or a pathname prefixed with \fBunix:\fR. If
15
/* Postfix is built without TLS support, the resulting posttls-finger
16
/* program has very limited functionality, and only the \fB-a\fR, \fB-c\fR,
17
/* \fB-h\fR, \fB-o\fR, \fB-S\fR, \fB-t\fR, \fB-T\fR and \fB-v\fR options
20
/* Note: this is an unsupported test program. No attempt is made
21
/* to maintain compatibility between successive versions.
23
/* For SMTP servers that don't support ESMTP, only the greeting banner
24
/* and the negative EHLO response are reported. Otherwise, the reported
25
/* EHLO response details further server capabilities.
27
/* If TLS support is enabled when \fBposttls-finger\fR(1) is compiled, and
28
/* the server supports \fBSTARTTLS\fR, a TLS handshake is attempted.
30
/* If DNSSEC support is available, the connection TLS security level
31
/* (\fB-l\fR option) defaults to \fBdane\fR; see TLS_README for
32
/* details. Otherwise, it defaults to \fBsecure\fR. This setting
33
/* determines the certificate matching policy.
35
/* If TLS negotiation succeeds, the TLS protocol and cipher details are
36
/* reported. The server certificate is then verified in accordance with
37
/* the policy at the chosen (or default) security level. With public
38
/* CA-based trust, when the \fB-L\fR option includes \fBcertmatch\fR,
39
/* (true by default) name matching is performed even if the certificate
40
/* chain is not trusted. This logs the names found in the remote SMTP
41
/* server certificate and which if any would match, were the certificate
44
/* Note: \fBposttls-finger\fR(1) does not perform any table lookups, so
45
/* the TLS policy table and obsolete per-site tables are not consulted.
46
/* It does not communicate with the \fBtlsmgr\fR(8) daemon (or any other
47
/* Postfix daemons); its TLS session cache is held in private memory, and
48
/* disappears when the process exits.
50
/* With the \fB-r \fIdelay\fR option, if the server assigns a TLS
51
/* session id, the TLS session is cached. The connection is then closed
52
/* and re-opened after the specified delay, and \fBposttls-finger\fR(1)
53
/* then reports whether the cached TLS session was re-used.
55
/* When the destination is a load-balancer, it may be distributing
56
/* load between multiple server caches. Typically, each server returns
57
/* its unique name in its EHLO response. If, upon reconnecting with
58
/* \fB-r\fR, a new server name is detected, another session is cached
59
/* for the new server, and the reconnect is repeated up to a maximum
60
/* number of times (default 5) that can be specified via the \fB-m\fR
63
/* The choice of SMTP or LMTP (\fB-S\fR option) determines the syntax of
64
/* the destination argument. With SMTP, one can specify a service on a
65
/* non-default port as \fIhost\fR:\fIservice\fR, and disable MX (mail
66
/* exchanger) DNS lookups with [\fIhost\fR] or [\fIhost\fR]:\fIport\fR.
67
/* The [] form is required when you specify an IP address instead of a
68
/* hostname. An IPv6 address takes the form [\fBipv6:\fIaddress\fR].
69
/* The default port for SMTP is taken from the \fBsmtp/tcp\fR entry in
70
/* /etc/services, defaulting to 25 if the entry is not found.
72
/* With LMTP, specify \fBunix:\fIpathname\fR to connect to a local server
73
/* listening on a unix-domain socket bound to the specified pathname;
74
/* otherwise, specify an optional \fBinet:\fR prefix followed by a
75
/* \fIdomain\fR and an optional port, with the same syntax as for
76
/* SMTP. The default TCP port for LMTP is 24.
79
/* .IP "\fB-a\fR \fIfamily\fR (default: \fBany\fR)"
80
/* Address family preference: \fBipv4\fR, \fBipv6\fR or \fBany\fR. When
81
/* using \fBany\fR, posttls-finger will randomly select one of the two as
82
/* the more preferred, and exhaust all MX preferences for the first
83
/* address family before trying any addresses for the other.
84
/* .IP "\fB-A\fR \fItrust-anchor.pem\fR (default: none)"
85
/* A list of PEM trust-anchor files that overrides CAfile and CApath
86
/* trust chain verification. Specify the option multiple times to
87
/* specify multiple files. See the main.cf documentation for
88
/* smtp_tls_trust_anchor_file for details.
90
/* Disable SMTP chat logging; only TLS-related information is logged.
92
/* Print the remote SMTP server certificate trust chain in PEM format.
93
/* The issuer DN, subject DN, certificate and public key fingerprints
94
/* (see \fB-d \fImdalg\fR option below) are printed above each PEM
95
/* certificate block. If you specify \fB-F \fICAfile\fR or
96
/* \fB-P \fICApath\fR, the OpenSSL library may augment the chain with
97
/* missing issuer certificates. To see the actual chain sent by the
98
/* remote SMTP server leave \fICAfile\fR and \fICApath\fR unset.
99
/* .IP "\fB-d \fImdalg\fR (default: \fBsha1\fR)"
100
/* The message digest algorithm to use for reporting remote SMTP server
101
/* fingerprints and matching against user provided certificate
102
/* fingerprints (with DANE TLSA records the algorithm is specified
105
/* Lookup the associated DANE TLSA RRset even when a hostname is not an
106
/* alias and its address records lie in an unsigned zone. See
107
/* smtp_tls_force_insecure_host_tlsa_lookup for details.
108
/* .IP "\fB-F \fICAfile.pem\fR (default: none)"
109
/* The PEM formatted CAfile for remote SMTP server certificate
110
/* verification. By default no CAfile is used and no public CAs
112
/* .IP "\fB-g \fIgrade\fR (default: medium)"
113
/* The minimum TLS cipher grade used by posttls-finger. See
114
/* smtp_tls_mandatory_ciphers for details.
115
/* .IP "\fB-h \fIhost_lookup\fR (default: \fBdns\fR)"
116
/* The hostname lookup methods used for the connection. See the
117
/* documentation of smtp_host_lookup for syntax and semantics.
118
/* .IP "\fB-l \fIlevel\fR (default: \fBdane\fR or \fBsecure\fR)"
119
/* The security level for the connection, default \fBdane\fR or
120
/* \fBsecure\fR depending on whether DNSSEC is available. For syntax
121
/* and semantics, see the documentation of smtp_tls_security_level.
122
/* When \fBdane\fR or \fBdane-only\fR is supported and selected, if no
123
/* TLSA records are found, or all the records found are unusable, the
124
/* \fIsecure\fR level will be used instead. The \fBfingerprint\fR
125
/* security level allows you to test certificate or public-key
126
/* fingerprint matches before you deploy them in the policy table.
128
/* Note, since \fBposttls-finger\fR does not actually deliver any email,
129
/* the \fBnone\fR, \fBmay\fR and \fBencrypt\fR security levels are not
130
/* very useful. Since \fBmay\fR and \fBencrypt\fR don't require peer
131
/* certificates, they will often negotiate anonymous TLS ciphersuites,
132
/* so you won't learn much about the remote SMTP server's certificates
133
/* at these levels if it also supports anonymous TLS (though you may
134
/* learn that the server supports anonymous TLS).
135
/* .IP "\fB-L \fIlogopts\fR (default: \fBroutine,certmatch\fR)"
136
/* Fine-grained TLS logging options. To tune the TLS features logged
137
/* during the TLS handshake, specify one or more of:
139
/* .IP "\fB0, none\fR"
140
/* These yield no TLS logging; you'll generally want more, but this
141
/* is handy if you just want the trust chain:
145
/* $ posttls-finger -cC -L none destination
148
/* .IP "\fB1, routine, summary\fR"
149
/* These synonymous values yield a normal one-line summary of the TLS
151
/* .IP "\fB2, debug\fR"
152
/* These synonymous values combine routine, ssl-debug, cache and verbose.
153
/* .IP "\fB3, ssl-expert\fR"
154
/* These synonymous values combine debug with ssl-handshake-packet-dump.
156
/* .IP "\fB4, ssl-developer\fR"
157
/* These synonymous values combine ssl-expert with ssl-session-packet-dump.
158
/* For experts only, and in most cases, use wireshark instead.
159
/* .IP "\fBssl-debug\fR"
160
/* Turn on OpenSSL logging of the progress of the SSL handshake.
161
/* .IP "\fBssl-handshake-packet-dump\fR"
162
/* Log hexadecimal packet dumps of the SSL handshake; for experts only.
163
/* .IP "\fBssl-session-packet-dump\fR"
164
/* Log hexadecimal packet dumps of the entire SSL session; only useful
165
/* to those who can debug SSL protocol problems from hex dumps.
166
/* .IP "\fBuntrusted\fR"
167
/* Logs trust chain verification problems. This is turned on
168
/* automatically at security levels that use peer names signed
169
/* by certificate authorities to validate certificates. So while
170
/* this setting is recognized, you should never need to set it
172
/* .IP "\fBpeercert\fR"
173
/* This logs a one line summary of the remote SMTP server certificate
174
/* subject, issuer, and fingerprints.
175
/* .IP "\fBcertmatch\fR"
176
/* This logs remote SMTP server certificate matching, showing the CN
177
/* and each subjectAltName and which name matched. With DANE, logs
178
/* matching of TLSA record trust-anchor and end-entity certificates.
180
/* This logs session cache operations, showing whether session caching
181
/* is effective with the remote SMTP server. Automatically used when
182
/* reconnecting with the \fB-r\fR option; rarely needs to be set
184
/* .IP "\fBverbose\fR"
185
/* Enables verbose logging in the Postfix TLS driver; includes all of
186
/* peercert..cache and more.
189
/* The default is \fBroutine,certmatch\fR. After a reconnect,
190
/* \fBpeercert\fR, \fBcertmatch\fR and \fBverbose\fR are automatically
191
/* disabled while \fBcache\fR and \fBsummary\fR are enabled.
192
/* .IP "\fB-m \fIcount\fR (default: \fB5\fR)"
193
/* When the \fB-r \fIdelay\fR option is specified, the \fB-m\fR option
194
/* determines the maximum number of reconnect attempts to use with
195
/* a server behind a load-balacer, to see whether connection caching
196
/* is likely to be effective for this destination. Some MTAs
197
/* don't expose the underlying server identity in their EHLO
198
/* response; with these servers there will never be more than
199
/* 1 reconnection attempt.
200
/* .IP "\fB-o \fIname=value\fR"
201
/* Specify zero or more times to override the value of the main.cf
202
/* parameter \fIname\fR with \fIvalue\fR. Possible use-cases include
203
/* overriding the values of TLS library parameters, or "myhostname" to
204
/* configure the SMTP EHLO name sent to the remote server.
205
/* .IP "\fB-p \fIprotocols\fR (default: !SSLv2)"
206
/* List of TLS protocols that posttls-finger will exclude or include. See
207
/* smtp_tls_mandatory_protocols for details.
208
/* .IP "\fB-P \fICApath/\fR (default: none)"
209
/* The OpenSSL CApath/ directory (indexed via c_rehash(1)) for remote
210
/* SMTP server certificate verification. By default no CApath is used
211
/* and no public CAs are trusted.
212
/* .IP "\fB-r \fIdelay\fR"
213
/* With a cachable TLS session, disconnect and reconnect after \fIdelay\fR
214
/* seconds. Report whether the session is re-used. Retry if a new server
215
/* is encountered, up to 5 times or as specified with the \fB-m\fR option.
216
/* By default reconnection is disabled, specify a positive delay to
217
/* enable this behavior.
219
/* Disable SMTP; that is, connect to an LMTP server. The default port for
220
/* LMTP over TCP is 24. Alternative ports can specified by appending
221
/* "\fI:servicename\fR" or ":\fIportnumber\fR" to the destination
223
/* .IP "\fB-t \fItimeout\fR (default: \fB30\fR)"
224
/* The TCP connection timeout to use. This is also the timeout for
225
/* reading the remote server's 220 banner.
226
/* .IP "\fB-T \fItimeout\fR (default: \fB30\fR)"
227
/* The SMTP/LMTP command timeout for EHLO/LHLO, STARTTLS and QUIT.
229
/* Enable verose Postfix logging. Specify more than once to increase
230
/* the level of verbose logging.
231
/* .IP "[\fBinet:\fR]\fIdomain\fR[:\fIport\fR]"
232
/* Connect via TCP to domain \fIdomain\fR, port \fIport\fR. The default
233
/* port is \fBsmtp\fR (or 24 with LMTP). With SMTP an MX lookup is
234
/* performed to resolve the domain to a host, unless the domain is
235
/* enclosed in \fB[]\fR. If you want to connect to a specific MX host,
236
/* for instance \fImx1.example.com\fR, specify [\fImx1.example.com\fR]
237
/* as the destination and \fIexample.com\fR as a \fBmatch\fR argument.
238
/* When using DNS, the destination domain is assumed fully qualified
239
/* and no default domain or search suffixes are applied; you must use
240
/* fully-qualified names or also enable \fBnative\fR host lookups
241
/* (these don't support \fBdane\fR or \fBdane-only\fR as no DNSSEC
242
/* validation information is available via \fBnative\fR lookups).
243
/* .IP "\fBunix:\fIpathname\fR"
244
/* Connect to the UNIX-domain socket at \fIpathname\fR. LMTP only.
245
/* .IP "\fBmatch ...\fR"
246
/* With no match arguments specified, certificate peername matching uses
247
/* the compiled-in default strategies for each security level. If you
248
/* specify one or more arguments, these will be used as the list of
249
/* certificate or public-key digests to match for the \fBfingerprint\fR
250
/* level, or as the list of DNS names to match in the certificate at the
251
/* \fBverify\fR and \fBsecure\fR levels. If the security level is
252
/* \fBdane\fR, or \fBdane-only\fR the match names are ignored, and
253
/* \fBhostname, nexthop\fR strategies are used.
259
/* .IP \fBMAIL_CONFIG\fR
260
/* Read configuration parameters from a non-default location.
261
/* .IP \fBMAIL_VERBOSE\fR
262
/* Same as \fB-v\fR option.
264
/* smtp-source(1), SMTP/LMTP message source
265
/* smtp-sink(1), SMTP/LMTP message dump
270
/* Use "\fBpostconf readme_directory\fR" or "\fBpostconf
271
/* html_directory\fR" to locate this information.
274
/* TLS_README, Postfix STARTTLS howto
278
/* The Secure Mailer license must be distributed with this software.
281
/* IBM T.J. Watson Research
283
/* Yorktown Heights, NY 10598, USA
291
#include <sys_defs.h>
300
#include <sys/socket.h>
302
#include <netinet/in.h>
303
#include <arpa/inet.h>
309
#include <msg_vstream.h>
312
#include <vstring_vstream.h>
313
#include <mymalloc.h>
314
#include <stringops.h>
316
#include <name_mask.h>
317
#include <name_code.h>
318
#include <chroot_uid.h>
319
#include <host_port.h>
320
#include <inet_proto.h>
322
#include <timed_connect.h>
323
#include <sane_connect.h>
324
#include <myaddrinfo.h>
325
#include <sock_addr.h>
327
#define STR(x) vstring_str(x)
332
#include <mail_params.h>
333
#include <mail_conf.h>
334
#include <smtp_stream.h>
344
#include <mail_server.h>
353
#include <openssl/engine.h>
357
* Application specific
359
#include "tlsmgrmem.h"
361
static int conn_tmout = 30;
362
static int smtp_tmout = 30;
364
#define HOST_FLAG_DNS (1<<0)
365
#define HOST_FLAG_NATIVE (1<<1)
367
#define MISC_FLAG_PREF_IPV6 (1<<0)
368
#define MISC_FLAG_PREF_IPV4 (1<<1)
370
static const NAME_MASK lookup_masks[] = {
371
"dns", HOST_FLAG_DNS,
372
"native", HOST_FLAG_NATIVE,
376
static const NAME_CODE addr_pref_map[] = {
377
INET_PROTO_NAME_IPV6, MISC_FLAG_PREF_IPV6,
378
INET_PROTO_NAME_IPV4, MISC_FLAG_PREF_IPV4,
379
INET_PROTO_NAME_ANY, 0,
383
typedef struct OPTIONS {
392
* Per-session data structure with state.
394
* This software can maintain multiple parallel connections to the same SMTP
395
* server. However, it makes no more than one connection request at a time
396
* to avoid overwhelming the server with SYN packets and having to back off.
397
* Back-off would screw up the benchmark. Pending connection requests are
398
* kept in a linear list.
400
typedef struct STATE {
401
int smtp; /* SMTP or LMTP? */
402
int host_lookup; /* dns|native|dns,native */
403
int addr_pref; /* v4, v6, both */
404
int log_mask; /* via tls_log_mask() */
405
int reconnect; /* -r option */
406
int max_reconnect; /* -m option */
407
int force_tlsa; /* -f option */
408
unsigned port; /* TCP port */
409
char *dest; /* Full destination spec */
410
char *addrport; /* [addr]:port */
411
char *namaddrport; /* name[addr]:port */
412
char *nexthop; /* Nexthop domain for verification */
413
char *hostname; /* Hostname for verification */
414
DNS_RR *addr; /* IPv[46] Address to (re)connect to */
415
DNS_RR *mx; /* MX RRset qname, rname, valid */
416
int pass; /* Pass number, 2 for reconnect */
417
int nochat; /* disable chat logging */
418
char *helo; /* Server name from EHLO reply */
419
DSN_BUF *why; /* SMTP-style error message */
420
VSTRING *buffer; /* Response buffer */
421
VSTREAM *stream; /* Open connection */
422
int level; /* TLS security level */
424
char *mdalg; /* fingerprint digest algorithm */
425
char *CAfile; /* Trusted public CAs */
426
char *CApath; /* Trusted public CAs */
427
ARGV *match; /* match arguments */
428
int print_trust; /* -C option */
429
BIO *tls_bio; /* BIO wrapper for stdout */
430
TLS_APPL_STATE *tls_ctx; /* Application TLS context */
431
TLS_SESS_STATE *tls_context; /* Session TLS context */
432
TLS_DANE *dane; /* DANE TLSA validation structure */
433
TLS_DANE *ddane; /* DANE TLSA from DNS */
434
char *grade; /* Minimum cipher grade */
435
char *protocols; /* Protocol inclusion/exclusion */
437
OPTIONS options; /* JCL */
440
static DNS_RR *host_addr(STATE *, const char *);
442
#define HNAME(addr) (addr->qname)
445
* Structure with broken-up SMTP server response.
447
typedef struct { /* server response */
448
int code; /* status */
449
char *str; /* text */
450
VSTRING *buf; /* origin of text */
454
/* command - send an SMTP command */
456
static void command(STATE *state, int verbose, char *fmt,...)
458
VSTREAM *stream = state->stream;
463
buf = vstring_alloc(100);
465
vstring_vsprintf(buf, fmt, ap);
467
line = vstring_str(buf);
469
while (line && *line) {
470
char *nextline = strchr(line, '\n');
474
if (verbose && !state->nochat)
475
msg_info("> %s", line);
476
smtp_printf(stream, "%s", line);
483
/* response - read and process SMTP server response */
485
static RESPONSE *response(STATE *state, int verbose)
487
VSTREAM *stream = state->stream;
488
VSTRING *buf = state->buffer;
489
static RESPONSE rdata;
494
* Initialize the response data buffer. Defend against a denial of
495
* service attack by limiting the amount of multi-line text that we are
498
if (rdata.buf == 0) {
499
rdata.buf = vstring_alloc(100);
500
vstring_ctl(rdata.buf, VSTRING_CTL_MAXLEN, (ssize_t) var_line_limit, 0);
504
* Censor out non-printable characters in server responses. Concatenate
505
* multi-line server responses. Separate the status code from the text.
506
* Leave further parsing up to the application.
508
#define BUF ((char *) vstring_str(buf))
509
VSTRING_RESET(rdata.buf);
511
smtp_get(buf, stream, var_line_limit, SMTP_GET_FLAG_SKIP);
512
for (cp = BUF; *cp != 0; cp++)
513
if (!ISPRINT(*cp) && !ISSPACE(*cp))
516
if (verbose && !state->nochat)
517
msg_info("< %s", cp);
520
rdata.code = (cp - BUF == 3 ? atoi(BUF) : 0);
521
if ((more = (*cp == '-')) != 0)
525
vstring_strcat(rdata.buf, cp);
528
VSTRING_ADDCH(rdata.buf, '\n');
530
VSTRING_TERMINATE(rdata.buf);
531
rdata.str = vstring_str(rdata.buf);
535
/* exception_text - translate exceptions from the smtp_stream module */
537
static char *exception_text(int except)
541
return ("lost connection");
545
msg_panic("exception_text: unknown exception %d", except);
549
/* ehlo - send EHLO/LHLO */
551
static RESPONSE *ehlo(STATE *state)
555
volatile char *ehlo = state->smtp ? "EHLO" : "LHLO";
556
VSTREAM *stream = state->stream;
560
verbose = (state->pass == 1 && state->nochat == 0);
566
* Send the standard greeting with our hostname
568
if ((except = vstream_setjmp(stream)) != 0) {
569
msg_info("%s while sending %s", exception_text(except), ehlo);
572
command(state, verbose, "%s %s", ehlo, var_myhostname);
574
resp = response(state, verbose);
575
if (resp->code / 100 != 2) {
576
msg_info("%s rejected: %d %s", ehlo, resp->code, resp->str);
584
static void print_stack(STATE *state, x509_stack_t *sk, int trustout)
588
for (i = 0; i < sk_X509_num(sk); i++) {
589
X509 *cert = sk_X509_value(sk, i);
590
char buf[CCERT_BUFSIZ];
594
if ((xn = X509_get_subject_name(cert)) != 0) {
595
X509_NAME_oneline(xn, buf, sizeof buf);
596
BIO_printf(state->tls_bio, "%2d subject: %s\n", i, buf);
598
if ((xn = X509_get_issuer_name(cert)) != 0) {
599
X509_NAME_oneline(xn, buf, sizeof buf);
600
BIO_printf(state->tls_bio, " issuer: %s\n", buf);
602
digest = tls_cert_fprint(cert, state->mdalg);
603
BIO_printf(state->tls_bio, " cert digest=%s\n", digest);
606
digest = tls_pkey_fprint(cert, state->mdalg);
607
BIO_printf(state->tls_bio, " pkey digest=%s\n", digest);
611
PEM_write_bio_X509_AUX(state->tls_bio, cert);
613
PEM_write_bio_X509(state->tls_bio, cert);
617
static void print_trust_info(STATE *state)
619
x509_stack_t *sk = SSL_get_peer_cert_chain(state->tls_context->con);
622
BIO_printf(state->tls_bio, "\n---\nCertificate chain\n");
623
print_stack(state, sk, 0);
625
#ifdef dane_verify_debug
626
/* print internally constructed untrusted chain */
627
if ((sk = state->tls_context->untrusted) != 0) {
628
BIO_printf(state->tls_bio, "\n---\nUntrusted chain\n");
629
print_stack(state, sk, 0);
631
/* print associated root CA */
632
if ((sk = state->tls_context->trusted) != 0) {
633
BIO_printf(state->tls_bio, "\n---\nTrusted chain\n");
634
print_stack(state, sk, 1);
639
/* starttls - SMTP STARTTLS handshake */
641
static int starttls(STATE *state)
643
VSTRING *cipher_exclusions;
646
VSTREAM *stream = state->stream;
647
TLS_CLIENT_START_PROPS tls_props;
649
/* SMTP stream with deadline timeouts */
650
smtp_stream_setup(stream, smtp_tmout, 1);
651
if ((except = vstream_setjmp(stream)) != 0) {
652
msg_fatal("%s while sending STARTTLS", exception_text(except));
655
command(state, state->pass == 1, "STARTTLS");
657
resp = response(state, state->pass == 1);
658
if (resp->code / 100 != 2) {
659
msg_info("STARTTLS rejected: %d %s", resp->code, resp->str);
664
* Discard any plain-text data that may be piggybacked after the server's
665
* 220 STARTTLS reply. Should we abort the session instead?
667
vstream_fpurge(stream, VSTREAM_PURGE_READ);
669
#define ADD_EXCLUDE(vstr, str) \
672
vstring_sprintf_append((vstr), "%s%s", \
673
VSTRING_LEN(vstr) ? " " : "", (str)); \
676
cipher_exclusions = vstring_alloc(10);
677
ADD_EXCLUDE(cipher_exclusions, DEF_SMTP_TLS_EXCL_CIPH);
678
if (TLS_REQUIRED(state->level))
679
ADD_EXCLUDE(cipher_exclusions, DEF_SMTP_TLS_MAND_EXCL);
682
* If we're authenticating suppress anonymous ciphersuites, otherwise at
683
* least encrypt, not much point in doing neither.
685
if (TLS_MUST_MATCH(state->level))
686
ADD_EXCLUDE(cipher_exclusions, "aNULL");
688
ADD_EXCLUDE(cipher_exclusions, "eNULL");
691
TLS_CLIENT_START(&tls_props,
692
ctx = state->tls_ctx,
694
timeout = smtp_tmout,
695
tls_level = state->level,
696
nexthop = state->nexthop,
697
host = state->hostname,
698
namaddr = state->namaddrport,
699
serverid = state->addrport,
700
helo = state->helo ? state->helo : "",
701
protocols = state->protocols,
702
cipher_grade = state->grade,
704
= vstring_str(cipher_exclusions),
705
matchargv = state->match,
706
mdalg = state->mdalg,
707
dane = state->ddane ? state->ddane : state->dane);
708
vstring_free(cipher_exclusions);
713
if (state->tls_context == 0) {
714
/* We must avoid further I/O, the peer is in an undefined state. */
715
(void) vstream_fpurge(stream, VSTREAM_PURGE_BOTH);
716
(void) vstream_fclose(stream);
720
if (state->pass == 1) {
722
if (!TLS_CERT_IS_PRESENT(state->tls_context))
723
msg_info("Server is anonymous");
724
else if (state->print_trust)
725
print_trust_info(state);
726
state->log_mask &= ~(TLS_LOG_CERTMATCH | TLS_LOG_PEERCERT |
727
TLS_LOG_VERBOSE | TLS_LOG_UNTRUSTED);
728
state->log_mask |= TLS_LOG_CACHE | TLS_LOG_SUMMARY;
729
tls_update_app_logmask(state->tls_ctx, state->log_mask);
736
/* doproto - do SMTP handshake */
738
static int doproto(STATE *state)
740
VSTREAM *stream = state->stream;
749
* Prepare for disaster.
751
smtp_stream_setup(stream, conn_tmout, 1);
752
if ((except = vstream_setjmp(stream)) != 0)
753
msg_fatal("%s while reading server greeting", exception_text(except));
756
* Read and parse the server's SMTP greeting banner.
758
if (((resp = response(state, 1))->code / 100) != 2) {
759
msg_info("SMTP service not available: %d %s", resp->code, resp->str);
764
* Send the standard greeting with our hostname
766
if ((resp = ehlo(state)) == 0)
770
for (n = 0; (words = mystrtok(&lines, "\n")) != 0; ++n) {
771
if ((word = mystrtok(&words, " \t=")) != 0) {
773
state->helo = mystrdup(word);
774
if (strcasecmp(word, "STARTTLS") == 0)
780
if (words && state->tls_ctx)
786
* Prepare for disaster.
788
smtp_stream_setup(stream, smtp_tmout, 1);
789
if ((except = vstream_setjmp(stream)) != 0) {
790
msg_warn("%s while sending QUIT command", exception_text(except));
793
command(state, 1, "QUIT");
794
(void) response(state, 1);
799
/* connect_sock - connect a socket over some transport */
801
static VSTREAM *connect_sock(int sock, struct sockaddr *sa, int salen,
802
const char *name, const char *addr, STATE *state)
804
DSN_BUF *why = state->why;
809
if (conn_tmout > 0) {
810
non_blocking(sock, NON_BLOCKING);
811
conn_stat = timed_connect(sock, sa, salen, conn_tmout);
813
non_blocking(sock, BLOCKING);
816
conn_stat = sane_connect(sock, sa, salen);
820
dsb_simple(why, "4.4.1", "connect to %s[%s]:%d: %m",
821
name, addr, ntohs(state->port));
823
dsb_simple(why, "4.4.1", "connect to %s[%s]: %m", name, addr);
827
stream = vstream_fdopen(sock, O_RDWR);
829
vstring_export(state->port == 0 ?
830
vstring_sprintf(vstring_alloc(10), "%s[%s]", name, addr) :
831
vstring_sprintf(vstring_alloc(10), "%s[%s]:%u",
832
name, addr, ntohs(state->port)));
834
vstring_export(state->port == 0 ?
835
vstring_sprintf(vstring_alloc(10), "%s", addr) :
836
vstring_sprintf(vstring_alloc(10), "[%s]:%u",
837
addr, ntohs(state->port)));
840
* Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE.
842
if (sa->sa_family == AF_INET
844
|| sa->sa_family == AF_INET6
847
vstream_tweak_tcp(stream);
852
/* connect_unix - connect to a unix-domain socket */
854
static VSTREAM *connect_unix(STATE *state, const char *path)
856
static const char *myname = "connect_unix";
857
DSN_BUF *why = state->why;
858
struct sockaddr_un sock_un;
859
int len = strlen(path);
863
state->nexthop = mystrdup(var_myhostname);
864
state->hostname = mystrdup(var_myhostname);
866
dsb_reset(why); /* Paranoia */
871
if (len >= (int) sizeof(sock_un.sun_path)) {
872
dsb_simple(why, "4.3.5", "unix-domain name too long: %s", path);
879
memset((char *) &sock_un, 0, sizeof(sock_un));
880
sock_un.sun_family = AF_UNIX;
882
sock_un.sun_len = len + 1;
884
memcpy(sock_un.sun_path, path, len + 1);
887
* Create a client socket.
889
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
890
msg_fatal("%s: socket: %m", myname);
893
* Connect to the server.
896
msg_info("%s: trying: %s...", myname, path);
898
return (connect_sock(sock, (struct sockaddr *) &sock_un, sizeof(sock_un),
899
var_myhostname, path, state));
902
/* connect_addr - connect to explicit address */
904
static VSTREAM *connect_addr(STATE *state, DNS_RR *addr)
906
static const char *myname = "connect_addr";
907
DSN_BUF *why = state->why;
908
struct sockaddr_storage ss; /* remote */
909
struct sockaddr *sa = (struct sockaddr *) &ss;
910
SOCKADDR_SIZE salen = sizeof(ss);
911
MAI_HOSTADDR_STR hostaddr;
914
dsb_reset(why); /* Paranoia */
919
if (dns_rr_to_sa(addr, state->port, sa, &salen) != 0) {
920
msg_warn("%s: skip address type %s: %m",
921
myname, dns_strtype(addr->type));
922
dsb_simple(why, "4.4.0", "network address conversion failed: %m");
929
if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
930
msg_fatal("%s: socket: %m", myname);
932
if (inet_windowsize > 0)
933
set_inet_windowsize(sock, inet_windowsize);
936
* Connect to the server.
938
SOCKADDR_TO_HOSTADDR(sa, salen, &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
940
msg_info("%s: trying: %s[%s] port %d...",
941
myname, HNAME(addr), hostaddr.buf, ntohs(state->port));
943
return (connect_sock(sock, sa, salen, HNAME(addr), hostaddr.buf, state));
946
#define HAS_DSN(why) (STR((why)->status)[0] != 0)
947
#define HAS_SOFT_DSN(why) (STR((why)->status)[0] == '4')
948
#define HAS_HARD_DSN(why) (STR((why)->status)[0] == '5')
949
#define HAS_LOOP_DSN(why) \
950
(HAS_DSN(why) && strcmp(STR((why)->status) + 1, ".4.6") == 0)
952
#define SET_SOFT_DSN(why) (STR((why)->status)[0] = '4')
953
#define SET_HARD_DSN(why) (STR((why)->status)[0] = '5')
955
/* addr_one - address lookup for one host name */
957
static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host,
958
int res_opt, unsigned pref)
960
static const char *myname = "addr_one";
961
DSN_BUF *why = state->why;
965
struct addrinfo *res0;
966
struct addrinfo *res;
967
INET_PROTO_INFO *proto_info = inet_proto_info();
971
msg_info("%s: host %s", myname, host);
974
* Interpret a numerical name as an address.
976
if (hostaddr_to_sockaddr(host, (char *) 0, 0, &res0) == 0
977
&& strchr((char *) proto_info->sa_family_list, res0->ai_family) != 0) {
978
if ((addr = dns_sa_to_rr(host, pref, res0->ai_addr)) == 0)
979
msg_fatal("host %s: conversion error for address family %d: %m",
980
host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
981
addr_list = dns_rr_append(addr_list, addr);
987
* Use DNS lookup, but keep the option open to use native name service.
989
* XXX A soft error dominates past and future hard errors. Therefore we
990
* should not clobber a soft error text and status code.
992
if (state->host_lookup & HOST_FLAG_DNS) {
993
switch (dns_lookup_v(host, res_opt, &addr, (VSTRING *) 0,
994
why->reason, DNS_REQ_FLAG_NONE,
995
proto_info->dns_atype_list)) {
997
for (rr = addr; rr; rr = rr->next)
999
addr_list = dns_rr_append(addr_list, addr);
1002
dsb_status(why, "4.4.3");
1005
dsb_status(why, HAS_SOFT_DSN(why) ? "4.4.3" : "5.4.3");
1008
dsb_status(why, HAS_SOFT_DSN(why) ? "4.4.4" : "5.4.4");
1011
dsb_status(why, HAS_SOFT_DSN(why) ? "4.4.4" : "5.4.4");
1012
/* maybe native naming service will succeed */
1018
* Use the native name service which also looks in /etc/hosts.
1020
* XXX A soft error dominates past and future hard errors. Therefore we
1021
* should not clobber a soft error text and status code.
1023
#define RETRY_AI_ERROR(e) \
1024
((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
1026
#define DSN_NOHOST(e) \
1027
((e) == EAI_AGAIN || (e) == EAI_NODATA || (e) == EAI_NONAME)
1029
#define DSN_NOHOST(e) \
1030
((e) == EAI_AGAIN || (e) == EAI_NONAME)
1033
if (state->host_lookup & HOST_FLAG_NATIVE) {
1034
if ((aierr = hostname_to_sockaddr(host, (char *) 0, 0, &res0)) != 0) {
1035
dsb_simple(why, (HAS_SOFT_DSN(why) || RETRY_AI_ERROR(aierr)) ?
1036
(DSN_NOHOST(aierr) ? "4.4.4" : "4.3.0") :
1037
(DSN_NOHOST(aierr) ? "5.4.4" : "5.3.0"),
1038
"unable to look up host %s: %s",
1039
host, MAI_STRERROR(aierr));
1041
for (found = 0, res = res0; res != 0; res = res->ai_next) {
1042
if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
1043
msg_info("skipping address family %d for host %s",
1044
res->ai_family, host);
1048
if ((addr = dns_sa_to_rr(host, pref, res->ai_addr)) == 0)
1049
msg_fatal("host %s: conversion error for address family %d: %m",
1050
host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
1051
addr_list = dns_rr_append(addr_list, addr);
1055
dsb_simple(why, HAS_SOFT_DSN(why) ? "4.4.4" : "5.4.4",
1056
"%s: host not found", host);
1063
* No further alternatives for host lookup.
1068
/* mx_addr_list - address lookup for a list of mail exchangers */
1070
static DNS_RR *mx_addr_list(STATE *state, DNS_RR *mx_names)
1072
static const char *myname = "mx_addr_list";
1073
DNS_RR *addr_list = 0;
1075
int res_opt = mx_names->dnssec_valid ? RES_USE_DNSSEC : 0;
1077
for (rr = mx_names; rr; rr = rr->next) {
1078
if (rr->type != T_MX)
1079
msg_panic("%s: bad resource type: %d", myname, rr->type);
1080
addr_list = addr_one(state, addr_list, (char *) rr->data, res_opt,
1086
/* smtp_domain_addr - mail exchanger address lookup */
1088
static DNS_RR *domain_addr(STATE *state, char *domain)
1091
DNS_RR *addr_list = 0;
1092
int r = 0; /* Resolver flags */
1094
dsb_reset(state->why);
1096
#if (RES_USE_DNSSEC != 0) && (RES_USE_EDNS0 != 0)
1097
r |= RES_USE_DNSSEC;
1100
switch (dns_lookup(domain, T_MX, r, &mx_names, (VSTRING *) 0,
1101
state->why->reason)) {
1103
dsb_status(state->why, "4.4.3");
1106
dsb_status(state->why, "5.4.4");
1109
dsb_status(state->why, "5.4.3");
1112
mx_names = dns_rr_sort(mx_names, dns_rr_compare_pref_any);
1113
addr_list = mx_addr_list(state, mx_names);
1114
state->mx = dns_rr_copy(mx_names);
1115
dns_rr_free(mx_names);
1116
if (addr_list == 0) {
1117
msg_warn("no MX host for %s has a valid address record", domain);
1120
#define COMPARE_ADDR(flags) \
1121
((flags & MISC_FLAG_PREF_IPV6) ? dns_rr_compare_pref_ipv6 : \
1122
(flags & MISC_FLAG_PREF_IPV4) ? dns_rr_compare_pref_ipv4 : \
1123
dns_rr_compare_pref_any)
1124
if (addr_list && addr_list->next) {
1125
addr_list = dns_rr_shuffle(addr_list);
1126
addr_list = dns_rr_sort(addr_list, COMPARE_ADDR(state->addr_pref));
1130
addr_list = host_addr(state, domain);
1137
/* host_addr - direct host lookup */
1139
static DNS_RR *host_addr(STATE *state, const char *host)
1141
DSN_BUF *why = state->why;
1145
dsb_reset(why); /* Paranoia */
1147
#if (RES_USE_DNSSEC != 0) && (RES_USE_EDNS0 != 0)
1148
res_opt |= RES_USE_DNSSEC;
1152
addr_list = addr_one(state, (DNS_RR *) 0, host, res_opt, PREF0);
1153
if (addr_list && addr_list->next) {
1154
addr_list = dns_rr_shuffle(addr_list);
1155
if (inet_proto_info()->ai_family_list[1] != 0)
1156
addr_list = dns_rr_sort(addr_list, COMPARE_ADDR(state->addr_pref));
1161
/* dane_host_level - canidate host "dane" or degraded security level */
1163
static int dane_host_level(STATE *state, DNS_RR *addr)
1165
int level = state->level;
1168
if (level == TLS_LEV_DANE) {
1169
if (state->mx == 0 || state->mx->dnssec_valid) {
1170
if (state->log_mask & (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE))
1171
tls_dane_verbose(1);
1173
tls_dane_verbose(0);
1175
/* See addr loop in connect_remote() */
1177
tls_dane_free(state->ddane);
1180
* When TLSA lookups fail, next host. If unusable or not found,
1181
* fallback to "secure"
1183
state->ddane = tls_dane_resolve(state->port, "tcp", addr,
1185
if (!state->ddane) {
1186
dsb_simple(state->why, "4.7.5",
1187
"TLSA lookup error for %s:%u",
1188
HNAME(addr), ntohs(state->port));
1189
level = TLS_LEV_INVALID;
1190
} else if (tls_dane_notfound(state->ddane)
1191
|| tls_dane_unusable(state->ddane)) {
1193
msg_info("no %sTLSA records found, "
1194
"resorting to \"secure\"",
1195
tls_dane_unusable(state->ddane) ?
1197
level = TLS_LEV_SECURE;
1198
} else if (!TLS_DANE_HASTA(state->ddane)
1199
&& !TLS_DANE_HASEE(state->ddane)) {
1200
msg_panic("empty DANE match list");
1203
argv_free(state->match);
1204
argv_add(state->match = argv_alloc(2),
1205
state->ddane->base_domain, ARGV_END);
1207
if (strcmp(state->mx->qname, state->mx->rname) == 0)
1208
argv_add(state->match, state->mx->qname, ARGV_END);
1210
argv_add(state->match, state->mx->rname,
1211
state->mx->qname, ARGV_END);
1215
level = TLS_LEV_SECURE;
1223
/* parse_destination - parse host/port destination */
1225
static char *parse_destination(char *destination, char *def_service,
1226
char **hostp, unsigned *portp)
1228
char *buf = mystrdup(destination);
1231
char *protocol = "tcp";
1236
msg_info("parse_destination: %s %s", destination, def_service);
1239
* Parse the host/port information. We're working with a copy of the
1240
* destination argument so the parsing can be destructive.
1242
if ((err = host_port(buf, hostp, (char *) 0, &service, def_service)) != 0)
1243
msg_fatal("%s in server description: %s", err, destination);
1246
* Convert service to port number, network byte order.
1248
if (alldig(service)) {
1249
if ((port = atoi(service)) >= 65536 || port == 0)
1250
msg_fatal("bad network port in destination: %s", destination);
1251
*portp = htons(port);
1253
if ((sp = getservbyname(service, protocol)) != 0)
1254
*portp = sp->s_port;
1255
else if (strcmp(service, "smtp") == 0)
1258
msg_fatal("unknown service: %s/%s", service, protocol);
1263
/* connect_remote - connect to TCP destination or log an error */
1265
static void connect_remote(STATE *state, char *dest)
1271
/* When reconnecting use IP address of previous session */
1272
if (state->addr == 0) {
1273
buf = parse_destination(dest, state->smtp ? "smtp" : "24",
1274
&domain, &state->port);
1275
if (!state->nexthop)
1276
state->nexthop = mystrdup(domain);
1277
if (state->smtp == 0 || *dest == '[')
1278
state->addr = host_addr(state, domain);
1280
state->addr = domain_addr(state, domain);
1283
if (state->addr == 0) {
1284
msg_info("Destination address lookup failed: %s",
1285
vstring_str(state->why->reason));
1289
for (addr = state->addr; addr; addr = addr->next) {
1290
int level = dane_host_level(state, addr);
1292
if (level == TLS_LEV_INVALID
1293
|| (state->stream = connect_addr(state, addr)) == 0) {
1294
msg_info("Failed to establish session to %s via %s: %s",
1295
dest, HNAME(addr), vstring_str(state->why->reason));
1298
/* We have a connection */
1299
state->level = level;
1300
state->hostname = mystrdup(HNAME(addr));
1302
/* We use the same address when reconnecting, so flush the rest. */
1303
addr = dns_rr_copy(addr);
1304
dns_rr_free(state->addr);
1310
/* connect_dest - connect to given inet: or unix: destination */
1312
static int connect_dest(STATE *state)
1314
char *dest = state->dest;
1317
* With LMTP we have direct-to-host delivery only. The destination may
1318
* have multiple IP addresses.
1320
if (state->smtp == 0) {
1321
if (strncmp(dest, "unix:", 5) == 0) {
1322
connect_unix(state, dest + 5);
1324
msg_info("Failed to establish session to %s: %s",
1325
dest, vstring_str(state->why->reason));
1328
if (strncmp(dest, "inet:", 5) == 0)
1331
connect_remote(state, dest);
1333
return (state->stream == 0);
1336
static void disconnect_dest(STATE *state)
1339
if (state->tls_context)
1340
tls_client_stop(state->tls_ctx, state->stream,
1341
smtp_tmout, 0, state->tls_context);
1342
state->tls_context = 0;
1344
tls_dane_free(state->ddane);
1349
vstream_fclose(state->stream);
1352
if (state->namaddrport)
1353
myfree(state->namaddrport);
1354
state->namaddrport = 0;
1356
if (state->addrport)
1357
myfree(state->addrport);
1358
state->addrport = 0;
1360
/* Reused on reconnect */
1361
if (state->reconnect <= 0) {
1363
dns_rr_free(state->addr);
1366
dns_rr_free(state->mx);
1370
myfree(state->nexthop);
1373
if (state->hostname)
1374
myfree(state->hostname);
1375
state->hostname = 0;
1377
dsb_free(state->why);
1378
vstring_free(state->buffer);
1381
static int finger(STATE *state)
1386
* Make sure the SMTP server cannot run us out of memory by sending
1387
* never-ending lines of text.
1389
state->buffer = vstring_alloc(100);
1390
vstring_ctl(state->buffer, VSTRING_CTL_MAXLEN,
1391
(ssize_t) var_line_limit, 0);
1392
state->why = dsb_create();
1394
if (!(err = connect_dest(state))) {
1395
if (state->pass == 1 && !state->nochat)
1396
msg_info("Connected to %s", state->namaddrport);
1397
err = doproto(state);
1399
disconnect_dest(state);
1405
if (state->reconnect > 0) {
1410
tlsmgrmem_status(&cache_enabled, &cache_count, &cache_hits);
1411
if (cache_enabled && cache_count == 0) {
1412
msg_info("Server declined session caching. Done reconnecting.");
1413
state->reconnect = 0;
1414
} else if (cache_hits > 0 && (state->log_mask & TLS_LOG_SESSTKT) != 0) {
1415
msg_info("Found a previously used server. Done reconnecting.");
1416
state->reconnect = 0;
1417
} else if (state->max_reconnect-- <= 0) {
1418
msg_info("Maximum reconnect count reached.");
1419
state->reconnect = 0;
1429
/* ssl_cleanup - free memory allocated in the OpenSSL library */
1431
static void ssl_cleanup(void)
1433
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
1434
ERR_remove_thread_state(0); /* Thread-id is now a pointer */
1436
ERR_remove_state(0); /* Deprecated with OpenSSL 1.0.0 */
1439
CONF_modules_unload(1);
1442
CRYPTO_cleanup_all_ex_data();
1447
/* run - do what we were asked to do. */
1449
static int run(STATE *state)
1453
if (finger(state) != 0)
1455
if (state->reconnect <= 0)
1457
msg_info("Reconnecting after %d seconds", state->reconnect);
1459
sleep(state->reconnect);
1465
/* cleanup - free memory allocated in main */
1467
static void cleanup(STATE *state)
1470
if (state->tls_ctx != 0)
1471
tls_free_app_context(state->tls_ctx);
1473
(void) BIO_free(state->tls_bio);
1476
myfree(state->mdalg);
1477
myfree(state->CApath);
1478
myfree(state->CAfile);
1479
if (state->options.level)
1480
myfree(state->options.level);
1481
myfree(state->options.logopts);
1483
argv_free(state->match);
1484
if (state->options.tas)
1485
argv_free(state->options.tas);
1487
tls_dane_free(state->dane);
1489
/* Flush and free DANE TLSA cache */
1491
/* Flush and free memory tlsmgr cache */
1493
myfree(state->grade);
1494
myfree(state->protocols);
1496
myfree(state->options.host_lookup);
1497
myfree(state->dest);
1502
/* usage - explain */
1504
static void usage(void)
1507
fprintf(stderr, "usage: %s %s \\\n\t%s \\\n\t%s \\\n\t%s"
1508
" destination [match ...]\n", var_procname,
1509
"[-acCfSv] [-t conn_tmout] [-T cmd_tmout] [-L logopts]",
1510
"[-h host_lookup] [-l level] [-d mdalg] [-g grade] [-p protocols]",
1511
"[-A tafile] [-F CAfile.pem] [-P CApath/] [-m count] [-r delay]",
1514
fprintf(stderr, "usage: %s [-acStTv] [-h host_lookup] [-o name=value] destination\n",
1520
/* tls_init - initialize application TLS library context */
1522
static void tls_init(STATE *state)
1525
TLS_CLIENT_INIT_PROPS props;
1527
if (state->level <= TLS_LEV_NONE)
1531
TLS_CLIENT_INIT(&props,
1532
log_param = "-L option",
1533
log_level = state->options.logopts,
1534
verifydepth = DEF_SMTP_TLS_SCERT_VD,
1535
cache_type = "memory",
1542
CAfile = state->CAfile,
1543
CApath = state->CApath,
1544
mdalg = state->mdalg);
1548
/* override - update main.cf parameter */
1550
static void override(const char *nameval)
1554
char *save = mystrdup(nameval);
1556
if (split_nameval(save, ¶m_name, ¶m_value) != 0)
1558
mail_conf_update(param_name, param_value);
1562
/* parse_options - (argc, argv) -> state */
1564
static void parse_options(STATE *state, int argc, char *argv[])
1570
state->reconnect = -1;
1571
state->max_reconnect = 5;
1573
state->protocols = mystrdup("!SSLv2");
1574
state->grade = mystrdup("medium");
1576
memset((char *) &state->options, 0, sizeof(state->options));
1577
state->options.host_lookup = mystrdup("dns");
1579
#define OPTS "a:ch:o:St:T:v"
1581
#define TLSOPTS "A:Cd:fF:g:l:L:m:p:P:r:"
1583
state->mdalg = mystrdup("sha1");
1584
state->CApath = mystrdup("");
1585
state->CAfile = mystrdup("");
1586
state->options.tas = argv_alloc(1);
1587
state->options.logopts = 0;
1588
state->level = TLS_LEV_DANE;
1591
state->level = TLS_LEV_NONE;
1594
while ((c = GETOPT(argc, argv, OPTS TLSOPTS)) > 0) {
1600
state->options.addr_pref = mystrdup(optarg);
1606
myfree(state->options.host_lookup);
1607
state->options.host_lookup = mystrdup(optarg);
1616
conn_tmout = atoi(optarg);
1619
smtp_tmout = atoi(optarg);
1626
argv_add(state->options.tas, optarg, ARGV_END);
1629
state->print_trust = 1;
1632
myfree(state->mdalg);
1633
state->mdalg = mystrdup(optarg);
1636
state->force_tlsa = 1;
1639
myfree(state->CAfile);
1640
state->CAfile = mystrdup(optarg);
1643
myfree(state->grade);
1644
state->grade = mystrdup(optarg);
1647
if (state->options.level)
1648
myfree(state->options.level);
1649
state->options.level = mystrdup(optarg);
1652
if (state->options.logopts)
1653
myfree(state->options.logopts);
1654
state->options.logopts = mystrdup(optarg);
1657
state->max_reconnect = atoi(optarg);
1660
myfree(state->protocols);
1661
state->protocols = mystrdup(optarg);
1664
myfree(state->CApath);
1665
state->CApath = mystrdup(optarg);
1668
state->reconnect = atoi(optarg);
1675
* Address family preference.
1678
name_code(addr_pref_map, NAME_CODE_FLAG_NONE, state->options.addr_pref ?
1679
state->options.addr_pref : "any");
1680
if (state->addr_pref < 0)
1681
msg_fatal("bad '-a' option value: %s", state->options.addr_pref);
1684
* Select hostname lookup mechanisms.
1686
state->host_lookup =
1687
name_mask("-h option", lookup_masks, state->options.host_lookup ?
1688
state->options.host_lookup : "dns");
1692
if (state->reconnect < 0)
1693
tlsmgrmem_disable();
1695
if (state->options.logopts == 0)
1696
state->options.logopts = mystrdup("routine,certmatch");
1697
state->log_mask = tls_log_mask("-L option", state->options.logopts);
1699
if (state->options.level) {
1700
state->level = tls_level_lookup(state->options.level);
1702
switch (state->level) {
1703
case TLS_LEV_DANE_ONLY:
1704
state->level = TLS_LEV_DANE;
1708
case TLS_LEV_INVALID:
1709
msg_fatal("Invalid TLS level \"%s\"", state->options.level);
1714
* We first call tls_init(), which ultimately calls SSL_library_init(),
1715
* since otherwise we can't tell whether we have the message digests
1716
* required for DANE support.
1719
if (state->level == TLS_LEV_DANE && !tls_dane_avail()) {
1720
msg_warn("The \"dane\" TLS security level is not available");
1721
state->level = TLS_LEV_SECURE;
1724
if (state->print_trust)
1725
state->tls_bio = BIO_new_fp(stdout, BIO_NOCLOSE);
1730
/* parse_match - process match arguments */
1732
static void parse_match(STATE *state, int argc, char *argv[])
1736
switch (state->level) {
1737
case TLS_LEV_SECURE:
1738
state->match = argv_alloc(2);
1740
argv_split_append(state->match, *argv++, "");
1741
if (state->match->argc == 0)
1742
argv_add(state->match, "nexthop", "dot-nexthop", ARGV_END);
1744
case TLS_LEV_VERIFY:
1745
state->match = argv_alloc(1);
1747
argv_split_append(state->match, *argv++, "");
1748
if (state->match->argc == 0)
1749
argv_add(state->match, "hostname", ARGV_END);
1751
case TLS_LEV_FPRINT:
1752
state->dane = tls_dane_alloc();
1754
tls_dane_add_ee_digests((TLS_DANE *) state->dane,
1755
state->mdalg, *argv++, "");
1758
state->match = argv_alloc(2);
1759
argv_add(state->match, "nexthop", "hostname", ARGV_END);
1765
/* parse_tas - process '-A' trust anchor file option */
1767
static void parse_tas(STATE *state)
1772
if (!state->options.tas->argc)
1775
switch (state->level) {
1778
case TLS_LEV_SECURE:
1779
case TLS_LEV_VERIFY:
1780
state->dane = tls_dane_alloc();
1781
for (file = state->options.tas->argv; *file; ++file) {
1782
if (!tls_dane_load_trustfile((TLS_DANE *) state->dane, *file))
1786
msg_fatal("Failed to load trust anchor file: %s", *file);
1793
int main(int argc, char *argv[])
1796
char *loopenv = getenv("VALGRINDLOOP");
1797
int loop = loopenv ? atoi(loopenv) : 1;
1799
/* Don't die when a peer goes away unexpectedly. */
1800
signal(SIGPIPE, SIG_IGN);
1802
/* We're a diagnostic utility, so diagnostic messages go to stdout. */
1803
var_procname = mystrdup(basename(argv[0]));
1804
set_mail_conf_str(VAR_PROCNAME, var_procname);
1805
msg_vstream_init(var_procname, VSTREAM_OUT);
1808
* Load main.cf, parse command-line options, then process main.cf
1809
* settings plus any command-line "-o" overrides.
1812
parse_options(&state, argc, argv);
1819
/* The first non-option argument is the destination. */
1823
state.dest = mystrdup(argv[0]);
1824
parse_match(&state, --argc, ++argv);
1826
/* Don't talk to remote systems as root */
1828
chroot_uid(0, var_mail_owner);
1833
/* Be valgrind friendly and clean-up */