From 43ddfbdb2dafc46cc9d4b54b7369d8155d41cb80 Mon Sep 17 00:00:00 2001 From: eric Date: Thu, 20 Sep 2018 11:42:28 +0000 Subject: [PATCH] properly handle credentials and fix auth in smtp(1) ok gilles@ --- usr.sbin/smtpd/smtp.h | 5 +-- usr.sbin/smtpd/smtp_client.c | 69 ++++++++++++++++++++++-------------- usr.sbin/smtpd/smtpc.c | 12 +++++-- 3 files changed, 55 insertions(+), 31 deletions(-) diff --git a/usr.sbin/smtpd/smtp.h b/usr.sbin/smtpd/smtp.h index 16fa459cfe4..a5eded2ff1e 100644 --- a/usr.sbin/smtpd/smtp.h +++ b/usr.sbin/smtpd/smtp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp.h,v 1.1 2018/04/26 13:57:13 eric Exp $ */ +/* $OpenBSD: smtp.h,v 1.2 2018/09/20 11:42:28 eric Exp $ */ /* * Copyright (c) 2018 Eric Faurot @@ -51,7 +51,8 @@ struct smtp_params { /* SMTP options */ int lmtp; /* use LMTP protocol */ const char *helo; /* string to use with HELO */ - const char *auth; /* credentials for AUTH */ + const char *auth_user; /* for AUTH */ + const char *auth_pass; /* for AUTH */ }; struct smtp_rcpt { diff --git a/usr.sbin/smtpd/smtp_client.c b/usr.sbin/smtpd/smtp_client.c index e1f75437dfb..f2113af2ab4 100644 --- a/usr.sbin/smtpd/smtp_client.c +++ b/usr.sbin/smtpd/smtp_client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp_client.c,v 1.7 2018/09/01 12:03:31 miko Exp $ */ +/* $OpenBSD: smtp_client.c,v 1.8 2018/09/20 11:42:28 eric Exp $ */ /* * Copyright (c) 2018 Eric Faurot @@ -251,7 +251,8 @@ smtp_client_state(struct smtp_client *proto, int newstate) { struct smtp_rcpt *rcpt; char ibuf[LINE_MAX], obuf[LINE_MAX]; - int oldstate, offset; + size_t n; + int oldstate; if (proto->reply) proto->reply[0] = '\0'; @@ -297,7 +298,7 @@ smtp_client_state(struct smtp_client *proto, int newstate) break; case STATE_AUTH: - if (!proto->params.auth) + if (!proto->params.auth_user) smtp_client_state(proto, STATE_READY); else if ((proto->flags & FLAG_TLS) == 0) smtp_client_cancel(proto, FAIL_IMPL, @@ -315,7 +316,32 @@ smtp_client_state(struct smtp_client *proto, int newstate) break; case STATE_AUTH_PLAIN: - smtp_client_sendcmd(proto, "AUTH PLAIN %s", proto->params.auth); + (void)strlcpy(ibuf, "-", sizeof(ibuf)); + (void)strlcat(ibuf, proto->params.auth_user, sizeof(ibuf)); + if (strlcat(ibuf, ":", sizeof(ibuf)) >= sizeof(ibuf)) { + errno = EMSGSIZE; + smtp_client_cancel(proto, FAIL_INTERNAL, + "credentials too large"); + break; + } + n = strlcat(ibuf, proto->params.auth_pass, sizeof(ibuf)); + if (n >= sizeof(ibuf)) { + errno = EMSGSIZE; + smtp_client_cancel(proto, FAIL_INTERNAL, + "credentials too large"); + break; + } + *strchr(ibuf, ':') = '\0'; + ibuf[0] = '\0'; + if (base64_encode(ibuf, n, obuf, sizeof(obuf)) == -1) { + errno = EMSGSIZE; + smtp_client_cancel(proto, FAIL_INTERNAL, + "credentials too large"); + break; + } + smtp_client_sendcmd(proto, "AUTH PLAIN %s", obuf); + explicit_bzero(ibuf, sizeof ibuf); + explicit_bzero(obuf, sizeof obuf); break; case STATE_AUTH_LOGIN: @@ -323,39 +349,28 @@ smtp_client_state(struct smtp_client *proto, int newstate) break; case STATE_AUTH_LOGIN_USER: - memset(ibuf, 0, sizeof ibuf); - if (base64_decode(proto->params.auth, (unsigned char *)ibuf, - sizeof(ibuf)-1) == -1) { - errno = EOVERFLOW; + if (base64_encode(proto->params.auth_user, + strlen(proto->params.auth_user), obuf, + sizeof(obuf)) == -1) { + errno = EMSGSIZE; smtp_client_cancel(proto, FAIL_INTERNAL, - "Credentials too large"); + "credentials too large"); break; } - - memset(obuf, 0, sizeof obuf); - base64_encode((unsigned char *)ibuf + 1, strlen(ibuf + 1), - obuf, sizeof obuf); smtp_client_sendcmd(proto, "%s", obuf); - explicit_bzero(ibuf, sizeof ibuf); explicit_bzero(obuf, sizeof obuf); break; case STATE_AUTH_LOGIN_PASS: - memset(ibuf, 0, sizeof ibuf); - if (base64_decode(proto->params.auth, (unsigned char *)ibuf, - sizeof(ibuf)-1) == -1) { - errno = EOVERFLOW; + if (base64_encode(proto->params.auth_pass, + strlen(proto->params.auth_pass), obuf, + sizeof(obuf)) == -1) { + errno = EMSGSIZE; smtp_client_cancel(proto, FAIL_INTERNAL, - "Credentials too large"); + "credentials too large"); break; } - - offset = strlen(ibuf+1)+2; - memset(obuf, 0, sizeof obuf); - base64_encode((unsigned char *)ibuf + offset, - strlen(ibuf + offset), obuf, sizeof obuf); smtp_client_sendcmd(proto, "%s", obuf); - explicit_bzero(ibuf, sizeof ibuf); explicit_bzero(obuf, sizeof obuf); break; @@ -452,7 +467,7 @@ smtp_client_response(struct smtp_client *proto, const char *line) * Otherwise, fallback to using HELO. */ if ((proto->params.tls_req == TLS_FORCE) || - (proto->params.auth)) + (proto->params.auth_user)) smtp_client_cancel(proto, FAIL_RESP, line); else smtp_client_state(proto, STATE_HELO); @@ -478,7 +493,7 @@ smtp_client_response(struct smtp_client *proto, const char *line) case STATE_STARTTLS: if (line[0] != '2') { if ((proto->params.tls_req == TLS_FORCE) || - (proto->params.auth)) { + (proto->params.auth_user)) { smtp_client_cancel(proto, FAIL_RESP, line); break; } diff --git a/usr.sbin/smtpd/smtpc.c b/usr.sbin/smtpd/smtpc.c index 8bbd1f43d87..d6bb2c8321e 100644 --- a/usr.sbin/smtpd/smtpc.c +++ b/usr.sbin/smtpd/smtpc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpc.c,v 1.3 2018/05/21 21:25:37 krw Exp $ */ +/* $OpenBSD: smtpc.c,v 1.4 2018/09/20 11:42:28 eric Exp $ */ /* * Copyright (c) 2018 Eric Faurot @@ -204,7 +204,15 @@ parse_server(char *server) if (port && port[0] == '\0') port = NULL; - params.auth = creds; + if (creds) { + p = strchr(creds, ':'); + if (p == NULL) + fatalx("invalid credentials"); + *p = '\0'; + + params.auth_user = creds; + params.auth_pass = p + 1; + } params.tls_req = TLS_YES; if (!strcmp(scheme, "lmtp")) { -- 2.20.1