Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/rainbow/nss/nss-rainbow.c
diff options
context:
space:
mode:
Diffstat (limited to 'rainbow/nss/nss-rainbow.c')
-rw-r--r--rainbow/nss/nss-rainbow.c176
1 files changed, 102 insertions, 74 deletions
diff --git a/rainbow/nss/nss-rainbow.c b/rainbow/nss/nss-rainbow.c
index de6be89..1f69ac3 100644
--- a/rainbow/nss/nss-rainbow.c
+++ b/rainbow/nss/nss-rainbow.c
@@ -20,7 +20,7 @@
#include "buf.h"
#include "nat.h"
-#include "list.h"
+#include "slist.h"
/* constants */
#include "config/shell.h"
@@ -62,6 +62,16 @@ out_error_spool:
return NSS_STATUS_UNAVAIL;
}
+int check_gid_in_range(gid_t gid)
+{
+ TST(gid < 10000 || gid > 60000, errno = ENOENT,
+ "Gid outside [10000, 60000].", out_error);
+ return 0;
+out_error:
+ return 1;
+}
+
+
int
read_gid_for_uid(unsigned long uid, unsigned long* gid) {
char gid_path[NAME_MAX+1];
@@ -191,19 +201,33 @@ out_error_name:
return NSS_STATUS_NOTFOUND;
}
-struct member_list {
- struct list_head list;
+struct member_row {
+ struct slist list;
char* name;
};
-
-struct gid_list {
- struct list_head list;
- struct member_list members;
+struct gid_row {
+ struct slist list;
+ struct member_row *members;
gid_t gid;
};
-struct gid_list g_gids;
-struct gid_list* g_gid;
+struct gid_row* g_gids;
+struct gid_row* g_cur_gid;
+
+void member_row_init(struct member_row* self) {
+ self->name = NULL;
+ slist_init(&self->list);
+}
+
+void gid_row_init(struct gid_row* self) {
+ slist_init(&self->list);
+ self->members = NULL;
+ self->gid = -1;
+}
+
+void gid_row_add_member(struct gid_row* self, struct member_row* mr) {
+ slist_extend(&self->members->list, &mr->list);
+}
int members_scanner(const struct dirent* d) {
size_t member_len = strlen(d->d_name);
@@ -214,17 +238,22 @@ int members_scanner(const struct dirent* d) {
|| (member_len == 2 && d->d_name[0] == '.' && d->d_name[1] == '.'),
"Invalid data-gid-to-member member path.", exit);
- /* g_gid now points to the appropriate gid_list node.
+ /* g_cur_gid now points to the appropriate gid_row node.
* There's no way that we could already have our current (uid, gid) row.
* I think. :)
* Therefore, we'll immediately insert it. */
- struct member_list* member_iter;
- LET(member_iter = calloc(1, sizeof(struct member_list)), !member_iter,
- "Unable to allocate new member_list node.", exit);
- LET(member_iter->name = malloc(member_len+1), !member_iter->name,
- "Unable to allocate new member_list->name.", exit);
- strncpy(member_iter->name, member_str, member_len+1);
- list_add_tail(&(member_iter->list), &(g_gid->members.list));
+ struct member_row* mr;
+
+ LET(mr = calloc(1, sizeof(struct member_row)), !mr,
+ "Unable to allocate new member_row node.", exit);
+ member_row_init(mr);
+
+ LET(mr->name = malloc(member_len+1), !mr->name,
+ "Unable to allocate new member_row->name.", exit);
+ strncpy(mr->name, member_str, member_len+1);
+
+ gid_row_add_member(g_cur_gid, mr);
+
exit:
return 0;
}
@@ -236,6 +265,8 @@ gid_to_members_scanner(const struct dirent* d) {
char path[NAME_MAX+1];
size_t path_len = NAME_MAX + 1;
char* path_str = path;
+ struct gid_row* gr;
+
CHK(path_len == 0
|| (path_len == 1 && d->d_name[0] == '.')
@@ -250,27 +281,28 @@ gid_to_members_scanner(const struct dirent* d) {
CHK(format_buf(&path_str, &path_len, SPOOL "/gid_to_members/%d", gid) == 1,
"Unable to calculate data-gid-to-members path.", exit);
- /* We might have already allocated a gid_list for our gid.
+ /* We might have already allocated a gid_row for our gid.
* Therefore, search for it. */
- struct gid_list* gid_iter = NULL;
- list_for_each_entry(gid_iter, &g_gids.list, list) {
- if (gid_iter->gid == gid) {
- g_gid = gid_iter;
- break;
- }
+ bool find_gid(struct gid_row* iter) {
+ if (iter->gid == gid) { g_cur_gid = iter; return 0; } else return 1;
}
+ slist_search(struct gid_row, list, g_gids, found, not_found, &find_gid);
- /* If we find no gid_list, make one and insert it. */
- if (&gid_iter->list == &g_gids.list) {
- LET(gid_iter = malloc(sizeof(struct gid_list)), !gid_iter,
- "Unable to allocate new gid_list node.", exit);
- gid_iter->gid = gid;
- INIT_LIST_HEAD(&(gid_iter->members.list));
- list_add_tail(&(gid_iter->list), &g_gids.list);
- g_gid = gid_iter;
- }
+not_found:
+ LET(gr = calloc(1, sizeof(struct gid_row)), !gr,
+ "Unable to allocate new gid_row node.", exit);
+ gid_row_init(gr);
+ gr->gid = gid;
+
+ LET(gr->members = calloc(1, sizeof(struct member_row)), !gr->members,
+ "Unable to allocate new gid_row->members node.", exit);
+ member_row_init(gr->members);
+
+ slist_extend(&g_gids->list, &gr->list);
+ g_cur_gid = gr;
- /* g_gid now points to an appropriate gid_list for us to fill in. */
+found:
+ /* g_cur_gid now points to an appropriate gid_row for us to fill in. */
CHK(scandir(path, &ents, members_scanner, versionsort) == -1,
"Unable to scan members dir from $RAINBOW_SPOOL/gid_to_members/$GID.", exit);
exit:
@@ -279,31 +311,29 @@ exit:
enum nss_status _nss_rainbow_setgrent(void) {
struct dirent** ents;
- INIT_LIST_HEAD(&g_gids.list);
- INIT_LIST_HEAD(&g_gids.members.list);
- g_gid = &g_gids;
+ LET(g_gids = calloc(1, sizeof(struct gid_row)), !g_gids,
+ "Unable to allocate new g_gids node.", out_error);
+ gid_row_init(g_gids);
CHK(scandir(SPOOL "/gid_to_members", &ents, gid_to_members_scanner, versionsort) == -1,
"Unable to extract gid->members dirs from $RAINBOW_SPOOL.", out_error);
- g_gid = list_entry(g_gids.list.next, struct gid_list, list);
+
+ g_cur_gid = container_of(g_gids->list.next, struct gid_row, list);
return NSS_STATUS_SUCCESS;
out_error:
return NSS_STATUS_UNAVAIL;
}
enum nss_status _nss_rainbow_endgrent(void) {
- struct gid_list* gid_iter;
- struct member_list* member_iter;
- while(!list_empty(&g_gids.list)) {
- gid_iter = list_entry(g_gids.list.next, struct gid_list, list);
- while(!list_empty(&(gid_iter->members.list))) {
- member_iter = list_entry(gid_iter->members.list.next, struct member_list, list);
- list_del(&(member_iter->list));
+ void free_gid(struct gid_row* gid_iter) {
+ void free_member(struct member_row* member_iter) {
free(member_iter->name);
free(member_iter);
}
- list_del(&(gid_iter->list));
+ slist_for(struct member_row, list, gid_iter->members, &free_member);
free(gid_iter);
}
+ slist_for(struct gid_row, list, g_gids, &free_gid);
+
return NSS_STATUS_SUCCESS;
}
/*
@@ -315,9 +345,19 @@ struct group
char **gr_mem;
};
*/
+int fill_member(struct member_row* member_iter, struct group* result, char** buf, size_t* buflen, size_t* member_count) {
+ result->gr_mem[*member_count] = *buf;
+ CHK(format_buf(buf, buflen, "%s", member_iter->name) == 1,
+ "Unable to write a group member.", out_error);
+ *member_count += 1;
+
+ return 0;
+out_error:
+ return 1;
+}
int
-fill_group(struct group* result, char* buf, size_t buflen, struct gid_list* gid_iter) {
+fill_group(struct group* result, char* buf, size_t buflen, struct gid_row* gid_iter) {
result->gr_gid = gid_iter->gid;
result->gr_name = result->gr_passwd = buf;
@@ -325,12 +365,9 @@ fill_group(struct group* result, char* buf, size_t buflen, struct gid_list* gid_
"Unable to calculate group name.", out_error);
/* count the number of members */
- struct member_list* member_iter;
- struct list_head* member_node_iter;
size_t member_count = 0;
- list_for_each(member_node_iter, &(gid_iter->members.list)) {
- member_count++;
- }
+ void count_member(struct member_row* iter) { member_count++; }
+ slist_for(struct member_row, list, gid_iter->members, &count_member);
/* reserve space for the member-pointers */
size_t member_size = (member_count+1)* sizeof(char*);
@@ -343,12 +380,8 @@ fill_group(struct group* result, char* buf, size_t buflen, struct gid_list* gid_
/* fill in the members and swing the pointers */
member_count = 0;
- list_for_each_entry(member_iter, &(gid_iter->members.list), list) {
- result->gr_mem[member_count] = buf;
- CHK(format_buf(&buf, &buflen, "%s", member_iter->name) == 1,
- "Unable to write a group member.", out_error);
- member_count++;
- }
+ slist_while(struct member_row, list, gid_iter->members, out_error,
+ &fill_member, result, &buf, &buflen, &member_count);
return 0;
@@ -358,12 +391,12 @@ out_error:
enum nss_status
_nss_rainbow_getgrent_r(struct group *result, char *buf, size_t buflen, int *errnop) {
- if (&g_gid->list == &g_gids.list)
+ if (&g_cur_gid->list == &g_gids->list)
return NSS_STATUS_NOTFOUND;
- CHK(fill_group(result, buf, buflen, g_gid) == 1,
+ CHK(fill_group(result, buf, buflen, g_cur_gid) == 1,
"Unable to fill in group struct.", out_error_errno);
- g_gid = list_entry(g_gid->list.next, struct gid_list, list);
+ g_cur_gid = container_of(g_cur_gid->list.next, struct gid_row, list);
return NSS_STATUS_SUCCESS;
@@ -372,15 +405,6 @@ out_error_errno:
return NSS_STATUS_TRYAGAIN;
}
-int check_gid_in_range(gid_t gid)
-{
- TST(gid < 10000 || gid > 60000, errno = ENOENT,
- "Gid outside [10000, 60000].", out_error);
- return 0;
-out_error:
- return 1;
-}
-
enum nss_status
_nss_rainbow_getgrgid_r(gid_t gid, struct group *result, char *buf, size_t buflen, int *errnop) {
/* Getting errno and the return code exactly right is a pain.
@@ -402,12 +426,16 @@ _nss_rainbow_getgrgid_r(gid_t gid, struct group *result, char *buf, size_t bufle
"Gid outside [10000, 60000].", out_error);
/* look up group data */
- struct gid_list* gid_iter = NULL;
- list_for_each_entry(gid_iter, &g_gids.list, list) {
- if (gid_iter->gid == gid) break;
+ struct gid_row* gid_iter = NULL;
+ bool find_gid(struct gid_row* iter, struct gid_row** result) {
+ if (iter->gid == gid) { *result = iter; return 0; } else return 1;
}
- TST(&gid_iter->list == &g_gids.list, ret = NSS_STATUS_NOTFOUND,
+ slist_search(struct gid_row, list, g_gids, resume, resume,
+ &find_gid, &gid_iter);
+resume:
+
+ TST(&gid_iter->list == NULL, ret = NSS_STATUS_NOTFOUND,
"Gid not found.", out_dealloc);
CHK(fill_group(result, buf, buflen, gid_iter) == 1,