Add priv.c: reworked version of priv dropping code
authorHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Wed, 10 Mar 2021 22:37:29 +0000 (23:37 +0100)
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Thu, 27 May 2021 19:30:42 +0000 (21:30 +0200)
(cherry picked from commit 82b545236e6dc82b7af34528c532811bfc74ea19)
(cherry picked from commit be31ef213f118abe5fc68732f5492b6b16d28b87)

14 files changed:
src/OS/Makefile-Base
src/scripts/MakeLinks
src/src/dbfn.c
src/src/functions.h
src/src/priv.c [new file with mode: 0644]
test/stderr/0275
test/stderr/0278
test/stderr/0386
test/stderr/0388
test/stderr/0402
test/stderr/0403
test/stderr/0404
test/stderr/0408
test/stderr/0487

index 77fb3474298a3fa399c0f252395ee6c749785a32..bc5fbc42c6d1bc65667cf713b4481d67eb4d2cf8 100644 (file)
@@ -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 \
         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 \
         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
 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
 queue.o:         $(HDRS) queue.c
 rda.o:           $(HDRS) rda.c
 readconf.o:      $(HDRS) readconf.c
index 54ca7fb615b9c3951cbe4401c6c5b64a750b5c7d..3e16ae13ae66f4879ecb49940ee083c39e7cb0b8 100755 (executable)
@@ -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 \
   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 \
   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 \
index b66d4603fdc563615b5cde3c4a1248b3d125cdba..5cbe10c1f2631333bf171023c1fd7ae7264093e9 100644 (file)
@@ -63,68 +63,6 @@ log_write(0, LOG_MAIN, "Berkeley DB error: %s", msg);
 #endif
 
 
 #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         *
 *************************************************/
 /*************************************************
 *          Open and lock a database file         *
 *************************************************/
index 06b6974ae8c7dec98e8acbdd01a4043f55673145..459a707a1193150bbeb7ee3df012b3b51d772476 100644 (file)
@@ -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 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);
 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 (file)
index 0000000..94d4254
--- /dev/null
@@ -0,0 +1,76 @@
+#include "exim.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+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;
+}
index 5a1188c403ec5d0e96ad8e586aef00f769007491..56edac09a8c00dbe35c4223ea24ef700ed72f4a6 100644 (file)
@@ -172,7 +172,6 @@ Delivery address list:
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> flags=O_RDONLY
  returned from EXIM_DBOPEN: (nil)
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> 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
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  failed to open DB file TESTSUITE/spool/db/retry: No such file or directory
 no retry data available
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
index 727a6b885dd573ae4c6fbcd02c40c9880acf9243..b8eb99af68d3c06c3e3d81069a4da4fc45fbfaaf 100644 (file)
@@ -131,7 +131,6 @@ Delivery address list:
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> flags=O_RDONLY
  returned from EXIM_DBOPEN: (nil)
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> 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
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  failed to open DB file TESTSUITE/spool/db/retry: No such file or directory
 no retry data available
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
index 545cf35b0e7bcd4bd0fa0eb6fadaa7314d77f44c..8b0ca464803c125ea830c845e11996f10e730626 100644 (file)
@@ -273,7 +273,6 @@ Delivery address list:
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> flags=O_RDONLY
  returned from EXIM_DBOPEN: (nil)
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> 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
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  failed to open DB file TESTSUITE/spool/db/retry: No such file or directory
 no retry data available
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
index 95484cca23c9f3c2e6afd8900e044ada3e0658a1..c835b58df85ca9061f3771fa99f25da0d00a9b8f 100644 (file)
@@ -10,7 +10,6 @@ set_process_info: pppp delivering 10HmaX-0005vi-00
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> flags=O_RDONLY
  returned from EXIM_DBOPEN: (nil)
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> 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
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  failed to open DB file TESTSUITE/spool/db/retry: No such file or directory
 no retry data available
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
index 3b47d10a64472329952909be97994b8a179307f2..e57f21d0232fedcf4a9fb68d2683e399aca181b0 100644 (file)
@@ -214,7 +214,6 @@ Delivery address list:
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> flags=O_RDONLY
  returned from EXIM_DBOPEN: (nil)
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> 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
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  failed to open DB file TESTSUITE/spool/db/retry: No such file or directory
 no retry data available
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
index e57c974c138261759e7b2925d3913947b2f4a04c..36b73ffa23535c5643cd5b3cbbf5d31da9da5146 100644 (file)
@@ -71,7 +71,6 @@ Delivery address list:
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> flags=O_RDONLY
  returned from EXIM_DBOPEN: (nil)
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> 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
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  failed to open DB file TESTSUITE/spool/db/retry: No such file or directory
 no retry data available
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
index d27d1c5d3b2968b1a92bb718e445ff8d32a0bfe5..43d37791283ca8aaa996382c9c22cea946b4dcfa 100644 (file)
@@ -172,7 +172,6 @@ Delivery address list:
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> flags=O_RDONLY
  returned from EXIM_DBOPEN: (nil)
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> 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
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  failed to open DB file TESTSUITE/spool/db/retry: No such file or directory
 no retry data available
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
index 02a6cfea143c777f842084739d3d20f6d9ac587c..acfafeb2d9e7d777354846aed7d570b70890ad63 100644 (file)
@@ -71,7 +71,6 @@ Delivery address list:
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> flags=O_RDONLY
  returned from EXIM_DBOPEN: (nil)
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> 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
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  failed to open DB file TESTSUITE/spool/db/retry: No such file or directory
 no retry data available
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
index e59361672f388fbd09b493c49562c3fd0b13cdd7..554b6051f901ef8318521255e7595ade3911027c 100644 (file)
@@ -99,7 +99,6 @@ Delivery address list:
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> flags=O_RDONLY
  returned from EXIM_DBOPEN: (nil)
  locked  TESTSUITE/spool/db/retry.lockfile
  EXIM_DBOPEN: file <TESTSUITE/spool/db/retry> dir <TESTSUITE/spool/db> 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
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  failed to open DB file TESTSUITE/spool/db/retry: No such file or directory
 no retry data available
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>