group: compat nonlocal
group_nonlocal: hesiod
-The module also assigns special properties to two local groups, if
-they exist:
+The module also assigns special properties to two local groups and one
+local user, if they exist:
• If the local group ‘nss-nonlocal-users’ exists, then nonlocal users
will be automatically added to it. Furthermore, if a local user is
• If the local group ‘nss-local-users’ exists, then local users will
be automatically added to it.
+• If the local user ‘nss-nonlocal-users’ is added to a local group,
+ then the local group will inherit the nonlocal membership of a group
+ of the same gid.
+
Copyright © 2007–2010 Anders Kaseorg <andersk@mit.edu> and Tim Abbott
<tabbott@mit.edu>
*/
#define MAGIC_LOCAL_GROUPNAME "nss-local-users"
+/*
+ * If the MAGIC_NONLOCAL_USERNAME local user is added to a local
+ * group, then the local group will inherit the nonlocal membership of
+ * a group of the same gid.
+ */
+#define MAGIC_NONLOCAL_USERNAME "nss-nonlocal-users"
+
enum nss_status
_nss_nonlocal_getgrnam_r(const char *name, struct group *grp,
enum nss_status
-check_nonlocal_gid(const char *user, gid_t gid, int *errnop)
+check_nonlocal_gid(const char *user, const char *group, gid_t gid, int *errnop)
{
enum nss_status status;
struct group gbuf;
#include "walk_nss.h"
#undef args
- if (status == NSS_STATUS_SUCCESS) {
- syslog(LOG_DEBUG, "nss_nonlocal: removing local group %u (%s) from non-local user %s\n", gbuf.gr_gid, gbuf.gr_name, user);
- free(buf);
- status = NSS_STATUS_NOTFOUND;
- } else if (status != NSS_STATUS_TRYAGAIN) {
- status = NSS_STATUS_SUCCESS;
+ if (status == NSS_STATUS_TRYAGAIN)
+ return status;
+ else if (status != NSS_STATUS_SUCCESS)
+ return NSS_STATUS_SUCCESS;
+
+ if (group == NULL || strcmp(gbuf.gr_name, group) == 0) {
+ char *const *mem;
+ for (mem = gbuf.gr_mem; *mem != NULL; mem++)
+ if (strcmp(*mem, MAGIC_NONLOCAL_USERNAME) == 0) {
+ status = check_nonlocal_user(*mem, errnop);
+ if (status == NSS_STATUS_TRYAGAIN) {
+ free(buf);
+ return status;
+ } else if (status == NSS_STATUS_NOTFOUND) {
+ free(buf);
+ return NSS_STATUS_SUCCESS;
+ }
+ break;
+ }
}
- return status;
+ syslog(LOG_DEBUG, "nss_nonlocal: removing local group %u (%s) from non-local user %s\n", gbuf.gr_gid, gbuf.gr_name, user);
+ free(buf);
+ return NSS_STATUS_NOTFOUND;
}
enum nss_status
gid = strtoul(grp->gr_name, &end, 10);
if (errno == 0 && *end == '\0' && (gid_t)gid == gid) {
errno = old_errno;
- status = check_nonlocal_gid(user, gid, errnop);
+ status = check_nonlocal_gid(user, grp->gr_name, gid, errnop);
} else
errno = old_errno;
if (status != NSS_STATUS_SUCCESS)
return status;
- return check_nonlocal_gid(user, grp->gr_gid, errnop);
+ return check_nonlocal_gid(user, grp->gr_name, grp->gr_gid, errnop);
}
enum nss_status
if (status == NSS_STATUS_SUCCESS) {
nonlocal_errno = *errnop;
- status = check_nonlocal_gid(user, pwbuf.pw_gid,
+ status = check_nonlocal_gid(user, NULL, pwbuf.pw_gid,
&nonlocal_errno);
free(buf);
}
if (i < out)
continue;
- status = check_nonlocal_gid(user, (*groupsp)[in], &nonlocal_errno);
+ status = check_nonlocal_gid(user, NULL, (*groupsp)[in],
+ &nonlocal_errno);
if (status == NSS_STATUS_SUCCESS) {
(*groupsp)[out++] = (*groupsp)[in];
} else if (status == NSS_STATUS_TRYAGAIN) {
if (status != NSS_STATUS_SUCCESS)
return status;
- if (check_nonlocal_gid(name, pwd->pw_gid, &group_errno) !=
+ if (check_nonlocal_gid(name, NULL, pwd->pw_gid, &group_errno) !=
NSS_STATUS_SUCCESS)
pwd->pw_gid = 65534 /* nogroup */;
return NSS_STATUS_SUCCESS;
if (status != NSS_STATUS_SUCCESS)
return status;
- if (check_nonlocal_gid(pwd->pw_name, pwd->pw_gid, &group_errno) !=
+ if (check_nonlocal_gid(pwd->pw_name, NULL, pwd->pw_gid, &group_errno) !=
NSS_STATUS_SUCCESS)
pwd->pw_gid = 65534 /* nogroup */;
return NSS_STATUS_SUCCESS;
};
enum nss_status check_nonlocal_uid(const char *user, uid_t uid, int *errnop);
-enum nss_status check_nonlocal_gid(const char *user, gid_t gid, int *errnop);
+enum nss_status check_nonlocal_gid(const char *user, const char *group,
+ gid_t gid, int *errnop);
enum nss_status check_nonlocal_user(const char *user, int *errnop);
enum nss_status get_nonlocal_passwd(const char *name, struct passwd *pwd,
char **buffer, int *errnop);