sz += 12 + sudo_ldap_value_len(grlist->groups[i]);
}
}
- if ((gidlist = sudo_get_gidlist(pw)) != NULL) {
+ if ((gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_ANY)) != NULL) {
for (i = 0; i < gidlist->ngids; i++) {
if (pw->pw_gid == gidlist->gids[i])
continue;
gid_t egid;
size_t glsize;
char *cp, *gid_list;
- struct gid_list *gidlist = sudo_get_gidlist(runas_pw);
+ struct gid_list *gidlist;
+
+ /* Only use results from a group db query, not the front end. */
+ gidlist = sudo_get_gidlist(runas_pw, ENTRY_TYPE_QUERIED);
/* We reserve an extra spot in the list for the effective gid. */
glsize = sizeof("runas_groups=") - 1 +
/*
- * Copyright (c) 1996, 1998-2005, 2007-2016
+ * Copyright (c) 1996, 1998-2005, 2007-2017
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
#endif
/*
- * Compare by uid.
+ * Compare by user ID.
+ * v1 is the key to find or data to insert, v2 is in-tree data.
*/
static int
cmp_pwuid(const void *v1, const void *v2)
const struct cache_item *ci2 = (const struct cache_item *) v2;
if (ci1->k.uid == ci2->k.uid)
return strcmp(ci1->registry, ci2->registry);
- return ci1->k.uid - ci2->k.uid;
+ if (ci1->k.uid < ci2->k.uid)
+ return -1;
+ return 1;
}
/*
- * Compare by user name.
+ * Compare by user/group name.
+ * v1 is the key to find or data to insert, v2 is in-tree data.
*/
static int
cmp_pwnam(const void *v1, const void *v2)
return ret;
}
+/*
+ * Compare by user name, taking into account the source type.
+ * Need to differentiate between group IDs received from the front-end
+ * (via getgroups()) and groups IDs queried from the group database.
+ * v1 is the key to find or data to insert, v2 is in-tree data.
+ */
+static int
+cmp_gidlist(const void *v1, const void *v2)
+{
+ const struct cache_item *ci1 = (const struct cache_item *) v1;
+ const struct cache_item *ci2 = (const struct cache_item *) v2;
+ int ret = strcmp(ci1->k.name, ci2->k.name);
+ if (ret == 0) {
+ if (ci1->type == ENTRY_TYPE_ANY || ci1->type == ci2->type)
+ return strcmp(ci1->registry, ci2->registry);
+ if (ci1->type < ci2->type)
+ return -1;
+ return 1;
+ }
+ return ret;
+}
+
void
sudo_pw_addref(struct passwd *pw)
{
}
/*
- * Compare by gid.
+ * Compare by group ID.
+ * v1 is the key to find or data to insert, v2 is in-tree data.
*/
static int
cmp_grgid(const void *v1, const void *v2)
const struct cache_item *ci2 = (const struct cache_item *) v2;
if (ci1->k.gid == ci2->k.gid)
return strcmp(ci1->registry, ci2->registry);
- return ci1->k.gid - ci2->k.gid;
+ if (ci1->k.gid < ci2->k.gid)
+ return -1;
+ return 1;
}
void
}
struct gid_list *
-sudo_get_gidlist(const struct passwd *pw)
+sudo_get_gidlist(const struct passwd *pw, unsigned int type)
{
struct cache_item key, *item;
struct rbnode *node;
__func__, pw->pw_name);
if (gidlist_cache == NULL) {
- gidlist_cache = rbcreate(cmp_pwnam);
+ gidlist_cache = rbcreate(cmp_gidlist);
if (gidlist_cache == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_ptr(NULL);
}
key.k.name = pw->pw_name;
+ key.type = type;
getauthregistry(pw->pw_name, key.registry);
if ((node = rbfind(gidlist_cache, &key)) != NULL) {
item = node->data;
/*
* Cache group db entry if it exists or a negative response if not.
*/
- item = sudo_make_gidlist_item(pw, NULL);
+ item = sudo_make_gidlist_item(pw, NULL, type);
if (item == NULL) {
/* Out of memory? */
debug_return_ptr(NULL);
}
int
-sudo_set_gidlist(struct passwd *pw, char * const *gids)
+sudo_set_gidlist(struct passwd *pw, char * const *gids, unsigned int type)
{
struct cache_item key, *item;
struct rbnode *node;
debug_decl(sudo_set_gidlist, SUDOERS_DEBUG_NSS)
if (gidlist_cache == NULL) {
- gidlist_cache = rbcreate(cmp_pwnam);
+ gidlist_cache = rbcreate(cmp_gidlist);
if (gidlist_cache == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_int(-1);
* Cache group db entry if it doesn't already exist
*/
key.k.name = pw->pw_name;
+ key.type = type;
getauthregistry(NULL, key.registry);
if ((node = rbfind(gidlist_cache, &key)) == NULL) {
- if ((item = sudo_make_gidlist_item(pw, gids)) == NULL) {
+ if ((item = sudo_make_gidlist_item(pw, gids, type)) == NULL) {
sudo_warnx(U_("unable to parse gids for %s"), pw->pw_name);
debug_return_int(-1);
}
matched = true;
goto done;
}
- if ((gidlist = sudo_get_gidlist(pw)) != NULL) {
+ if ((gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_ANY)) != NULL) {
for (i = 0; i < gidlist->ngids; i++) {
if (gid == gidlist->gids[i]) {
matched = true;
}
/* Check the supplementary group vector. */
- if (gidlist == NULL && (gidlist = sudo_get_gidlist(pw)) != NULL) {
- for (i = 0; i < gidlist->ngids; i++) {
- if (gid == gidlist->gids[i]) {
- matched = true;
- goto done;
+ if (gidlist == NULL) {
+ if ((gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_ANY)) != NULL) {
+ for (i = 0; i < gidlist->ngids; i++) {
+ if (gid == gidlist->gids[i]) {
+ matched = true;
+ goto done;
+ }
}
}
}
/*
- * Copyright (c) 2010-2013 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2010-2013, 2015-2017 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
*/
struct cache_item {
unsigned int refcnt;
- char registry[16];
+ unsigned int type; /* only used for gidlist */
+ char registry[16]; /* AIX-specific, empty otherwise */
/* key */
union {
uid_t uid;
struct cache_item *sudo_make_gritem(gid_t gid, const char *group);
struct cache_item *sudo_make_grlist_item(const struct passwd *pw, char * const *groups);
-struct cache_item *sudo_make_gidlist_item(const struct passwd *pw, char * const *gids);
+struct cache_item *sudo_make_gidlist_item(const struct passwd *pw, char * const *gids, unsigned int type);
struct cache_item *sudo_make_pwitem(uid_t uid, const char *user);
#endif /* SUDOERS_PWUTIL_H */
/*
- * Copyright (c) 1996, 1998-2005, 2007-2015
+ * Copyright (c) 1996, 1998-2005, 2007-2017
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* elements. Fills in datum from user_gids or from getgrouplist(3).
*/
struct cache_item *
-sudo_make_gidlist_item(const struct passwd *pw, char * const *unused1)
+sudo_make_gidlist_item(const struct passwd *pw, char * const *unused1,
+ unsigned int type)
{
char *cp;
size_t nsize, total;
int i, ngids;
debug_decl(sudo_make_gidlist_item, SUDOERS_DEBUG_NSS)
- if (pw == sudo_user.pw && sudo_user.gids != NULL) {
+ /* Don't use user_gids if the entry type says we must query the db. */
+ if (type != ENTRY_TYPE_QUERIED && pw == sudo_user.pw && sudo_user.gids != NULL) {
gids = user_gids;
ngids = user_ngids;
user_gids = NULL;
user_ngids = 0;
+ type = ENTRY_TYPE_FRONTEND;
} else {
+ type = ENTRY_TYPE_QUERIED;
if (sudo_user.max_groups > 0) {
ngids = sudo_user.max_groups;
gids = reallocarray(NULL, ngids, sizeof(GETGROUPS_T));
glitem->cache.k.name = cp;
glitem->cache.d.gidlist = gidlist;
glitem->cache.refcnt = 1;
+ glitem->cache.type = type;
/*
* Store group IDs.
int i, groupname_len;
debug_decl(sudo_make_grlist_item, SUDOERS_DEBUG_NSS)
- gidlist = sudo_get_gidlist(pw);
+ gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_ANY);
if (gidlist == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"no gid list for use %s", pw->pw_name);
/*
- * Copyright (c) 1994-1996,1998-2015 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1994-1996, 1998-2017 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
debug_return_ptr(user_gid_list);
}
+ /* Only use results from a group db query, not the front end. */
pw = runas_pw ? runas_pw : sudo_user.pw;
- gidlist = sudo_get_gidlist(pw);
+ gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_QUERIED);
if (gidlist != NULL) {
if (sudo_setgroups(gidlist->ngids, gidlist->gids) < 0) {
sudo_gidlist_delref(gidlist);
/*
- * Copyright (c) 1993-1996, 1998-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1993-1996, 1998-2017 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
}
}
if (user_gid_list == NULL)
- user_gid_list = sudo_get_gidlist(sudo_user.pw);
+ user_gid_list = sudo_get_gidlist(sudo_user.pw, ENTRY_TYPE_ANY);
/* Store initialize permissions so we can restore them later. */
if (!set_perms(PERM_INITIAL))
/*
- * Copyright (c) 1993-1996, 1998-2005, 2007-2016
+ * Copyright (c) 1993-1996, 1998-2005, 2007-2017
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
pid_t sid;
};
+/*
+ * sudo_get_gidlist() type values
+ */
+#define ENTRY_TYPE_ANY 0x00
+#define ENTRY_TYPE_QUERIED 0x01
+#define ENTRY_TYPE_FRONTEND 0x02
+
/*
* sudo_user flag values
*/
__dso_public void sudo_gr_delref(struct group *);
bool user_in_group(const struct passwd *, const char *);
struct group *sudo_fakegrnam(const char *);
-struct gid_list *sudo_get_gidlist(const struct passwd *pw);
+struct gid_list *sudo_get_gidlist(const struct passwd *pw, unsigned int type);
struct group_list *sudo_get_grlist(const struct passwd *pw);
struct passwd *sudo_fakepwnam(const char *, gid_t);
struct passwd *sudo_mkpwent(const char *user, uid_t uid, gid_t gid, const char *home, const char *shell);
void sudo_grlist_delref(struct group_list *);
void sudo_pw_addref(struct passwd *);
void sudo_pw_delref(struct passwd *);
-int sudo_set_gidlist(struct passwd *pw, char * const *gids);
+int sudo_set_gidlist(struct passwd *pw, char * const *gids, unsigned int type);
int sudo_set_grlist(struct passwd *pw, char * const *groups);
void sudo_setspent(void);