diff --git a/src/lib-sieve/util/program-client-local.c b/src/lib-sieve/util/program-client-local.c index e79841b38835a1ef9f4d7c3e24d48b2dc2473983..0300ad9c9952837f9efae055603569588d0ee2ca 100644 --- a/src/lib-sieve/util/program-client-local.c +++ b/src/lib-sieve/util/program-client-local.c @@ -18,7 +18,7 @@ #include <sys/wait.h> #include <unistd.h> #include <fcntl.h> - +#include <grp.h> struct program_client_local { struct program_client client; @@ -186,33 +186,30 @@ static int program_client_local_connect if (seteuid(0) < 0) i_fatal("seteuid(0) failed: %m"); - /* drop gid first */ + /* drop gids first */ gid = getgid(); if ( gid == 0 || gid != pclient->set.gid ) { - if ( pclient->set.gid != 0 ) { - if ( setgid(pclient->set.gid) < 0 ) - i_fatal("setgid(%d) failed: %m", pclient->set.gid); - } else { + if ( pclient->set.gid != 0 ) + gid = pclient->set.gid; + else gid = getegid(); - if (gid != 0 && setgid(gid) < 0) { - i_fatal("setgid(%d) failed: %m", gid); - } - } } + if ( setgroups(1, &gid) < 0 ) + i_fatal("setgroups(%d) failed: %m", gid); + if ( gid != 0 && setgid(gid) < 0 ) + i_fatal("setgid(%d) failed: %m", gid); /* drop uid */ - if ( pclient->set.uid != 0 ) { - if ( setuid(pclient->set.uid) ) - i_fatal("setuid(%d) failed: %m", pclient->set.uid); - } else { + if ( pclient->set.uid != 0 ) + uid = pclient->set.uid; + else uid = geteuid(); - if ( uid != 0 && setuid(uid) < 0 ) - i_fatal("setuid(%d) failed: %m", uid); - } + if ( uid != 0 && setuid(uid) < 0 ) + i_fatal("setuid(%d) failed: %m", uid); } - i_assert(getuid() != 0); - i_assert(getgid() != 0); + i_assert(pclient->set.uid == 0 || getuid() != 0); + i_assert(pclient->set.gid == 0 || getgid() != 0); if ( array_is_created(&pclient->envs) ) envs = array_get(&pclient->envs, &count);