Hi,

When using smarthost ("host" option of "relay") for outgoing mails, TLS
connection aren't verified. If it could make sens for standard MX, I
think it would be better to verify the connection by default if the user
specifies a TLS-aware url for the relay.

The diff below changes the behaviour of:
        action "foo" relay host "smtps://example.com"

Currently, smtpd will connect to example.com without verifying TLS at
all. There is no option to force such verification (it was present in
with previous grammar).

With the following diff, the TLS connection is verified by default (and
the connection aborted on error). Opportunistic TLS will be still possible
with a new option: tls no-verify.

So, for having the old behaviour the syntax will be:
        action "foo" relay host "smtps://example.com" tls no-verify

It affects only smarthost connection. Outgoing using MX still use
opportunistic TLS.

Regarding the diff, it adds F_TLS_VERIFY option by default for each call
of text_to_relayhost(), so also for "smtp://" or "lmtp://" urls. I checked
that "smtp://" isn't affected by such flag (there is no TLS connection
to verify), and I hope it will be the same for "lmtp://" (confirmation
will be welcome). Next, the grammar is extended to permit to clear the
flag if requested. smtpd(1) already have all the magic to check the
connection.

Thanks.
-- 
Sebastien Marie


Index: smtpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtpd.conf.5,v
retrieving revision 1.183
diff -u -p -r1.183 smtpd.conf.5
--- smtpd.conf.5        31 May 2018 13:36:35 -0000      1.183
+++ smtpd.conf.5        31 May 2018 13:50:55 -0000
@@ -205,6 +205,9 @@ to advertise during the HELO phase.
 .It Cm host Ar relay-url
 Do not perform MX lookups but relay messages to the relay host described by
 .Ar relay-url .
+If the url uses tls, the connection will be verified by default.
+.It Cm tls Ar no-verify
+Do not perform tls verification for the specified host.
 .It Cm auth Pf < Ar table Ns >
 Use the mapping
 .Ar table
Index: smtpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v
retrieving revision 1.545
diff -u -p -r1.545 smtpd.h
--- smtpd.h     29 May 2018 21:05:52 -0000      1.545
+++ smtpd.h     31 May 2018 13:50:56 -0000
@@ -1068,6 +1068,7 @@ struct dispatcher_remote {
 
        char    *smarthost;
        char    *auth;
+       int      tls_noverify;
 
        int      backup;
        char    *backupmx;
Index: to.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/to.c,v
retrieving revision 1.30
diff -u -p -r1.30 to.c
--- to.c        29 May 2018 21:05:52 -0000      1.30
+++ to.c        31 May 2018 13:50:57 -0000
@@ -348,7 +348,8 @@ text_to_relayhost(struct relayhost *rela
        else
                p = buffer + strlen(schemas[i].name);
 
-       relay->flags = schemas[i].flags;
+       /* require valid tls by default (if tls is used) */
+       relay->flags = schemas[i].flags | F_TLS_VERIFY;
 
        /* need to specify an explicit port for LMTP */
        if (relay->flags & F_LMTP)
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v
retrieving revision 1.206
diff -u -p -r1.206 parse.y
--- parse.y     30 May 2018 19:01:58 -0000      1.206
+++ parse.y     31 May 2018 13:50:58 -0000
@@ -182,7 +182,7 @@ typedef struct {
 %token KEY
 %token LIMIT LISTEN LMTP LOCAL
 %token MAIL_FROM MAILDIR MASK_SRC MASQUERADE MATCH MAX_MESSAGE_SIZE 
MAX_DEFERRED MBOX MDA MTA MX
-%token NODSN
+%token NODSN NOVERIFY
 %token ON
 %token PKI PORT
 %token QUEUE
@@ -541,6 +541,19 @@ HELO STRING {
 
        dispatcher->u.remote.smarthost = strdup(t->t_name);
 }
+| TLS NOVERIFY {
+       if (dispatcher->u.remote.smarthost == NULL) {
+               yyerror("tls no-verify may not be specified without host on a 
dispatcher");
+               YYERROR;
+       }
+
+       if (dispatcher->u.remote.tls_noverify == 1) {
+               yyerror("tls no-verify already specified for this dispatcher");
+               YYERROR;
+       }
+
+       dispatcher->u.remote.tls_noverify = 1;
+}
 | AUTH tables {
        struct table   *t = $2;
 
@@ -1571,6 +1584,7 @@ lookup(char *s)
                { "mta",                MTA },
                { "mx",                 MX },
                { "no-dsn",             NODSN },
+               { "no-verify",          NOVERIFY },
                { "on",                 ON },
                { "pki",                PKI },
                { "port",               PORT },
Index: mta.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/mta.c,v
retrieving revision 1.212
diff -u -p -r1.212 mta.c
--- mta.c       31 May 2018 11:56:10 -0000      1.212
+++ mta.c       31 May 2018 13:51:00 -0000
@@ -616,6 +616,9 @@ mta_route_next_task(struct mta_relay *re
                        m_add_int(p_queue, 0);
                        m_close(p_queue);
                }
+
+               if (dispatcher->u.remote.tls_noverify == 1)
+                       evp->agent.mta.relay.flags &= ~F_TLS_VERIFY;
        }
 
        return (task);

Reply via email to