From: Wietse Z Venema Date: Sun, 9 Aug 2026 05:00:00 +0000 (-0500) Subject: postfix-3.12-20260809 X-Git-Url: http://git.ipfire.org/index.cgi?a=commitdiff_plain;h=HEAD;p=thirdparty%2Fpostfix.git postfix-3.12-20260809 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 8d9cfd50b..ea84639e2 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -31883,6 +31883,37 @@ Apologies for any names omitted. with Oracle MySQL 8 and later. Report and fix by OpenAI Security. File: dict_mysql.c. +20250807 + + Hardening command-line email submission: the postdrop + command now disallows null and line-break characters in + queue file envelope records (line-break characters in other + queue file records are already neutralized by default with + "cleanup_replace_stray_cr_lf = yes"). + + The new constraint not only eliminates line-break injection + into local mailbox files as reported by OpenAI Security, + but also prevents other forms of misuse. Later, this + constraint may be moved into the Postfix core. Fix by Wietse. + File: postdrop.c. + +20260806 + + Shut up nagging from multiple AIs and harden the virtual + delivery agent against an evil SQL database. Files: + virtual/mailbox.c, virtual/mailbox_test.c. + + Bug (defect introduced: Postfix 1.1, date: 20021116): address + verification cache poisoning. A local user could use the + postdrop command to submit an address verification probe + with envelope or message content that Postfix will reject + later, resulting in a negative address verification cache + entry for that address. On systems that enable address + verification, the negative address verification cache entry + would force the Postfix SMTP server to reject a message + that it should accept (denial of service). Problem reported + by OpenAI Security. File: postdrop.c. + TODO Reorganize PTEST_LIB, PMOCK_LIB, TESTLIB, TESTLIBS, etc. diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 585b82df6..9b5e08b32 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20260805" +#define MAIL_RELEASE_DATE "20260809" #define MAIL_VERSION_NUMBER "3.12" #ifdef SNAPSHOT diff --git a/postfix/src/postdrop/Makefile.in b/postfix/src/postdrop/Makefile.in index a6d44fedd..804a7fd5c 100644 --- a/postfix/src/postdrop/Makefile.in +++ b/postfix/src/postdrop/Makefile.in @@ -52,7 +52,9 @@ postdrop.o: ../../include/attr.h postdrop.o: ../../include/check_arg.h postdrop.o: ../../include/clean_env.h postdrop.o: ../../include/cleanup_user.h +postdrop.o: ../../include/deliver_request.h postdrop.o: ../../include/dict.h +postdrop.o: ../../include/dsn.h postdrop.o: ../../include/htable.h postdrop.o: ../../include/iostuff.h postdrop.o: ../../include/login_sender_match.h @@ -67,6 +69,7 @@ postdrop.o: ../../include/mail_task.h postdrop.o: ../../include/mail_version.h postdrop.o: ../../include/maillog_client.h postdrop.o: ../../include/msg.h +postdrop.o: ../../include/msg_stats.h postdrop.o: ../../include/msg_vstream.h postdrop.o: ../../include/myflock.h postdrop.o: ../../include/mymalloc.h @@ -74,6 +77,7 @@ postdrop.o: ../../include/mypwd.h postdrop.o: ../../include/nvtable.h postdrop.o: ../../include/rec_attr_map.h postdrop.o: ../../include/rec_type.h +postdrop.o: ../../include/recipient_list.h postdrop.o: ../../include/record.h postdrop.o: ../../include/stringops.h postdrop.o: ../../include/sys_defs.h diff --git a/postfix/src/postdrop/postdrop.c b/postfix/src/postdrop/postdrop.c index 1ce06ed40..df48f8685 100644 --- a/postfix/src/postdrop/postdrop.c +++ b/postfix/src/postdrop/postdrop.c @@ -145,6 +145,7 @@ /* Global library. */ +#include #include #include #include @@ -514,6 +515,11 @@ int main(int argc, char **argv) msg_fatal("uid=%ld: malformed input", (long) uid); if (rec_type == 0 || strchr(*expected, rec_type) == 0) msg_fatal("uid=%ld: unexpected record type: %d", (long) uid, rec_type); + /* 2092607 OpenAI: reject line breaks and nulls in envelope content. */ + if (rec_type != REC_TYPE_NORM && rec_type != REC_TYPE_CONT + && strcspn(vstring_str(buf), "\r\n") != VSTRING_LEN(buf)) + msg_fatal("uid=%ld: null or line break in '%s' record type: %.200s", + (long) uid, rec_type_name(rec_type), vstring_str(buf)); if (rec_type == **expected) expected++; /* Override time information from the untrusted caller. */ @@ -536,6 +542,19 @@ int main(int argc, char **argv) } #define STREQ(x,y) (strcmp(x,y) == 0) + /* 202607 OpenAI: allow only sendmail '-v' and '-bv' tracing. */ + if (STREQ(attr_name, MAIL_ATTR_TRACE_FLAGS)) { + int tflags = atoi(attr_value); + + if (tflags == DEL_REQ_FLAG_USR_VRFY + || tflags == DEL_REQ_FLAG_RECORD) + rec_fprintf(dst->stream, REC_TYPE_ATTR, "%s=%d", + attr_name, tflags); + else + msg_warn("uid=%ld: ignoring unexpected trace flags: %.200s", + (long) uid, attr_value); + continue; + } if ((STREQ(attr_name, MAIL_ATTR_ENCODING) && (STREQ(attr_value, MAIL_ATTR_ENC_7BIT) || STREQ(attr_value, MAIL_ATTR_ENC_8BIT) @@ -545,8 +564,7 @@ int main(int argc, char **argv) || rec_attr_map(attr_name) || (STREQ(attr_name, MAIL_ATTR_RWR_CONTEXT) && (STREQ(attr_value, MAIL_ATTR_RWR_LOCAL) - || STREQ(attr_value, MAIL_ATTR_RWR_REMOTE))) - || STREQ(attr_name, MAIL_ATTR_TRACE_FLAGS)) { /* XXX */ + || STREQ(attr_value, MAIL_ATTR_RWR_REMOTE)))) { rec_fprintf(dst->stream, REC_TYPE_ATTR, "%s=%s", attr_name, attr_value); } else { diff --git a/postfix/src/virtual/Makefile.in b/postfix/src/virtual/Makefile.in index 2526526f4..0958f76ed 100644 --- a/postfix/src/virtual/Makefile.in +++ b/postfix/src/virtual/Makefile.in @@ -2,11 +2,12 @@ SHELL = /bin/sh SRCS = virtual.c mailbox.c recipient.c deliver_attr.c maildir.c unknown.c OBJS = virtual.o mailbox.o recipient.o deliver_attr.o maildir.o unknown.o HDRS = virtual.h -TESTSRC = +TESTSRC = mailbox_test.c DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) CFLAGS = $(DEBUG) $(OPT) $(DEFS) PROG = virtual -TESTPROG= +TESTPROG= mailbox_test +TESTLIB= ../../lib/libptest.a INC_DIR = ../../include LIBS = ../../lib/lib$(LIB_PREFIX)master$(LIB_SUFFIX) \ ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \ @@ -24,7 +25,7 @@ Makefile: Makefile.in test: $(TESTPROG) -tests: +tests: test_mailbox root_tests: @@ -38,6 +39,14 @@ clean: tidy: clean +MAILBOX_TEST_OBJ = mailbox.o $(TESTLIB) + +mailbox_test: mailbox_test.o $(MAILBOX_TEST_OBJ) $(LIBS) + $(CC) $(CFLAGS) -o $@ $@.o $(MAILBOX_TEST_OBJ) $(LIBS) $(SYSLIBS) + +test_mailbox: mailbox_test + $(SHLIB_ENV) $(VALGRIND) ./mailbox_test + depend: $(MAKES) (sed '1,/^# do not edit/!d' Makefile.in; \ set -e; for i in [a-z][a-z0-9]*.c; do \ @@ -96,6 +105,7 @@ mailbox.o: ../../include/nvtable.h mailbox.o: ../../include/pol_stats.h mailbox.o: ../../include/recipient_list.h mailbox.o: ../../include/safe_open.h +mailbox.o: ../../include/sane_strtol.h mailbox.o: ../../include/sent.h mailbox.o: ../../include/set_eugid.h mailbox.o: ../../include/stringops.h @@ -105,6 +115,40 @@ mailbox.o: ../../include/vstream.h mailbox.o: ../../include/vstring.h mailbox.o: mailbox.c mailbox.o: virtual.h +mailbox_test.o: ../../include/argv.h +mailbox_test.o: ../../include/attr.h +mailbox_test.o: ../../include/bounce.h +mailbox_test.o: ../../include/check_arg.h +mailbox_test.o: ../../include/defer.h +mailbox_test.o: ../../include/deliver_request.h +mailbox_test.o: ../../include/dict.h +mailbox_test.o: ../../include/dsn.h +mailbox_test.o: ../../include/dsn_buf.h +mailbox_test.o: ../../include/htable.h +mailbox_test.o: ../../include/mail_params.h +mailbox_test.o: ../../include/maps.h +mailbox_test.o: ../../include/mbox_conf.h +mailbox_test.o: ../../include/msg.h +mailbox_test.o: ../../include/msg_jmp.h +mailbox_test.o: ../../include/msg_output.h +mailbox_test.o: ../../include/msg_stats.h +mailbox_test.o: ../../include/msg_vstream.h +mailbox_test.o: ../../include/myflock.h +mailbox_test.o: ../../include/mymalloc.h +mailbox_test.o: ../../include/myrand.h +mailbox_test.o: ../../include/nvtable.h +mailbox_test.o: ../../include/pmock_expect.h +mailbox_test.o: ../../include/pol_stats.h +mailbox_test.o: ../../include/ptest.h +mailbox_test.o: ../../include/ptest_main.h +mailbox_test.o: ../../include/recipient_list.h +mailbox_test.o: ../../include/stringops.h +mailbox_test.o: ../../include/sys_defs.h +mailbox_test.o: ../../include/vbuf.h +mailbox_test.o: ../../include/vstream.h +mailbox_test.o: ../../include/vstring.h +mailbox_test.o: mailbox_test.c +mailbox_test.o: virtual.h maildir.o: ../../include/argv.h maildir.o: ../../include/attr.h maildir.o: ../../include/bounce.h diff --git a/postfix/src/virtual/mailbox.c b/postfix/src/virtual/mailbox.c index 19afca877..39d08fa5e 100644 --- a/postfix/src/virtual/mailbox.c +++ b/postfix/src/virtual/mailbox.c @@ -57,6 +57,7 @@ #include #include #include +#include /* Global library. */ @@ -176,7 +177,8 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) const char *uid_res; const char *gid_res; DSN_BUF *why = state.msg_attr.why; - long n; + char *end; + unsigned long n; /* * Make verbose logging easier to understand. @@ -215,6 +217,15 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) #define RETURN(res) { myfree(usr_attr.mailbox); return (res); } + if (strstr(usr_attr.mailbox + strlen(var_virt_mailbox_base), "/../")) { + msg_warn("recipient %s: bad mailbox path %s in %s", + state.msg_attr.user, mailbox_res, virtual_mailbox_maps->title); + dsb_simple(why, "4.3.5", "mail system configuration error"); + *statusp = defer_append(BOUNCE_FLAGS(state.request), + BOUNCE_ATTR(state.msg_attr)); + RETURN(YES); + } + /* * Look up the mailbox owner rights. Defer in case of trouble. */ @@ -228,7 +239,10 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) BOUNCE_ATTR(state.msg_attr)); RETURN(YES); } - if ((n = atol(uid_res)) < var_virt_minimum_uid) { + usr_attr.uid = (uid_t) (n = sane_strtoul(uid_res, &end, 10)); + if (*end != 0 || errno != 0 || usr_attr.uid != n + || usr_attr.uid == (uid_t) - 1 /* Special for safe_open()) */ + || usr_attr.uid < var_virt_minimum_uid) { msg_warn("recipient %s: bad uid %s in %s", state.msg_attr.user, uid_res, virtual_uid_maps->title); dsb_simple(why, "4.3.5", "mail system configuration error"); @@ -236,7 +250,6 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) BOUNCE_ATTR(state.msg_attr)); RETURN(YES); } - usr_attr.uid = (uid_t) n; /* * Look up the mailbox group rights. Defer in case of trouble. @@ -251,7 +264,9 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) BOUNCE_ATTR(state.msg_attr)); RETURN(YES); } - if ((n = atol(gid_res)) <= 0) { + usr_attr.gid = (gid_t) (n = sane_strtoul(gid_res, &end, 10)); + if (*end != 0 || errno != 0 || usr_attr.gid !=n + || usr_attr.gid == (gid_t) - 1) { /* Special for safe_open()) */ msg_warn("recipient %s: bad gid %s in %s", state.msg_attr.user, gid_res, virtual_gid_maps->title); dsb_simple(why, "4.3.5", "mail system configuration error"); @@ -259,12 +274,10 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) BOUNCE_ATTR(state.msg_attr)); RETURN(YES); } - usr_attr.gid = (gid_t) n; - if (msg_verbose) - msg_info("%s[%d]: set user_attr: %s, uid = %u, gid = %u", + msg_info("%s[%d]: set user_attr: %s, uid = %lu, gid = %lu", myname, state.level, usr_attr.mailbox, - (unsigned) usr_attr.uid, (unsigned) usr_attr.gid); + (unsigned long) usr_attr.uid, (unsigned long) usr_attr.gid); /* * Deliver to mailbox or to maildir. diff --git a/postfix/src/virtual/mailbox_test.c b/postfix/src/virtual/mailbox_test.c new file mode 100644 index 000000000..5b7ff73ae --- /dev/null +++ b/postfix/src/virtual/mailbox_test.c @@ -0,0 +1,366 @@ + /* + * System library. + */ +#include +#include + + /* + * Global library. + */ +#include +#include +#include +#include +#include + + /* + * Application-specific. + */ +#include + + /* + * Test library. + */ +#include + + /* + * Test case and data. + */ +typedef struct PTEST_CASE { + char *testname; + void (*action) (PTEST_CTX *t, const struct PTEST_CASE *); + char *user; + int minimum_uid; + char *mailbox_maps; + char *uid_maps; + char *gid_maps; + char *mailbox_base; + char *mailbox_lock; + char **want_log; + int want_status; + int want_known; +} PTEST_CASE; + +#define STATUS_FINAL 0 +#define STATUS_DEFER 1 +#define STATUS_UNSET -1 + +#define USER_UNKNOWN 0 +#define USER_KNOWN 1 + /* + * Surriogate parameter dependencies. + */ +int var_virt_minimum_uid; +char *var_virt_mailbox_maps; +char *var_virt_uid_maps; +char *var_virt_gid_maps; +char *var_virt_mailbox_base; +char *var_virt_mailbox_lock; +bool var_strict_mbox_owner; +int virtual_mbox_lock_mask; +char *var_rcpt_delim = "+"; + + /* + * Data dependencies. + */ +MAPS *virtual_mailbox_maps; +MAPS *virtual_uid_maps; +MAPS *virtual_gid_maps; + +static LOCAL_STATE state; +static USER_ATTR usr_attr; +static DELIVER_REQUEST request; + + /* + * Surrogate code dependencies. + * + * deliver_mailbox() will call deliver_mailbox_file() in the same file which + * has too many dependencies. Instead we trigger maildir-style delivery and + * use a fake deliver_maildir() to verify some of the arguments. + * + * defer_append() has too many dependencies. Instead we use a fake + * defer_append() to verify some of the arguments. + */ +int deliver_maildir(LOCAL_STATE state, USER_ATTR user_attr) +{ + msg_info("fake deliver_maildir: mailbox='%s', uid=%lu, gid=%lu", + user_attr.mailbox, (unsigned long) user_attr.uid, + (unsigned long) user_attr.gid); + return (0); +} + +int defer_append(int flags, const char *id, MSG_STATS *stats, + RECIPIENT *rcpt, const char *relay, + const POL_STATS *tstats, DSN *dsn) +{ + msg_info("fake defer_append: dsn=%s reason=%s", dsn->status, dsn->reason); + return (1); +} + +static void teardown_test(void) +{ + if (virtual_mailbox_maps) { + maps_free(virtual_mailbox_maps); + virtual_mailbox_maps = 0; + } + if (virtual_uid_maps) { + maps_free(virtual_uid_maps); + virtual_uid_maps = 0; + } + if (virtual_gid_maps) { + maps_free(virtual_gid_maps); + virtual_gid_maps = 0; + } + if (state.msg_attr.why) { + dsb_free(state.msg_attr.why); + state.msg_attr.why = 0; + } +} + +static void setup_test(const PTEST_CASE *tp) +{ + /* In case a previous test failed. */ + teardown_test(); + + /* + * Set parameters so that warning messages log as expected. + */ + var_virt_minimum_uid = tp->minimum_uid; + var_virt_mailbox_maps = tp->mailbox_maps; + var_virt_uid_maps = tp->uid_maps; + var_virt_gid_maps = tp->gid_maps; + var_virt_mailbox_base = tp->mailbox_base; + var_virt_mailbox_lock = tp->mailbox_lock; + + /* + * Open databases. + */ + if (var_virt_mailbox_maps) + virtual_mailbox_maps = + maps_create(VAR_VIRT_MAILBOX_MAPS, var_virt_mailbox_maps, + DICT_FLAG_LOCK | DICT_FLAG_PARANOID + | DICT_FLAG_UTF8_REQUEST); + if (var_virt_uid_maps) + virtual_uid_maps = + maps_create(VAR_VIRT_UID_MAPS, var_virt_uid_maps, + DICT_FLAG_LOCK | DICT_FLAG_PARANOID + | DICT_FLAG_UTF8_REQUEST); + if (var_virt_gid_maps) + virtual_gid_maps = + maps_create(VAR_VIRT_GID_MAPS, var_virt_gid_maps, + DICT_FLAG_LOCK | DICT_FLAG_PARANOID + | DICT_FLAG_UTF8_REQUEST); + + /* + * Initialize local state, request, and user attributes. + */ + state.msg_attr.why = dsb_create();; + state.msg_attr.user = tp->user; + state.msg_attr.rcpt.address = tp->user; + state.msg_attr.delivered = tp->user; + request.flags = 0; + state.request = &request; +} + +static void test_deliver_mailbox(PTEST_CTX *t, const struct PTEST_CASE *tp) +{ + int got_status = STATUS_UNSET; + int got_known; + char **cpp; + + if (sizeof(uid_t) > 4) { + ptest_info(t, "uid_t is too large -- skipping this test"); + ptest_skip(t); + } + if (sizeof(long) <= 4) { + ptest_info(t, "long is too small -- skipping this test"); + ptest_skip(t); + } + setup_test(tp); + if (tp->want_log) + for (cpp = (char **) tp->want_log; *cpp; cpp++) + expect_ptest_log_event(t, *cpp); + got_known = deliver_mailbox(state, usr_attr, &got_status); + if (got_known != tp->want_known) + ptest_error(t, "user known: got %d, want %d", + got_known, tp->want_known); + if (got_status != tp->want_status) + ptest_error(t, "user status: got %d, want %d", + got_status, tp->want_status); + teardown_test(); +} + + /* + * Test cases. + */ +const PTEST_CASE ptestcases[] = { + { + .testname = "normal case", + .action = test_deliver_mailbox, + .user = "example-user", + .minimum_uid = 1, + .mailbox_maps = "static:user-1-1/", + .uid_maps = "static:1", + .gid_maps = "static:1", + .mailbox_base = "/base", + .want_log = (char *[]) {"mailbox='/base/user-1-1/', uid=1, gid=1", 0,}, + .want_known = USER_KNOWN, + .want_status = USER_UNKNOWN, + },{ + .testname = "relative base", + .action = test_deliver_mailbox, + .user = "example-user", + .mailbox_base = "base", + .want_log = (char *[]) {"do not specify relative pathname", 0,}, + .want_known = USER_UNKNOWN, + .want_status = STATUS_UNSET, + },{ + .testname = "user unknown", + .action = test_deliver_mailbox, + .user = "example-user", + .mailbox_maps = "inline:{x=x}", + .mailbox_base = "/base", + .want_known = USER_UNKNOWN, + .want_status = STATUS_UNSET, + },{ + .testname = "trailing .. in path", + .action = test_deliver_mailbox, + .user = "example-user", + .mailbox_maps = "static:here/../", + .mailbox_base = "/base", + .want_log = (char *[]) { + "recipient example-user: bad mailbox path here/../", + "dsn=4.3.5 reason=mail system configuration error", + 0, + }, + .want_known = USER_KNOWN, + .want_status = STATUS_DEFER, + },{ + .testname = "leading .. in path", + .action = test_deliver_mailbox, + .user = "example-user", + .mailbox_maps = "static:../here/", + .mailbox_base = "/base", + .want_log = (char *[]) { + "recipient example-user: bad mailbox path ../here/", + "dsn=4.3.5 reason=mail system configuration error", + 0, + }, + .want_known = USER_KNOWN, + .want_status = STATUS_DEFER, + },{ + .testname = "missing entry in virtual_gid_maps", + .action = test_deliver_mailbox, + .user = "example-user", + .minimum_uid = 1, + .mailbox_maps = "static:user-1-1/", + .uid_maps = "static:1", + .gid_maps = "inline:{x=x}", + .mailbox_base = "/base", + .want_log = (char *[]) { + "recipient example-user: not found in virtual_gid_maps", + "dsn=4.3.5 reason=mail system configuration error", + 0, + }, + .want_known = USER_KNOWN, + .want_status = STATUS_DEFER, + },{ + .testname = "missing entry in virtual_uid_maps", + .action = test_deliver_mailbox, + .user = "example-user", + .minimum_uid = 1, + .mailbox_maps = "static:user-1-1/", + .uid_maps = "inline:{x=x}", + .mailbox_base = "/base", + .want_log = (char *[]) { + "recipient example-user: not found in virtual_uid_maps", + "dsn=4.3.5 reason=mail system configuration error", + 0, + }, + .want_known = USER_KNOWN, + .want_status = STATUS_DEFER, + },{ + .testname = "gid too large", + .action = test_deliver_mailbox, + .user = "example-user", + .minimum_uid = 1, + .mailbox_maps = "static:user-1-1/", + .uid_maps = "static:1", + .gid_maps = "static:9223372036854775807L", + .mailbox_base = "/base", + .want_log = (char *[]) { + "bad gid 9223372036854775807L in virtual_gid_maps", + "dsn=4.3.5 reason=mail system configuration error", + 0, + }, + .want_known = USER_KNOWN, + .want_status = STATUS_DEFER, + },{ + .testname = "uid too large", + .action = test_deliver_mailbox, + .user = "example-user", + .minimum_uid = 1, + .mailbox_maps = "static:user-1-1/", + .uid_maps = "static:9223372036854775807L", + .gid_maps = "static:1", + .mailbox_base = "/base", + .want_log = (char *[]) { + "bad uid 9223372036854775807L in virtual_uid_maps", + "dsn=4.3.5 reason=mail system configuration error", + 0, + }, + .want_known = USER_KNOWN, + .want_status = STATUS_DEFER, + },{ + .testname = "bad uid conversion", + .action = test_deliver_mailbox, + .user = "example-user", + .minimum_uid = 1, + .mailbox_maps = "static:user-1-1/", + .uid_maps = "static:9223372X36854775807L", + .gid_maps = "static:1", + .mailbox_base = "/base", + .want_log = (char *[]) { + "bad uid 9223372X36854775807L in virtual_uid_maps", + "dsn=4.3.5 reason=mail system configuration error", + 0, + }, + .want_known = USER_KNOWN, + .want_status = STATUS_DEFER, + },{ + .testname = "bad gid conversion", + .action = test_deliver_mailbox, + .user = "example-user", + .minimum_uid = 1, + .mailbox_maps = "static:user-1-1/", + .uid_maps = "static:1", + .gid_maps = "static:9223372X36854775807L", + .mailbox_base = "/base", + .want_log = (char *[]) { + "bad gid 9223372X36854775807L in virtual_gid_maps", + "dsn=4.3.5 reason=mail system configuration error", + 0, + }, + .want_known = USER_KNOWN, + .want_status = STATUS_DEFER, + }, { + .testname = "uid too small", + .action = test_deliver_mailbox, + .user = "example-user", + .minimum_uid = 1, + .mailbox_maps = "static:user-1-1/", + .uid_maps = "static:0", + .gid_maps = "static:1", + .mailbox_base = "/base", + .want_log = (char *[]) { + "bad uid 0 in virtual_uid_maps", + "dsn=4.3.5 reason=mail system configuration error", + 0, + }, + .want_known = USER_KNOWN, + .want_status = STATUS_DEFER, + }, + /* TODO(wietse) database error returns. */ +}; + +#include