ip/cifsd: implement primitive per-share unix id mapping for wstat()
parent
badbf50b0c
commit
d0c87bada6
|
@ -6,6 +6,9 @@ typedef struct Share Share;
|
|||
typedef struct File File;
|
||||
typedef struct Find Find;
|
||||
typedef struct Tree Tree;
|
||||
typedef struct Idmap Idmap;
|
||||
|
||||
#pragma incomplete Idmap
|
||||
|
||||
struct Rop
|
||||
{
|
||||
|
@ -96,6 +99,9 @@ struct Share
|
|||
vlong freesize;
|
||||
int sectorsize;
|
||||
int blocksize;
|
||||
|
||||
Idmap *users;
|
||||
Idmap *groups;
|
||||
};
|
||||
|
||||
struct Tree
|
||||
|
|
|
@ -83,3 +83,9 @@ void putfind(Find *f);
|
|||
int xdirread(char **path, int (*namecmp)(char *, char *), Dir **d);
|
||||
Dir *xdirstat(char **path, int (*namecmp)(char *, char *));
|
||||
void xdirflush(char *path, int (*namecmp)(char *, char *));
|
||||
|
||||
/* idmap */
|
||||
void unixidmap(Share *share);
|
||||
char* unixname(Share *share, int id, int group);
|
||||
int unixuid(Share *share, char *name);
|
||||
int unixgid(Share *share, char *name);
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
#include <bio.h>
|
||||
|
||||
enum {
|
||||
NHASH = 251,
|
||||
};
|
||||
|
||||
typedef struct Ident Ident;
|
||||
struct Ident
|
||||
{
|
||||
Ident *nextid;
|
||||
Ident *nextname;
|
||||
int id;
|
||||
char name[];
|
||||
};
|
||||
|
||||
struct Idmap
|
||||
{
|
||||
Ident *tab[NHASH];
|
||||
};
|
||||
|
||||
static Ident**
|
||||
nametab(Idmap *map, char *name)
|
||||
{
|
||||
return &map->tab[(uint)namehash(name) % NHASH];
|
||||
}
|
||||
static Ident**
|
||||
idtab(Idmap *map, int id)
|
||||
{
|
||||
return &map->tab[(uint)id % NHASH];
|
||||
}
|
||||
|
||||
static int
|
||||
name2id(Idmap *map, char *name)
|
||||
{
|
||||
Ident *e;
|
||||
|
||||
for(e = *nametab(map, name); e != nil; e = e->nextid){
|
||||
if(strcmp(e->name, name) == 0)
|
||||
return e->id;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char*
|
||||
id2name(Idmap *map, int id)
|
||||
{
|
||||
Ident *e;
|
||||
|
||||
for(e = *idtab(map, id); e != nil; e = e->nextname){
|
||||
if(e->id == id)
|
||||
return e->name;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
idmap(Idmap *map, char *name, int id)
|
||||
{
|
||||
Ident *e, **h;
|
||||
int n;
|
||||
|
||||
n = strlen(name)+1;
|
||||
e = malloc(sizeof(Ident)+n);
|
||||
if(e == nil)
|
||||
return;
|
||||
|
||||
e->id = id;
|
||||
h = idtab(map, e->id);
|
||||
e->nextid = *h;
|
||||
*h = e;
|
||||
|
||||
memmove(e->name, name, n);
|
||||
h = nametab(map, e->name);
|
||||
e->nextname = *h;
|
||||
*h = e;
|
||||
}
|
||||
|
||||
static Idmap*
|
||||
readidmap(char *file, int style)
|
||||
{
|
||||
Biobuf *b;
|
||||
Idmap *m;
|
||||
char *l, *name;
|
||||
int id;
|
||||
|
||||
if((b = Bopen(file, OREAD)) == nil)
|
||||
return nil;
|
||||
|
||||
if((m = mallocz(sizeof(*m), 1)) == nil)
|
||||
goto Out;
|
||||
|
||||
while((l = Brdline(b, '\n')) != nil){
|
||||
l[Blinelen(b)-1] = 0;
|
||||
switch(style){
|
||||
case '9':
|
||||
id = 9000000 + strtol(l, &l, 10);
|
||||
if(*l != ':')
|
||||
continue;
|
||||
name = ++l;
|
||||
l = strchr(l, ':');
|
||||
if(l == 0)
|
||||
continue;
|
||||
*l = 0;
|
||||
break;
|
||||
default:
|
||||
name = l;
|
||||
l = strchr(l, ':');
|
||||
if(l == 0)
|
||||
continue;
|
||||
*l++ = 0;
|
||||
/* skip password */
|
||||
l = strchr(l, ':');
|
||||
if(l == 0)
|
||||
continue;
|
||||
id = strtol(l+1, 0, 10);
|
||||
break;
|
||||
}
|
||||
idmap(m, name, id);
|
||||
}
|
||||
Out:
|
||||
Bterm(b);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
void
|
||||
unixidmap(Share *share)
|
||||
{
|
||||
static Idmap emptymap;
|
||||
char *file;
|
||||
|
||||
if(share->stype != STYPE_DISKTREE)
|
||||
goto Out;
|
||||
|
||||
file = smprint("%s/etc/passwd", share->root);
|
||||
share->users = readidmap(file, 'u');
|
||||
free(file);
|
||||
file = smprint("%s/etc/group", share->root);
|
||||
share->groups = readidmap(file, 'u');
|
||||
free(file);
|
||||
if(share->users != nil && share->groups != nil)
|
||||
return;
|
||||
|
||||
file = smprint("%s/adm/users", share->root);
|
||||
share->users = share->groups = readidmap(file, '9');
|
||||
free(file);
|
||||
if(share->users != nil && share->groups != nil)
|
||||
return;
|
||||
|
||||
Out:
|
||||
share->users = share->groups = &emptymap;
|
||||
}
|
||||
|
||||
char*
|
||||
unixname(Share *share, int id, int group)
|
||||
{
|
||||
return id2name(group? share->groups: share->users, id);
|
||||
}
|
||||
|
||||
int
|
||||
unixuid(Share *share, char *name)
|
||||
{
|
||||
return name2id(share->users, name);
|
||||
}
|
||||
|
||||
int
|
||||
unixgid(Share *share, char *name)
|
||||
{
|
||||
return name2id(share->groups, name);
|
||||
}
|
|
@ -6,6 +6,7 @@ TARG=cifsd
|
|||
HFILES=dat.h fns.h
|
||||
|
||||
OFILES=\
|
||||
idmap.$O \
|
||||
pack.$O \
|
||||
util.$O \
|
||||
error.$O \
|
||||
|
|
|
@ -114,6 +114,8 @@ mapshare(char *path)
|
|||
s->allocsize = 0;
|
||||
s->freesize = s->blocksize;
|
||||
|
||||
unixidmap(s);
|
||||
|
||||
s->next = shares;
|
||||
shares = s;
|
||||
|
||||
|
|
|
@ -1019,16 +1019,6 @@ smbqueryinformationdisk(Req *r, uchar *h, uchar *p, uchar *e)
|
|||
r->respond(r, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
unixuid(char *)
|
||||
{
|
||||
return 99999;
|
||||
}
|
||||
static int
|
||||
unixgid(char *)
|
||||
{
|
||||
return 99999;
|
||||
}
|
||||
static int
|
||||
unixtype(Dir *d)
|
||||
{
|
||||
|
@ -1081,7 +1071,7 @@ fpackdir(Req *r, Dir *d, Tree *t, int i, int level, uchar *b, uchar *p, uchar *e
|
|||
0, i,
|
||||
dlen, alen,
|
||||
mtime, atime, mtime,
|
||||
(vlong)unixuid(d->uid), (vlong)unixgid(d->gid), unixtype(d),
|
||||
(vlong)unixuid(share, d->uid), (vlong)unixgid(share, d->gid), unixtype(d),
|
||||
0LL, 0LL, /* MAJ/MIN */
|
||||
(vlong)d->qid.path,
|
||||
(vlong)d->mode & 0777,
|
||||
|
@ -1147,7 +1137,7 @@ qpackdir(Req *, Dir *d, Tree *t, File *f, int level, uchar *b, uchar *p, uchar *
|
|||
return pack(b, p, e, "vvvvvvvlvvvvv",
|
||||
dlen, alen,
|
||||
mtime, atime, mtime,
|
||||
(vlong)unixuid(d->uid), (vlong)unixgid(d->gid), unixtype(d),
|
||||
(vlong)unixuid(share, d->uid), (vlong)unixgid(share, d->gid), unixtype(d),
|
||||
0LL, 0LL, /* MAJ/MIN */
|
||||
(vlong)d->qid.path,
|
||||
(vlong)d->mode & 0777,
|
||||
|
@ -1229,10 +1219,10 @@ out:
|
|||
}
|
||||
|
||||
static int
|
||||
setfilepathinformation(Req *r, Dir *d, File *f, char *path, int level, uchar *b, uchar *p, uchar *e)
|
||||
setfilepathinformation(Req *r, Dir *d, Tree *t, File *f, char *path, int level, uchar *b, uchar *p, uchar *e)
|
||||
{
|
||||
int attr, adt, atm, mdt, mtm, delete;
|
||||
vlong len, ctime, atime, mtime, mode;
|
||||
vlong len, ctime, atime, mtime, mode, uid, gid;
|
||||
Dir nd;
|
||||
|
||||
nulldir(&nd);
|
||||
|
@ -1283,8 +1273,8 @@ setfilepathinformation(Req *r, Dir *d, File *f, char *path, int level, uchar *b,
|
|||
break;
|
||||
|
||||
case 0x0200: /* SMB_SET_FILE_UNIX_BASIC */
|
||||
if(!unpack(b, p, e, "v________vvv____________________________________________v________",
|
||||
&len, &ctime, &atime, &mtime, &mode))
|
||||
if(!unpack(b, p, e, "v________vvvvv____________________________v________",
|
||||
&len, &ctime, &atime, &mtime, &uid, &gid, &mode))
|
||||
goto unsup;
|
||||
if(len != -1LL)
|
||||
nd.length = len;
|
||||
|
@ -1294,6 +1284,14 @@ setfilepathinformation(Req *r, Dir *d, File *f, char *path, int level, uchar *b,
|
|||
nd.mtime = fromfiletime(mtime);
|
||||
else if(ctime && ctime != -1LL)
|
||||
nd.mtime = fromfiletime(ctime);
|
||||
if(uid != -1LL){
|
||||
if((nd.uid = unixname(t->share, (int)uid, 0)) == nil)
|
||||
return STATUS_SMB_BAD_UID;
|
||||
}
|
||||
if(gid != -1LL){
|
||||
if((nd.gid = unixname(t->share, (int)gid, 1)) == nil)
|
||||
return STATUS_SMB_BAD_UID;
|
||||
}
|
||||
if(mode != -1LL)
|
||||
nd.mode = (d->mode & ~0777) | (mode & 0777);
|
||||
break;
|
||||
|
@ -1305,8 +1303,8 @@ setfilepathinformation(Req *r, Dir *d, File *f, char *path, int level, uchar *b,
|
|||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
if(debug)
|
||||
fprint(2, "wstat\nmode %lo\natime %ld\nmtime %ld\nlength %llux\n",
|
||||
nd.mode, nd.atime, nd.mtime, nd.length);
|
||||
fprint(2, "wstat\nmode %lo\natime %ld\nmtime %ld\nlength %llux\nuid %s\ngid %s\n",
|
||||
nd.mode, nd.atime, nd.mtime, nd.length, nd.uid, nd.gid);
|
||||
if(((f && f->fd >= 0) ? dirfwstat(f->fd, &nd) : dirwstat(path, &nd)) < 0)
|
||||
return smbmkerror();
|
||||
xdirflush(path, r->namecmp);
|
||||
|
@ -1334,7 +1332,7 @@ trans2setpathinformation(Trans *t)
|
|||
t->respond(t, smbmkerror());
|
||||
goto out;
|
||||
}
|
||||
if(err = setfilepathinformation(t->r, d, nil, path, level, t->in.data.b, t->in.data.p, t->in.data.e)){
|
||||
if(err = setfilepathinformation(t->r, d, tree, nil, path, level, t->in.data.b, t->in.data.p, t->in.data.e)){
|
||||
errout:
|
||||
t->respond(t, err);
|
||||
goto out;
|
||||
|
@ -1367,7 +1365,7 @@ trans2setfileinformation(Trans *t)
|
|||
t->respond(t, smbmkerror());
|
||||
goto out;
|
||||
}
|
||||
if(err = setfilepathinformation(t->r, d, f, f->path, level, t->in.data.b, t->in.data.p, t->in.data.e)){
|
||||
if(err = setfilepathinformation(t->r, d, tree, f, f->path, level, t->in.data.b, t->in.data.p, t->in.data.e)){
|
||||
errout:
|
||||
t->respond(t, err);
|
||||
goto out;
|
||||
|
|
Loading…
Reference in New Issue