From 4021cd6e8c7d3df208e9ecb6a46c00f2044cbc38 Mon Sep 17 00:00:00 2001 From: eric Date: Sat, 22 May 2021 09:09:07 +0000 Subject: [PATCH] allow to specify TLS ciphers and protocols in smtp(1) improvements from jmc@ schwarze@ tb@ ok tb@ --- usr.sbin/smtpd/smtp.1 | 25 +++++++++++++++++-- usr.sbin/smtpd/smtpc.c | 55 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/usr.sbin/smtpd/smtp.1 b/usr.sbin/smtpd/smtp.1 index 10740653b68..f020fe607f9 100644 --- a/usr.sbin/smtpd/smtp.1 +++ b/usr.sbin/smtpd/smtp.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: smtp.1,v 1.9 2021/02/13 08:07:48 jmc Exp $ +.\" $OpenBSD: smtp.1,v 1.10 2021/05/22 09:09:07 eric Exp $ .\" .\" Copyright (c) 2018, Eric Faurot .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: February 13 2021 $ +.Dd $Mdocdate: May 22 2021 $ .Dt SMTP 1 .Os .Sh NAME @@ -27,6 +27,7 @@ .Op Fl F Ar from .Op Fl H Ar helo .Op Fl s Ar server +.Op Fl T Ar params .Op Ar recipient ... .Sh DESCRIPTION The @@ -91,6 +92,26 @@ SMTP session with forced TLS on connection. .Pp Defaults to .Dq smtp://localhost:25 . +.It Fl T Ar params +Set specific parameters for TLS sessions. +The +.Ar params +string is a comma or space separated list of options. +The available options are: +.Bl -tag -width Ds +.It protocols Ns = Ns Ar value +Specify the protocols to use. +Refer to +.Xr tls_config_parse_protocols 3 +for +.Ar value . +.It ciphers Ns = Ns Ar value +Specify the allowed ciphers. +Refer to +.Xr tls_config_set_ciphers 3 +for +.Ar value . +.El .It Fl v Be more verbose. This option can be specified multiple times. diff --git a/usr.sbin/smtpd/smtpc.c b/usr.sbin/smtpd/smtpc.c index ca48604feb5..4bf64fc4d46 100644 --- a/usr.sbin/smtpd/smtpc.c +++ b/usr.sbin/smtpd/smtpc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpc.c,v 1.15 2021/04/10 10:19:19 eric Exp $ */ +/* $OpenBSD: smtpc.c,v 1.16 2021/05/22 09:09:07 eric Exp $ */ /* * Copyright (c) 2018 Eric Faurot @@ -48,22 +48,57 @@ static struct smtp_mail mail; static const char *servname = NULL; static struct tls_config *tls_config; +static const char *protocols = NULL; +static const char *ciphers = NULL; + static void usage(void) { extern char *__progname; fprintf(stderr, "usage: %s [-Chnv] [-a authfile] [-F from] [-H helo] " - "[-s server] [recipient ...]\n", __progname); + "[-s server] [-T params] [recipient ...]\n", __progname); exit(1); } +static void +parse_tls_options(char *opt) +{ + static char * const tokens[] = { +#define CIPHERS 0 + "ciphers", +#define PROTOCOLS 1 + "protocols", + NULL }; + char *value; + + while (*opt) { + switch (getsubopt(&opt, tokens, &value)) { + case CIPHERS: + if (value == NULL) + fatalx("missing value for ciphers"); + ciphers = value; + break; + case PROTOCOLS: + if (value == NULL) + fatalx("missing value for protocols"); + protocols = value; + break; + case -1: + if (suboptarg) + fatalx("invalid TLS option \"%s\"", suboptarg); + fatalx("missing TLS option"); + } + } +} + int main(int argc, char **argv) { char hostname[256]; FILE *authfile; int ch, i; + uint32_t protos; char *server = "localhost"; char *authstr = NULL; size_t alloc = 0; @@ -91,7 +126,7 @@ main(int argc, char **argv) memset(&mail, 0, sizeof(mail)); mail.from = pw->pw_name; - while ((ch = getopt(argc, argv, "CF:H:S:a:hns:v")) != -1) { + while ((ch = getopt(argc, argv, "CF:H:S:T:a:hns:v")) != -1) { switch (ch) { case 'C': params.tls_verify = 0; @@ -105,6 +140,9 @@ main(int argc, char **argv) case 'S': servname = optarg; break; + case 'T': + parse_tls_options(optarg); + break; case 'a': if ((authfile = fopen(optarg, "r")) == NULL) fatal("%s: open", optarg); @@ -159,6 +197,17 @@ main(int argc, char **argv) tls_config = tls_config_new(); if (tls_config == NULL) fatal("tls_config_new"); + + if (protocols) { + if (tls_config_parse_protocols(&protos, protocols) == -1) + fatalx("failed to parse protocol '%s'", protocols); + if (tls_config_set_protocols(tls_config, protos) == -1) + fatalx("tls_config_set_protocols: %s", + tls_config_error(tls_config)); + } + if (ciphers && tls_config_set_ciphers(tls_config, ciphers) == -1) + fatalx("tls_config_set_ciphers: %s", + tls_config_error(tls_config)); if (tls_config_set_ca_file(tls_config, tls_default_ca_cert_file()) == -1) fatal("tls_set_ca_file"); if (!params.tls_verify) { -- 2.20.1