With the recent changes in the smarthost syntax, and the removal of the "secure" keyword, it's now possible to clarify the mta code by changing the TLS option from a set flags to exclusive values. This is far less confusing.
More cleanup to come in mta_session.c after that. Eric. Index: mta.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/mta.c,v retrieving revision 1.222 diff -u -p -r1.222 mta.c --- mta.c 22 Aug 2018 10:11:43 -0000 1.222 +++ mta.c 5 Sep 2018 12:42:19 -0000 @@ -635,6 +635,7 @@ mta_handle_envelope(struct envelope *evp } memset(&relayh, 0, sizeof(relayh)); + relayh.tls = RELAY_TLS_OPPORTUNISTIC; if (smarthost && !text_to_relayhost(&relayh, smarthost)) { log_warnx("warn: Failed to parse smarthost %s", smarthost); m_create(p_queue, IMSG_MTA_DELIVERY_TEMPFAIL, 0, 0, -1); @@ -1730,10 +1731,9 @@ mta_relay(struct envelope *e, struct rel key.flags |= RELAY_MX; } else { key.domain = mta_domain(e->dest.domain, 0); - if (!(relayh->flags & RELAY_STARTTLS)) - key.flags |= RELAY_TLS_OPTIONAL; } + key.tls = relayh->tls; key.flags |= relayh->flags; key.port = relayh->port; key.authlabel = relayh->authlabel; @@ -1748,6 +1748,7 @@ mta_relay(struct envelope *e, struct rel r = xcalloc(1, sizeof *r); TAILQ_INIT(&r->tasks); r->id = generate_uid(); + r->tls = key.tls; r->flags = key.flags; r->domain = key.domain; r->backupname = key.backupname ? @@ -1834,14 +1835,25 @@ mta_relay_to_text(struct mta_relay *rela (void)strlcat(buf, tmp, sizeof buf); } - if (relay->flags & RELAY_STARTTLS) { - (void)strlcat(buf, sep, sizeof buf); - (void)strlcat(buf, "starttls", sizeof buf); - } - - if (relay->flags & RELAY_SMTPS) { - (void)strlcat(buf, sep, sizeof buf); + (void)strlcat(buf, sep, sizeof buf); + switch(relay->tls) { + case RELAY_TLS_OPPORTUNISTIC: + (void)strlcat(buf, "smtp", sizeof buf); + break; + case RELAY_TLS_STARTTLS: + (void)strlcat(buf, "smtp+tls", sizeof buf); + break; + case RELAY_TLS_SMTPS: (void)strlcat(buf, "smtps", sizeof buf); + break; + case RELAY_TLS_NO: + if (relay->flags & RELAY_LMTP) + (void)strlcat(buf, "lmtp", sizeof buf); + else + (void)strlcat(buf, "smtp+notls", sizeof buf); + break; + default: + (void)strlcat(buf, "???", sizeof buf); } if (relay->flags & RELAY_AUTH) { @@ -1993,6 +2005,11 @@ mta_relay_cmp(const struct mta_relay *a, if (a->domain < b->domain) return (-1); if (a->domain > b->domain) + return (1); + + if (a->tls < b->tls) + return (-1); + if (a->tls > b->tls) return (1); if (a->flags < b->flags) Index: mta_session.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/mta_session.c,v retrieving revision 1.109 diff -u -p -r1.109 mta_session.c --- mta_session.c 5 Sep 2018 10:15:41 -0000 1.109 +++ mta_session.c 5 Sep 2018 12:42:19 -0000 @@ -199,24 +199,23 @@ mta_session(struct mta_relay *relay, str if (relay->flags & RELAY_LMTP) s->flags |= MTA_LMTP; - switch (relay->flags & (RELAY_SSL|RELAY_TLS_OPTIONAL)) { - case RELAY_SSL: - s->flags |= MTA_FORCE_ANYSSL; - s->flags |= MTA_WANT_SECURE; - break; - case RELAY_SMTPS: + switch (relay->tls) { + case RELAY_TLS_SMTPS: s->flags |= MTA_FORCE_SMTPS; s->flags |= MTA_WANT_SECURE; break; - case RELAY_STARTTLS: + case RELAY_TLS_STARTTLS: s->flags |= MTA_FORCE_TLS; s->flags |= MTA_WANT_SECURE; break; - case RELAY_TLS_OPTIONAL: + case RELAY_TLS_OPPORTUNISTIC: /* do not force anything, try tls then smtp */ break; - default: + case RELAY_TLS_NO: s->flags |= MTA_FORCE_PLAIN; + break; + default: + fatalx("bad value for relay->tls: %d", relay->tls); } if (relay->flags & RELAY_BACKUP) Index: smtpd.h =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v retrieving revision 1.558 diff -u -p -r1.558 smtpd.h --- smtpd.h 4 Sep 2018 13:04:42 -0000 1.558 +++ smtpd.h 5 Sep 2018 12:42:19 -0000 @@ -84,11 +84,11 @@ #define F_RECEIVEDAUTH 0x800 #define F_MASQUERADE 0x1000 +#define RELAY_TLS_OPPORTUNISTIC 0 +#define RELAY_TLS_STARTTLS 1 +#define RELAY_TLS_SMTPS 2 +#define RELAY_TLS_NO 3 -#define RELAY_STARTTLS 0x01 -#define RELAY_SMTPS 0x02 -#define RELAY_TLS_OPTIONAL 0x04 -#define RELAY_SSL (RELAY_STARTTLS | RELAY_SMTPS) #define RELAY_AUTH 0x08 #define RELAY_BACKUP 0x10 #define RELAY_MX 0x20 @@ -115,6 +115,7 @@ struct netaddr { struct relayhost { uint16_t flags; + int tls; char hostname[HOST_NAME_MAX+1]; uint16_t port; char authlabel[PATH_MAX]; @@ -732,6 +733,7 @@ struct mta_relay { struct dispatcher *dispatcher; struct mta_domain *domain; struct mta_limits *limits; + int tls; int flags; char *backupname; int backuppref; Index: to.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/to.c,v retrieving revision 1.32 diff -u -p -r1.32 to.c --- to.c 3 Sep 2018 11:30:14 -0000 1.32 +++ to.c 5 Sep 2018 12:42:19 -0000 @@ -304,17 +304,18 @@ text_to_relayhost(struct relayhost *rela { static const struct schema { const char *name; - uint16_t flags; + int tls; + uint16_t flags; } schemas [] = { /* * new schemas should be *appended* otherwise the default * schema index needs to be updated later in this function. */ - { "smtp://", RELAY_TLS_OPTIONAL }, - { "smtp+tls://", RELAY_STARTTLS }, - { "smtp+notls://", 0 }, - { "lmtp://", RELAY_LMTP }, - { "smtps://", RELAY_SMTPS } + { "smtp://", RELAY_TLS_OPPORTUNISTIC, 0 }, + { "smtp+tls://", RELAY_TLS_STARTTLS, 0 }, + { "smtp+notls://", RELAY_TLS_NO, 0 }, + { "lmtp://", RELAY_TLS_NO, RELAY_LMTP }, + { "smtps://", RELAY_TLS_SMTPS, 0 } }; const char *errstr = NULL; char *p, *q; @@ -344,6 +345,7 @@ text_to_relayhost(struct relayhost *rela else p = buffer + strlen(schemas[i].name); + relay->tls = schemas[i].tls; relay->flags = schemas[i].flags; /* need to specify an explicit port for LMTP */ @@ -395,7 +397,8 @@ text_to_relayhost(struct relayhost *rela return 0; if (relay->authlabel[0]) { /* disallow auth on non-tls scheme. */ - if (!(relay->flags & (RELAY_STARTTLS | RELAY_SMTPS))) + if (relay->tls != RELAY_TLS_STARTTLS && + relay->tls != RELAY_TLS_SMTPS) return 0; relay->flags |= RELAY_AUTH; }