allow to specify tls ciphers and protocols on listeners
authoreric <eric@openbsd.org>
Fri, 9 Apr 2021 16:43:43 +0000 (16:43 +0000)
committereric <eric@openbsd.org>
Fri, 9 Apr 2021 16:43:43 +0000 (16:43 +0000)
ok tb@

usr.sbin/smtpd/config.c
usr.sbin/smtpd/mta.c
usr.sbin/smtpd/parse.y
usr.sbin/smtpd/smtp.c
usr.sbin/smtpd/smtpd.conf.5
usr.sbin/smtpd/smtpd.h

index 73a76ac..c9f7afa 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: config.c,v 1.54 2021/03/05 12:37:32 eric Exp $        */
+/*     $OpenBSD: config.c,v 1.55 2021/04/09 16:43:43 eric Exp $        */
 
 /*
  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -252,6 +252,8 @@ purge_config(uint8_t what)
        if (what & PURGE_LISTENERS) {
                while ((l = TAILQ_FIRST(env->sc_listeners)) != NULL) {
                        TAILQ_REMOVE(env->sc_listeners, l, entry);
+                       free(l->tls_ciphers);
+                       free(l->tls_protocols);
                        free(l->pki);
                        free(l);
                }
index 4339481..bd5585b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mta.c,v 1.237 2021/04/02 06:30:55 eric Exp $  */
+/*     $OpenBSD: mta.c,v 1.238 2021/04/09 16:43:43 eric Exp $  */
 
 /*
  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -508,10 +508,14 @@ mta_setup_dispatcher(struct dispatcher *dispatcher)
        if (ciphers && tls_config_set_ciphers(config, ciphers) == -1)
                err(1, "%s", tls_config_error(config));
 
-       if (remote->tls_protocols &&
-           (tls_config_parse_protocols(&protos, remote->tls_protocols) == -1
-           || tls_config_set_protocols(config, protos) == -1))
-               err(1, "%s", tls_config_error(config));
+       if (remote->tls_protocols) {
+               if (tls_config_parse_protocols(&protos,
+                   remote->tls_protocols) == -1)
+                       err(1, "failed to parse protocols \"%s\"",
+                           remote->tls_protocols);
+               if (tls_config_set_protocols(config, protos) == -1)
+                       err(1, "%s", tls_config_error(config));
+       }
 
        if (remote->pki) {
                pki = dict_get(env->sc_pki_dict, remote->pki);
index e813279..f654d76 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.y,v 1.286 2021/03/31 17:47:16 eric Exp $        */
+/*     $OpenBSD: parse.y,v 1.287 2021/04/09 16:43:43 eric Exp $        */
 
 /*
  * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -137,6 +137,8 @@ static struct listen_opts {
        char           *filtername;
        char           *pki[PKI_MAX];
        int             pkicount;
+       char           *tls_ciphers;
+       char           *tls_protocols;
        char           *ca;
        uint16_t        auth;
        struct table   *authtable;
@@ -2333,6 +2335,20 @@ opt_if_listen : INET4 {
                        listen_opts.options |= LO_SSL;
                        listen_opts.ssl = F_STARTTLS|F_STARTTLS_REQUIRE|F_TLS_VERIFY;
                }
+               | CIPHERS STRING {
+                       if (listen_opts.tls_ciphers) {
+                               yyerror("ciphers already specified");
+                               YYERROR;
+                       }
+                       listen_opts.tls_ciphers = $2;
+               }
+               | PROTOCOLS STRING {
+                       if (listen_opts.tls_protocols) {
+                               yyerror("protocols already specified");
+                               YYERROR;
+                       }
+                       listen_opts.tls_protocols = $2;
+               }
                | PKI STRING                    {
                        if (listen_opts.pkicount == PKI_MAX) {
                                yyerror("too many pki specified");
@@ -2516,7 +2532,11 @@ listen           : LISTEN {
                        memset(&listen_opts, 0, sizeof listen_opts);
                        listen_opts.family = AF_UNSPEC;
                        listen_opts.flags |= F_EXT_DSN;
-               } ON listener_type
+               } ON listener_type {
+                       free(listen_opts.tls_protocols);
+                       free(listen_opts.tls_ciphers);
+                       memset(&listen_opts, 0, sizeof listen_opts);
+               }
                ;
 
 table          : TABLE STRING STRING   {
@@ -3312,6 +3332,16 @@ config_listener(struct listener *h,  struct listen_opts *lo)
                }
        }
 
+       if (lo->tls_ciphers != NULL &&
+           (h->tls_ciphers = strdup(lo->tls_ciphers)) == NULL) {
+               fatal("strdup");
+       }
+
+       if (lo->tls_protocols != NULL &&
+           (h->tls_protocols = strdup(lo->tls_protocols)) == NULL) {
+               fatal("strdup");
+       }
+
        if (lo->ca != NULL) {
                if (!lowercase(h->ca_name, lo->ca, sizeof(h->ca_name))) {
                        log_warnx("ca name too long: %s", lo->ca);
index 5ca11ad..a2371f7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: smtp.c,v 1.168 2021/03/10 17:25:59 eric Exp $ */
+/*     $OpenBSD: smtp.c,v 1.169 2021/04/09 16:43:43 eric Exp $ */
 
 /*
  * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -169,6 +169,8 @@ smtp_setup_listener_tls(struct listener *l)
 {
        static const char *dheparams[] = { "none", "auto", "legacy" };
        struct tls_config *config;
+       const char *ciphers;
+       uint32_t protos;
        struct pki *pki;
        struct ca *ca;
        int i;
@@ -176,9 +178,19 @@ smtp_setup_listener_tls(struct listener *l)
        if ((config = tls_config_new()) == NULL)
                fatal("smtpd: tls_config_new");
 
-       if (env->sc_tls_ciphers &&
-           tls_config_set_ciphers(config, env->sc_tls_ciphers) == -1)
+       ciphers = env->sc_tls_ciphers;
+       if (l->tls_ciphers)
+               ciphers = l->tls_ciphers;
+       if (ciphers && tls_config_set_ciphers(config, ciphers) == -1)
+               err(1, "%s", tls_config_error(config));
+
+       if (l->tls_protocols) {
+               if (tls_config_parse_protocols(&protos, l->tls_protocols) == -1)
+                       err(1, "failed to parse protocols \"%s\"",
+                           l->tls_protocols);
+               if (tls_config_set_protocols(config, protos) == -1)
                        err(1, "%s", tls_config_error(config));
+       }
 
        pki = l->pki[0];
        if (pki == NULL)
index 74def42..ca4cd64 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: smtpd.conf.5,v 1.259 2021/03/31 17:47:16 eric Exp $
+.\"    $OpenBSD: smtpd.conf.5,v 1.260 2021/04/09 16:43:43 eric Exp $
 .\"
 .\" Copyright (c) 2008 Janne Johansson <jj@openbsd.org>
 .\" Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
@@ -17,7 +17,7 @@
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
 .\"
-.Dd $Mdocdate: March 31 2021 $
+.Dd $Mdocdate: April 9 2021 $
 .Dt SMTPD.CONF 5
 .Os
 .Sh NAME
@@ -527,6 +527,18 @@ With the
 .Cm verify
 option, clients must also provide a valid certificate
 to establish an SMTP session.
+.It Cm protocols Ar protostr
+Define the protocol versions to be used for TLS sessions.
+Refer to the
+.Xr tls_config_parse_protocols 3
+manpage for the format of
+.Ar protostr .
+.It Cm ciphers Ar cipherstr
+Define the list of ciphers that may be used for TLS sessions.
+Refer to the
+.Xr tls_config_set_ciphers 3
+manpage for the format of
+.Ar cipherstr .
 .El
 .It Ic listen on Cm socket Op Ar options
 Listen for incoming SMTP connections on the Unix domain socket
index d36e332..b6556ac 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: smtpd.h,v 1.664 2021/03/31 19:09:19 eric Exp $        */
+/*     $OpenBSD: smtpd.h,v 1.665 2021/04/09 16:43:43 eric Exp $        */
 
 /*
  * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -543,6 +543,8 @@ struct listener {
 
        int                      local;         /* there must be a better way */
 
+       char                    *tls_protocols;
+       char                    *tls_ciphers;
        struct tls              *tls;
        struct pki              **pki;
        int                      pkicount;