Example #1
0
/*
 * Take a user, uid and gid and return a faked up passwd struct.
 */
struct passwd *
sudo_fakepwnamid(const char *user, uid_t uid, gid_t gid)
{
    struct cache_item_pw *pwitem;
    struct passwd *pw;
    struct rbnode *node;
    size_t len, namelen;
    int i;
    debug_decl(sudo_fakepwnam, SUDO_DEBUG_NSS)

    namelen = strlen(user);
    len = sizeof(*pwitem) + namelen + 1 /* pw_name */ +
	sizeof("*") /* pw_passwd */ + sizeof("") /* pw_gecos */ +
	sizeof("/") /* pw_dir */ + sizeof(_PATH_BSHELL);

    for (i = 0; i < 2; i++) {
	pwitem = ecalloc(1, len);
	pw = &pwitem->pw;
	pw->pw_uid = uid;
	pw->pw_gid = gid;
	pw->pw_name = (char *)(pwitem + 1);
	memcpy(pw->pw_name, user, namelen + 1);
	pw->pw_passwd = pw->pw_name + namelen + 1;
	memcpy(pw->pw_passwd, "*", 2);
	pw->pw_gecos = pw->pw_passwd + 2;
	pw->pw_gecos[0] = '\0';
	pw->pw_dir = pw->pw_gecos + 1;
	memcpy(pw->pw_dir, "/", 2);
	pw->pw_shell = pw->pw_dir + 2;
	memcpy(pw->pw_shell, _PATH_BSHELL, sizeof(_PATH_BSHELL));

	pwitem->cache.refcnt = 1;
	pwitem->cache.d.pw = pw;
	if (i == 0) {
	    /* Store by uid, overwriting cached version. */
	    pwitem->cache.k.uid = pw->pw_uid;
	    if ((node = rbinsert(pwcache_byuid, &pwitem->cache)) != NULL) {
		sudo_pw_delref_item(node->data);
		node->data = &pwitem->cache;
	    }
	} else {
	    /* Store by name, overwriting cached version. */
	    pwitem->cache.k.name = pw->pw_name;
	    if ((node = rbinsert(pwcache_byname, &pwitem->cache)) != NULL) {
		sudo_pw_delref_item(node->data);
		node->data = &pwitem->cache;
	    }
	}
    }
    pwitem->cache.refcnt++;
    debug_return_ptr(pw);
}
Example #2
0
void
sudo_pw_delref(struct passwd *pw)
{
    debug_decl(sudo_pw_delref, SUDO_DEBUG_NSS)
    sudo_pw_delref_item(ptr_to_item(pw));
    debug_return;
}
Example #3
0
/*
 * Take a user, uid, gid, home and shell and return a faked up passwd struct.
 * If home or shell are NULL default values will be used.
 */
struct passwd *
sudo_mkpwent(const char *user, uid_t uid, gid_t gid, const char *home,
    const char *shell)
{
    struct cache_item_pw *pwitem;
    struct cache_item *item;
    struct passwd *pw;
    size_t len, name_len, home_len, shell_len;
    int i;
    debug_decl(sudo_mkpwent, SUDOERS_DEBUG_NSS)

    /* Optional arguments. */
    if (home == NULL)
	home = "/";
    if (shell == NULL)
	shell = _PATH_BSHELL;

    name_len = strlen(user);
    home_len = strlen(home);
    shell_len = strlen(shell);
    len = sizeof(*pwitem) + name_len + 1 /* pw_name */ +
	sizeof("*") /* pw_passwd */ + sizeof("") /* pw_gecos */ +
	home_len + 1 /* pw_dir */ + shell_len + 1 /* pw_shell */;

    for (i = 0; i < 2; i++) {
	struct rbtree *pwcache;
	struct rbnode *node;

	pwitem = sudo_ecalloc(1, len);
	pw = &pwitem->pw;
	pw->pw_uid = uid;
	pw->pw_gid = gid;
	pw->pw_name = (char *)(pwitem + 1);
	memcpy(pw->pw_name, user, name_len + 1);
	pw->pw_passwd = pw->pw_name + name_len + 1;
	memcpy(pw->pw_passwd, "*", 2);
	pw->pw_gecos = pw->pw_passwd + 2;
	pw->pw_gecos[0] = '\0';
	pw->pw_dir = pw->pw_gecos + 1;
	memcpy(pw->pw_dir, home, home_len + 1);
	pw->pw_shell = pw->pw_dir + home_len + 1;
	memcpy(pw->pw_shell, shell, shell_len + 1);

	item = &pwitem->cache;
	item->refcnt = 1;
	item->d.pw = pw;
	if (i == 0) {
	    /* Store by uid if it doesn't already exist. */
	    item->k.uid = pw->pw_uid;
	    pwcache = pwcache_byuid;
	} else {
	    /* Store by name if it doesn't already exist. */
	    item->k.name = pw->pw_name;
	    pwcache = pwcache_byname;
	}
	if ((node = rbinsert(pwcache, item)) != NULL) {
	    /* Already exists. */
	    item = node->data;
	    if (item->d.pw == NULL) {
		/* Negative cache entry, replace with ours. */
		sudo_pw_delref_item(item);
		item = node->data = &pwitem->cache;
	    } else {
		/* Good entry, discard our fake one. */
		sudo_efree(pwitem);
	    }
	}
    }
    item->refcnt++;
    debug_return_ptr(item->d.pw);
}