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);
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