nightmaremail

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 30a44402454eca17beb8339a8b661cc8683be5b3
parent 2a469cc632ac74bc2cb915e6f8cd0ccc330d88f6
Author: Amitai Schleier <schmonz-web-git@schmonz.com>
Date:   Mon,  2 Sep 2019 11:47:45 -0400

qmail-pop3d: exit 1, pronto, if running as root.

At least checkpassword-pam and DJB's original checkpassword are willing
to authenticate the root user and run a child program with UID 0. For
POP3 service -- the canonical checkpassword use case! -- this produces
runtime behavior that is inconsistent with...

- qmail's design, because qmail-local will never run as root to populate
  a Maildir that qmail-pop3d could serve, and

- qmail's security focus, because it lets abusers dictionary-attack the
  root password over the network.

Instead, in qmail-pop3d, if getuid() returns 0, we write to the logs and
exit 1. If someone manages to guess the root password, they won't know
they did: it looks exactly like any other failed checkpassword login.
And the sysadmin could potentially be alerted.

Diffstat:
MCHANGES | 3+++
Mqmail-pop3d.8 | 19++++++++++++++++++-
Mqmail-pop3d.c | 9+++++++++
3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/CHANGES b/CHANGES @@ -1,3 +1,6 @@ +20200514 bug: qmail-pop3d runs as root if root authenticates. + impact: vector for dictionary attack on root password. + fix: exit 1, same as a failed checkpassword login. 20200514 code: changed qmail-popup interface (leave kid's fd 2 alone). 20200511 code: remove tryshsgr.c and use uid_t, gid_t types. 20200511 add first unittest, run with "make test" diff --git a/qmail-pop3d.8 b/qmail-pop3d.8 @@ -22,9 +22,26 @@ under .BR qmail-popup , which reads a username and password, and -.BR /bin/checkpassword , +.BR checkpassword , which checks the password and sets up environment variables. +Since root will never have a +.B maildir +(because +.B qmail-lspawn +refuses to run +.B qmail-local +as root), +.B qmail-pop3d +also refuses to run as root. +The event will be logged and +.B qmail-pop3d +will exit 1, looking to +.B qmail-popup +like any other failed +.B checkpassword +login. + .B qmail-pop3d has a 20-minute idle timeout. diff --git a/qmail-pop3d.c b/qmail-pop3d.c @@ -1,5 +1,6 @@ #include <sys/types.h> #include <sys/stat.h> +#include <unistd.h> #include "commands.h" #include "sig.h" #include "getln.h" @@ -35,6 +36,9 @@ int safewrite(fd,buf,len) int fd; char *buf; int len; return r; } +char sserrbuf[128]; +substdio sserr = SUBSTDIO_FDBUF(safewrite,2,sserrbuf,sizeof sserrbuf); + char ssoutbuf[1024]; substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); @@ -63,6 +67,10 @@ void err(s) char *s; void die_nomem() { err("out of memory"); die(); } void die_nomaildir() { err("this user has no $HOME/Maildir"); die(); } +void die_root() { + substdio_putsflush(&sserr,"qmail-pop3d invoked as uid 0, terminating\n"); + _exit(1); +} void die_scan() { err("unable to scan $HOME/Maildir"); die(); } void err_syntax() { err("syntax error"); } @@ -294,6 +302,7 @@ char **argv; sig_alarmcatch(die); sig_pipeignore(); + if (!getuid()) die_root(); if (!argv[1]) die_nomaildir(); if (chdir(argv[1]) == -1) die_nomaildir();