49 #include <sys/types.h>
53 #ifndef _SC_GETPW_R_SIZE_MAX
54 #define _SC_GETPW_R_SIZE_MAX 16384
57 #ifndef _SC_GETGR_R_SIZE_MAX
58 #define _SC_GETGR_R_SIZE_MAX 16384
61 static const char* privdrop_str =
"privdrop";
72 struct passwd* result;
85 buf = (
char*) calloc(bufsize,
sizeof(
char));
87 ods_log_error(
"[%s] calloc failed: out of memory?", privdrop_str);
91 s = getpwnam_r(username, &pwd, buf, bufsize, &result);
94 privdrop_str, username, strerror(s));
115 struct group* result;
128 buf = (
char*) calloc(bufsize,
sizeof(
char));
130 ods_log_error(
"[%s] calloc failed: out of memory?", privdrop_str);
134 s = getgrnam_r(groupname, &grp, buf, bufsize, &result);
137 privdrop_str, groupname, strerror(s));
139 if (result != NULL) {
155 privdrop(
const char *username,
const char *groupname,
const char *newroot,
156 uid_t* puid, gid_t* pgid)
163 int final_group_len = -1;
166 uid = olduid = geteuid();
172 if (uid == (uid_t)-1) {
182 if (gid == (gid_t)-1) {
192 status = chroot(newroot);
193 if (status != 0 || chdir(
"/") != 0) {
194 ods_log_error(
"[%s] chroot to %s failed: %.100s", privdrop_str,
195 newroot, strerror(errno));
199 ods_log_error(
"[%s] chroot to %s failed: !HAVE_CHROOT", privdrop_str,
206 if (username != NULL && !olduid) {
207 #ifdef HAVE_INITGROUPS
208 if (initgroups(username, gid) < 0) {
209 ods_log_error(
"[%s] initgroups failed: %s: %.100s", privdrop_str,
210 username, strerror(errno));
214 ods_log_error(
"initgroups failed: %s: !HAVE_INITGROUPS", username);
218 ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
219 final_groups = (gid_t *)malloc(ngroups_max *
sizeof(gid_t));
223 #if defined(HAVE_GETGROUPS) && defined(HAVE_SETGROUPS)
224 final_group_len = getgroups(ngroups_max, final_groups);
227 setgroups(final_group_len, final_groups);
230 free((
void*)final_groups);
234 #if defined(HAVE_SETGROUPS)
235 if (!olduid) setgroups(1, &(gid));
242 #if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID)
243 status = setresgid(gid, gid, gid);
244 #elif defined(HAVE_SETREGID) && !defined(BROKEN_SETREGID)
245 status = setregid(gid, gid);
248 # ifndef SETEUID_BREAKS_SETUID
249 status = setegid(gid);
252 privdrop_str, groupname, (
unsigned long) gid, strerror(errno));
257 status = setgid(gid);
262 privdrop_str, groupname, (
unsigned long) gid, strerror(errno));
266 groupname, (
unsigned long) gid);
273 #if defined(HAVE_SETRESUID) && !defined(BROKEN_SETRESUID)
274 status = setresuid(uid, uid, uid);
275 #elif defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID)
276 status = setreuid(uid, uid);
279 # ifndef SETEUID_BREAKS_SETUID
280 status = seteuid(uid);
283 privdrop_str, username, (
unsigned long) uid, strerror(errno));
288 status = setuid(uid);
293 privdrop_str, username, (
unsigned long) uid, strerror(errno));
297 username, (
unsigned long) uid);