/* Pure Load Balancer - (C)opyleft 2003 Jedi/Sector One <j@pureftpd.org> */
#include <config.h>
#include "plb.h"
#include "plb_globals.h"
#ifdef WITH_DMALLOC
# include <dmalloc.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1