version 1.1.1.2, 2012/05/29 12:26:49
|
version 1.1.1.3, 2012/10/09 09:29:52
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (c) 1996, 1998-2005, 2007-2011 | * Copyright (c) 1996, 1998-2005, 2007-2012 |
* Todd C. Miller <Todd.Miller@courtesan.com> |
* Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
Line 224 make_pwitem(const struct passwd *pw, const char *name)
|
Line 224 make_pwitem(const struct passwd *pw, const char *name)
|
} |
} |
|
|
void |
void |
pw_addref(struct passwd *pw) | sudo_pw_addref(struct passwd *pw) |
{ |
{ |
debug_decl(pw_addref, SUDO_DEBUG_NSS) | debug_decl(sudo_pw_addref, SUDO_DEBUG_NSS) |
ptr_to_item(pw)->refcnt++; |
ptr_to_item(pw)->refcnt++; |
debug_return; |
debug_return; |
} |
} |
|
|
static void |
static void |
pw_delref_item(void *v) | sudo_pw_delref_item(void *v) |
{ |
{ |
struct cache_item *item = v; |
struct cache_item *item = v; |
debug_decl(pw_delref_item, SUDO_DEBUG_NSS) | debug_decl(sudo_pw_delref_item, SUDO_DEBUG_NSS) |
|
|
if (--item->refcnt == 0) |
if (--item->refcnt == 0) |
efree(item); |
efree(item); |
Line 244 pw_delref_item(void *v)
|
Line 244 pw_delref_item(void *v)
|
} |
} |
|
|
void |
void |
pw_delref(struct passwd *pw) | sudo_pw_delref(struct passwd *pw) |
{ |
{ |
debug_decl(pw_delref, SUDO_DEBUG_NSS) | debug_decl(sudo_pw_delref, SUDO_DEBUG_NSS) |
pw_delref_item(ptr_to_item(pw)); | sudo_pw_delref_item(ptr_to_item(pw)); |
debug_return; |
debug_return; |
} |
} |
|
|
Line 378 sudo_fakepwnamid(const char *user, uid_t uid, gid_t gi
|
Line 378 sudo_fakepwnamid(const char *user, uid_t uid, gid_t gi
|
/* Store by uid, overwriting cached version. */ |
/* Store by uid, overwriting cached version. */ |
pwitem->cache.k.uid = pw->pw_uid; |
pwitem->cache.k.uid = pw->pw_uid; |
if ((node = rbinsert(pwcache_byuid, &pwitem->cache)) != NULL) { |
if ((node = rbinsert(pwcache_byuid, &pwitem->cache)) != NULL) { |
pw_delref_item(node->data); | sudo_pw_delref_item(node->data); |
node->data = &pwitem->cache; |
node->data = &pwitem->cache; |
} |
} |
} else { |
} else { |
/* Store by name, overwriting cached version. */ |
/* Store by name, overwriting cached version. */ |
pwitem->cache.k.name = pw->pw_name; |
pwitem->cache.k.name = pw->pw_name; |
if ((node = rbinsert(pwcache_byname, &pwitem->cache)) != NULL) { |
if ((node = rbinsert(pwcache_byname, &pwitem->cache)) != NULL) { |
pw_delref_item(node->data); | sudo_pw_delref_item(node->data); |
node->data = &pwitem->cache; |
node->data = &pwitem->cache; |
} |
} |
} |
} |
Line 426 sudo_freepwcache(void)
|
Line 426 sudo_freepwcache(void)
|
debug_decl(sudo_freepwcache, SUDO_DEBUG_NSS) |
debug_decl(sudo_freepwcache, SUDO_DEBUG_NSS) |
|
|
if (pwcache_byuid != NULL) { |
if (pwcache_byuid != NULL) { |
rbdestroy(pwcache_byuid, pw_delref_item); | rbdestroy(pwcache_byuid, sudo_pw_delref_item); |
pwcache_byuid = NULL; |
pwcache_byuid = NULL; |
} |
} |
if (pwcache_byname != NULL) { |
if (pwcache_byname != NULL) { |
rbdestroy(pwcache_byname, pw_delref_item); | rbdestroy(pwcache_byname, sudo_pw_delref_item); |
pwcache_byname = NULL; |
pwcache_byname = NULL; |
} |
} |
|
|
Line 598 again:
|
Line 598 again:
|
if (cp - (char *)grlitem + len > total) { |
if (cp - (char *)grlitem + len > total) { |
total += len + GROUPNAME_LEN; |
total += len + GROUPNAME_LEN; |
efree(grlitem); |
efree(grlitem); |
gr_delref(grp); | sudo_gr_delref(grp); |
goto again; |
goto again; |
} |
} |
memcpy(cp, grp->gr_name, len); |
memcpy(cp, grp->gr_name, len); |
grlist->groups[ngroups++] = cp; |
grlist->groups[ngroups++] = cp; |
cp += len; |
cp += len; |
gr_delref(grp); | sudo_gr_delref(grp); |
} |
} |
} |
} |
grlist->ngroups = ngroups; |
grlist->ngroups = ngroups; |
Line 617 again:
|
Line 617 again:
|
} |
} |
|
|
void |
void |
gr_addref(struct group *gr) | sudo_gr_addref(struct group *gr) |
{ |
{ |
debug_decl(gr_addref, SUDO_DEBUG_NSS) | debug_decl(sudo_gr_addref, SUDO_DEBUG_NSS) |
ptr_to_item(gr)->refcnt++; |
ptr_to_item(gr)->refcnt++; |
debug_return; |
debug_return; |
} |
} |
|
|
static void |
static void |
gr_delref_item(void *v) | sudo_gr_delref_item(void *v) |
{ |
{ |
struct cache_item *item = v; |
struct cache_item *item = v; |
debug_decl(gr_delref_item, SUDO_DEBUG_NSS) | debug_decl(sudo_gr_delref_item, SUDO_DEBUG_NSS) |
|
|
if (--item->refcnt == 0) |
if (--item->refcnt == 0) |
efree(item); |
efree(item); |
Line 637 gr_delref_item(void *v)
|
Line 637 gr_delref_item(void *v)
|
} |
} |
|
|
void |
void |
gr_delref(struct group *gr) | sudo_gr_delref(struct group *gr) |
{ |
{ |
debug_decl(gr_delref, SUDO_DEBUG_NSS) | debug_decl(sudo_gr_delref, SUDO_DEBUG_NSS) |
gr_delref_item(ptr_to_item(gr)); | sudo_gr_delref_item(ptr_to_item(gr)); |
debug_return; |
debug_return; |
} |
} |
|
|
Line 748 sudo_fakegrnam(const char *group)
|
Line 748 sudo_fakegrnam(const char *group)
|
/* Store by gid, overwriting cached version. */ |
/* Store by gid, overwriting cached version. */ |
gritem->cache.k.gid = gr->gr_gid; |
gritem->cache.k.gid = gr->gr_gid; |
if ((node = rbinsert(grcache_bygid, &gritem->cache)) != NULL) { |
if ((node = rbinsert(grcache_bygid, &gritem->cache)) != NULL) { |
gr_delref_item(node->data); | sudo_gr_delref_item(node->data); |
node->data = &gritem->cache; |
node->data = &gritem->cache; |
} |
} |
} else { |
} else { |
/* Store by name, overwriting cached version. */ |
/* Store by name, overwriting cached version. */ |
gritem->cache.k.name = gr->gr_name; |
gritem->cache.k.name = gr->gr_name; |
if ((node = rbinsert(grcache_byname, &gritem->cache)) != NULL) { |
if ((node = rbinsert(grcache_byname, &gritem->cache)) != NULL) { |
gr_delref_item(node->data); | sudo_gr_delref_item(node->data); |
node->data = &gritem->cache; |
node->data = &gritem->cache; |
} |
} |
} |
} |
Line 765 sudo_fakegrnam(const char *group)
|
Line 765 sudo_fakegrnam(const char *group)
|
} |
} |
|
|
void |
void |
grlist_addref(struct group_list *grlist) | sudo_grlist_addref(struct group_list *grlist) |
{ |
{ |
debug_decl(gr_addref, SUDO_DEBUG_NSS) | debug_decl(sudo_gr_addref, SUDO_DEBUG_NSS) |
ptr_to_item(grlist)->refcnt++; |
ptr_to_item(grlist)->refcnt++; |
debug_return; |
debug_return; |
} |
} |
|
|
static void |
static void |
grlist_delref_item(void *v) | sudo_grlist_delref_item(void *v) |
{ |
{ |
struct cache_item *item = v; |
struct cache_item *item = v; |
debug_decl(gr_delref_item, SUDO_DEBUG_NSS) | debug_decl(sudo_gr_delref_item, SUDO_DEBUG_NSS) |
|
|
if (--item->refcnt == 0) |
if (--item->refcnt == 0) |
efree(item); |
efree(item); |
Line 785 grlist_delref_item(void *v)
|
Line 785 grlist_delref_item(void *v)
|
} |
} |
|
|
void |
void |
grlist_delref(struct group_list *grlist) | sudo_grlist_delref(struct group_list *grlist) |
{ |
{ |
debug_decl(gr_delref, SUDO_DEBUG_NSS) | debug_decl(sudo_gr_delref, SUDO_DEBUG_NSS) |
grlist_delref_item(ptr_to_item(grlist)); | sudo_grlist_delref_item(ptr_to_item(grlist)); |
debug_return; |
debug_return; |
} |
} |
|
|
Line 814 sudo_freegrcache(void)
|
Line 814 sudo_freegrcache(void)
|
debug_decl(sudo_freegrcache, SUDO_DEBUG_NSS) |
debug_decl(sudo_freegrcache, SUDO_DEBUG_NSS) |
|
|
if (grcache_bygid != NULL) { |
if (grcache_bygid != NULL) { |
rbdestroy(grcache_bygid, gr_delref_item); | rbdestroy(grcache_bygid, sudo_gr_delref_item); |
grcache_bygid = NULL; |
grcache_bygid = NULL; |
} |
} |
if (grcache_byname != NULL) { |
if (grcache_byname != NULL) { |
rbdestroy(grcache_byname, gr_delref_item); | rbdestroy(grcache_byname, sudo_gr_delref_item); |
grcache_byname = NULL; |
grcache_byname = NULL; |
} |
} |
if (grlist_cache != NULL) { |
if (grlist_cache != NULL) { |
rbdestroy(grlist_cache, grlist_delref_item); | rbdestroy(grlist_cache, sudo_grlist_delref_item); |
grlist_cache = NULL; |
grlist_cache = NULL; |
} |
} |
|
|
Line 841 sudo_endgrent(void)
|
Line 841 sudo_endgrent(void)
|
} |
} |
|
|
struct group_list * |
struct group_list * |
get_group_list(struct passwd *pw) | sudo_get_grlist(struct passwd *pw) |
{ |
{ |
struct cache_item key, *item; |
struct cache_item key, *item; |
struct rbnode *node; |
struct rbnode *node; |
size_t len; |
size_t len; |
GETGROUPS_T *gids; |
GETGROUPS_T *gids; |
int ngids; |
int ngids; |
debug_decl(get_group_list, SUDO_DEBUG_NSS) | debug_decl(sudo_get_grlist, SUDO_DEBUG_NSS) |
|
|
key.k.name = pw->pw_name; |
key.k.name = pw->pw_name; |
if ((node = rbfind(grlist_cache, &key)) != NULL) { |
if ((node = rbfind(grlist_cache, &key)) != NULL) { |
Line 857 get_group_list(struct passwd *pw)
|
Line 857 get_group_list(struct passwd *pw)
|
} |
} |
/* |
/* |
* Cache group db entry if it exists or a negative response if not. |
* Cache group db entry if it exists or a negative response if not. |
|
* Use gids list from front-end if possible, otherwise getgrouplist(). |
*/ |
*/ |
|
if (pw == sudo_user.pw && sudo_user.gids != NULL) { |
|
gids = user_gids; |
|
ngids = user_ngids; |
|
user_gids = NULL; |
|
user_ngids = 0; |
|
} else { |
#if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX) |
#if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX) |
ngids = (int)sysconf(_SC_NGROUPS_MAX) * 2; | ngids = (int)sysconf(_SC_NGROUPS_MAX) * 2; |
if (ngids < 0) | if (ngids < 0) |
#endif |
#endif |
ngids = NGROUPS_MAX * 2; | ngids = NGROUPS_MAX * 2; |
gids = emalloc2(ngids, sizeof(GETGROUPS_T)); | |
if (getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids) == -1) { | |
efree(gids); | |
gids = emalloc2(ngids, sizeof(GETGROUPS_T)); |
gids = emalloc2(ngids, sizeof(GETGROUPS_T)); |
if (getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids) == -1) { |
if (getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids) == -1) { |
efree(gids); |
efree(gids); |
debug_return_ptr(NULL); | gids = emalloc2(ngids, sizeof(GETGROUPS_T)); |
| if (getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids) == -1) { |
| efree(gids); |
| debug_return_ptr(NULL); |
| } |
} |
} |
} |
} |
if (ngids > 0) { |
if (ngids > 0) { |
Line 896 done:
|
Line 904 done:
|
debug_return_ptr(item->d.grlist); |
debug_return_ptr(item->d.grlist); |
} |
} |
|
|
void |
|
set_group_list(const char *user, GETGROUPS_T *gids, int ngids) |
|
{ |
|
struct cache_item key, *item; |
|
struct rbnode *node; |
|
debug_decl(set_group_list, SUDO_DEBUG_NSS) |
|
|
|
/* |
|
* Cache group db entry if it doesn't already exist |
|
*/ |
|
key.k.name = (char *) user; |
|
if ((node = rbfind(grlist_cache, &key)) == NULL) { |
|
if ((item = make_grlist_item(user, gids, ngids)) == NULL) |
|
errorx(1, "unable to parse group list for %s", user); |
|
if (rbinsert(grlist_cache, item) != NULL) |
|
errorx(1, "unable to cache group list for %s, already exists", |
|
user); |
|
} |
|
debug_return; |
|
} |
|
|
|
bool |
bool |
user_in_group(struct passwd *pw, const char *group) |
user_in_group(struct passwd *pw, const char *group) |
{ |
{ |
Line 926 user_in_group(struct passwd *pw, const char *group)
|
Line 913 user_in_group(struct passwd *pw, const char *group)
|
bool matched = false; |
bool matched = false; |
debug_decl(user_in_group, SUDO_DEBUG_NSS) |
debug_decl(user_in_group, SUDO_DEBUG_NSS) |
|
|
if ((grlist = get_group_list(pw)) != NULL) { | if ((grlist = sudo_get_grlist(pw)) != NULL) { |
/* |
/* |
* If it could be a sudo-style group ID check gids first. |
* If it could be a sudo-style group ID check gids first. |
*/ |
*/ |
Line 964 user_in_group(struct passwd *pw, const char *group)
|
Line 951 user_in_group(struct passwd *pw, const char *group)
|
} |
} |
done: |
done: |
if (grp != NULL) |
if (grp != NULL) |
gr_delref(grp); | sudo_gr_delref(grp); |
grlist_delref(grlist); | sudo_grlist_delref(grlist); |
} |
} |
debug_return_bool(matched); |
debug_return_bool(matched); |
} |
} |