/* * Copyright (c) 2013, Coraid, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Coraid nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL CORAID BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include <9p.h> #include "dat.h" #define MAXFIELDS 100 typedef struct Filebuf Filebuf; typedef struct P9user P9user; typedef struct Unixgroup Unixgroup; typedef struct Unixsys Unixsys; typedef struct Unixuser Unixuser; struct Filebuf { char *buf; char **lines; int nlines; }; struct P9user { char *id; char *name; char *leader; char **members; int nmembers; }; struct Unixgroup { char *name; int id; char **members; int nmembers; }; struct Unixsys { char *name; int nusers, ngroups; Unixuser *users; Unixgroup *groups; Unixsys *next; }; struct Unixuser { char *name; int id; }; static P9user *p9users; static int np9users; static Unixsys *unixhd; void dumpusers(int fd) { P9user *u; Unixsys *us; int i, j; fprint(fd, "/adm/users:\n"); for(u = p9users, i = 0; i < np9users; ++u, ++i) { fprint(fd, " id:%s name:%s leader:%s nmembers:%d\n ", u->id, u->name, u->leader, u->nmembers); for(j = 0; j < u->nmembers; ++j) fprint(fd, "%s ", u->members[j]); fprint(fd, "\n"); } fprint(fd, "/adm/nfs:\n"); for(us = unixhd; us; us = us->next) { fprint(fd, " name=%s nusers=%d ngroup=%d\n", us->name, us->nusers, us->ngroups); fprint(fd, " users: "); for(i = 0; i < us->nusers; ++i) fprint(fd, "%s:%d, ", us->users[i].name, us->users[i].id); fprint(fd, "\n groups: "); for(i = 0; i < us->ngroups; ++i) fprint(fd, "%s:%d, ", us->groups[i].name, us->groups[i].id); fprint(fd, "\n"); } } static Filebuf * loadfile(char *name) { Filebuf *fb; char *p; uvlong len; uvlong qpath, meta; long n; qpath = p2q(-1, name, 0); if(qpath == 0) return nil; meta = q2m(-1, qpath, 0); if(meta == 0) return nil; if(getmetaint(-1, meta, "length", &len) == MTnone) return nil; fb = θmalloc(sizeof(Filebuf)); fb->buf = θmalloc(len+1); n = θpread(-1, qpath, fb->buf, len, 0); if(n < len) { free(fb->buf); free(fb); return nil; } fb->buf[len] = 0; for(p = fb->buf; p < fb->buf + n; ++p) if(*p == '\n') ++fb->nlines; fb->lines = θmalloc(fb->nlines * sizeof(char *)); gettokens(fb->buf, fb->lines, fb->nlines, "\n"); return fb; } static void freefile(Filebuf *fb) { free(fb->buf); free(fb->lines); free(fb); } static void loadusers(void) { Filebuf *fb; char *flds[MAXFIELDS]; int i, j, n; np9users = 0; fb = loadfile("//adm/users"); if(fb == nil) return; if(p9users) free(p9users); p9users = θmalloc(fb->nlines * sizeof(P9user)); for(i = 0; i < fb->nlines; ++i) { if(fb->lines[i][0] == '#') continue; n = getfields(fb->lines[i], flds, MAXFIELDS, 0, ":,"); if(n < 3) continue; if(n == 3 || flds[3] == nil || flds[3][0] == 0) p9users[np9users].nmembers = 0; else p9users[np9users].nmembers = n - 3; p9users[np9users].id = estrdup9p(flds[0]); p9users[np9users].name = estrdup9p(flds[1]); if(flds[2] && flds[2][0] != '\0') p9users[np9users].leader = estrdup9p(flds[2]); else p9users[np9users].leader = estrdup9p(flds[1]); p9users[np9users].members = θmalloc((n - 3) * sizeof(char *)); for(j = 3; j < n; ++j) p9users[np9users].members[j-3] = estrdup9p(flds[j]); ++np9users; } freefile(fb); } static Unixsys * buildsys(char *toks[3]) { Filebuf *ufb, *gfb; Unixsys *us; char *flds[MAXFIELDS]; int i, j, k, n; ufb = loadfile(toks[1]); if(ufb == nil) return nil; gfb = loadfile(toks[2]); if(gfb == nil) { freefile(ufb); return nil; } us = θmalloc(sizeof(Unixsys)); us->name = estrdup9p(toks[0]); us->nusers = ufb->nlines; us->users = θmalloc(us->nusers *sizeof(Unixuser)); us->ngroups = gfb->nlines; us->groups = θmalloc(us->ngroups *sizeof(Unixgroup)); for(i = 0, k = 0; i < us->nusers; ++i) { if(ufb->lines[i][0] == '#') continue; n = getfields(ufb->lines[i], flds, MAXFIELDS, 0, ":"); if(n < 3) continue; us->users[k].name = estrdup9p(flds[0]); if(us->users[k].name == nil) continue; us->users[k].id = atoi(flds[2]); ++k; } us->nusers = k; for(i = 0, k = 0; i < us->ngroups; ++i) { if(gfb->lines[i][0] == '#') continue; n = getfields(gfb->lines[i], flds, MAXFIELDS, 0, ":,"); if(n < 3) continue; us->groups[k].name = estrdup9p(flds[0]); if(us->groups[k].name == nil) continue; us->groups[k].id = atoi(flds[2]); us->groups[k].nmembers = n - 3; us->groups[k].members = θmalloc(us->groups[k].nmembers * sizeof(char *)); for(j = 0; j < us->groups[k].nmembers; ++j) us->groups[k].members[j] = estrdup9p(flds[j+3]); ++k; } us->ngroups = k; freefile(ufb); freefile(gfb); return us; } void inituid(void) { Filebuf *fb; Unixsys *us; char *toks[3]; int i, j; loadusers(); // dumpusers(); fb = loadfile("//adm/nfs"); if(fb != nil) { while(unixhd) { us = unixhd; unixhd = unixhd->next; free(us->name); for(i = 0; i < us->nusers; ++i) free(us->users[i].name); free(us->users); for(i = 0; i < us->ngroups; ++i) { free(us->groups[i].name); for(j = 0; j < us->groups[i].nmembers; ++j) free(us->groups[i].members[j]); free(us->groups[i].members); } free(us->groups); free(us); } for(i = 0; i < fb->nlines; ++i) { tokenize(fb->lines[i], toks, 3); us = buildsys(toks); if(us) { us->next = unixhd; unixhd = us; } } freefile(fb); } } int ingroup(char *user, char *group) { int i, j; if(strcmp(user, group) == 0) return 1; for(i = 0; i < np9users && strcmp(group, p9users[i].name); ++i) ; if(i >= np9users) return 0; for(j = 0; j < p9users[i].nmembers && strcmp(user, p9users[i].members[j]); ++j) ; if(j >= p9users[i].nmembers) return 0; return 1; } int isleader(char *user, char *group) { int i; for(i = 0; i < np9users && strcmp(group, p9users[i].name); ++i) ; if(i >= np9users) return 0; if(p9users[i].leader == nil) return 0; if(strcmp(user, p9users[i].leader) == 0) return 1; return 0; } char * id2uname(char *sys, int id) { Unixsys *s; int i; if(debugnfs) fprint(2, "In id2uname sys=%s, id=%d\n", sys, id); for(s = unixhd; s && strcmp(s->name, sys) != 0; s = s->next) ; if(s == nil) return nil; for(i = 0; i < s->nusers && s->users[i].id != id; ++i) ; if(i >= s->nusers) return nil; return s->users[i].name; } int uname2id(char *sys, char *uname) { Unixsys *s; int i; if(debugnfs) fprint(2, "in uname2id: sys=%s uname=%s\n", sys, uname); for(s = unixhd; s && strcmp(s->name, sys) != 0; s = s->next) ; if(s == nil) return -2; if(uname) { for(i = 0; i < s->nusers && strcmp(s->users[i].name, uname) != 0; ++i) ; if(i < s->nusers) return s->users[i].id; } for(i = 0; i < s->nusers && strcmp(s->users[i].name, "nfsnobody") != 0; ++i) ; if(i < s->nusers) return s->users[i].id; for(i = 0; i < s->nusers && strcmp(s->users[i].name, "nobody") != 0; ++i) ; if(i < s->nusers) return s->users[i].id; return -2; } char * id2gname(char *sys, int id) { Unixsys *s; int i; for(s = unixhd; s && strcmp(s->name, sys) != 0; s = s->next) ; if(s == nil) return nil; for(i = 0; i < s->ngroups && s->groups[i].id != id; ++i) ; if(i >= s->ngroups) return nil; return s->groups[i].name; } int gname2id(char *sys, char *gname) { Unixsys *s; int i; if(debugnfs) fprint(2, "In gname2id: sys=%s gname=%s\n", sys, gname); for(s = unixhd; s && strcmp(s->name, sys) != 0; s = s->next) ; if(s == nil) return -2; if(gname) { for(i = 0; i < s->ngroups && strcmp(gname, s->groups[i].name) != 0; ++i) ; if(i < s->ngroups) return s->groups[i].id; } for(i = 0; i < s->ngroups && strcmp(s->groups[i].name, "nfsnobody") != 0; ++i) ; if(i < s->ngroups) return s->groups[i].id; for(i = 0; i < s->ngroups && strcmp(s->groups[i].name, "nobody") != 0; ++i) ; if(i < s->ngroups) return s->groups[i].id; return -2; }