-/*
- * Dynamically allocate space for a struct item plus the key and data
- * elements. If name is non-NULL it is used as the key, else the
- * gid is the key. Fills in datum from struct group.
- */
-static struct cache_item *
-make_gritem(const struct group *gr, const char *name)
-{
- char *cp;
- size_t nsize, psize, nmem, total, len;
- struct cache_item_gr *gritem;
- struct group *newgr;
- debug_decl(make_gritem, SUDO_DEBUG_NSS)
-
- /* Allocate in one big chunk for easy freeing. */
- nsize = psize = nmem = 0;
- total = sizeof(*gritem);
- FIELD_SIZE(gr, gr_name, nsize);
- FIELD_SIZE(gr, gr_passwd, psize);
- if (gr->gr_mem) {
- for (nmem = 0; gr->gr_mem[nmem] != NULL; nmem++)
- total += strlen(gr->gr_mem[nmem]) + 1;
- nmem++;
- total += sizeof(char *) * nmem;
- }
- if (name != NULL)
- total += strlen(name) + 1;
-
- gritem = ecalloc(1, total);
-
- /*
- * Copy in group contents and make strings relative to space
- * at the end of the buffer. Note that gr_mem must come
- * immediately after struct group to guarantee proper alignment.
- */
- newgr = &gritem->gr;
- memcpy(newgr, gr, sizeof(*gr));
- cp = (char *)(gritem + 1);
- if (gr->gr_mem) {
- newgr->gr_mem = (char **)cp;
- cp += sizeof(char *) * nmem;
- for (nmem = 0; gr->gr_mem[nmem] != NULL; nmem++) {
- len = strlen(gr->gr_mem[nmem]) + 1;
- memcpy(cp, gr->gr_mem[nmem], len);
- newgr->gr_mem[nmem] = cp;
- cp += len;
- }
- newgr->gr_mem[nmem] = NULL;
- }
- FIELD_COPY(gr, newgr, gr_passwd, psize);
- FIELD_COPY(gr, newgr, gr_name, nsize);
-
- /* Set key and datum. */
- if (name != NULL) {
- memcpy(cp, name, strlen(name) + 1);
- gritem->cache.k.name = cp;
- } else {
- gritem->cache.k.gid = gr->gr_gid;
- }
- gritem->cache.d.gr = newgr;
- gritem->cache.refcnt = 1;
-
- debug_return_ptr(&gritem->cache);
-}
-
-#ifdef HAVE_UTMPX_H
-# define GROUPNAME_LEN (sizeof((struct utmpx *)0)->ut_user + 1)
-#else
-# ifdef HAVE_STRUCT_UTMP_UT_USER
-# define GROUPNAME_LEN (sizeof((struct utmp *)0)->ut_user + 1)
-# else
-# define GROUPNAME_LEN (sizeof((struct utmp *)0)->ut_name + 1)
-# endif
-#endif /* HAVE_UTMPX_H */
-
-/*
- * Dynamically allocate space for a struct item plus the key and data
- * elements. Fills in datum from the groups and gids arrays.
- */
-static struct cache_item *
-make_grlist_item(const char *user, GETGROUPS_T *gids, int ngids)
-{
- char *cp;
- size_t i, nsize, ngroups, total, len;
- struct cache_item_grlist *grlitem;
- struct group_list *grlist;
- struct group *grp;
- debug_decl(make_grlist_item, SUDO_DEBUG_NSS)
-
-#ifdef HAVE_SETAUTHDB
- aix_setauthdb((char *) user);
-#endif
-
- /* Allocate in one big chunk for easy freeing. */
- nsize = strlen(user) + 1;
- total = sizeof(*grlitem) + nsize;
- total += sizeof(char *) * ngids;
- total += sizeof(gid_t *) * ngids;
- total += GROUPNAME_LEN * ngids;
-
-again:
- grlitem = ecalloc(1, total);
-
- /*
- * Copy in group list and make pointers relative to space
- * at the end of the buffer. Note that the groups array must come
- * immediately after struct group to guarantee proper alignment.
- */
- grlist = &grlitem->grlist;
- cp = (char *)(grlitem + 1);
- grlist->groups = (char **)cp;
- cp += sizeof(char *) * ngids;
- grlist->gids = (gid_t *)cp;
- cp += sizeof(gid_t) * ngids;
-
- /* Set key and datum. */
- memcpy(cp, user, nsize);
- grlitem->cache.k.name = cp;
- grlitem->cache.d.grlist = grlist;
- grlitem->cache.refcnt = 1;
- cp += nsize;
-
- /*
- * Store group IDs.
- */
- for (i = 0; i < ngids; i++)
- grlist->gids[i] = gids[i];
- grlist->ngids = ngids;
-
- /*
- * Resolve and store group names by ID.
- */
- ngroups = 0;
- for (i = 0; i < ngids; i++) {
- if ((grp = sudo_getgrgid(gids[i])) != NULL) {
- len = strlen(grp->gr_name) + 1;
- if (cp - (char *)grlitem + len > total) {
- total += len + GROUPNAME_LEN;
- efree(grlitem);
- sudo_gr_delref(grp);
- goto again;
- }
- memcpy(cp, grp->gr_name, len);
- grlist->groups[ngroups++] = cp;
- cp += len;
- sudo_gr_delref(grp);
- }
- }
- grlist->ngroups = ngroups;
-
-#ifdef HAVE_SETAUTHDB
- aix_restoreauthdb();
-#endif
-
- debug_return_ptr(&grlitem->cache);
-}
-