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;
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);
96 privdrop_str, username, strerror(s));
117 struct group* result;
130 buf = (
char*) calloc(bufsize,
sizeof(
char));
132 ods_log_error(
"[%s] calloc failed: out of memory?", privdrop_str);
136 s = getgrnam_r(groupname, &grp, buf, bufsize, &result);
139 privdrop_str, groupname, strerror(s));
141 if (result != NULL) {
157 privdrop(
const char *username,
const char *groupname,
const char *newroot,
158 uid_t* puid, gid_t* pgid)
165 int final_group_len = -1;
168 uid = olduid = geteuid();
174 if (uid == (uid_t)-1) {
184 if (gid == (gid_t)-1) {
194 status = chroot(newroot);
195 if (status != 0 || chdir(
"/") != 0) {
196 ods_log_error(
"[%s] chroot to %s failed: %.100s", privdrop_str,
197 newroot, strerror(errno));
201 ods_log_error(
"[%s] chroot to %s failed: !HAVE_CHROOT", privdrop_str,
208 if (username != NULL && !olduid) {
209 #ifdef HAVE_INITGROUPS
210 if (initgroups(username, gid) < 0) {
211 ods_log_error(
"[%s] initgroups failed: %s: %.100s", privdrop_str,
212 username, strerror(errno));
216 ods_log_error(
"initgroups failed: %s: !HAVE_INITGROUPS", username);
220 ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
221 final_groups = (gid_t *)malloc(ngroups_max *
sizeof(gid_t));
225 #if defined(HAVE_GETGROUPS) && defined(HAVE_SETGROUPS)
226 final_group_len = getgroups(ngroups_max, final_groups);
229 setgroups(final_group_len, final_groups);
232 free((
void*)final_groups);
236 #if defined(HAVE_SETGROUPS)
237 if (!olduid) setgroups(1, &(gid));
244 #if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID)
245 status = setresgid(gid, gid, gid);
246 #elif defined(HAVE_SETREGID) && !defined(BROKEN_SETREGID)
247 status = setregid(gid, gid);
250 # ifndef SETEUID_BREAKS_SETUID
251 status = setegid(gid);
254 privdrop_str, groupname, (
unsigned long) gid, strerror(errno));
259 status = setgid(gid);
264 privdrop_str, groupname, (
unsigned long) gid, strerror(errno));
268 groupname, (
unsigned long) gid);
275 #if defined(HAVE_SETRESUID) && !defined(BROKEN_SETRESUID)
276 status = setresuid(uid, uid, uid);
277 #elif defined(HAVE_SETREUID) && !defined(BROKEN_SETREUID)
278 status = setreuid(uid, uid);
281 # ifndef SETEUID_BREAKS_SETUID
282 status = seteuid(uid);
285 privdrop_str, username, (
unsigned long) uid, strerror(errno));
290 status = setuid(uid);
295 privdrop_str, username, (
unsigned long) uid, strerror(errno));
299 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