untrusted comment: verify with openbsd-65-base.pub RWSZaRmt1LEQT0X/RONWttpdZ/WjynoR5jTj3k+10Wvns6P0Je2ftZOIJwtwUtXqIriLFHjlJp5gDe21yHRYMHYcmrG09m1QdAM= OpenBSD 6.5 errata 031, February 24, 2020: An out of bounds read in smtpd allows an attacker to inject arbitrary commands into the envelope file which are then executed as root. Separately, missing privilege revocation in smtpctl allows arbitrary commands to be run with the _smtpq group. Apply by doing: signify -Vep /etc/signify/openbsd-65-base.pub -x \ 031_smtpd_envelope.patch.sig -m - | (cd /usr/src && patch -p0) And then rebuild and install smtpd: cd /usr/src/usr.sbin/smtpd make obj make make install Index: usr.sbin/smtpd/makemap.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/makemap.c,v retrieving revision 1.72 diff -u -r1.72 makemap.c --- usr.sbin/smtpd/makemap.c 28 Dec 2018 11:40:29 -0000 1.72 +++ usr.sbin/smtpd/makemap.c 20 Feb 2020 01:20:50 -0000 @@ -83,8 +83,13 @@ int ch, dbputs = 0, Uflag = 0; DBTYPE dbtype = DB_HASH; char *p; + gid_t gid; int fd = -1; + gid = getgid(); + if (setresgid(gid, gid, gid) == -1) + err(1, "setresgid"); + if ((env = config_default()) == NULL) err(1, NULL); @@ -161,9 +166,9 @@ errx(1, "database name too long"); } - execlp("makemap", "makemap", "-d", argv[0], "-o", dbname, "-", - (char *)NULL); - err(1, "execlp"); + execl(PATH_MAKEMAP, "makemap", "-d", argv[0], "-o", dbname, + "-", (char *)NULL); + err(1, "execl"); } if (mode == P_NEWALIASES) { Index: usr.sbin/smtpd/mta_session.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/mta_session.c,v retrieving revision 1.115.2.1 diff -u -r1.115.2.1 mta_session.c --- usr.sbin/smtpd/mta_session.c 28 Jan 2020 21:36:28 -0000 1.115.2.1 +++ usr.sbin/smtpd/mta_session.c 20 Feb 2020 01:20:50 -0000 @@ -1156,7 +1156,7 @@ if (cont) { if (s->replybuf[0] == '\0') (void)strlcat(s->replybuf, line, sizeof s->replybuf); - else { + else if (len > 4) { line = line + 4; if (isdigit((int)*line) && *(line + 1) == '.' && isdigit((int)*line+2) && *(line + 3) == '.' && @@ -1171,7 +1171,9 @@ /* 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') { + if (s->replybuf[0] == '\0') + (void)strlcat(s->replybuf, line, sizeof s->replybuf); + else if (len > 4) { p = line + 4; if (isdigit((int)*p) && *(p + 1) == '.' && isdigit((int)*p+2) && *(p + 3) == '.' && @@ -1180,8 +1182,6 @@ 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("%016"PRIx64" mta disconnected reason=quit messages=%zu", Index: usr.sbin/smtpd/smtpctl.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/smtpctl.c,v retrieving revision 1.163 diff -u -r1.163 smtpctl.c --- usr.sbin/smtpd/smtpctl.c 14 Jan 2019 09:37:40 -0000 1.163 +++ usr.sbin/smtpd/smtpctl.c 20 Feb 2020 01:20:50 -0000 @@ -1124,7 +1124,7 @@ */ for (i = 1; i < argc; i++) if (strncmp(argv[i], "-bi", 3) == 0) - exit(makemap(P_NEWALIASES, argc, argv)); + exit(makemap(P_SENDMAIL, argc, argv)); if (!srv_connect()) offlinefp = offline_file(); Index: usr.sbin/smtpd/smtpd-defines.h =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/smtpd-defines.h,v retrieving revision 1.10 diff -u -r1.10 smtpd-defines.h --- usr.sbin/smtpd/smtpd-defines.h 27 Dec 2018 15:41:50 -0000 1.10 +++ usr.sbin/smtpd/smtpd-defines.h 20 Feb 2020 01:20:50 -0000 @@ -37,6 +37,7 @@ #define SMTPD_QUEUE_USER "_smtpq" #define SMTPD_QUEUE_GROUP "_smtpq" #define PATH_SPOOL "/var/spool/smtpd" +#define PATH_MAKEMAP "/usr/sbin/makemap" #define SUBADDRESSING_DELIMITER "+" Index: usr.sbin/smtpd/smtpd.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/smtpd.c,v retrieving revision 1.318 diff -u -r1.318 smtpd.c --- usr.sbin/smtpd/smtpd.c 31 Mar 2019 03:36:18 -0000 1.318 +++ usr.sbin/smtpd/smtpd.c 20 Feb 2020 01:20:50 -0000 @@ -81,9 +81,9 @@ static int imsg_wait(struct imsgbuf *, struct imsg *, int); static void offline_scan(int, short, void *); -static int offline_add(char *); +static int offline_add(char *, uid_t, gid_t); static void offline_done(void); -static int offline_enqueue(char *); +static int offline_enqueue(char *, uid_t, gid_t); static void purge_task(void); static int parent_auth_user(const char *, const char *); @@ -112,6 +112,8 @@ struct offline { TAILQ_ENTRY(offline) entry; + uid_t uid; + gid_t gid; char *path; }; @@ -1509,7 +1511,8 @@ continue; } - if (offline_add(e->fts_name)) { + if (offline_add(e->fts_name, e->fts_statp->st_uid, + e->fts_statp->st_gid)) { log_warnx("warn: smtpd: " "could not add offline message %s", e->fts_name); continue; @@ -1529,7 +1532,7 @@ } static int -offline_enqueue(char *name) +offline_enqueue(char *name, uid_t uid, gid_t gid) { char *path; struct stat sb; @@ -1592,6 +1595,18 @@ _exit(1); } + if (sb.st_uid != uid) { + log_warnx("warn: smtpd: file %s has bad uid %d", + path, sb.st_uid); + _exit(1); + } + + if (sb.st_gid != gid) { + log_warnx("warn: smtpd: file %s has bad gid %d", + path, sb.st_gid); + _exit(1); + } + pw = getpwuid(sb.st_uid); if (pw == NULL) { log_warnx("warn: smtpd: getpwuid for uid %d failed", @@ -1648,17 +1663,19 @@ } static int -offline_add(char *path) +offline_add(char *path, uid_t uid, gid_t gid) { struct offline *q; if (offline_running < OFFLINE_QUEUEMAX) /* skip queue */ - return offline_enqueue(path); + return offline_enqueue(path, uid, gid); q = malloc(sizeof(*q) + strlen(path) + 1); if (q == NULL) return (-1); + q->uid = uid; + q->gid = gid; q->path = (char *)q + sizeof(*q); memmove(q->path, path, strlen(path) + 1); TAILQ_INSERT_TAIL(&offline_q, q, entry); @@ -1677,7 +1694,7 @@ if ((q = TAILQ_FIRST(&offline_q)) == NULL) break; /* all done */ TAILQ_REMOVE(&offline_q, q, entry); - offline_enqueue(q->path); + offline_enqueue(q->path, q->uid, q->gid); free(q); } } Index: usr.sbin/smtpd/smtpd.h =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v retrieving revision 1.621 diff -u -r1.621 smtpd.h --- usr.sbin/smtpd/smtpd.h 8 Apr 2019 08:22:32 -0000 1.621 +++ usr.sbin/smtpd/smtpd.h 20 Feb 2020 01:20:50 -0000 @@ -97,8 +97,9 @@ #define MTA_EXT_DSN 0x400 -#define P_NEWALIASES 0 -#define P_MAKEMAP 1 +#define P_SENDMAIL 0 +#define P_NEWALIASES 1 +#define P_MAKEMAP 2 #define CERT_ERROR -1 #define CERT_OK 0