diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2015-12-01 15:30:43 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2015-12-01 15:30:43 +0000 |
commit | 07cbd9360b513281162bcff563a61e9fe68684d2 (patch) | |
tree | f03a579376ec748c8fcddd292349c852864462c8 /usr.sbin/smtpd/mta_session.c | |
parent | c4ed28f037019ca260a3072f1055dec3e602b153 (diff) |
when peer outputs a multi-line response, concat response into a single log
ok sunil@, jung@
Diffstat (limited to 'usr.sbin/smtpd/mta_session.c')
-rw-r--r-- | usr.sbin/smtpd/mta_session.c | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/usr.sbin/smtpd/mta_session.c b/usr.sbin/smtpd/mta_session.c index 93f06197dd5..feef15c5131 100644 --- a/usr.sbin/smtpd/mta_session.c +++ b/usr.sbin/smtpd/mta_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mta_session.c,v 1.75 2015/11/30 12:49:35 gilles Exp $ */ +/* $OpenBSD: mta_session.c,v 1.76 2015/12/01 15:30:42 gilles Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -129,6 +129,8 @@ struct mta_session { FILE *datafp; size_t failures; + + char replybuf[2048]; }; static void mta_session_init(void); @@ -597,6 +599,8 @@ mta_enter_state(struct mta_session *s, int newstate) s->state = newstate; + memset(s->replybuf, 0, sizeof s->replybuf); + /* don't try this at home! */ #define mta_enter_state(_s, _st) do { newstate = _st; goto again; } while (0) @@ -1229,8 +1233,36 @@ mta_io(struct io *io, int evt) s->ext |= MTA_EXT_DSN; } - if (cont) + /* continuation reply, we parse out the repeating statuses and ESC */ + if (cont) { + if (s->replybuf[0] == '\0') + (void)strlcat(s->replybuf, line, sizeof s->replybuf); + else { + line = line + 4; + if (isdigit((int)*line) && *(line + 1) == '.' && + isdigit((int)*line+2) && *(line + 3) == '.' && + isdigit((int)*line+4) && isspace((int)*(line + 5))) + (void)strlcat(s->replybuf, line+5, sizeof s->replybuf); + else + (void)strlcat(s->replybuf, line, sizeof s->replybuf); + } goto nextline; + } + + /* last line of a reply, check if we're on a continuation to parse out status and ESC. + * if we overflow reply buffer or are not on continuation, log entire last line. + */ + if (s->replybuf[0] != '\0') { + p = line + 4; + if (isdigit((int)*p) && *(p + 1) == '.' && + isdigit((int)*p+2) && *(p + 3) == '.' && + isdigit((int)*p+4) && isspace((int)*(p + 5))) + p += 5; + if (strlcat(s->replybuf, p, sizeof s->replybuf) >= sizeof s->replybuf) + (void)strlcpy(s->replybuf, line, sizeof s->replybuf); + } + else + (void)strlcpy(s->replybuf, line, sizeof s->replybuf); if (s->state == MTA_QUIT) { log_info("smtp-out: Closing session %016"PRIx64 @@ -1240,7 +1272,7 @@ mta_io(struct io *io, int evt) return; } io_set_write(io); - mta_response(s, line); + mta_response(s, s->replybuf); if (s->flags & MTA_FREE) { mta_free(s); return; @@ -1562,12 +1594,12 @@ mta_verify_certificate(struct mta_session *s) X509_free(x); if (cert_len[0] < 0) { - log_warnx("warn: failed to encode certificate"); + log_warnx("warn: failed to encode certificate"); goto end; } log_debug("debug: certificate 0: len=%d", cert_len[0]); if (cert_len[0] > (int)MAX_CERT_LEN) { - log_warnx("warn: certificate too long"); + log_warnx("warn: certificate too long"); goto end; } @@ -1586,12 +1618,12 @@ mta_verify_certificate(struct mta_session *s) x = sk_X509_value(xchain, i); cert_len[i+1] = i2d_X509(x, &cert_der[i+1]); if (cert_len[i+1] < 0) { - log_warnx("warn: failed to encode certificate"); + log_warnx("warn: failed to encode certificate"); goto end; } log_debug("debug: certificate %i: len=%d", i+1, cert_len[i+1]); if (cert_len[i+1] > (int)MAX_CERT_LEN) { - log_warnx("warn: certificate too long"); + log_warnx("warn: certificate too long"); goto end; } } |