launcher/nss: allow UIDs/GIDs to be provided directly instead of user/group names
If a user/group name can be parsed as an UID/GID, use that directly rather
than trying to resolve it via nss. A number that is an invalid UID/GID still
falls through to resolution via nss.
@@ -64,6 +64,8 @@ static int nss_cache_node_compare(CRBTree *t, void *k, CRBNode *rb) {
int nss_cache_get_uid(NSSCache *cache, uid_t *uidp, const char *user) {
NSSCacheNode *node;
CRBNode **slot, *parent;
+ char *end;
+ unsigned long long int uid;
int r;
if (!strcmp(user, "root")) {
@@ -71,6 +73,14 @@ int nss_cache_get_uid(NSSCache *cache, uid_t *uidp, const char *user) {
return 0;
}
+ static_assert(sizeof(uid_t) == sizeof(uint32_t), "uid_t is not 32 bits");
+ errno = 0;
+ uid = strtoull(user, &end, 10);
+ if (end != user && *end == '\0' && errno == 0 && uid < UINT32_MAX) {
+ *uidp = uid;
+ return 0;
+ }
+
slot = c_rbtree_find_slot(&cache->user_tree, nss_cache_node_compare, user, &parent);
if (!slot) {
node = c_rbnode_entry(parent, NSSCacheNode, rb);
@@ -96,6 +106,8 @@ int nss_cache_get_uid(NSSCache *cache, uid_t *uidp, const char *user) {
int nss_cache_get_gid(NSSCache *cache, gid_t *gidp, const char *group) {
NSSCacheNode *node;
CRBNode **slot, *parent;
+ char *end;
+ unsigned long long int gid;
int r;
if (!strcmp(group, "root")) {
@@ -103,6 +115,14 @@ int nss_cache_get_gid(NSSCache *cache, gid_t *gidp, const char *group) {
return 0;
}
+ static_assert(sizeof(gid_t) == sizeof(uint32_t), "gid_t is not 32 bits");
+ errno = 0;
+ gid = strtoull(group, &end, 10);
+ if (end != group && *end == '\0' && errno == 0 && gid < UINT32_MAX) {
+ *gidp = gid;
+ return 0;
+ }
+
slot = c_rbtree_find_slot(&cache->group_tree, nss_cache_node_compare, group, &parent);
if (!slot) {
node = c_rbnode_entry(parent, NSSCacheNode, rb);
