From fe8dfb3fb3f31fe91555041d7412aaca71f501d3 Mon Sep 17 00:00:00 2001 From: Gilles Chehade Date: Fri, 20 Sep 2019 19:56:25 +0200 Subject: sync --- smtpd/config.c | 3 ++- smtpd/lka_session.c | 27 ++++++++++++++++++++++++--- smtpd/mta.c | 9 ++++++++- smtpd/mta_session.c | 24 ++++++++++++++++++++++-- smtpd/parse.y | 43 +++++++++++++++++++++++++++++++++++++++++-- smtpd/smtpd.conf.5 | 20 ++++++++++++++++++-- smtpd/smtpd.h | 14 +++++++++++++- 7 files changed, 128 insertions(+), 12 deletions(-) diff --git a/smtpd/config.c b/smtpd/config.c index 8b8b8570..cc53272a 100644 --- a/smtpd/config.c +++ b/smtpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.49 2018/12/28 14:21:02 eric Exp $ */ +/* $OpenBSD: config.c,v 1.50 2019/09/20 17:46:05 gilles Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard @@ -60,6 +60,7 @@ config_default(void) conf->sc_maxsize = DEFAULT_MAX_BODY_SIZE; conf->sc_subaddressing_delim = SUBADDRESSING_DELIMITER; conf->sc_ttl = SMTPD_QUEUE_EXPIRY; + conf->sc_srs_ttl = SMTPD_QUEUE_EXPIRY / 86400; conf->sc_mta_max_deferred = 100; conf->sc_scheduler_max_inflight = 5000; diff --git a/smtpd/lka_session.c b/smtpd/lka_session.c index ed17adcb..ed1fd36f 100644 --- a/smtpd/lka_session.c +++ b/smtpd/lka_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka_session.c,v 1.92 2018/12/28 11:40:29 eric Exp $ */ +/* $OpenBSD: lka_session.c,v 1.93 2019/09/20 17:46:05 gilles Exp $ */ /* * Copyright (c) 2011 Gilles Chehade @@ -267,7 +267,8 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn) int r; union lookup lk; char *tag; - + const char *srs_decoded; + if (xn->depth >= EXPAND_DEPTH) { log_trace(TRACE_EXPAND, "expand: lka_expand: node too deep."); lks->error = LKA_PERMFAIL; @@ -287,12 +288,32 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn) "[depth=%d]", xn->u.mailaddr.user, xn->u.mailaddr.domain, xn->depth); - /* Pass the node through the ruleset */ + ep = lks->envelope; ep.dest = xn->u.mailaddr; if (xn->parent) /* nodes with parent are forward addresses */ ep.flags |= EF_INTERNAL; + /* handle SRS */ + if (env->sc_srs_key != NULL && + ep.sender.user[0] == '\0' && + (strncasecmp(ep.rcpt.user, "SRS0=", 5) == 0 || + strncasecmp(ep.rcpt.user, "SRS1=", 5) == 0)) { + srs_decoded = srs_decode(mailaddr_to_text(&ep.rcpt)); + if (srs_decoded && + text_to_mailaddr(&ep.rcpt, srs_decoded)) { + /* flag envelope internal and override rcpt */ + ep.flags |= EF_INTERNAL; + xn->u.mailaddr = ep.rcpt; + lks->envelope = ep; + } + else { + log_warn("SRS failed to decode: %s", + mailaddr_to_text(&ep.rcpt)); + } + } + + /* Pass the node through the ruleset */ rule = ruleset_match(&ep); if (rule == NULL || rule->reject) { lks->error = (errno == EAGAIN) ? diff --git a/smtpd/mta.c b/smtpd/mta.c index 926b089a..6c817d00 100644 --- a/smtpd/mta.c +++ b/smtpd/mta.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mta.c,v 1.231 2019/09/18 11:26:30 eric Exp $ */ +/* $OpenBSD: mta.c,v 1.232 2019/09/20 17:46:05 gilles Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard @@ -1735,6 +1735,7 @@ mta_relay(struct envelope *e, struct relayhost *relayh) key.sourcetable = dispatcher->u.remote.source; key.helotable = dispatcher->u.remote.helo_source; key.heloname = dispatcher->u.remote.helo; + key.srs = dispatcher->u.remote.srs; if (relayh->hostname[0]) { key.domain = mta_domain(relayh->hostname, 1); @@ -1782,6 +1783,7 @@ mta_relay(struct envelope *e, struct relayhost *relayh) r->helotable = xstrdup(key.helotable); if (key.heloname) r->heloname = xstrdup(key.heloname); + r->srs = key.srs; SPLAY_INSERT(mta_relay_tree, &relays, r); stat_increment("mta.relay", 1); } else { @@ -2089,6 +2091,11 @@ mta_relay_cmp(const struct mta_relay *a, const struct mta_relay *b) if (a->backupname && ((r = strcmp(a->backupname, b->backupname)))) return (r); + if (a->srs < b->srs) + return (-1); + if (a->srs > b->srs) + return (1); + return (0); } diff --git a/smtpd/mta_session.c b/smtpd/mta_session.c index f5366623..72969e0a 100644 --- a/smtpd/mta_session.c +++ b/smtpd/mta_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mta_session.c,v 1.121 2019/09/18 11:26:30 eric Exp $ */ +/* $OpenBSD: mta_session.c,v 1.122 2019/09/20 17:46:05 gilles Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard @@ -529,8 +529,9 @@ mta_enter_state(struct mta_session *s, int newstate) char ibuf[LINE_MAX]; char obuf[LINE_MAX]; int offset; + const char *srs_sender; - again: +again: oldstate = s->state; log_trace(TRACE_MTA, "mta: %p: %s -> %s", s, @@ -728,6 +729,25 @@ mta_enter_state(struct mta_session *s, int newstate) s->hangon = 0; s->msgtried++; envid_sz = strlen(e->dsn_envid); + + /* SRS-encode if requested for the relay action, AND we're not + * bouncing, AND we have an RCPT which means we are forwarded, + * AND the RCPT has a '@' just for sanity check (will always). + */ + if (env->sc_srs_key != NULL && + s->relay->srs && + strchr(s->task->sender, '@') && + e->rcpt && + strchr(e->rcpt, '@')) { + /* encode and replace task sender with new SRS-sender */ + srs_sender = srs_encode(s->task->sender, + strchr(e->rcpt, '@') + 1); + if (srs_sender) { + free(s->task->sender); + s->task->sender = xstrdup(srs_sender); + } + } + if (s->ext & MTA_EXT_DSN) { mta_send(s, "MAIL FROM:<%s>%s%s%s%s", s->task->sender, diff --git a/smtpd/parse.y b/smtpd/parse.y index e52077aa..4801d14f 100644 --- a/smtpd/parse.y +++ b/smtpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.261 2019/09/06 08:23:56 martijn Exp $ */ +/* $OpenBSD: parse.y,v 1.262 2019/09/20 17:46:05 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade @@ -191,7 +191,7 @@ typedef struct { %token PHASE PKI PORT PROC PROC_EXEC PROXY_V2 %token QUEUE QUIT %token RCPT_TO RDNS RECIPIENT RECEIVEDAUTH REGEX RELAY REJECT REPORT REWRITE RSET -%token SCHEDULER SENDER SENDERS SMTP SMTP_IN SMTP_OUT SMTPS SOCKET SRC SUB_ADDR_DELIM +%token SCHEDULER SENDER SENDERS SMTP SMTP_IN SMTP_OUT SMTPS SOCKET SRC SRS SUB_ADDR_DELIM %token TABLE TAG TAGGED TLS TLS_REQUIRE TTL %token USER USERBASE %token VERIFY VIRTUAL @@ -217,6 +217,7 @@ grammar : /* empty */ | grammar queue '\n' | grammar scheduler '\n' | grammar smtp '\n' + | grammar srs '\n' | grammar listen '\n' | grammar table '\n' | grammar dispatcher '\n' @@ -537,6 +538,31 @@ SMTP LIMIT limits_smtp } ; +srs: +SRS KEY STRING { + conf->sc_srs_key = $3; +} +SRS KEY BACKUP STRING { + conf->sc_srs_key_backup = $3; +} +| SRS TTL STRING { + conf->sc_srs_ttl = delaytonum($3); + if (conf->sc_srs_ttl == -1) { + yyerror("ttl delay \"%s\" is invalid", $3); + free($3); + YYERROR; + } + + conf->sc_srs_ttl /= 86400; + if (conf->sc_srs_ttl == 0) { + yyerror("ttl delay \"%s\" is too short", $3); + free($3); + YYERROR; + } + free($3); +} +; + dispatcher_local_option: USER STRING { @@ -830,6 +856,18 @@ HELO STRING { dispatcher->u.remote.auth = strdup(t->t_name); } +| SRS { + if (conf->sc_srs_key == NULL) { + yyerror("an srs key is required for srs to be specified in an action"); + YYERROR; + } + if (dispatcher->u.remote.srs == 1) { + yyerror("srs already specified for this dispatcher"); + YYERROR; + } + + dispatcher->u.remote.srs = 1; +} ; dispatcher_remote_options: @@ -2377,6 +2415,7 @@ lookup(char *s) { "smtps", SMTPS }, { "socket", SOCKET }, { "src", SRC }, + { "srs", SRS }, { "sub-addr-delim", SUB_ADDR_DELIM }, { "table", TABLE }, { "tag", TAG }, diff --git a/smtpd/smtpd.conf.5 b/smtpd/smtpd.conf.5 index 4de04c95..1da4189c 100644 --- a/smtpd/smtpd.conf.5 +++ b/smtpd/smtpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: smtpd.conf.5,v 1.224 2019/09/06 08:23:56 martijn Exp $ +.\" $OpenBSD: smtpd.conf.5,v 1.225 2019/09/20 17:46:05 gilles Exp $ .\" .\" Copyright (c) 2008 Janne Johansson .\" Copyright (c) 2009 Jacek Masiulaniec @@ -17,7 +17,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .\" -.Dd $Mdocdate: September 6 2019 $ +.Dd $Mdocdate: September 20 2019 $ .Dt SMTPD.CONF 5 .Os .Sh NAME @@ -270,6 +270,9 @@ and .Dq smtps protocols for authentication. Server certificates for those protocols are verified by default. +.It Cm srs +When relaying a mail resulting from a forward, +use the Sender Rewriting Scheme to rewrite sender address. .It Cm tls Op Cm no-verify Require TLS to be used when relaying, using mandatory STARTTLS by default. When used with a smarthost, the protocol must not be @@ -842,6 +845,19 @@ When resolving the local part of a local email address, ignore the ASCII and all characters following it. The default is .Ql + . +.It Ic srs Cm key Ar secret +Set the secret key to use for SRS, +the Sender Rewriting Scheme. +.It Ic srs Cm key backup Ar secret +Set a backup secret key to use as a fallback for SRS. +This can be used to implementation SRS key rotation. +.It Ic srs Cm ttl Ar delay +Set the time-to-live delay for SRS envelopes. +After this delay, +a bounce reply to the SRS address will be discarded to limit risks of forged addresses. +The default is four days +.Pq 4d . +The delay .It Ic table Ar name Oo Ar type : Oc Ns Ar pathname Tables provide additional configuration information for .Xr smtpd 8 diff --git a/smtpd/smtpd.h b/smtpd/smtpd.h index e5a968e9..7ba6a472 100644 --- a/smtpd/smtpd.h +++ b/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.638 2019/09/19 07:35:36 gilles Exp $ */ +/* $OpenBSD: smtpd.h,v 1.639 2019/09/20 17:46:05 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade @@ -618,6 +618,10 @@ struct smtpd { char *sc_tls_ciphers; char *sc_subaddressing_delim; + + char *sc_srs_key; + char *sc_srs_key_backup; + int sc_srs_ttl; }; #define TRACE_DEBUG 0x0001 @@ -804,6 +808,7 @@ struct mta_relay { char *helotable; char *heloname; char *secret; + int srs; int state; size_t ntask; @@ -1162,6 +1167,8 @@ struct dispatcher_remote { int backup; char *backupmx; + + int srs; }; struct dispatcher_bounce { @@ -1587,6 +1594,11 @@ void log_imsg(int, int, struct imsg *); int fork_proc_backend(const char *, const char *, const char *); +/* srs.c */ +const char *srs_encode(const char *, const char *); +const char *srs_decode(const char *); + + /* ssl_smtpd.c */ void *ssl_mta_init(void *, char *, off_t, const char *); void *ssl_smtp_init(void *, int); -- cgit v1.2.3-59-g8ed1b