/* Pure Load Balancer - (C)opyleft 2003 Jedi/Sector One */ #include #include "plb.h" #include "plb_globals.h" #ifdef WITH_DMALLOC # include #endif int plb_drop_caps(const char * const user, const char * const group, const char * const emptydir) { struct passwd *pw; struct group *gr; gid_t gid; uid_t uid; int isroot = 0; if (user == NULL || *user == 0 || group == NULL || *group == 0 || emptydir == NULL || *emptydir == 0) { return -1; } if (geteuid() == (uid_t) 0) { isroot = 1; } if ((pw = getpwnam(user)) != NULL) { uid = pw->pw_uid; } else { uid = (uid_t) strtoul(user, NULL, 10); } if ((gr = getgrnam(group)) != NULL) { gid = gr->gr_gid; } else { gid = (gid_t) strtoul(group, NULL, 10); } if (uid <= (uid_t) 0 || gid <= (uid_t) 0) { plb_log(LL_FATAL, "I will only switch to a non-root/non-wheel uid/gid"); return -1; } if (isroot != 0) { #ifdef HAVE_SETGROUPS if (setgroups(1U, &gid) != 0) { plb_log(LL_FATAL, "Unable to switch to the requested group"); return -1; } #endif if (chdir(emptydir) != 0 || chroot(emptydir) != 0 || chdir("/") != 0) { plb_log(LL_FATAL, "Unable to chroot to [%s] : [%s]", emptydir, strerror(errno)); return -1; } if (setgid(gid) || setegid(gid) || setuid(uid) || seteuid(uid) || chdir("/")) { plb_log(LL_FATAL, "Unable to switch to [%s]:[%s] : [%s]", user, group, strerror(errno)); return -1; } } else { if (geteuid() != uid) { plb_log(LL_WARNING, "Uid [%lu] requested in configuration file, " "but your effective uid is [%lu]", (unsigned long) uid, (unsigned long) geteuid()); } if (chdir(emptydir) != 0) { plb_log(LL_WARNING, "[%s] is not reachable : [%s]", emptydir, strerror(errno)); } } if (isroot != 0) { plb_log(LL_NOTIFY, "Switching to [%s]:[%s], chrooting to [%s]", user, group, emptydir); } else { plb_log(LL_NOTIFY, "Software started by a non-root user"); } return 0; }