summaryrefslogtreecommitdiffstats
path: root/src/posttls-finger
diff options
context:
space:
mode:
Diffstat (limited to 'src/posttls-finger')
-rw-r--r--src/posttls-finger/posttls-finger.c64
1 files changed, 44 insertions, 20 deletions
diff --git a/src/posttls-finger/posttls-finger.c b/src/posttls-finger/posttls-finger.c
index d64c355..b474a40 100644
--- a/src/posttls-finger/posttls-finger.c
+++ b/src/posttls-finger/posttls-finger.c
@@ -103,7 +103,7 @@
/* in the DNS). In Postfix versions prior to 3.6, the default value
/* was "md5".
/* .IP "\fB-f\fR"
-/* Lookup the associated DANE TLSA RRset even when a hostname is not an
+/* Look up the associated DANE TLSA RRset even when a hostname is not an
/* alias and its address records lie in an unsigned zone. See
/* smtp_tls_force_insecure_host_tlsa_lookup for details.
/* .IP "\fB-F \fICAfile.pem\fR (default: none)"
@@ -264,6 +264,15 @@
/* the SMTP-in-SSL protocol, rather than the STARTTLS protocol.
/* The destination \fIdomain\fR:\fIport\fR must of course provide such
/* a service.
+/* .IP "\fB-x\fR"
+/* Prefer RFC7250 non-X.509 raw public key (RPK) server credentials. By
+/* default only X.509 certificates are accepted. This is analogous to
+/* setting \fBsmtp_tls_enable_rpk = yes\fR in the smtp(8) client. At the
+/* fingerprint security level, when raw public keys are enabled, only
+/* public key (and not certificate) fingerprints will be compared against
+/* the specified list of \fImatch\fR arguments. Certificate fingerprints
+/* are fragile when raw public keys are solicited, the server may at some
+/* point in time start returning only the public key.
/* .IP "\fB-X\fR"
/* Enable \fBtlsproxy\fR(8) mode. This is an unsupported mode,
/* for program development only.
@@ -441,6 +450,9 @@ typedef struct OPTIONS {
ARGV *tas;
char *host_lookup;
char *addr_pref;
+#ifdef USE_TLS
+ int enable_rpk;
+#endif
} OPTIONS;
/*
@@ -696,7 +708,7 @@ static void print_stack(STATE *state, x509_stack_t *sk, int trustout)
BIO_printf(state->tls_bio, " cert digest=%s\n", digest);
myfree(digest);
- digest = tls_pkey_fprint(cert, state->mdalg);
+ digest = tls_pkey_fprint(X509_get0_pubkey(cert), state->mdalg);
BIO_printf(state->tls_bio, " pkey digest=%s\n", digest);
myfree(digest);
@@ -809,6 +821,7 @@ static int starttls(STATE *state)
mdalg = state->mdalg);
TLS_PROXY_CLIENT_START_PROPS(&start_props,
timeout = smtp_tmout,
+ enable_rpk = state->options.enable_rpk,
tls_level = state->level,
nexthop = state->nexthop,
host = state->hostname,
@@ -826,7 +839,7 @@ static int starttls(STATE *state)
state->ddane : state->dane);
#define PROXY_OPEN_FLAGS \
- (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_SEND_CONTEXT)
+ (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_SEND_CONTEXT)
#define var_tlsproxy_service
if ((cwd_fd = open(".", O_RDONLY)) < 0)
@@ -886,13 +899,19 @@ static int starttls(STATE *state)
state->tls_context = tls_proxy_context_receive(state->stream);
if (state->tls_context) {
if (state->log_mask &
- (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT))
- msg_info("%s: subject_CN=%s, issuer_CN=%s, "
- "fingerprint=%s, pkey_fingerprint=%s",
- state->namaddrport, state->tls_context->peer_CN,
- state->tls_context->issuer_CN,
- state->tls_context->peer_cert_fprint,
- state->tls_context->peer_pkey_fprint);
+ (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) {
+ if (state->tls_context->stoc_rpk)
+ msg_info("%s: pkey_fingerprint=%s", state->namaddrport,
+ state->tls_context->peer_pkey_fprint);
+ else
+ msg_info("%s: subject_CN=%s, issuer_CN=%s, "
+ "fingerprint=%s, pkey_fingerprint=%s",
+ state->namaddrport,
+ state->tls_context->peer_CN,
+ state->tls_context->issuer_CN,
+ state->tls_context->peer_cert_fprint,
+ state->tls_context->peer_pkey_fprint);
+ }
tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_NEW,
state->tls_context);
} else {
@@ -906,6 +925,7 @@ static int starttls(STATE *state)
stream = stream,
fd = -1,
timeout = smtp_tmout,
+ enable_rpk = state->options.enable_rpk,
tls_level = state->level,
nexthop = state->nexthop,
host = state->hostname,
@@ -938,7 +958,7 @@ static int starttls(STATE *state)
if (state->pass == 1) {
ehlo(state);
- if (!TLS_CERT_IS_PRESENT(state->tls_context))
+ if (!TLS_CRED_IS_PRESENT(state->tls_context))
msg_info("Server is anonymous");
else if (state->tlsproxy_mode == 0) {
if (state->print_trust)
@@ -1232,7 +1252,7 @@ static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host,
* should not clobber a soft error text and status code.
*/
#define RETRY_AI_ERROR(e) \
- ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
+ ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
#ifdef EAI_NODATA
#define DSN_NOHOST(e) \
((e) == EAI_AGAIN || (e) == EAI_NODATA || (e) == EAI_NONAME)
@@ -1833,14 +1853,14 @@ static void usage(void)
#ifdef USE_TLS
fprintf(stderr, "usage: %s %s \\\n\t%s \\\n\t%s \\\n\t%s \\\n\t%s"
" destination [match ...]\n", var_procname,
- "[-acCfSvw] [-t conn_tmout] [-T cmd_tmout] [-L logopts]",
+ "[-acCfRSvwx] [-t conn_tmout] [-T cmd_tmout] [-L logopts]",
"[-h host_lookup] [-l level] [-d mdalg] [-g grade] [-p protocols]",
"[-A tafile] [-F CAfile.pem] [-P CApath/] [-s servername]",
"[ [-H chainfiles] | [-k certfile [-K keyfile]] ]",
"[-m count] [-r delay] [-o name=value]");
#else
- fprintf(stderr, "usage: %s [-acStTv] [-h host_lookup] [-o name=value] destination\n",
- var_procname);
+ fprintf(stderr, "usage: %s [-acRStTv] [-h host_lookup] [-o name=value]"
+ " destination\n", var_procname);
#endif
exit(1);
}
@@ -1910,7 +1930,7 @@ static void parse_options(STATE *state, int argc, char *argv[])
#define OPTS "a:ch:o:RSt:T:v"
#ifdef USE_TLS
-#define TLSOPTS "A:Cd:fF:g:H:k:K:l:L:m:M:p:P:r:s:wX"
+#define TLSOPTS "A:Cd:fF:g:H:k:K:l:L:m:M:p:P:r:s:wxX"
state->mdalg = 0;
state->CApath = mystrdup("");
@@ -1921,6 +1941,7 @@ static void parse_options(STATE *state, int argc, char *argv[])
state->sni = mystrdup("");
state->options.tas = argv_alloc(1);
state->options.logopts = 0;
+ state->options.enable_rpk = 0;
state->level = TLS_LEV_DANE;
state->mxinsec_level = TLS_LEV_DANE;
state->tlsproxy_mode = 0;
@@ -2054,6 +2075,9 @@ static void parse_options(STATE *state, int argc, char *argv[])
case 'w':
state->wrapper_mode = 1;
break;
+ case 'x':
+ state->options.enable_rpk = 1;
+ break;
case 'X':
state->tlsproxy_mode = 1;
break;
@@ -2119,8 +2143,8 @@ static void parse_match(STATE *state, int argc, char *argv[])
int smtp_mode = 1;
/*
- * DANE match names are configured late, once the TLSA records are in
- * hand. For now, prepare to fall back to "secure".
+ * DANE match names are configured late, once the TLSA records are in hand.
+ * For now, prepare to fall back to "secure".
*/
switch (state->level) {
default:
@@ -2148,8 +2172,8 @@ static void parse_match(STATE *state, int argc, char *argv[])
case TLS_LEV_FPRINT:
state->dane = tls_dane_alloc();
while (*argv)
- tls_dane_add_fpt_digests((TLS_DANE *) state->dane, *argv++, "",
- smtp_mode);
+ tls_dane_add_fpt_digests(state->dane, state->options.enable_rpk,
+ *argv++, "", smtp_mode);
break;
}
#endif