cwfs: add optional uid argument to allow command, unify permission override code
the allow command now takes an optional uid argument for the user to be granted temporary god status on the fileserver for maintenance. this was kenji okomotos idea, so thanks :) remove wstatallow and writeallow flags. instead, we have global: int allowed; that contains the uid of the currently allowed user id or -1 if permission checking is globally disabled for the fileserver. when zero, normal permission checking takes place. added int isallowed(File*) function that returns non-zero when the context is the console, or the allowed user. this is also used internally by iaccess(), so all the extra code of in the callers of iaccess() is gone now. dont conflate allowed user with noauth flag and auto-allow on ream. the installer already knows about noauth and allow flags so theres no problem with bootstraping.
This commit is contained in:
parent
30d4d8984b
commit
427e925eea
8 changed files with 101 additions and 99 deletions
|
@ -9,6 +9,7 @@ fs, exsort \- file server maintenance
|
||||||
]
|
]
|
||||||
.PP
|
.PP
|
||||||
.B allow
|
.B allow
|
||||||
|
.RI [ uid ]
|
||||||
.PP
|
.PP
|
||||||
.B arp
|
.B arp
|
||||||
.I subcommand
|
.I subcommand
|
||||||
|
@ -158,7 +159,10 @@ incorrect or incomplete parameters.
|
||||||
.PP
|
.PP
|
||||||
.I Allow
|
.I Allow
|
||||||
disables permission checking and allows
|
disables permission checking and allows
|
||||||
.BR wstat .
|
.BR wstat
|
||||||
|
for the specified
|
||||||
|
.I uid
|
||||||
|
or for any user if omited.
|
||||||
This may help in initializing a file system.
|
This may help in initializing a file system.
|
||||||
Use this with caution.
|
Use this with caution.
|
||||||
.PP
|
.PP
|
||||||
|
|
|
@ -57,7 +57,7 @@ f_session(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
memmove(aip->rchal, in->chal, sizeof(aip->rchal));
|
memmove(aip->rchal, in->chal, sizeof(aip->rchal));
|
||||||
mkchallenge(aip);
|
mkchallenge(aip);
|
||||||
memmove(ou->chal, aip->chal, sizeof(ou->chal));
|
memmove(ou->chal, aip->chal, sizeof(ou->chal));
|
||||||
if(noauth || wstatallow)
|
if(noauth)
|
||||||
memset(ou->authid, 0, sizeof(ou->authid));
|
memset(ou->authid, 0, sizeof(ou->authid));
|
||||||
else
|
else
|
||||||
memmove(ou->authid, nvr.authid, sizeof(ou->authid));
|
memmove(ou->authid, nvr.authid, sizeof(ou->authid));
|
||||||
|
@ -78,7 +78,7 @@ authorize(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
ulong bit;
|
ulong bit;
|
||||||
Authinfo *aip;
|
Authinfo *aip;
|
||||||
|
|
||||||
if(noauth || wstatallow) /* set to allow entry during boot */
|
if(noauth)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if(strcmp(in->uname, "none") == 0)
|
if(strcmp(in->uname, "none") == 0)
|
||||||
|
@ -370,7 +370,7 @@ f_walk(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
}
|
}
|
||||||
if(ou->err = mkqidcmp(&f->qid, d))
|
if(ou->err = mkqidcmp(&f->qid, d))
|
||||||
goto out;
|
goto out;
|
||||||
if(cp != cons.chan && iaccess(f, d, DEXEC)) {
|
if(iaccess(f, d, DEXEC)) {
|
||||||
ou->err = Eaccess;
|
ou->err = Eaccess;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -469,7 +469,7 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
File *f;
|
File *f;
|
||||||
Tlock *t;
|
Tlock *t;
|
||||||
Qid qid;
|
Qid qid;
|
||||||
int ro, fmod, wok;
|
int ro, fmod;
|
||||||
|
|
||||||
if(CHAT(cp)) {
|
if(CHAT(cp)) {
|
||||||
fprint(2, "c_open %d\n", cp->chan);
|
fprint(2, "c_open %d\n", cp->chan);
|
||||||
|
@ -477,10 +477,6 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
fprint(2, "\tmode = %o\n", in->mode);
|
fprint(2, "\tmode = %o\n", in->mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
wok = 0;
|
|
||||||
if(cp == cons.chan || writeallow)
|
|
||||||
wok = 1;
|
|
||||||
|
|
||||||
p = 0;
|
p = 0;
|
||||||
f = filep(cp, in->fid, 0);
|
f = filep(cp, in->fid, 0);
|
||||||
if(!f) {
|
if(!f) {
|
||||||
|
@ -528,14 +524,13 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
switch(in->mode & 7) {
|
switch(in->mode & 7) {
|
||||||
|
|
||||||
case OREAD:
|
case OREAD:
|
||||||
if(iaccess(f, d, DREAD) && !wok)
|
if(iaccess(f, d, DREAD))
|
||||||
goto badaccess;
|
goto badaccess;
|
||||||
fmod = FREAD;
|
fmod = FREAD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OWRITE:
|
case OWRITE:
|
||||||
if((d->mode & DDIR) ||
|
if((d->mode & DDIR) || iaccess(f, d, DWRITE))
|
||||||
(iaccess(f, d, DWRITE) && !wok))
|
|
||||||
goto badaccess;
|
goto badaccess;
|
||||||
if(ro) {
|
if(ro) {
|
||||||
ou->err = Eronly;
|
ou->err = Eronly;
|
||||||
|
@ -545,9 +540,7 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ORDWR:
|
case ORDWR:
|
||||||
if((d->mode & DDIR) ||
|
if((d->mode & DDIR) || iaccess(f, d, DREAD) || iaccess(f, d, DWRITE))
|
||||||
(iaccess(f, d, DREAD) && !wok) ||
|
|
||||||
(iaccess(f, d, DWRITE) && !wok))
|
|
||||||
goto badaccess;
|
goto badaccess;
|
||||||
if(ro) {
|
if(ro) {
|
||||||
ou->err = Eronly;
|
ou->err = Eronly;
|
||||||
|
@ -557,8 +550,7 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OEXEC:
|
case OEXEC:
|
||||||
if((d->mode & DDIR) ||
|
if((d->mode & DDIR) || iaccess(f, d, DEXEC))
|
||||||
(iaccess(f, d, DEXEC) && !wok))
|
|
||||||
goto badaccess;
|
goto badaccess;
|
||||||
fmod = FREAD;
|
fmod = FREAD;
|
||||||
break;
|
break;
|
||||||
|
@ -568,8 +560,7 @@ f_open(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if(in->mode & OTRUNC) {
|
if(in->mode & OTRUNC) {
|
||||||
if((d->mode & DDIR) ||
|
if((d->mode & DDIR) || iaccess(f, d, DWRITE))
|
||||||
(iaccess(f, d, DWRITE) && !wok))
|
|
||||||
goto badaccess;
|
goto badaccess;
|
||||||
if(ro) {
|
if(ro) {
|
||||||
ou->err = Eronly;
|
ou->err = Eronly;
|
||||||
|
@ -617,7 +608,7 @@ f_create(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
Iobuf *p, *p1;
|
Iobuf *p, *p1;
|
||||||
Dentry *d, *d1;
|
Dentry *d, *d1;
|
||||||
File *f;
|
File *f;
|
||||||
int slot, slot1, fmod, wok;
|
int slot, slot1, fmod;
|
||||||
Off addr, addr1, path;
|
Off addr, addr1, path;
|
||||||
Qid qid;
|
Qid qid;
|
||||||
Tlock *t;
|
Tlock *t;
|
||||||
|
@ -632,10 +623,6 @@ f_create(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
fprint(2, "\tmode = %o\n", in->mode);
|
fprint(2, "\tmode = %o\n", in->mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
wok = 0;
|
|
||||||
if(cp == cons.chan || writeallow)
|
|
||||||
wok = 1;
|
|
||||||
|
|
||||||
p = 0;
|
p = 0;
|
||||||
f = filep(cp, in->fid, 0);
|
f = filep(cp, in->fid, 0);
|
||||||
if(!f) {
|
if(!f) {
|
||||||
|
@ -659,7 +646,7 @@ f_create(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
ou->err = Edir2;
|
ou->err = Edir2;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if(iaccess(f, d, DWRITE) && !wok) {
|
if(iaccess(f, d, DWRITE)) {
|
||||||
ou->err = Eaccess;
|
ou->err = Eaccess;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1118,7 +1105,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
doremove(File *f, int wok)
|
doremove(File *f)
|
||||||
{
|
{
|
||||||
Iobuf *p, *p1;
|
Iobuf *p, *p1;
|
||||||
Dentry *d, *d1;
|
Dentry *d, *d1;
|
||||||
|
@ -1144,7 +1131,7 @@ doremove(File *f, int wok)
|
||||||
err = Ephase;
|
err = Ephase;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if(iaccess(f, d1, DWRITE) && !wok) {
|
if(iaccess(f, d1, DWRITE)) {
|
||||||
err = Eaccess;
|
err = Eaccess;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1202,7 +1189,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
doclunk(File* f, int remove, int wok)
|
doclunk(File* f, int remove)
|
||||||
{
|
{
|
||||||
Tlock *t;
|
Tlock *t;
|
||||||
int err;
|
int err;
|
||||||
|
@ -1214,7 +1201,7 @@ doclunk(File* f, int remove, int wok)
|
||||||
f->tlock = 0;
|
f->tlock = 0;
|
||||||
}
|
}
|
||||||
if(remove)
|
if(remove)
|
||||||
err = doremove(f, wok);
|
err = doremove(f);
|
||||||
f->open = 0;
|
f->open = 0;
|
||||||
freewp(f->wpath);
|
freewp(f->wpath);
|
||||||
freefp(f);
|
freefp(f);
|
||||||
|
@ -1236,7 +1223,7 @@ f_clunk(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
if(!f)
|
if(!f)
|
||||||
ou->err = Efid;
|
ou->err = Efid;
|
||||||
else {
|
else {
|
||||||
doclunk(f, f->open & FREMOV, 0);
|
doclunk(f, f->open & FREMOV);
|
||||||
qunlock(f);
|
qunlock(f);
|
||||||
}
|
}
|
||||||
ou->fid = in->fid;
|
ou->fid = in->fid;
|
||||||
|
@ -1256,7 +1243,7 @@ f_remove(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
if(!f)
|
if(!f)
|
||||||
ou->err = Efid;
|
ou->err = Efid;
|
||||||
else {
|
else {
|
||||||
ou->err = doclunk(f, 1, cp==cons.chan);
|
ou->err = doclunk(f, 1);
|
||||||
qunlock(f);
|
qunlock(f);
|
||||||
}
|
}
|
||||||
ou->fid = in->fid;
|
ou->fid = in->fid;
|
||||||
|
@ -1371,7 +1358,7 @@ f_wstat(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
* if chown,
|
* if chown,
|
||||||
* must be god
|
* must be god
|
||||||
*/
|
*/
|
||||||
if(xd.uid != d->uid && !wstatallow) { /* set to allow chown during boot */
|
if(xd.uid != d->uid && !isallowed(f)) {
|
||||||
ou->err = Ewstatu;
|
ou->err = Ewstatu;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1382,10 +1369,9 @@ f_wstat(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
* a) owner and in new group
|
* a) owner and in new group
|
||||||
* b) leader of both groups
|
* b) leader of both groups
|
||||||
*/
|
*/
|
||||||
if (xd.gid != d->gid &&
|
if (xd.gid != d->gid && !isallowed(f) &&
|
||||||
(!wstatallow && !writeallow && /* set to allow chgrp during boot */
|
|
||||||
(d->uid != f->uid || !ingroup(f->uid, xd.gid)) &&
|
(d->uid != f->uid || !ingroup(f->uid, xd.gid)) &&
|
||||||
(!leadgroup(f->uid, xd.gid) || !leadgroup(f->uid, d->gid)))) {
|
(!leadgroup(f->uid, xd.gid) || !leadgroup(f->uid, d->gid))) {
|
||||||
ou->err = Ewstatg;
|
ou->err = Ewstatg;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1439,8 +1425,7 @@ f_wstat(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wstatallow && !writeallow && /* set to allow rename during boot */
|
if(iaccess(f, d1, DWRITE)) {
|
||||||
(!d1 || iaccess(f, d1, DWRITE))) {
|
|
||||||
ou->err = Eaccess;
|
ou->err = Eaccess;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1453,8 +1438,7 @@ f_wstat(Chan *cp, Fcall *in, Fcall *ou)
|
||||||
*/
|
*/
|
||||||
if (d->mtime != xd.mtime ||
|
if (d->mtime != xd.mtime ||
|
||||||
((d->mode^xd.mode) & (DAPND|DLOCK|0777)))
|
((d->mode^xd.mode) & (DAPND|DLOCK|0777)))
|
||||||
if (!wstatallow && /* set to allow chmod during boot */
|
if (d->uid != f->uid && !isallowed(f) &&
|
||||||
d->uid != f->uid &&
|
|
||||||
!leadgroup(f->uid, xd.gid) &&
|
!leadgroup(f->uid, xd.gid) &&
|
||||||
!leadgroup(f->uid, d->gid)) {
|
!leadgroup(f->uid, d->gid)) {
|
||||||
ou->err = Ewstatu;
|
ou->err = Ewstatu;
|
||||||
|
|
|
@ -148,7 +148,7 @@ auth(Chan* chan, Fcall* f, Fcall* r)
|
||||||
Filsys *fs;
|
Filsys *fs;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if(noauth || wstatallow)
|
if(noauth)
|
||||||
return Eauthdisabled;
|
return Eauthdisabled;
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
|
@ -201,7 +201,7 @@ authorize(Chan* chan, Fcall* f)
|
||||||
|
|
||||||
db = cons.flags & authdebugflag;
|
db = cons.flags & authdebugflag;
|
||||||
|
|
||||||
if(noauth || wstatallow){
|
if(noauth){
|
||||||
uid = strtouid(f->uname);
|
uid = strtouid(f->uname);
|
||||||
if(db)
|
if(db)
|
||||||
fprint(2, "permission granted by noauth uid %s = %d\n",
|
fprint(2, "permission granted by noauth uid %s = %d\n",
|
||||||
|
@ -394,7 +394,7 @@ walkname(File* file, char* wname, Qid* wqid)
|
||||||
* For walked elements the implied user must
|
* For walked elements the implied user must
|
||||||
* have permission to search the directory.
|
* have permission to search the directory.
|
||||||
*/
|
*/
|
||||||
if(file->cp != cons.chan && iaccess(file, d, DEXEC)){
|
if(iaccess(file, d, DEXEC)){
|
||||||
error = Eaccess;
|
error = Eaccess;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -607,14 +607,9 @@ fs_open(Chan* chan, Fcall* f, Fcall* r)
|
||||||
File *file;
|
File *file;
|
||||||
Tlock *t;
|
Tlock *t;
|
||||||
Qid qid;
|
Qid qid;
|
||||||
int error, ro, fmod, wok;
|
int error, ro, fmod;
|
||||||
|
|
||||||
wok = 0;
|
|
||||||
p = nil;
|
p = nil;
|
||||||
|
|
||||||
if(chan == cons.chan || writeallow)
|
|
||||||
wok = 1;
|
|
||||||
|
|
||||||
if((file = filep(chan, f->fid, 0)) == nil){
|
if((file = filep(chan, f->fid, 0)) == nil){
|
||||||
error = Efid;
|
error = Efid;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -672,13 +667,13 @@ fs_open(Chan* chan, Fcall* f, Fcall* r)
|
||||||
switch(f->mode & 7){
|
switch(f->mode & 7){
|
||||||
|
|
||||||
case OREAD:
|
case OREAD:
|
||||||
if(iaccess(file, d, DREAD) && !wok)
|
if(iaccess(file, d, DREAD))
|
||||||
goto badaccess;
|
goto badaccess;
|
||||||
fmod = FREAD;
|
fmod = FREAD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OWRITE:
|
case OWRITE:
|
||||||
if((d->mode & DDIR) || (iaccess(file, d, DWRITE) && !wok))
|
if((d->mode & DDIR) || iaccess(file, d, DWRITE))
|
||||||
goto badaccess;
|
goto badaccess;
|
||||||
if(ro){
|
if(ro){
|
||||||
error = Eronly;
|
error = Eronly;
|
||||||
|
@ -689,8 +684,8 @@ fs_open(Chan* chan, Fcall* f, Fcall* r)
|
||||||
|
|
||||||
case ORDWR:
|
case ORDWR:
|
||||||
if((d->mode & DDIR)
|
if((d->mode & DDIR)
|
||||||
|| (iaccess(file, d, DREAD) && !wok)
|
|| iaccess(file, d, DREAD)
|
||||||
|| (iaccess(file, d, DWRITE) && !wok))
|
|| iaccess(file, d, DWRITE))
|
||||||
goto badaccess;
|
goto badaccess;
|
||||||
if(ro){
|
if(ro){
|
||||||
error = Eronly;
|
error = Eronly;
|
||||||
|
@ -700,7 +695,7 @@ fs_open(Chan* chan, Fcall* f, Fcall* r)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OEXEC:
|
case OEXEC:
|
||||||
if((d->mode & DDIR) || (iaccess(file, d, DEXEC) && !wok))
|
if((d->mode & DDIR) || iaccess(file, d, DEXEC))
|
||||||
goto badaccess;
|
goto badaccess;
|
||||||
fmod = FREAD;
|
fmod = FREAD;
|
||||||
break;
|
break;
|
||||||
|
@ -710,7 +705,7 @@ fs_open(Chan* chan, Fcall* f, Fcall* r)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if(f->mode & OTRUNC){
|
if(f->mode & OTRUNC){
|
||||||
if((d->mode & DDIR) || (iaccess(file, d, DWRITE) && !wok))
|
if((d->mode & DDIR) || iaccess(file, d, DWRITE))
|
||||||
goto badaccess;
|
goto badaccess;
|
||||||
if(ro){
|
if(ro){
|
||||||
error = Eronly;
|
error = Eronly;
|
||||||
|
@ -759,17 +754,13 @@ fs_create(Chan* chan, Fcall* f, Fcall* r)
|
||||||
Iobuf *p, *p1;
|
Iobuf *p, *p1;
|
||||||
Dentry *d, *d1;
|
Dentry *d, *d1;
|
||||||
File *file;
|
File *file;
|
||||||
int error, slot, slot1, fmod, wok;
|
int error, slot, slot1, fmod;
|
||||||
Off addr, addr1, path;
|
Off addr, addr1, path;
|
||||||
Tlock *t;
|
Tlock *t;
|
||||||
Wpath *w;
|
Wpath *w;
|
||||||
|
|
||||||
wok = 0;
|
|
||||||
p = nil;
|
p = nil;
|
||||||
|
|
||||||
if(chan == cons.chan || writeallow)
|
|
||||||
wok = 1;
|
|
||||||
|
|
||||||
if((file = filep(chan, f->fid, 0)) == nil){
|
if((file = filep(chan, f->fid, 0)) == nil){
|
||||||
error = Efid;
|
error = Efid;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -799,7 +790,7 @@ fs_create(Chan* chan, Fcall* f, Fcall* r)
|
||||||
error = Edir2;
|
error = Edir2;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if(iaccess(file, d, DWRITE) && !wok) {
|
if(iaccess(file, d, DWRITE)) {
|
||||||
error = Eaccess;
|
error = Eaccess;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1273,7 +1264,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_clunk(File* file, int remove, int wok)
|
_clunk(File* file, int remove)
|
||||||
{
|
{
|
||||||
Tlock *t;
|
Tlock *t;
|
||||||
int error;
|
int error;
|
||||||
|
@ -1285,7 +1276,7 @@ _clunk(File* file, int remove, int wok)
|
||||||
file->tlock = 0;
|
file->tlock = 0;
|
||||||
}
|
}
|
||||||
if(remove && (file->qid.type & QTAUTH) == 0)
|
if(remove && (file->qid.type & QTAUTH) == 0)
|
||||||
error = doremove(file, wok);
|
error = doremove(file);
|
||||||
file->open = 0;
|
file->open = 0;
|
||||||
freewp(file->wpath);
|
freewp(file->wpath);
|
||||||
authfree(file->auth);
|
authfree(file->auth);
|
||||||
|
@ -1304,7 +1295,7 @@ clunk(Chan* chan, Fcall* f, Fcall*)
|
||||||
if((file = filep(chan, f->fid, 0)) == nil)
|
if((file = filep(chan, f->fid, 0)) == nil)
|
||||||
return Efid;
|
return Efid;
|
||||||
|
|
||||||
_clunk(file, file->open & FREMOV, 0);
|
_clunk(file, file->open & FREMOV);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1315,8 +1306,7 @@ fs_remove(Chan* chan, Fcall* f, Fcall*)
|
||||||
|
|
||||||
if((file = filep(chan, f->fid, 0)) == nil)
|
if((file = filep(chan, f->fid, 0)) == nil)
|
||||||
return Efid;
|
return Efid;
|
||||||
|
return _clunk(file, 1);
|
||||||
return _clunk(file, 1, chan == cons.chan);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1433,13 +1423,10 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
|
||||||
* .qid.path, .qid.vers and .muid are checked for validity but
|
* .qid.path, .qid.vers and .muid are checked for validity but
|
||||||
* any attempt to change them is an error.
|
* any attempt to change them is an error.
|
||||||
* .qid.type/.mode, .mtime, .name, .length, .uid and .gid can
|
* .qid.type/.mode, .mtime, .name, .length, .uid and .gid can
|
||||||
* possibly be changed (and .muid iff wstatallow).
|
* possibly be changed (and .muid iff is god).
|
||||||
*
|
*
|
||||||
* 'Op' flags there are changed fields, i.e. it's not a no-op.
|
* 'Op' flags there are changed fields, i.e. it's not a no-op.
|
||||||
* 'Tsync' flags all fields are defaulted.
|
* 'Tsync' flags all fields are defaulted.
|
||||||
*
|
|
||||||
* Wstatallow and writeallow are set to allow changes during the
|
|
||||||
* fileserver bootstrap phase.
|
|
||||||
*/
|
*/
|
||||||
tsync = 1;
|
tsync = 1;
|
||||||
if(dir.qid.path != ~0){
|
if(dir.qid.path != ~0){
|
||||||
|
@ -1526,7 +1513,7 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
|
||||||
gl = leadgroup(file->uid, gid) != 0;
|
gl = leadgroup(file->uid, gid) != 0;
|
||||||
gl += leadgroup(file->uid, d->gid) != 0;
|
gl += leadgroup(file->uid, d->gid) != 0;
|
||||||
|
|
||||||
if(op && !wstatallow && d->uid != file->uid && !gl){
|
if(op && !isallowed(file) && d->uid != file->uid && !gl){
|
||||||
error = Ewstato;
|
error = Ewstato;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1613,7 +1600,7 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
|
||||||
/*
|
/*
|
||||||
* Check write permission in the parent.
|
* Check write permission in the parent.
|
||||||
*/
|
*/
|
||||||
if(!wstatallow && !writeallow && iaccess(file, d1, DWRITE)){
|
if(iaccess(file, d1, DWRITE)){
|
||||||
error = Eaccess;
|
error = Eaccess;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1625,7 +1612,7 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
|
||||||
if(dir.uid != nil && *dir.uid != '\0'){
|
if(dir.uid != nil && *dir.uid != '\0'){
|
||||||
uid = strtouid(dir.uid);
|
uid = strtouid(dir.uid);
|
||||||
if(uid != d->uid){
|
if(uid != d->uid){
|
||||||
if(!wstatallow){
|
if(!isallowed(file)){
|
||||||
error = Ewstatu;
|
error = Ewstatu;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1637,7 +1624,7 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
|
||||||
if(dir.muid != nil && *dir.muid != '\0'){
|
if(dir.muid != nil && *dir.muid != '\0'){
|
||||||
muid = strtouid(dir.muid);
|
muid = strtouid(dir.muid);
|
||||||
if(muid != d->muid){
|
if(muid != d->muid){
|
||||||
if(!wstatallow){
|
if(!isallowed(file)){
|
||||||
error = Ewstatm;
|
error = Ewstatm;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1652,7 +1639,7 @@ fs_wstat(Chan* chan, Fcall* f, Fcall*, char* strs)
|
||||||
* either owner and in new group or leader of both groups.
|
* either owner and in new group or leader of both groups.
|
||||||
*/
|
*/
|
||||||
if(gid != d->gid){
|
if(gid != d->gid){
|
||||||
if(!(wstatallow || writeallow)
|
if(!isallowed(file)
|
||||||
&& !(d->uid == file->uid && ingroup(file->uid, gid))
|
&& !(d->uid == file->uid && ingroup(file->uid, gid))
|
||||||
&& !(gl == 2)){
|
&& !(gl == 2)){
|
||||||
error = Ewstatg;
|
error = Ewstatg;
|
||||||
|
|
|
@ -85,12 +85,10 @@ int noauth; /* auth is disable */
|
||||||
int nonone; /* attach as none disabled */
|
int nonone; /* attach as none disabled */
|
||||||
int noatime; /* atime is disabled */
|
int noatime; /* atime is disabled */
|
||||||
int noatimeset; /* noatime was changed (reset after dump) */
|
int noatimeset; /* noatime was changed (reset after dump) */
|
||||||
int wstatallow; /* set to circumvent wstat permissions */
|
int allowed; /* allow wstat and disable permission checks
|
||||||
int writeallow; /* set to circumvent write permissions */
|
* for user or anyone when -1 */
|
||||||
int duallow; /* single user to allow du */
|
int duallow; /* single user to allow du */
|
||||||
int readonly; /* disable writes if true */
|
int readonly; /* disable writes if true */
|
||||||
|
|
||||||
|
|
||||||
int rawreadok; /* allow reading raw data */
|
int rawreadok; /* allow reading raw data */
|
||||||
|
|
||||||
File* flist[5003]; /* base of file structures */
|
File* flist[5003]; /* base of file structures */
|
||||||
|
|
|
@ -461,15 +461,31 @@ cmd_clri(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_allow(int, char**)
|
cmd_allow(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
wstatallow = writeallow = 1;
|
char *name;
|
||||||
|
int uid;
|
||||||
|
|
||||||
|
uid = -1;
|
||||||
|
name = "any user";
|
||||||
|
if(argc > 1){
|
||||||
|
name = argv[1];
|
||||||
|
uid = strtouid(name);
|
||||||
|
if(uid < 0)
|
||||||
|
uid = number(name, -2, 10);
|
||||||
|
if(uid < 0) {
|
||||||
|
print("bad uid %s\n", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print("allowed %s\n", name);
|
||||||
|
allowed = uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_disallow(int, char**)
|
cmd_disallow(int, char**)
|
||||||
{
|
{
|
||||||
wstatallow = writeallow = 0;
|
allowed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -748,14 +764,14 @@ cmd_chatty(int argc, char *argv[])
|
||||||
static void
|
static void
|
||||||
installcmds(void)
|
installcmds(void)
|
||||||
{
|
{
|
||||||
cmd_install("allow", "-- disable permission checking", cmd_allow);
|
cmd_install("allow", "[uid] -- disable permission checking", cmd_allow);
|
||||||
cmd_install("cfs", "[file] -- set current filesystem", cmd_cfs);
|
cmd_install("cfs", "[file] -- set current filesystem", cmd_cfs);
|
||||||
cmd_install("chatty", "n -- set chattiness", cmd_chatty);
|
cmd_install("chatty", "n -- set chattiness", cmd_chatty);
|
||||||
cmd_install("clean", "file [bno [addr]] -- block print/fix", cmd_clean);
|
cmd_install("clean", "file [bno [addr]] -- block print/fix", cmd_clean);
|
||||||
cmd_install("check", "[options]", cmd_check);
|
cmd_install("check", "[options]", cmd_check);
|
||||||
cmd_install("clri", "[file ...] -- purge files/dirs", cmd_clri);
|
cmd_install("clri", "[file ...] -- purge files/dirs", cmd_clri);
|
||||||
cmd_install("create", "path uid gid perm [lad] -- make a file/dir", cmd_create);
|
cmd_install("create", "path uid gid perm [lad] -- make a file/dir", cmd_create);
|
||||||
cmd_install("disallow", "-- enable permission checking", cmd_disallow);
|
cmd_install("disallow", "-- (re)enable permission checking", cmd_disallow);
|
||||||
cmd_install("duallow", "uid -- duallow", cmd_duallow);
|
cmd_install("duallow", "uid -- duallow", cmd_duallow);
|
||||||
cmd_install("flag", "-- print set flags", cmd_flag);
|
cmd_install("flag", "-- print set flags", cmd_flag);
|
||||||
cmd_install("fstat", "path -- print info on a file/dir", cmd_fstat);
|
cmd_install("fstat", "path -- print info on a file/dir", cmd_fstat);
|
||||||
|
|
|
@ -1105,9 +1105,6 @@ arginit(void)
|
||||||
}
|
}
|
||||||
switch(verb) {
|
switch(verb) {
|
||||||
case FREAM:
|
case FREAM:
|
||||||
if(strcmp(fs->name, "main") == 0)
|
|
||||||
wstatallow = 1; /* only set, never reset */
|
|
||||||
/* fallthrough */
|
|
||||||
case FRECOVER:
|
case FRECOVER:
|
||||||
fs->flags |= verb;
|
fs->flags |= verb;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -66,7 +66,7 @@ Devsize devsize(Device*);
|
||||||
int devwrite(Device*, Off, void*);
|
int devwrite(Device*, Off, void*);
|
||||||
Iobuf* dnodebuf(Iobuf*, Dentry*, Off, int, int);
|
Iobuf* dnodebuf(Iobuf*, Dentry*, Off, int, int);
|
||||||
Iobuf* dnodebuf1(Iobuf*, Dentry*, Off, int, int);
|
Iobuf* dnodebuf1(Iobuf*, Dentry*, Off, int, int);
|
||||||
int doremove(File*, int);
|
int doremove(File*);
|
||||||
void dtrunc(Iobuf*, Dentry*, int);
|
void dtrunc(Iobuf*, Dentry*, int);
|
||||||
int dtrunclen(Iobuf *p, Dentry *, Off newsize, int uid);
|
int dtrunclen(Iobuf *p, Dentry *, Off newsize, int uid);
|
||||||
int dumpblock(Device*);
|
int dumpblock(Device*);
|
||||||
|
@ -107,6 +107,7 @@ void iobufinit(void);
|
||||||
void* iobufmap(Iobuf*);
|
void* iobufmap(Iobuf*);
|
||||||
void iobufunmap(Iobuf*);
|
void iobufunmap(Iobuf*);
|
||||||
int iobufql(QLock*);
|
int iobufql(QLock*);
|
||||||
|
int isallowed(File*);
|
||||||
int jukeread(Device*, Off, void*);
|
int jukeread(Device*, Off, void*);
|
||||||
int jukewrite(Device*, Off, void*);
|
int jukewrite(Device*, Off, void*);
|
||||||
void jukeinit(Device*);
|
void jukeinit(Device*);
|
||||||
|
|
|
@ -89,7 +89,7 @@ loop:
|
||||||
f->tlock = 0;
|
f->tlock = 0;
|
||||||
}
|
}
|
||||||
if(f->open & FREMOV)
|
if(f->open & FREMOV)
|
||||||
doremove(f, 0);
|
doremove(f);
|
||||||
freewp(f->wpath);
|
freewp(f->wpath);
|
||||||
f->open = 0;
|
f->open = 0;
|
||||||
authfree(f->auth);
|
authfree(f->auth);
|
||||||
|
@ -237,26 +237,41 @@ iaccess(File *f, Dentry *d, int m)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* other */
|
||||||
* other
|
|
||||||
*/
|
|
||||||
if(m & d->mode) {
|
if(m & d->mode) {
|
||||||
|
/*
|
||||||
|
* walk directories regardless.
|
||||||
|
* otherwise its impossible to get
|
||||||
|
* from the root to noworld's directories.
|
||||||
|
*/
|
||||||
if((d->mode & DDIR) && (m == DEXEC))
|
if((d->mode & DDIR) && (m == DEXEC))
|
||||||
return 0;
|
return 0;
|
||||||
if(!ingroup(f->uid, 9999))
|
if(!ingroup(f->uid, 9999))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* read access for du */
|
||||||
* various forms of superuser
|
|
||||||
*/
|
|
||||||
if(wstatallow)
|
|
||||||
return 0;
|
|
||||||
if(duallow != 0 && duallow == f->uid)
|
if(duallow != 0 && duallow == f->uid)
|
||||||
if((d->mode & DDIR) && (m == DREAD || m == DEXEC))
|
if((d->mode & DDIR) && (m == DREAD || m == DEXEC))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* allow god */
|
||||||
|
return !isallowed(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
isallowed(File *f)
|
||||||
|
{
|
||||||
|
if(f->cp == cons.chan)
|
||||||
return 1;
|
return 1;
|
||||||
|
switch(allowed){
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
case -1:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return f->uid == allowed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Tlock*
|
Tlock*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue