예제 #1
0
/*
 * range_exists: Check whether @owner owns any ranges
 *
 * @db: database to query
 * @owner: owner being queried
 *
 * Returns true if @owner owns any subuid ranges, false otherwise.
 */
static const bool range_exists(struct commonio_db *db, const char *owner)
{
	const struct subordinate_range *range;
	commonio_rewind(db);
	while ((range = commonio_next(db)) != NULL) {
		if (0 == strcmp(range->owner, owner))
			return true;
	}
	return false;
}
예제 #2
0
/*
 * find_free_range: find an unused consecutive sequence of ids to allocate
 *                  to a user.
 * @db: database to search
 * @min: the first uid in the range to find
 * @max: the highest uid to find
 * @count: the number of uids needed
 *
 * Return the lowest new uid, or ULONG_MAX on failure.
 */
static unsigned long find_free_range(struct commonio_db *db,
				     unsigned long min, unsigned long max,
				     unsigned long count)
{
	const struct subordinate_range *range;
	unsigned long low, high;

	/* When given invalid parameters fail */
	if ((count == 0) || (max < min))
		goto fail;

	/* Sort by range then by owner */
	commonio_sort (db, subordinate_range_cmp);
	commonio_rewind(db);

	low = min;
	while ((range = commonio_next(db)) != NULL) {
		unsigned long first = range->start;
		unsigned long last = first + range->count - 1;

		/* Find the top end of the hole before this range */
		high = first;

		/* Don't allocate IDs after max (included) */
		if (high > max + 1) {
			high = max + 1;
		}

		/* Is the hole before this range large enough? */
		if ((high > low) && ((high - low) >= count))
			return low;

		/* Compute the low end of the next hole */
		if (low < (last + 1))
			low = last + 1;
		if (low > max)
			goto fail;
	}

	/* Is the remaining unclaimed area large enough? */
	if (((max - low) + 1) >= count)
		return low;
fail:
	return ULONG_MAX;
}
예제 #3
0
int
spw_rewind(void)
{
	return commonio_rewind(&shadow_db);
}
예제 #4
0
int gr_rewind (void)
{
	return commonio_rewind (&group_db);
}
예제 #5
0
/*
 * find_range: find a range which @owner is authorized to use which includes
 *             subuid @val.
 *
 * @db: database to query
 * @owner: owning uid being queried
 * @val: subuid being searched for.
 *
 * Returns a range of subuids belonging to @owner and including the subuid
 * @val, or NULL if no such range exists.
 */
static const struct subordinate_range *find_range(struct commonio_db *db,
						  const char *owner, unsigned long val)
{
	const struct subordinate_range *range;

	/*
	 * Search for exact username/group specification
	 *
	 * This is the original method - go fast through the db, doing only
	 * exact username/group string comparison. Therefore we leave it as-is
	 * for the time being, in order to keep it equally fast as it was
	 * before.
	 */
	commonio_rewind(db);
	while ((range = commonio_next(db)) != NULL) {
		unsigned long first = range->start;
		unsigned long last = first + range->count - 1;

		if (0 != strcmp(range->owner, owner))
			continue;

		if ((val >= first) && (val <= last))
			return range;
	}


        /*
         * We only do special handling for these two files
         */
        if ((0 != strcmp(db->filename, "/etc/subuid")) && (0 != strcmp(db->filename, "/etc/subgid")))
                return NULL;

        /*
         * Search loop above did not produce any result. Let's rerun it,
         * but this time try to match actual UIDs. The first entry that
         * matches is considered a success.
         * (It may be specified as literal UID or as another username which
         * has the same UID as the username we are looking for.)
         */
        struct passwd *pwd;
        uid_t          owner_uid;
        char           owner_uid_string[33] = "";


        /* Get UID of the username we are looking for */
        pwd = getpwnam(owner);
        if (NULL == pwd) {
                /* Username not defined in /etc/passwd, or error occured during lookup */
                return NULL;
        }
        owner_uid = pwd->pw_uid;
        sprintf(owner_uid_string, "%lu", (unsigned long int)owner_uid);

        commonio_rewind(db);
        while ((range = commonio_next(db)) != NULL) {
                unsigned long first = range->start;
                unsigned long last = first + range->count - 1;

                /* For performance reasons check range before using getpwnam() */
                if ((val < first) || (val > last)) {
                        continue;
                }

                /*
                 * Range matches. Check if range owner is specified
                 * as numeric UID and if it matches.
                 */
                if (0 == strcmp(range->owner, owner_uid_string)) {
                        return range;
                }

                /*
                 * Ok, this range owner is not specified as numeric UID
                 * we are looking for. It may be specified as another
                 * UID or as a literal username.
                 *
                 * If specified as another UID, the call to getpwnam()
                 * will return NULL.
                 *
                 * If specified as literal username, we will get its
                 * UID and compare that to UID we are looking for.
                 */
                const struct passwd *range_owner_pwd;

                range_owner_pwd = getpwnam(range->owner);
                if (NULL == range_owner_pwd) {
                        continue;
                }

                if (owner_uid == range_owner_pwd->pw_uid) {
                        return range;
                }
        }

	return NULL;
}
예제 #6
0
파일: pwio.c 프로젝트: DavidChenLiang/study
int pw_rewind (void)
{
	return commonio_rewind (&passwd_db);
}
예제 #7
0
파일: sgroupio.c 프로젝트: OPSF/uClinux
int sgr_rewind (void)
{
	return commonio_rewind (&gshadow_db);
}