#include <string.h>
#include <unistd.h>
#include <ctype.h>
+#include <limits.h>
#include <netinet/in.h>
struct addrinfo **pai,
bool skip_canonname);
+#ifdef HAVE_GETGROUPLIST
+static int nwrap_getgrouplist(const char *user,
+ gid_t group,
+ long int *size,
+ gid_t **groupsp,
+ long int limit);
+#endif
+
/*
* VECTORS
*/
static int nwrap_initgroups(const char *user, gid_t group)
{
+#if defined(NGROUPS_MAX) && NGROUPS_MAX == 0
+ /* No extra groups allowed. */
return 0;
+#elif !defined(HAVE_GETGROUPLIST)
+ return 0;
+#else
+ long int size;
+ long int limit;
+ gid_t *groups;
+ int ngroups;
+ int result;
+ const char *env = getenv("UID_WRAPPER");
+
+ if (env == NULL || env[0] != '1') {
+ NWRAP_LOG(NWRAP_LOG_WARN,
+ "initgroups() requires uid_wrapper to work!");
+ return 0;
+ }
+
+ limit = sysconf(_SC_NGROUPS_MAX);
+ if (limit > 0) {
+ size = MIN(limit, 64);
+ } else {
+ size = 16;
+ }
+
+ groups = (gid_t *)malloc(size * sizeof(gid_t));
+ if (groups == NULL) {
+ /* No more memory. */
+ return -1;
+ }
+
+ ngroups = nwrap_getgrouplist(user, group, &size, &groups, limit);
+
+ /* Try to set the maximum number of groups the kernel can handle. */
+ do {
+ result = setgroups(ngroups, groups);
+ } while (result == -1 && errno == EINVAL && --ngroups > 0);
+
+ free(groups);
+
+ return result;
+#endif
}
int initgroups(const char *user, gid_t group)