/*
* 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 <u.h>
#include <libc.h>
#include <thread.h>
#include <fcall.h>
#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;
}
|