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 File File;
|
||||||
typedef struct Find Find;
|
typedef struct Find Find;
|
||||||
typedef struct Tree Tree;
|
typedef struct Tree Tree;
|
||||||
|
typedef struct Idmap Idmap;
|
||||||
|
|
||||||
|
#pragma incomplete Idmap
|
||||||
|
|
||||||
struct Rop
|
struct Rop
|
||||||
{
|
{
|
||||||
|
@ -96,6 +99,9 @@ struct Share
|
||||||
vlong freesize;
|
vlong freesize;
|
||||||
int sectorsize;
|
int sectorsize;
|
||||||
int blocksize;
|
int blocksize;
|
||||||
|
|
||||||
|
Idmap *users;
|
||||||
|
Idmap *groups;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Tree
|
struct Tree
|
||||||
|
|
|
@ -83,3 +83,9 @@ void putfind(Find *f);
|
||||||
int xdirread(char **path, int (*namecmp)(char *, char *), Dir **d);
|
int xdirread(char **path, int (*namecmp)(char *, char *), Dir **d);
|
||||||
Dir *xdirstat(char **path, int (*namecmp)(char *, char *));
|
Dir *xdirstat(char **path, int (*namecmp)(char *, char *));
|
||||||
void xdirflush(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
|
HFILES=dat.h fns.h
|
||||||
|
|
||||||
OFILES=\
|
OFILES=\
|
||||||
|
idmap.$O \
|
||||||
pack.$O \
|
pack.$O \
|
||||||
util.$O \
|
util.$O \
|
||||||
error.$O \
|
error.$O \
|
||||||
|
|
|
@ -114,6 +114,8 @@ mapshare(char *path)
|
||||||
s->allocsize = 0;
|
s->allocsize = 0;
|
||||||
s->freesize = s->blocksize;
|
s->freesize = s->blocksize;
|
||||||
|
|
||||||
|
unixidmap(s);
|
||||||
|
|
||||||
s->next = shares;
|
s->next = shares;
|
||||||
shares = s;
|
shares = s;
|
||||||
|
|
||||||
|
|
|
@ -1019,16 +1019,6 @@ smbqueryinformationdisk(Req *r, uchar *h, uchar *p, uchar *e)
|
||||||
r->respond(r, 0);
|
r->respond(r, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
unixuid(char *)
|
|
||||||
{
|
|
||||||
return 99999;
|
|
||||||
}
|
|
||||||
static int
|
|
||||||
unixgid(char *)
|
|
||||||
{
|
|
||||||
return 99999;
|
|
||||||
}
|
|
||||||
static int
|
static int
|
||||||
unixtype(Dir *d)
|
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,
|
0, i,
|
||||||
dlen, alen,
|
dlen, alen,
|
||||||
mtime, atime, mtime,
|
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 */
|
0LL, 0LL, /* MAJ/MIN */
|
||||||
(vlong)d->qid.path,
|
(vlong)d->qid.path,
|
||||||
(vlong)d->mode & 0777,
|
(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",
|
return pack(b, p, e, "vvvvvvvlvvvvv",
|
||||||
dlen, alen,
|
dlen, alen,
|
||||||
mtime, atime, mtime,
|
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 */
|
0LL, 0LL, /* MAJ/MIN */
|
||||||
(vlong)d->qid.path,
|
(vlong)d->qid.path,
|
||||||
(vlong)d->mode & 0777,
|
(vlong)d->mode & 0777,
|
||||||
|
@ -1229,10 +1219,10 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
int attr, adt, atm, mdt, mtm, delete;
|
||||||
vlong len, ctime, atime, mtime, mode;
|
vlong len, ctime, atime, mtime, mode, uid, gid;
|
||||||
Dir nd;
|
Dir nd;
|
||||||
|
|
||||||
nulldir(&nd);
|
nulldir(&nd);
|
||||||
|
@ -1283,8 +1273,8 @@ setfilepathinformation(Req *r, Dir *d, File *f, char *path, int level, uchar *b,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0200: /* SMB_SET_FILE_UNIX_BASIC */
|
case 0x0200: /* SMB_SET_FILE_UNIX_BASIC */
|
||||||
if(!unpack(b, p, e, "v________vvv____________________________________________v________",
|
if(!unpack(b, p, e, "v________vvvvv____________________________v________",
|
||||||
&len, &ctime, &atime, &mtime, &mode))
|
&len, &ctime, &atime, &mtime, &uid, &gid, &mode))
|
||||||
goto unsup;
|
goto unsup;
|
||||||
if(len != -1LL)
|
if(len != -1LL)
|
||||||
nd.length = len;
|
nd.length = len;
|
||||||
|
@ -1294,6 +1284,14 @@ setfilepathinformation(Req *r, Dir *d, File *f, char *path, int level, uchar *b,
|
||||||
nd.mtime = fromfiletime(mtime);
|
nd.mtime = fromfiletime(mtime);
|
||||||
else if(ctime && ctime != -1LL)
|
else if(ctime && ctime != -1LL)
|
||||||
nd.mtime = fromfiletime(ctime);
|
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)
|
if(mode != -1LL)
|
||||||
nd.mode = (d->mode & ~0777) | (mode & 0777);
|
nd.mode = (d->mode & ~0777) | (mode & 0777);
|
||||||
break;
|
break;
|
||||||
|
@ -1305,8 +1303,8 @@ setfilepathinformation(Req *r, Dir *d, File *f, char *path, int level, uchar *b,
|
||||||
return STATUS_NOT_SUPPORTED;
|
return STATUS_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if(debug)
|
if(debug)
|
||||||
fprint(2, "wstat\nmode %lo\natime %ld\nmtime %ld\nlength %llux\n",
|
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.mode, nd.atime, nd.mtime, nd.length, nd.uid, nd.gid);
|
||||||
if(((f && f->fd >= 0) ? dirfwstat(f->fd, &nd) : dirwstat(path, &nd)) < 0)
|
if(((f && f->fd >= 0) ? dirfwstat(f->fd, &nd) : dirwstat(path, &nd)) < 0)
|
||||||
return smbmkerror();
|
return smbmkerror();
|
||||||
xdirflush(path, r->namecmp);
|
xdirflush(path, r->namecmp);
|
||||||
|
@ -1334,7 +1332,7 @@ trans2setpathinformation(Trans *t)
|
||||||
t->respond(t, smbmkerror());
|
t->respond(t, smbmkerror());
|
||||||
goto out;
|
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:
|
errout:
|
||||||
t->respond(t, err);
|
t->respond(t, err);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1367,7 +1365,7 @@ trans2setfileinformation(Trans *t)
|
||||||
t->respond(t, smbmkerror());
|
t->respond(t, smbmkerror());
|
||||||
goto out;
|
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:
|
errout:
|
||||||
t->respond(t, err);
|
t->respond(t, err);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
Loading…
Reference in New Issue