Reference count cached passwd and group structs. The cache holds
one reference itself and another is added by sudo_getgr{gid,nam} and sudo_getpw{uid,nam}. The final ref on the runas and user passwd and group structs are persistent for now.
This commit is contained in:
@@ -648,6 +648,10 @@ remove_timestamp(int remove)
|
|||||||
|
|
||||||
efree(timestampdir);
|
efree(timestampdir);
|
||||||
efree(timestampfile);
|
efree(timestampfile);
|
||||||
|
if (auth_pw) {
|
||||||
|
pw_delref(auth_pw);
|
||||||
|
auth_pw = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -801,13 +801,17 @@ sudo_ldap_build_pass1(struct passwd *pw)
|
|||||||
sz = 29 + strlen(pw->pw_name);
|
sz = 29 + strlen(pw->pw_name);
|
||||||
|
|
||||||
/* Add space for groups */
|
/* Add space for groups */
|
||||||
if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL)
|
if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) {
|
||||||
sz += 12 + strlen(grp->gr_name); /* primary group */
|
sz += 12 + strlen(grp->gr_name); /* primary group */
|
||||||
|
gr_delref(grp);
|
||||||
|
}
|
||||||
for (i = 0; i < user_ngroups; i++) {
|
for (i = 0; i < user_ngroups; i++) {
|
||||||
if (user_groups[i] == pw->pw_gid)
|
if (user_groups[i] == pw->pw_gid)
|
||||||
continue;
|
continue;
|
||||||
if ((grp = sudo_getgrgid(user_groups[i])) != NULL)
|
if ((grp = sudo_getgrgid(user_groups[i])) != NULL) {
|
||||||
sz += 12 + strlen(grp->gr_name); /* supplementary group */
|
sz += 12 + strlen(grp->gr_name); /* supplementary group */
|
||||||
|
gr_delref(grp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buf = emalloc(sz);
|
buf = emalloc(sz);
|
||||||
|
|
||||||
@@ -821,6 +825,7 @@ sudo_ldap_build_pass1(struct passwd *pw)
|
|||||||
(void) strlcat(buf, "(sudoUser=%", sz);
|
(void) strlcat(buf, "(sudoUser=%", sz);
|
||||||
(void) strlcat(buf, grp->gr_name, sz);
|
(void) strlcat(buf, grp->gr_name, sz);
|
||||||
(void) strlcat(buf, ")", sz);
|
(void) strlcat(buf, ")", sz);
|
||||||
|
gr_delref(grp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Append supplementary groups */
|
/* Append supplementary groups */
|
||||||
@@ -831,6 +836,7 @@ sudo_ldap_build_pass1(struct passwd *pw)
|
|||||||
(void) strlcat(buf, "(sudoUser=%", sz);
|
(void) strlcat(buf, "(sudoUser=%", sz);
|
||||||
(void) strlcat(buf, grp->gr_name, sz);
|
(void) strlcat(buf, grp->gr_name, sz);
|
||||||
(void) strlcat(buf, ")", sz);
|
(void) strlcat(buf, ")", sz);
|
||||||
|
gr_delref(grp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -771,25 +771,41 @@ group_matches(char *sudoers_group, struct group *gr)
|
|||||||
int
|
int
|
||||||
usergr_matches(char *group, char *user, struct passwd *pw)
|
usergr_matches(char *group, char *user, struct passwd *pw)
|
||||||
{
|
{
|
||||||
|
int matched = FALSE;
|
||||||
|
struct passwd *pw0 = NULL;
|
||||||
|
|
||||||
/* make sure we have a valid usergroup, sudo style */
|
/* make sure we have a valid usergroup, sudo style */
|
||||||
if (*group++ != '%')
|
if (*group++ != '%')
|
||||||
return(FALSE);
|
goto done;
|
||||||
|
|
||||||
if (*group == ':' && def_group_plugin)
|
if (*group == ':' && def_group_plugin) {
|
||||||
return(group_plugin_query(user, group + 1, pw));
|
matched = group_plugin_query(user, group + 1, pw);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* look up user's primary gid in the passwd file */
|
/* look up user's primary gid in the passwd file */
|
||||||
if (pw == NULL && (pw = sudo_getpwnam(user)) == NULL)
|
if (pw == NULL) {
|
||||||
return(FALSE);
|
if ((pw0 = sudo_getpwnam(user)) == NULL)
|
||||||
|
goto done;
|
||||||
|
pw = pw0;
|
||||||
|
}
|
||||||
|
|
||||||
if (user_in_group(pw, group))
|
if (user_in_group(pw, group)) {
|
||||||
return(TRUE);
|
matched = TRUE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* not a Unix group, could be an external group */
|
/* not a Unix group, could be an external group */
|
||||||
if (def_group_plugin && group_plugin_query(user, group, pw))
|
if (def_group_plugin && group_plugin_query(user, group, pw)) {
|
||||||
return(TRUE);
|
matched = TRUE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
return(FALSE);
|
done:
|
||||||
|
if (pw0 != NULL)
|
||||||
|
pw_delref(pw0);
|
||||||
|
|
||||||
|
return(matched);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -66,7 +66,10 @@ static int cmp_grgid(const void *, const void *);
|
|||||||
|
|
||||||
#define cmp_grnam cmp_pwnam
|
#define cmp_grnam cmp_pwnam
|
||||||
|
|
||||||
|
#define ptr_to_item(p) ((struct cache_item *)((char *)(p) - sizeof(struct cache_item)))
|
||||||
|
|
||||||
struct cache_item {
|
struct cache_item {
|
||||||
|
unsigned int refcnt;
|
||||||
/* key */
|
/* key */
|
||||||
union {
|
union {
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
@@ -188,10 +191,40 @@ make_pwitem(const struct passwd *pw, const char *name)
|
|||||||
item->k.uid = pw->pw_uid;
|
item->k.uid = pw->pw_uid;
|
||||||
}
|
}
|
||||||
item->d.pw = newpw;
|
item->d.pw = newpw;
|
||||||
|
item->refcnt = 1;
|
||||||
|
|
||||||
return(item);
|
return(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pw_addref(struct passwd *pw)
|
||||||
|
{
|
||||||
|
ptr_to_item(pw)->refcnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pw_delref_item(void *v)
|
||||||
|
{
|
||||||
|
struct cache_item *item = v;
|
||||||
|
struct passwd *pw = item->d.pw;
|
||||||
|
|
||||||
|
if (--item->refcnt == 0) {
|
||||||
|
if (pw != NULL && pw->pw_passwd != NULL) {
|
||||||
|
zero_bytes(pw->pw_passwd, strlen(pw->pw_passwd));
|
||||||
|
if ((char *)pw->pw_passwd < (char *)pw ||
|
||||||
|
(char *)pw->pw_passwd > (char *)pw->pw_gecos)
|
||||||
|
efree(pw->pw_passwd); /* free if separate allocation */
|
||||||
|
}
|
||||||
|
efree(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pw_delref(struct passwd *pw)
|
||||||
|
{
|
||||||
|
pw_delref_item(ptr_to_item(pw));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a password entry by uid and allocate space for it.
|
* Get a password entry by uid and allocate space for it.
|
||||||
* Fills in pw_passwd from shadow file if necessary.
|
* Fills in pw_passwd from shadow file if necessary.
|
||||||
@@ -225,6 +258,7 @@ sudo_getpwuid(uid_t uid)
|
|||||||
uid, item->d.pw->pw_name);
|
uid, item->d.pw->pw_name);
|
||||||
} else {
|
} else {
|
||||||
item = emalloc(sizeof(*item));
|
item = emalloc(sizeof(*item));
|
||||||
|
item->refcnt = 1;
|
||||||
item->k.uid = uid;
|
item->k.uid = uid;
|
||||||
item->d.pw = NULL;
|
item->d.pw = NULL;
|
||||||
if (rbinsert(pwcache_byuid, item) != NULL)
|
if (rbinsert(pwcache_byuid, item) != NULL)
|
||||||
@@ -234,6 +268,7 @@ sudo_getpwuid(uid_t uid)
|
|||||||
aix_restoreauthdb();
|
aix_restoreauthdb();
|
||||||
#endif
|
#endif
|
||||||
done:
|
done:
|
||||||
|
item->refcnt++;
|
||||||
return(item->d.pw);
|
return(item->d.pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,6 +306,7 @@ sudo_getpwnam(const char *name)
|
|||||||
} else {
|
} else {
|
||||||
len = strlen(name) + 1;
|
len = strlen(name) + 1;
|
||||||
item = emalloc(sizeof(*item) + len);
|
item = emalloc(sizeof(*item) + len);
|
||||||
|
item->refcnt = 1;
|
||||||
item->k.name = (char *) item + sizeof(*item);
|
item->k.name = (char *) item + sizeof(*item);
|
||||||
memcpy(item->k.name, name, len);
|
memcpy(item->k.name, name, len);
|
||||||
item->d.pw = NULL;
|
item->d.pw = NULL;
|
||||||
@@ -281,6 +317,7 @@ sudo_getpwnam(const char *name)
|
|||||||
aix_restoreauthdb();
|
aix_restoreauthdb();
|
||||||
#endif
|
#endif
|
||||||
done:
|
done:
|
||||||
|
item->refcnt++;
|
||||||
return(item->d.pw);
|
return(item->d.pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,71 +355,28 @@ sudo_fakepwnam(const char *user, gid_t gid)
|
|||||||
pw->pw_shell = pw->pw_dir + 2;
|
pw->pw_shell = pw->pw_dir + 2;
|
||||||
memcpy(pw->pw_shell, _PATH_BSHELL, sizeof(_PATH_BSHELL));
|
memcpy(pw->pw_shell, _PATH_BSHELL, sizeof(_PATH_BSHELL));
|
||||||
|
|
||||||
|
item->refcnt = 1;
|
||||||
|
item->d.pw = pw;
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
/* Store by uid, overwriting cached version. */
|
/* Store by uid, overwriting cached version. */
|
||||||
item->k.uid = pw->pw_uid;
|
item->k.uid = pw->pw_uid;
|
||||||
item->d.pw = pw;
|
|
||||||
if ((node = rbinsert(pwcache_byuid, item)) != NULL) {
|
if ((node = rbinsert(pwcache_byuid, item)) != NULL) {
|
||||||
efree(node->data);
|
pw_delref_item(node->data);
|
||||||
node->data = item;
|
node->data = item;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Store by name, overwriting cached version. */
|
/* Store by name, overwriting cached version. */
|
||||||
item->k.name = pw->pw_name;
|
item->k.name = pw->pw_name;
|
||||||
item->d.pw = pw;
|
|
||||||
if ((node = rbinsert(pwcache_byname, item)) != NULL) {
|
if ((node = rbinsert(pwcache_byname, item)) != NULL) {
|
||||||
efree(node->data);
|
pw_delref_item(node->data);
|
||||||
node->data = item;
|
node->data = item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
item->refcnt++;
|
||||||
return(pw);
|
return(pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Take a gid in string form "#123" and return a faked up group struct.
|
|
||||||
*/
|
|
||||||
struct group *
|
|
||||||
sudo_fakegrnam(const char *group)
|
|
||||||
{
|
|
||||||
struct cache_item *item;
|
|
||||||
struct group *gr;
|
|
||||||
struct rbnode *node;
|
|
||||||
size_t len, namelen;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
namelen = strlen(group);
|
|
||||||
len = sizeof(*item) + sizeof(*gr) + namelen + 1;
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
|
||||||
item = emalloc(len);
|
|
||||||
zero_bytes(item, sizeof(*item) + sizeof(*gr));
|
|
||||||
gr = (struct group *) ((char *)item + sizeof(*item));
|
|
||||||
gr->gr_gid = (gid_t) atoi(group + 1);
|
|
||||||
gr->gr_name = (char *)gr + sizeof(struct group);
|
|
||||||
memcpy(gr->gr_name, group, namelen + 1);
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
/* Store by gid, overwriting cached version. */
|
|
||||||
item->k.gid = gr->gr_gid;
|
|
||||||
item->d.gr = gr;
|
|
||||||
if ((node = rbinsert(grcache_bygid, item)) != NULL) {
|
|
||||||
efree(node->data);
|
|
||||||
node->data = item;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Store by name, overwriting cached version. */
|
|
||||||
item->k.name = gr->gr_name;
|
|
||||||
item->d.gr = gr;
|
|
||||||
if ((node = rbinsert(grcache_byname, item)) != NULL) {
|
|
||||||
efree(node->data);
|
|
||||||
node->data = item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(gr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sudo_setpwent(void)
|
sudo_setpwent(void)
|
||||||
{
|
{
|
||||||
@@ -394,46 +388,25 @@ sudo_setpwent(void)
|
|||||||
pwcache_byname = rbcreate(cmp_pwnam);
|
pwcache_byname = rbcreate(cmp_pwnam);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PURIFY
|
|
||||||
static void pw_free(void *);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sudo_freepwcache(void)
|
sudo_freepwcache(void)
|
||||||
{
|
{
|
||||||
if (pwcache_byuid != NULL) {
|
if (pwcache_byuid != NULL) {
|
||||||
rbdestroy(pwcache_byuid, pw_free);
|
rbdestroy(pwcache_byuid, pw_delref_item);
|
||||||
pwcache_byuid = NULL;
|
pwcache_byuid = NULL;
|
||||||
}
|
}
|
||||||
if (pwcache_byname != NULL) {
|
if (pwcache_byname != NULL) {
|
||||||
rbdestroy(pwcache_byname, pw_free);
|
rbdestroy(pwcache_byname, pw_delref_item);
|
||||||
pwcache_byname = NULL;
|
pwcache_byname = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
pw_free(void *v)
|
|
||||||
{
|
|
||||||
struct cache_item *item = (struct cache_item *) v;
|
|
||||||
struct passwd *pw = item->d.pw;
|
|
||||||
|
|
||||||
if (pw != NULL && pw->pw_passwd != NULL) {
|
|
||||||
zero_bytes(pw->pw_passwd, strlen(pw->pw_passwd));
|
|
||||||
if ((char *)pw->pw_passwd < (char *)pw ||
|
|
||||||
(char *)pw->pw_passwd > (char *)pw->pw_gecos)
|
|
||||||
efree(pw->pw_passwd); /* free if separate allocation */
|
|
||||||
}
|
|
||||||
efree(item);
|
|
||||||
}
|
|
||||||
#endif /* PURIFY */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sudo_endpwent(void)
|
sudo_endpwent(void)
|
||||||
{
|
{
|
||||||
endpwent();
|
endpwent();
|
||||||
sudo_endspent();
|
sudo_endspent();
|
||||||
#ifdef PURIFY
|
sudo_freepwcache();
|
||||||
sudo_freepwcache(); /* XXX - use after free */
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -508,10 +481,32 @@ make_gritem(const struct group *gr, const char *name)
|
|||||||
item->k.gid = gr->gr_gid;
|
item->k.gid = gr->gr_gid;
|
||||||
}
|
}
|
||||||
item->d.gr = newgr;
|
item->d.gr = newgr;
|
||||||
|
item->refcnt = 1;
|
||||||
|
|
||||||
return(item);
|
return(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gr_addref(struct group *gr)
|
||||||
|
{
|
||||||
|
ptr_to_item(gr)->refcnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gr_delref_item(void *v)
|
||||||
|
{
|
||||||
|
struct cache_item *item = v;
|
||||||
|
|
||||||
|
if (--item->refcnt == 0)
|
||||||
|
efree(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gr_delref(struct group *gr)
|
||||||
|
{
|
||||||
|
gr_delref_item(ptr_to_item(gr));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a group entry by gid and allocate space for it.
|
* Get a group entry by gid and allocate space for it.
|
||||||
*/
|
*/
|
||||||
@@ -536,12 +531,14 @@ sudo_getgrgid(gid_t gid)
|
|||||||
gid, key.d.gr->gr_name);
|
gid, key.d.gr->gr_name);
|
||||||
} else {
|
} else {
|
||||||
item = emalloc(sizeof(*item));
|
item = emalloc(sizeof(*item));
|
||||||
|
item->refcnt = 1;
|
||||||
item->k.gid = gid;
|
item->k.gid = gid;
|
||||||
item->d.gr = NULL;
|
item->d.gr = NULL;
|
||||||
if (rbinsert(grcache_bygid, item) != NULL)
|
if (rbinsert(grcache_bygid, item) != NULL)
|
||||||
errorx(1, "unable to cache gid %lu, already exists, gid");
|
errorx(1, "unable to cache gid %lu, already exists, gid");
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
item->refcnt++;
|
||||||
return(item->d.gr);
|
return(item->d.gr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,6 +567,7 @@ sudo_getgrnam(const char *name)
|
|||||||
} else {
|
} else {
|
||||||
len = strlen(name) + 1;
|
len = strlen(name) + 1;
|
||||||
item = emalloc(sizeof(*item) + len);
|
item = emalloc(sizeof(*item) + len);
|
||||||
|
item->refcnt = 1;
|
||||||
item->k.name = (char *) item + sizeof(*item);
|
item->k.name = (char *) item + sizeof(*item);
|
||||||
memcpy(item->k.name, name, len);
|
memcpy(item->k.name, name, len);
|
||||||
item->d.gr = NULL;
|
item->d.gr = NULL;
|
||||||
@@ -577,9 +575,55 @@ sudo_getgrnam(const char *name)
|
|||||||
errorx(1, "unable to cache group %s, already exists", name);
|
errorx(1, "unable to cache group %s, already exists", name);
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
item->refcnt++;
|
||||||
return(item->d.gr);
|
return(item->d.gr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Take a gid in string form "#123" and return a faked up group struct.
|
||||||
|
*/
|
||||||
|
struct group *
|
||||||
|
sudo_fakegrnam(const char *group)
|
||||||
|
{
|
||||||
|
struct cache_item *item;
|
||||||
|
struct group *gr;
|
||||||
|
struct rbnode *node;
|
||||||
|
size_t len, namelen;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
namelen = strlen(group);
|
||||||
|
len = sizeof(*item) + sizeof(*gr) + namelen + 1;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
item = emalloc(len);
|
||||||
|
zero_bytes(item, sizeof(*item) + sizeof(*gr));
|
||||||
|
gr = (struct group *) ((char *)item + sizeof(*item));
|
||||||
|
gr->gr_gid = (gid_t) atoi(group + 1);
|
||||||
|
gr->gr_name = (char *)gr + sizeof(struct group);
|
||||||
|
memcpy(gr->gr_name, group, namelen + 1);
|
||||||
|
|
||||||
|
item->refcnt = 1;
|
||||||
|
item->d.gr = gr;
|
||||||
|
if (i == 0) {
|
||||||
|
/* Store by gid, overwriting cached version. */
|
||||||
|
item->k.gid = gr->gr_gid;
|
||||||
|
if ((node = rbinsert(grcache_bygid, item)) != NULL) {
|
||||||
|
gr_delref_item(node->data);
|
||||||
|
node->data = item;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Store by name, overwriting cached version. */
|
||||||
|
item->k.name = gr->gr_name;
|
||||||
|
if ((node = rbinsert(grcache_byname, item)) != NULL) {
|
||||||
|
gr_delref_item(node->data);
|
||||||
|
node->data = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item->refcnt++;
|
||||||
|
return(gr);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sudo_setgrent(void)
|
sudo_setgrent(void)
|
||||||
{
|
{
|
||||||
@@ -590,28 +634,24 @@ sudo_setgrent(void)
|
|||||||
grcache_byname = rbcreate(cmp_grnam);
|
grcache_byname = rbcreate(cmp_grnam);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PURIFY
|
|
||||||
void
|
void
|
||||||
sudo_freegrcache(void)
|
sudo_freegrcache(void)
|
||||||
{
|
{
|
||||||
if (grcache_bygid != NULL) {
|
if (grcache_bygid != NULL) {
|
||||||
rbdestroy(grcache_bygid, free);
|
rbdestroy(grcache_bygid, gr_delref_item);
|
||||||
grcache_bygid = NULL;
|
grcache_bygid = NULL;
|
||||||
}
|
}
|
||||||
if (grcache_byname != NULL) {
|
if (grcache_byname != NULL) {
|
||||||
rbdestroy(grcache_byname, NULL);
|
rbdestroy(grcache_byname, gr_delref_item);
|
||||||
grcache_byname = NULL;
|
grcache_byname = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* PURIFY */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sudo_endgrent(void)
|
sudo_endgrent(void)
|
||||||
{
|
{
|
||||||
endgrent();
|
endgrent();
|
||||||
#ifdef PURIFY
|
sudo_freegrcache();
|
||||||
sudo_freegrcache(); /* XXX - use after free */
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -625,6 +665,7 @@ user_in_group(struct passwd *pw, const char *group)
|
|||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
struct group *grp;
|
struct group *grp;
|
||||||
|
int retval = FALSE;
|
||||||
|
|
||||||
#ifdef HAVE_SETAUTHDB
|
#ifdef HAVE_SETAUTHDB
|
||||||
aix_setauthdb(pw->pw_name);
|
aix_setauthdb(pw->pw_name);
|
||||||
@@ -634,23 +675,29 @@ user_in_group(struct passwd *pw, const char *group)
|
|||||||
aix_restoreauthdb();
|
aix_restoreauthdb();
|
||||||
#endif
|
#endif
|
||||||
if (grp == NULL)
|
if (grp == NULL)
|
||||||
return(FALSE);
|
goto done;
|
||||||
|
|
||||||
/* check against user's primary (passwd file) gid */
|
/* check against user's primary (passwd file) gid */
|
||||||
if (grp->gr_gid == pw->pw_gid)
|
if (grp->gr_gid == pw->pw_gid) {
|
||||||
return(TRUE);
|
retval = TRUE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_MBR_CHECK_MEMBERSHIP
|
#ifdef HAVE_MBR_CHECK_MEMBERSHIP
|
||||||
/* If we are matching the invoking user use the stashed uuid. */
|
/* If we are matching the invoking user use the stashed uuid. */
|
||||||
if (strcmp(pw->pw_name, user_name) == 0) {
|
if (strcmp(pw->pw_name, user_name) == 0) {
|
||||||
if (mbr_gid_to_uuid(grp->gr_gid, gu) == 0 &&
|
if (mbr_gid_to_uuid(grp->gr_gid, gu) == 0 &&
|
||||||
mbr_check_membership(user_uuid, gu, &ismember) == 0 && ismember)
|
mbr_check_membership(user_uuid, gu, &ismember) == 0 && ismember) {
|
||||||
return(TRUE);
|
retval = TRUE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (mbr_uid_to_uuid(pw->pw_uid, uu) == 0 &&
|
if (mbr_uid_to_uuid(pw->pw_uid, uu) == 0 &&
|
||||||
mbr_gid_to_uuid(grp->gr_gid, gu) == 0 &&
|
mbr_gid_to_uuid(grp->gr_gid, gu) == 0 &&
|
||||||
mbr_check_membership(uu, gu, &ismember) == 0 && ismember)
|
mbr_check_membership(uu, gu, &ismember) == 0 && ismember) {
|
||||||
return(TRUE);
|
retval = TRUE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else /* HAVE_MBR_CHECK_MEMBERSHIP */
|
#else /* HAVE_MBR_CHECK_MEMBERSHIP */
|
||||||
# ifdef HAVE_GETGROUPS
|
# ifdef HAVE_GETGROUPS
|
||||||
@@ -661,20 +708,26 @@ user_in_group(struct passwd *pw, const char *group)
|
|||||||
if (user_ngroups >= 0 &&
|
if (user_ngroups >= 0 &&
|
||||||
strcmp(pw->pw_name, list_pw ? list_pw->pw_name : user_name) == 0) {
|
strcmp(pw->pw_name, list_pw ? list_pw->pw_name : user_name) == 0) {
|
||||||
for (i = 0; i < user_ngroups; i++) {
|
for (i = 0; i < user_ngroups; i++) {
|
||||||
if (grp->gr_gid == user_groups[i])
|
if (grp->gr_gid == user_groups[i]) {
|
||||||
return(TRUE);
|
retval = TRUE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
# endif /* HAVE_GETGROUPS */
|
# endif /* HAVE_GETGROUPS */
|
||||||
{
|
{
|
||||||
if (grp != NULL && grp->gr_mem != NULL) {
|
if (grp != NULL && grp->gr_mem != NULL) {
|
||||||
for (gr_mem = grp->gr_mem; *gr_mem; gr_mem++) {
|
for (gr_mem = grp->gr_mem; *gr_mem; gr_mem++) {
|
||||||
if (strcmp(*gr_mem, pw->pw_name) == 0)
|
if (strcmp(*gr_mem, pw->pw_name) == 0) {
|
||||||
return(TRUE);
|
retval = TRUE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* HAVE_MBR_CHECK_MEMBERSHIP */
|
#endif /* HAVE_MBR_CHECK_MEMBERSHIP */
|
||||||
|
|
||||||
return(FALSE);
|
done:
|
||||||
|
gr_delref(grp);
|
||||||
|
return(retval);
|
||||||
}
|
}
|
||||||
|
@@ -406,6 +406,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
|||||||
log_error(0, "timestamp owner (%s): No such user",
|
log_error(0, "timestamp owner (%s): No such user",
|
||||||
def_timestampowner);
|
def_timestampowner);
|
||||||
timestamp_uid = pw->pw_uid;
|
timestamp_uid = pw->pw_uid;
|
||||||
|
pw_delref(pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If given the -P option, set the "preserve_groups" flag. */
|
/* If given the -P option, set the "preserve_groups" flag. */
|
||||||
@@ -459,6 +460,8 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
|||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
||||||
if ((pw = sudo_getpwnam(prev_user)) != NULL) {
|
if ((pw = sudo_getpwnam(prev_user)) != NULL) {
|
||||||
|
if (sudo_user.pw != NULL)
|
||||||
|
pw_delref(sudo_user.pw);
|
||||||
sudo_user.pw = pw;
|
sudo_user.pw = pw;
|
||||||
#ifdef HAVE_MBR_CHECK_MEMBERSHIP
|
#ifdef HAVE_MBR_CHECK_MEMBERSHIP
|
||||||
mbr_uid_to_uuid(user_uid, user_uuid);
|
mbr_uid_to_uuid(user_uid, user_uuid);
|
||||||
@@ -1066,12 +1069,14 @@ set_fqdn(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get passwd entry for the user we are going to run commands as.
|
* Get passwd entry for the user we are going to run commands as
|
||||||
* By default, this is "root". Updates runas_pw as a side effect.
|
* and store it in runas_pw. By default, commands run as "root".
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
set_runaspw(char *user)
|
set_runaspw(char *user)
|
||||||
{
|
{
|
||||||
|
if (runas_pw != NULL)
|
||||||
|
pw_delref(runas_pw);
|
||||||
if (*user == '#') {
|
if (*user == '#') {
|
||||||
if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
|
if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
|
||||||
runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0);
|
runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0);
|
||||||
@@ -1084,12 +1089,14 @@ set_runaspw(char *user)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get group entry for the group we are going to run commands as.
|
* Get group entry for the group we are going to run commands as
|
||||||
* Updates runas_pw as a side effect.
|
* and store it in runas_gr.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
set_runasgr(char *group)
|
set_runasgr(char *group)
|
||||||
{
|
{
|
||||||
|
if (runas_gr != NULL)
|
||||||
|
gr_delref(runas_gr);
|
||||||
if (*group == '#') {
|
if (*group == '#') {
|
||||||
if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL)
|
if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL)
|
||||||
runas_gr = sudo_fakegrnam(group);
|
runas_gr = sudo_fakegrnam(group);
|
||||||
@@ -1119,9 +1126,12 @@ get_authpw(void)
|
|||||||
if (runas_pw->pw_name == NULL)
|
if (runas_pw->pw_name == NULL)
|
||||||
log_error(NO_MAIL|MSG_ONLY, "unknown uid: %lu",
|
log_error(NO_MAIL|MSG_ONLY, "unknown uid: %lu",
|
||||||
(unsigned long) runas_pw->pw_uid);
|
(unsigned long) runas_pw->pw_uid);
|
||||||
|
pw_addref(runas_pw);
|
||||||
pw = runas_pw;
|
pw = runas_pw;
|
||||||
} else
|
} else {
|
||||||
|
pw_addref(sudo_user.pw);
|
||||||
pw = sudo_user.pw;
|
pw = sudo_user.pw;
|
||||||
|
}
|
||||||
|
|
||||||
return(pw);
|
return(pw);
|
||||||
}
|
}
|
||||||
|
@@ -270,6 +270,10 @@ struct passwd *sudo_getpwuid(uid_t);
|
|||||||
struct group *sudo_getgrnam(const char *);
|
struct group *sudo_getgrnam(const char *);
|
||||||
struct group *sudo_fakegrnam(const char *);
|
struct group *sudo_fakegrnam(const char *);
|
||||||
struct group *sudo_getgrgid(gid_t);
|
struct group *sudo_getgrgid(gid_t);
|
||||||
|
void gr_addref(struct group *);
|
||||||
|
void gr_delref(struct group *);
|
||||||
|
void pw_addref(struct passwd *);
|
||||||
|
void pw_delref(struct passwd *);
|
||||||
int user_in_group(struct passwd *, const char *);
|
int user_in_group(struct passwd *, const char *);
|
||||||
|
|
||||||
/* timestr.c */
|
/* timestr.c */
|
||||||
|
Reference in New Issue
Block a user