From: Heiko Schlittermann (HS12-RIPE) Date: Wed, 10 Mar 2021 22:37:29 +0000 (+0100) Subject: Add priv.c: reworked version of priv dropping code X-Git-Tag: exim-4.95-RC0~51^2~25 X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/84dcbc72b968ebc666387874171580463f1944dd Add priv.c: reworked version of priv dropping code (cherry picked from commit 82b545236e6dc82b7af34528c532811bfc74ea19) (cherry picked from commit be31ef213f118abe5fc68732f5492b6b16d28b87) --- diff --git a/src/OS/Makefile-Base b/src/OS/Makefile-Base index 77fb34742..bc5fbc42c 100644 --- a/src/OS/Makefile-Base +++ b/src/OS/Makefile-Base @@ -486,7 +486,7 @@ OBJ_EXIM = acl.o base64.o child.o crypt16.o daemon.o dbfn.o debug.o deliver.o \ directory.o dns.o drtables.o enq.o exim.o expand.o filter.o \ filtertest.o globals.o dkim.o dkim_transport.o dnsbl.o hash.o \ header.o host.o ip.o log.o lss.o match.o md5.o moan.o \ - os.o parse.o queue.o \ + os.o parse.o priv.o queue.o \ rda.o readconf.o receive.o retry.o rewrite.o rfc2047.o \ route.o search.o sieve.o smtp_in.o smtp_out.o spool_in.o spool_out.o \ std-crypto.o store.o string.o tls.o tod.o transport.o tree.o verify.o \ @@ -793,6 +793,7 @@ md5.o: $(HDRS) md5.c moan.o: $(HDRS) moan.c os.o: $(HDRS) $(OS_C_INCLUDES) os.c parse.o: $(HDRS) parse.c +priv.o: $(HDRS) priv.c queue.o: $(HDRS) queue.c rda.o: $(HDRS) rda.c readconf.o: $(HDRS) readconf.c diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks index 54ca7fb61..3e16ae13a 100755 --- a/src/scripts/MakeLinks +++ b/src/scripts/MakeLinks @@ -103,7 +103,7 @@ for f in blob.h dbfunctions.h dbstuff.h exim.h functions.h globals.h \ deliver.c directory.c dns.c dnsbl.c drtables.c dummies.c enq.c exim.c \ exim_dbmbuild.c exim_dbutil.c exim_lock.c expand.c filter.c filtertest.c \ globals.c hash.c header.c host.c ip.c log.c lss.c match.c md5.c moan.c \ - parse.c perl.c queue.c rda.c readconf.c receive.c retry.c rewrite.c \ + parse.c perl.c priv.c queue.c rda.c readconf.c receive.c retry.c rewrite.c \ rfc2047.c route.c search.c setenv.c environment.c \ sieve.c smtp_in.c smtp_out.c spool_in.c spool_out.c std-crypto.c store.c \ string.c tls.c tlscert-gnu.c tlscert-openssl.c tls-cipher-stdname.c \ diff --git a/src/src/dbfn.c b/src/src/dbfn.c index b66d4603f..5cbe10c1f 100644 --- a/src/src/dbfn.c +++ b/src/src/dbfn.c @@ -63,68 +63,6 @@ log_write(0, LOG_MAIN, "Berkeley DB error: %s", msg); #endif - - -static enum { - PRIV_DROPPING, PRIV_DROPPED, - PRIV_RESTORING, PRIV_RESTORED -} priv_state = PRIV_RESTORED; - -static uid_t priv_euid; -static gid_t priv_egid; -static gid_t priv_groups[EXIM_GROUPLIST_SIZE + 1]; -static int priv_ngroups; - -/* Inspired by OpenSSH's temporarily_use_uid(). Thanks! */ - -static void -priv_drop_temp(const uid_t temp_uid, const gid_t temp_gid) -{ -if (priv_state != PRIV_RESTORED) _exit(EXIT_FAILURE); -priv_state = PRIV_DROPPING; - -priv_euid = geteuid(); -if (priv_euid == root_uid) - { - priv_egid = getegid(); - priv_ngroups = getgroups(nelem(priv_groups), priv_groups); - if (priv_ngroups < 0) _exit(EXIT_FAILURE); - - if (priv_ngroups > 0 && setgroups(1, &temp_gid) != 0) _exit(EXIT_FAILURE); - if (setegid(temp_gid) != 0) _exit(EXIT_FAILURE); - if (seteuid(temp_uid) != 0) _exit(EXIT_FAILURE); - - if (geteuid() != temp_uid) _exit(EXIT_FAILURE); - if (getegid() != temp_gid) _exit(EXIT_FAILURE); - } - -priv_state = PRIV_DROPPED; -} - -/* Inspired by OpenSSH's restore_uid(). Thanks! */ - -static void -priv_restore(void) -{ -if (priv_state != PRIV_DROPPED) _exit(EXIT_FAILURE); -priv_state = PRIV_RESTORING; - -if (priv_euid == root_uid) - { - if (seteuid(priv_euid) != 0) _exit(EXIT_FAILURE); - if (setegid(priv_egid) != 0) _exit(EXIT_FAILURE); - if (priv_ngroups > 0 && setgroups(priv_ngroups, priv_groups) != 0) _exit(EXIT_FAILURE); - - if (geteuid() != priv_euid) _exit(EXIT_FAILURE); - if (getegid() != priv_egid) _exit(EXIT_FAILURE); - } - -priv_state = PRIV_RESTORED; -} - - - - /************************************************* * Open and lock a database file * *************************************************/ diff --git a/src/src/functions.h b/src/src/functions.h index 06b6974ae..459a707a1 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -381,6 +381,8 @@ extern const uschar *parse_fix_phrase(const uschar *, int); extern const uschar *parse_message_id(const uschar *, uschar **, uschar **); extern const uschar *parse_quote_2047(const uschar *, int, uschar *, BOOL); extern const uschar *parse_date_time(const uschar *str, time_t *t); +extern void priv_drop_temp(const uid_t, const gid_t); +extern void priv_restore(void); extern int vaguely_random_number(int); #ifndef DISABLE_TLS extern int vaguely_random_number_fallback(int); diff --git a/src/src/priv.c b/src/src/priv.c new file mode 100644 index 000000000..94d425401 --- /dev/null +++ b/src/src/priv.c @@ -0,0 +1,76 @@ +#include "exim.h" +#include +#include +#include + +static enum { + PRIV_DROPPING, PRIV_DROPPED, + PRIV_RESTORING, PRIV_RESTORED +} priv_state = PRIV_RESTORED; + + +static uid_t priv_euid; +static gid_t priv_egid; +static gid_t priv_groups[EXIM_GROUPLIST_SIZE + 1]; +static int priv_ngroups; + +/* Inspired by OpenSSH's temporarily_use_uid(). Thanks! */ + +void +priv_drop_temp(const uid_t temp_uid, const gid_t temp_gid) +{ +if (priv_state != PRIV_RESTORED) + log_write(0, LOG_PANIC_DIE, "priv_drop_temp: unexpected priv_state %d != %d", priv_state, PRIV_RESTORED); + +priv_state = PRIV_DROPPING; + +priv_euid = geteuid(); +if (priv_euid == root_uid) + { + priv_egid = getegid(); + priv_ngroups = getgroups(nelem(priv_groups), priv_groups); + if (priv_ngroups < 0) + log_write(0, LOG_PANIC_DIE, "getgroups: %s", strerror(errno)); + + if (priv_ngroups > 0 && setgroups(1, &temp_gid) != 0) + log_write(0, LOG_PANIC_DIE, "setgroups: %s", strerror(errno)); + if (setegid(temp_gid) != 0) + log_write(0, LOG_PANIC_DIE, "setegid(%d): %s", temp_gid, strerror(errno)); + if (seteuid(temp_uid) != 0) + log_write(0, LOG_PANIC_DIE, "seteuid(%d): %s", temp_uid, strerror(errno)); + + if (geteuid() != temp_uid) + log_write(0, LOG_PANIC_DIE, "getdeuid() != %d", temp_uid); + if (getegid() != temp_gid) + log_write(0, LOG_PANIC_DIE, "getegid() != %d", temp_gid); + } + +priv_state = PRIV_DROPPED; +} + +/* Inspired by OpenSSH's restore_uid(). Thanks! */ + +void +priv_restore(void) +{ +if (priv_state != PRIV_DROPPED) + log_write(0, LOG_PANIC_DIE, "priv_restore: unexpected priv_state %d != %d", priv_state, PRIV_DROPPED); +priv_state = PRIV_RESTORING; + +if (priv_euid == root_uid) + { + if (seteuid(priv_euid) != 0) + log_write(0, LOG_PANIC_DIE, "seteuid(%d): %s", priv_euid, strerror(errno)); + if (setegid(priv_egid) != 0) + log_write(0, LOG_PANIC_DIE, "setegid(%d): %s", priv_egid, strerror(errno)); + if (priv_ngroups > 0 && setgroups(priv_ngroups, priv_groups) != 0) + log_write(0, LOG_PANIC_DIE, "setgroups: %s", strerror(errno)); + + if (geteuid() != priv_euid) + log_write(0, LOG_PANIC_DIE, "getdeuid() != %d", priv_euid); + if (getegid() != priv_egid) + log_write(0, LOG_PANIC_DIE, "getdegid() != %d", priv_egid); + } + +priv_state = PRIV_RESTORED; +} diff --git a/test/stderr/0275 b/test/stderr/0275 index 5a1188c40..56edac09a 100644 --- a/test/stderr/0275 +++ b/test/stderr/0275 @@ -172,7 +172,6 @@ Delivery address list: locked TESTSUITE/spool/db/retry.lockfile EXIM_DBOPEN: file dir flags=O_RDONLY returned from EXIM_DBOPEN: (nil) - ensuring TESTSUITE/spool/db/retry.lockfile is owned by exim failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/test/stderr/0278 b/test/stderr/0278 index 727a6b885..b8eb99af6 100644 --- a/test/stderr/0278 +++ b/test/stderr/0278 @@ -131,7 +131,6 @@ Delivery address list: locked TESTSUITE/spool/db/retry.lockfile EXIM_DBOPEN: file dir flags=O_RDONLY returned from EXIM_DBOPEN: (nil) - ensuring TESTSUITE/spool/db/retry.lockfile is owned by exim failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/test/stderr/0386 b/test/stderr/0386 index 545cf35b0..8b0ca4648 100644 --- a/test/stderr/0386 +++ b/test/stderr/0386 @@ -273,7 +273,6 @@ Delivery address list: locked TESTSUITE/spool/db/retry.lockfile EXIM_DBOPEN: file dir flags=O_RDONLY returned from EXIM_DBOPEN: (nil) - ensuring TESTSUITE/spool/db/retry.lockfile is owned by exim failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/test/stderr/0388 b/test/stderr/0388 index 95484cca2..c835b58df 100644 --- a/test/stderr/0388 +++ b/test/stderr/0388 @@ -10,7 +10,6 @@ set_process_info: pppp delivering 10HmaX-0005vi-00 locked TESTSUITE/spool/db/retry.lockfile EXIM_DBOPEN: file dir flags=O_RDONLY returned from EXIM_DBOPEN: (nil) - ensuring TESTSUITE/spool/db/retry.lockfile is owned by exim failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/test/stderr/0402 b/test/stderr/0402 index 3b47d10a6..e57f21d02 100644 --- a/test/stderr/0402 +++ b/test/stderr/0402 @@ -214,7 +214,6 @@ Delivery address list: locked TESTSUITE/spool/db/retry.lockfile EXIM_DBOPEN: file dir flags=O_RDONLY returned from EXIM_DBOPEN: (nil) - ensuring TESTSUITE/spool/db/retry.lockfile is owned by exim failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/test/stderr/0403 b/test/stderr/0403 index e57c974c1..36b73ffa2 100644 --- a/test/stderr/0403 +++ b/test/stderr/0403 @@ -71,7 +71,6 @@ Delivery address list: locked TESTSUITE/spool/db/retry.lockfile EXIM_DBOPEN: file dir flags=O_RDONLY returned from EXIM_DBOPEN: (nil) - ensuring TESTSUITE/spool/db/retry.lockfile is owned by exim failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/test/stderr/0404 b/test/stderr/0404 index d27d1c5d3..43d377912 100644 --- a/test/stderr/0404 +++ b/test/stderr/0404 @@ -172,7 +172,6 @@ Delivery address list: locked TESTSUITE/spool/db/retry.lockfile EXIM_DBOPEN: file dir flags=O_RDONLY returned from EXIM_DBOPEN: (nil) - ensuring TESTSUITE/spool/db/retry.lockfile is owned by exim failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/test/stderr/0408 b/test/stderr/0408 index 02a6cfea1..acfafeb2d 100644 --- a/test/stderr/0408 +++ b/test/stderr/0408 @@ -71,7 +71,6 @@ Delivery address list: locked TESTSUITE/spool/db/retry.lockfile EXIM_DBOPEN: file dir flags=O_RDONLY returned from EXIM_DBOPEN: (nil) - ensuring TESTSUITE/spool/db/retry.lockfile is owned by exim failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/test/stderr/0487 b/test/stderr/0487 index e59361672..554b6051f 100644 --- a/test/stderr/0487 +++ b/test/stderr/0487 @@ -99,7 +99,6 @@ Delivery address list: locked TESTSUITE/spool/db/retry.lockfile EXIM_DBOPEN: file dir flags=O_RDONLY returned from EXIM_DBOPEN: (nil) - ensuring TESTSUITE/spool/db/retry.lockfile is owned by exim failed to open DB file TESTSUITE/spool/db/retry: No such file or directory no retry data available >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>