subids: support nsswitch
Closes #154 When starting any operation to do with subuid delegation, check nsswitch for a module to use. If none is specified, then use the traditional /etc/subuid and /etc/subgid files. Currently only one module is supported, and there is no fallback to the files on errors. Several possibilities could be considered: 1. in case of connection error, fall back to files 2. in case of unknown user, also fall back to files etc... When non-files nss module is used, functions to edit the range are not supported. It may make sense to support it, but it also may make sense to require another tool to be used. libsubordinateio also uses the nss_ helpers. This is how for instance lxc could easily be converted to supporting nsswitch. Add a set of test cases, including a dummy libsubid_zzz module. This hardcodes values such that: 'ubuntu' gets 200000 - 300000 'user1' gets 100000 - 165536 'error' emulates an nss module error 'unknown' emulates a user unknown to the nss module 'conn' emulates a connection error ot the nss module Changes to libsubid: Change the list_owner_ranges api: return a count instead of making the array null terminated. This is a breaking change, so bump the libsubid abi major number. Rename free_subuid_range and free_subgid_range to ungrant_subuid_range, because otherwise it's confusing with free_subid_ranges which frees memory. Run libsubid tests in jenkins Switch argument order in find_subid_owners Move the db locking into subordinateio.c Signed-off-by: Serge Hallyn <serge@hallyn.com>
This commit is contained in:
168
libsubid/api.c
168
libsubid/api.c
@ -38,132 +38,48 @@
|
||||
#include "idmapping.h"
|
||||
#include "api.h"
|
||||
|
||||
static struct subordinate_range **get_subid_ranges(const char *owner, enum subid_type id_type)
|
||||
static
|
||||
int get_subid_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges)
|
||||
{
|
||||
struct subordinate_range **ranges = NULL;
|
||||
|
||||
switch (id_type) {
|
||||
case ID_TYPE_UID:
|
||||
if (!sub_uid_open(O_RDONLY)) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case ID_TYPE_GID:
|
||||
if (!sub_gid_open(O_RDONLY)) {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ranges = list_owner_ranges(owner, id_type);
|
||||
|
||||
if (id_type == ID_TYPE_UID)
|
||||
sub_uid_close();
|
||||
else
|
||||
sub_gid_close();
|
||||
|
||||
return ranges;
|
||||
return list_owner_ranges(owner, id_type, ranges);
|
||||
}
|
||||
|
||||
struct subordinate_range **get_subuid_ranges(const char *owner)
|
||||
int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges)
|
||||
{
|
||||
return get_subid_ranges(owner, ID_TYPE_UID);
|
||||
return get_subid_ranges(owner, ID_TYPE_UID, ranges);
|
||||
}
|
||||
|
||||
struct subordinate_range **get_subgid_ranges(const char *owner)
|
||||
int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges)
|
||||
{
|
||||
return get_subid_ranges(owner, ID_TYPE_GID);
|
||||
return get_subid_ranges(owner, ID_TYPE_GID, ranges);
|
||||
}
|
||||
|
||||
void subid_free_ranges(struct subordinate_range **ranges)
|
||||
void subid_free_ranges(struct subordinate_range **ranges, int count)
|
||||
{
|
||||
return free_subordinate_ranges(ranges);
|
||||
return free_subordinate_ranges(ranges, count);
|
||||
}
|
||||
|
||||
int get_subid_owner(unsigned long id, uid_t **owner, enum subid_type id_type)
|
||||
static
|
||||
int get_subid_owner(unsigned long id, enum subid_type id_type, uid_t **owner)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
switch (id_type) {
|
||||
case ID_TYPE_UID:
|
||||
if (!sub_uid_open(O_RDONLY)) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case ID_TYPE_GID:
|
||||
if (!sub_gid_open(O_RDONLY)) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = find_subid_owners(id, owner, id_type);
|
||||
|
||||
if (id_type == ID_TYPE_UID)
|
||||
sub_uid_close();
|
||||
else
|
||||
sub_gid_close();
|
||||
|
||||
return ret;
|
||||
return find_subid_owners(id, id_type, owner);
|
||||
}
|
||||
|
||||
int get_subuid_owners(uid_t uid, uid_t **owner)
|
||||
{
|
||||
return get_subid_owner((unsigned long)uid, owner, ID_TYPE_UID);
|
||||
return get_subid_owner((unsigned long)uid, ID_TYPE_UID, owner);
|
||||
}
|
||||
|
||||
int get_subgid_owners(gid_t gid, uid_t **owner)
|
||||
{
|
||||
return get_subid_owner((unsigned long)gid, owner, ID_TYPE_GID);
|
||||
return get_subid_owner((unsigned long)gid, ID_TYPE_GID, owner);
|
||||
}
|
||||
|
||||
static
|
||||
bool grant_subid_range(struct subordinate_range *range, bool reuse,
|
||||
enum subid_type id_type)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
switch (id_type) {
|
||||
case ID_TYPE_UID:
|
||||
if (!sub_uid_lock()) {
|
||||
printf("Failed loging subuids (errno %d)\n", errno);
|
||||
return false;
|
||||
}
|
||||
if (!sub_uid_open(O_CREAT | O_RDWR)) {
|
||||
printf("Failed opening subuids (errno %d)\n", errno);
|
||||
sub_uid_unlock();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ID_TYPE_GID:
|
||||
if (!sub_gid_lock()) {
|
||||
printf("Failed loging subgids (errno %d)\n", errno);
|
||||
return false;
|
||||
}
|
||||
if (!sub_gid_open(O_CREAT | O_RDWR)) {
|
||||
printf("Failed opening subgids (errno %d)\n", errno);
|
||||
sub_gid_unlock();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = new_subid_range(range, id_type, reuse);
|
||||
|
||||
if (id_type == ID_TYPE_UID) {
|
||||
sub_uid_close();
|
||||
sub_uid_unlock();
|
||||
} else {
|
||||
sub_gid_close();
|
||||
sub_gid_unlock();
|
||||
}
|
||||
|
||||
return ret;
|
||||
return new_subid_range(range, id_type, reuse);
|
||||
}
|
||||
|
||||
bool grant_subuid_range(struct subordinate_range *range, bool reuse)
|
||||
@ -176,56 +92,18 @@ bool grant_subgid_range(struct subordinate_range *range, bool reuse)
|
||||
return grant_subid_range(range, reuse, ID_TYPE_GID);
|
||||
}
|
||||
|
||||
bool free_subid_range(struct subordinate_range *range, enum subid_type id_type)
|
||||
static
|
||||
bool ungrant_subid_range(struct subordinate_range *range, enum subid_type id_type)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
switch (id_type) {
|
||||
case ID_TYPE_UID:
|
||||
if (!sub_uid_lock()) {
|
||||
printf("Failed loging subuids (errno %d)\n", errno);
|
||||
return false;
|
||||
}
|
||||
if (!sub_uid_open(O_CREAT | O_RDWR)) {
|
||||
printf("Failed opening subuids (errno %d)\n", errno);
|
||||
sub_uid_unlock();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ID_TYPE_GID:
|
||||
if (!sub_gid_lock()) {
|
||||
printf("Failed loging subgids (errno %d)\n", errno);
|
||||
return false;
|
||||
}
|
||||
if (!sub_gid_open(O_CREAT | O_RDWR)) {
|
||||
printf("Failed opening subgids (errno %d)\n", errno);
|
||||
sub_gid_unlock();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = release_subid_range(range, id_type);
|
||||
|
||||
if (id_type == ID_TYPE_UID) {
|
||||
sub_uid_close();
|
||||
sub_uid_unlock();
|
||||
} else {
|
||||
sub_gid_close();
|
||||
sub_gid_unlock();
|
||||
}
|
||||
|
||||
return ret;
|
||||
return release_subid_range(range, id_type);
|
||||
}
|
||||
|
||||
bool free_subuid_range(struct subordinate_range *range)
|
||||
bool ungrant_subuid_range(struct subordinate_range *range)
|
||||
{
|
||||
return free_subid_range(range, ID_TYPE_UID);
|
||||
return ungrant_subid_range(range, ID_TYPE_UID);
|
||||
}
|
||||
|
||||
bool free_subgid_range(struct subordinate_range *range)
|
||||
bool ungrant_subgid_range(struct subordinate_range *range)
|
||||
{
|
||||
return free_subid_range(range, ID_TYPE_GID);
|
||||
return ungrant_subid_range(range, ID_TYPE_GID);
|
||||
}
|
||||
|
Reference in New Issue
Block a user