diff options
author | Eric Faurot <eric@cvs.openbsd.org> | 2011-12-11 19:58:10 +0000 |
---|---|---|
committer | Eric Faurot <eric@cvs.openbsd.org> | 2011-12-11 19:58:10 +0000 |
commit | 862f63944db00d55fc36806c09f2822e6ac59833 (patch) | |
tree | 577302cc5b27fc454a72375f49db4827f6716e61 | |
parent | 1745e407ef64115755c24e068e14ed20c9211d67 (diff) |
utility function for parsing and validating SMTP response lines
ok gilles@
-rw-r--r-- | usr.sbin/smtpd/client.c | 56 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 3 | ||||
-rw-r--r-- | usr.sbin/smtpd/util.c | 36 |
3 files changed, 51 insertions, 44 deletions
diff --git a/usr.sbin/smtpd/client.c b/usr.sbin/smtpd/client.c index f3807210dfc..6d1a45d1199 100644 --- a/usr.sbin/smtpd/client.c +++ b/usr.sbin/smtpd/client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: client.c,v 1.38 2011/11/03 14:34:13 chl Exp $ */ +/* $OpenBSD: client.c,v 1.39 2011/12/11 19:58:09 eric Exp $ */ /* * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net> @@ -44,6 +44,8 @@ SSL *ssl_client_init(int, char *, size_t, char *, size_t); int ssl_buf_read(SSL *, struct ibuf_read *); int ssl_buf_write(SSL *, struct msgbuf *); +const char *parse_smtp_response(char *, size_t, char **, int *); + /* * Initialize SMTP session. */ @@ -630,17 +632,19 @@ client_status(struct smtp_client *sp, char *fmt, ...) int client_getln(struct smtp_client *sp, int type) { - char *ln = NULL, *cause = ""; - int i, rv = -1; + const char *e; + char *ln = NULL, *msg, cause[1024]; + int cont, rv = -1; sp->reply[0] = '\0'; /* get a reply, dealing with multiline responses */ - for (;;) { + for (cont = 1; cont;) { + free(ln); errno = 0; if ((ln = buf_getln(&sp->r)) == NULL) { if (errno) - cause = "150 buf_getln error"; + strlcpy(cause, "150 buf_getln error", sizeof(cause)); else rv = 0; goto done; @@ -648,51 +652,19 @@ client_getln(struct smtp_client *sp, int type) fprintf(sp->verbose, "<<< %s\n", ln); - /* 3-char replies are invalid on their own, append space */ - if (strlen(ln) == 3) { - char buf[5]; - - strlcpy(buf, ln, sizeof(buf)); - strlcat(buf, " ", sizeof(buf)); - free(ln); - if ((ln = strdup(buf)) == NULL) { - cause = "150 strdup error"; - goto done; - } - } - - if (strlen(ln) < 4 || (ln[3] != ' ' && ln[3] != '-')) { - cause = "150 garbled smtp reply"; + if ((e = parse_smtp_response(ln, strlen(ln), &msg, &cont))) { + snprintf(cause, sizeof(cause), "150 %s", e); goto done; } if (type == CLIENT_EHLO) { - if (strcmp(ln + 4, "STARTTLS") == 0) + if (strcmp(msg, "STARTTLS") == 0) sp->exts[CLIENT_EXT_STARTTLS].have = 1; - else if (strncmp(ln + 4, "AUTH", 4) == 0) + else if (strncmp(msg, "AUTH", 4) == 0) sp->exts[CLIENT_EXT_AUTH].have = 1; - else if (strcmp(ln + 4, "PIPELINING") == 0) + else if (strcmp(msg, "PIPELINING") == 0) sp->exts[CLIENT_EXT_PIPELINING].have = 1; } - - if (ln[3] == ' ') - break; - - free(ln); - } - - /* validate reply code */ - if (ln[0] < '2' || ln[0] > '5' || !isdigit(ln[1]) || !isdigit(ln[2])) { - cause = "150 reply code out of range"; - goto done; - } - - /* validate reply message */ - for (i = 0; ln[i] != '\0'; i++) { - if (!isprint(ln[i])) { - cause = "150 non-printable character in reply"; - goto done; - } } strlcpy(sp->reply, ln, sizeof(sp->reply)); diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index 6ffafc74186..f8aa32952fc 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.257 2011/12/11 17:02:10 eric Exp $ */ +/* $OpenBSD: smtpd.h,v 1.258 2011/12/11 19:58:09 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -1220,3 +1220,4 @@ u_int32_t evpid_to_msgid(u_int64_t); u_int64_t msgid_to_evpid(u_int32_t); void log_imsg(int, int, struct imsg*); int ckdir(const char *, mode_t, uid_t, gid_t, int); +const char *parse_smtp_response(char *, size_t, char **, int *); diff --git a/usr.sbin/smtpd/util.c b/usr.sbin/smtpd/util.c index e1e0c95a87d..a36eda191d6 100644 --- a/usr.sbin/smtpd/util.c +++ b/usr.sbin/smtpd/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.51 2011/11/16 19:38:56 eric Exp $ */ +/* $OpenBSD: util.c,v 1.52 2011/12/11 19:58:09 eric Exp $ */ /* * Copyright (c) 2000,2001 Markus Friedl. All rights reserved. @@ -591,3 +591,37 @@ msgid_to_evpid(u_int32_t msgid) { return ((u_int64_t)msgid << 32); } + +const char * +parse_smtp_response(char *line, size_t len, char **msg, int *cont) +{ + size_t i; + + if (len >= SMTP_LINE_MAX) + return "line too long"; + + if (len > 3) { + if (msg) + *msg = line + 4; + if (cont) + *cont = (line[3] == '-'); + } else if (len == 3) { + if (msg) + *msg = line + 3; + if (cont) + *cont = 0; + } else + return "line too short"; + + /* validate reply code */ + if (line[0] < '2' || line[0] > '5' || !isdigit(line[1]) || + !isdigit(line[2])) + return "reply code out of range"; + + /* validate reply message */ + for (i = 0; i < len; i++) + if (!isprint(line[i])) + return "non-printable character in reply"; + + return NULL; +} |