51 #include <sys/types.h>
55 #ifndef _SC_GETPW_R_SIZE_MAX
56 #define _SC_GETPW_R_SIZE_MAX 16384
59 #ifndef _SC_GETGR_R_SIZE_MAX
60 #define _SC_GETGR_R_SIZE_MAX 16384
63 static const char* privdrop_str =
"privdrop";
74 struct passwd* result;
80 uid = olduid = geteuid();
87 buf = (
char*) calloc(bufsize,
sizeof(
char));
89 ods_log_error(
"[%s] calloc failed: out of memory?", privdrop_str);
93 s = getpwnam_r(username, &pwd, buf, bufsize, &result);
113 struct group* result;
119 gid = oldgid = getegid();
126 buf = (
char*) calloc(bufsize,
sizeof(
char));
128 ods_log_error(
"[%s] calloc failed: out of memory?", privdrop_str);
132 s = getgrnam_r(groupname, &grp, buf, bufsize, &result);
133 if (result != NULL) {
149 privdrop(
const char *username,
const char *groupname,
const char *newroot,
150 uid_t* puid, gid_t* pgid)
157 int final_group_len = -1;
160 uid = olduid = geteuid();
161 gid = oldgid = getegid();
166 if (uid == (uid_t)-1) {
176 if (gid == (gid_t)-1) {
186 status = chroot(newroot);
187 if (status != 0 || chdir(
"/") != 0) {
188 ods_log_error(
"[%s] chroot to %s failed: %.100s", privdrop_str,
189 newroot, strerror(errno));
193 ods_log_error(
"[%s] chroot to %s failed: !HAVE_CHROOT", privdrop_str,
200 if (username != NULL && !olduid) {
201 #ifdef HAVE_INITGROUPS
202 if (initgroups(username, gid) < 0) {
203 ods_log_error(
"[%s] initgroups failed: %s: %.100s", privdrop_str,
204 username, strerror(errno));
208 ods_log_error(
"initgroups failed: %s: !HAVE_INITGROUPS", username);
212 ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
213 final_groups = (gid_t *)malloc(ngroups_max *
sizeof(gid_t));
217 #if defined(HAVE_GETGROUPS) && defined(HAVE_SETGROUPS)
218 final_group_len = getgroups(ngroups_max, final_groups);
221 setgroups(final_group_len, final_groups);
224 free((
void*)final_groups);
228 #if defined(HAVE_SETGROUPS)
229 if (!olduid) setgroups(1, &(gid));
236 #if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID)
237 status = setresgid(gid, gid, gid);
238 #elif defined(HAVE_SETREGID) && !defined(BROKEN_SETREGID)
239 status = setregid(gid, gid);
242 # ifndef SETEUID_BREAKS_SETUID
243 status = setegid(gid);
246 privdrop_str, groupname, (
unsigned long) gid, strerror(errno));
251 status = setgid(gid);
256 privdrop_str, groupname, (
unsigned long) gid, strerror(errno));
260 groupname, (
unsigned long) gid);
267 #if defined(HAVE_SETRESUID) && !defined(BROKEN_SETRESUID)
268 status = setresuid(uid, uid, uid);
269 #elif defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID)
270 status = setreuid(uid, uid);
273 # ifndef SETEUID_BREAKS_SETUID
274 status = seteuid(uid);
277 privdrop_str, username, (
unsigned long) uid, strerror(errno));
282 status = setuid(uid);
287 privdrop_str, username, (
unsigned long) uid, strerror(errno));
291 username, (
unsigned long) uid);
gid_t privgid(const char *groupname)
void privclose(const char *username, const char *groupname)
void ods_log_debug(const char *format,...)
enum ods_enum_status ods_status
void ods_log_error(const char *format,...)
uid_t privuid(const char *username)
ods_status privdrop(const char *username, const char *groupname, const char *newroot, uid_t *puid, gid_t *pgid)
#define _SC_GETGR_R_SIZE_MAX
#define _SC_GETPW_R_SIZE_MAX