return check_nonlocal_group(grp->gr_name, grp, errnop);
}
+static bool
+add_group(gid_t group, long int *start, long int *size, gid_t **groupsp,
+ long int limit, int *errnop, enum nss_status *status)
+{
+ int i, old_errno = errno;
+ for (i = 0; i < *start; ++i)
+ if ((*groupsp)[i] == group)
+ return true;
+ if (*start + 1 > *size) {
+ gid_t *newgroups;
+ long int newsize = 2 * *size;
+ if (limit > 0) {
+ if (*size >= limit) {
+ *status = NSS_STATUS_SUCCESS;
+ return false;
+ }
+ if (newsize > limit)
+ newsize = limit;
+ }
+ newgroups = realloc(*groupsp, newsize * sizeof((*groupsp)[0]));
+ errno = old_errno;
+ if (newgroups == NULL) {
+ *errnop = ENOMEM;
+ *status = NSS_STATUS_TRYAGAIN;
+ return false;
+ }
+ *groupsp = newgroups;
+ *size = newsize;
+ }
+ (*groupsp)[(*start)++] = group;
+ return true;
+}
+
enum nss_status
_nss_nonlocal_initgroups_dyn(const char *user, gid_t group, long int *start,
long int *size, gid_t **groupsp, long int limit,
const __typeof__(&_nss_nonlocal_initgroups_dyn) self = NULL;
struct group local_users_group, nonlocal_users_group;
- gid_t local_users_gid, gid;
- int is_local = 0;
+ bool is_nonlocal = true;
char *buffer;
- int old_errno;
int in, out, i;
/* Check that the user is a nonlocal user before adding any groups. */
status = check_nonlocal_user(user, errnop);
- if (status == NSS_STATUS_TRYAGAIN)
+ if (status == NSS_STATUS_TRYAGAIN) {
return status;
- else if (status != NSS_STATUS_SUCCESS)
- is_local = 1;
-
- old_errno = errno;
-
- status = get_local_group(MAGIC_LOCAL_GROUPNAME,
- &local_users_group, &buffer, errnop);
- if (status == NSS_STATUS_SUCCESS) {
- local_users_gid = local_users_group.gr_gid;
- free(buffer);
- } else if (status == NSS_STATUS_TRYAGAIN) {
- return status;
- } else {
- syslog(LOG_WARNING, "nss_nonlocal: Group %s does not exist locally!",
- MAGIC_LOCAL_GROUPNAME);
- local_users_gid = -1;
- }
+ } else if (status != NSS_STATUS_SUCCESS) {
+ is_nonlocal = false;
- if (is_local) {
- gid = local_users_gid;
+ status = get_local_group(MAGIC_LOCAL_GROUPNAME,
+ &local_users_group, &buffer, errnop);
+ if (status == NSS_STATUS_SUCCESS) {
+ free(buffer);
+ if (!add_group(local_users_group.gr_gid, start, size, groupsp,
+ limit, errnop, &status))
+ return status;
+ } else if (status == NSS_STATUS_TRYAGAIN) {
+ return status;
+ } else {
+ syslog(LOG_WARNING,
+ "nss_nonlocal: Group %s does not exist locally!",
+ MAGIC_LOCAL_GROUPNAME);
+ }
} else {
status = get_local_group(MAGIC_NONLOCAL_GROUPNAME,
&nonlocal_users_group, &buffer, errnop);
if (status == NSS_STATUS_SUCCESS) {
- gid = nonlocal_users_group.gr_gid;
free(buffer);
+ if (!add_group(nonlocal_users_group.gr_gid, start, size, groupsp,
+ limit, errnop, &status))
+ return status;
} else if (status == NSS_STATUS_TRYAGAIN) {
return status;
} else {
syslog(LOG_WARNING, "nss_nonlocal: Group %s does not exist locally!",
MAGIC_NONLOCAL_GROUPNAME);
- gid = -1;
- }
- }
-
- if (gid != -1) {
- int i;
- for (i = 0; i < *start; ++i)
- if ((*groupsp)[i] == gid)
- break;
- if (i >= *start) {
- if (*start + 1 > *size) {
- gid_t *newgroups;
- long int newsize = 2 * *size;
- if (limit > 0) {
- if (*size >= limit)
- return NSS_STATUS_SUCCESS;
- if (newsize > limit)
- newsize = limit;
- }
- newgroups = realloc(*groupsp, newsize * sizeof((*groupsp)[0]));
- errno = old_errno;
- if (newgroups == NULL) {
- *errnop = ENOMEM;
- return NSS_STATUS_TRYAGAIN;
- }
- *groupsp = newgroups;
- *size = newsize;
- }
- (*groupsp)[(*start)++] = gid;
}
}
- if (is_local)
+ if (!is_nonlocal)
return NSS_STATUS_SUCCESS;
in = out = *start;
if (i < out)
continue;
- /* Don't let users get into MAGIC_LOCAL_GROUPNAME from nonlocal reasons. */
- if (local_users_gid == (*groupsp)[in]) {
- syslog(LOG_WARNING, "nss_nonlocal: Nonlocal user %s removed from special local users group %s",
- user, MAGIC_LOCAL_GROUPNAME);
- continue;
- }
-
status = check_nonlocal_gid(user, (*groupsp)[in], &nonlocal_errno);
if (status == NSS_STATUS_SUCCESS) {
(*groupsp)[out++] = (*groupsp)[in];