add more TLS options to smtp(1):
authoreric <eric@openbsd.org>
Sun, 23 May 2021 15:57:32 +0000 (15:57 +0000)
committereric <eric@openbsd.org>
Sun, 23 May 2021 15:57:32 +0000 (15:57 +0000)
- cafile=<path>:  override the default root certificates
- nosni:  disable SNI completely
- noverify:  do not verify sevrer certificate (replaces -C)
- servername=<name>:  set server name for SNI

ok tb@

usr.sbin/smtpd/smtp.1
usr.sbin/smtpd/smtpc.c

index 3e5b7ef..704e36d 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: smtp.1,v 1.12 2021/05/22 22:30:57 eric Exp $
+.\"    $OpenBSD: smtp.1,v 1.13 2021/05/23 15:57:32 eric Exp $
 .\"
 .\" Copyright (c) 2018, Eric Faurot <eric@openbsd.org>
 .\"
@@ -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: May 22 2021 $
+.Dd $Mdocdate: May 23 2021 $
 .Dt SMTP 1
 .Os
 .Sh NAME
@@ -53,6 +53,10 @@ This option requires a TLS or STARTTLS
 .Ar server .
 .It Fl C
 Do not require server certificate to be valid.
+This flag is deprecated.
+Use
+.Dq Fl T Cm noverify
+instead.
 .It Fl F Ar from
 Set the return-path (MAIL FROM) for the SMTP transaction.
 Default to the current username.
@@ -105,12 +109,21 @@ Refer to
 .Xr tls_config_set_ciphers 3
 for
 .Ar value .
+.It Cm nosni
+Disable Server Name Indication (SNI).
+.It Cm noverify
+Do not require server certificate to be valid.
 .It Cm protocols Ns = Ns Ar value
 Specify the protocols to use.
 Refer to
 .Xr tls_config_parse_protocols 3
 for
 .Ar value .
+.It Cm servername Ns = Ns Ar value
+Use
+.Ar value
+for Server Name Indication (SNI).
+Defaults to the specified server hostname.
 .El
 .It Fl v
 Be more verbose.
index 4bf64fc..aca45be 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: smtpc.c,v 1.16 2021/05/22 09:09:07 eric Exp $ */
+/*     $OpenBSD: smtpc.c,v 1.17 2021/05/23 15:57:32 eric Exp $ */
 
 /*
  * Copyright (c) 2018 Eric Faurot <eric@openbsd.org>
@@ -48,6 +48,8 @@ static struct smtp_mail mail;
 static const char *servname = NULL;
 static struct tls_config *tls_config;
 
+static int nosni = 0;
+static const char *cafile = NULL;
 static const char *protocols = NULL;
 static const char *ciphers = NULL;
 
@@ -65,25 +67,53 @@ static void
 parse_tls_options(char *opt)
 {
        static char * const tokens[] = {
-#define CIPHERS 0
+#define CAFILE 0
+               "cafile",
+#define CIPHERS 1
                "ciphers",
-#define PROTOCOLS 1
+#define NOSNI 2
+               "nosni",
+#define NOVERIFY 3
+               "noverify",
+#define PROTOCOLS 4
                "protocols",
+#define SERVERNAME 5
+               "servername",
                NULL };
        char *value;
 
        while (*opt) {
                switch (getsubopt(&opt, tokens, &value)) {
+               case CAFILE:
+                       if (value == NULL)
+                               fatalx("missing value for cafile");
+                       cafile = value;
+                       break;
                case CIPHERS:
                        if (value == NULL)
                                fatalx("missing value for ciphers");
                        ciphers = value;
                        break;
+               case NOSNI:
+                       if (value != NULL)
+                               fatalx("no value expected for nosni");
+                       nosni = 1;
+                       break;
+               case NOVERIFY:
+                       if (value != NULL)
+                               fatalx("no value expected for noverify");
+                       params.tls_verify = 0;
+                       break;
                case PROTOCOLS:
                        if (value == NULL)
                                fatalx("missing value for protocols");
                        protocols = value;
                        break;
+               case SERVERNAME:
+                       if (value == NULL)
+                               fatalx("missing value for servername");
+                       servname = value;
+                       break;
                case -1:
                        if (suboptarg)
                                fatalx("invalid TLS option \"%s\"", suboptarg);
@@ -208,7 +238,10 @@ main(int argc, char **argv)
        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)
+
+       if (cafile == NULL)
+               cafile = tls_default_ca_cert_file();
+       if (tls_config_set_ca_file(tls_config, cafile) == -1)
                fatal("tls_set_ca_file");
        if (!params.tls_verify) {
                tls_config_insecure_noverifycert(tls_config);
@@ -332,7 +365,8 @@ parse_server(char *server)
 
        if (servname == NULL)
                servname = host;
-       params.tls_servname = servname;
+       if (nosni == 0)
+               params.tls_servname = servname;
 
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_UNSPEC;