Пример #1
0
static Npfcall *
np_attach(Npreq *req, Npfcall *tc)
{
	Npconn *conn;
	Npfid *fid, *afid;
	Npfcall *rc;

	rc = NULL;
	conn = req->conn;
	afid = NULL;

	/* the fid that the connecting client wants to call root  */
	fid = np_fid_find(conn, tc->fid);

	/* if this fid exists then report error  */
	if (fid) {
		np_werror(Einuse, EIO);
		goto done;
	}

	/* create a fid structure for the root   */
	fid = np_fid_create(conn, tc->fid, NULL);
	if (!fid) {
		np_werror(Enomem, ENOMEM);
		goto done;
	} else 
	  /* maintain a reference count for fid   */
		np_fid_incref(fid);

	req->fid = fid;
	afid = np_fid_find(conn, tc->afid);
	if (!afid) {
		if (tc->afid!=NOFID) {
			np_werror(Eunknownfid, EIO);
			goto done;
		}

		if (!afid->type&Qtauth) {
			np_werror(Ebadusefid, EIO);
			goto done;
		}
	} else 
		np_fid_incref(afid);

	if (conn->srv->auth) {
		rc = (*conn->srv->auth->attach)(afid, &tc->uname, &tc->aname);
		if (rc)
			goto done;
	}

	rc = (*conn->srv->attach)(fid, afid, &tc->uname, &tc->aname);

done:
	np_fid_decref(fid);
	np_fid_decref(afid);
	return rc;
}
Пример #2
0
static Npfcall* openssl_auth(Npfid *afid, Npstr *uname, Npstr *aname) {
    struct openssl_session_auth_context* ctx;
    Npqid aqid;

    ctx = new_session_context(afid);
    if ( ctx == NULL )
        return np_create_rerror("No mem",ENOMEM,1);


    ctx->uname = malloc(uname->len);
    if ( !ctx->uname )
        return np_create_rerror("No mem",ENOMEM,1);

    memcpy(ctx->uname, uname->str, uname->len);

    afid->aux = ctx;

    np_fid_incref(afid);

    pthread_create(&ctx->auth_thread, NULL, run_auth, ctx);

    aqid.type = Qtauth;

    return np_create_rauth(&aqid);
    //return execute_openssl_auth_protocol(ctx);
}
Пример #3
0
static Npfcall *
np_open(Npreq *req, Npfcall *tc)
{
	Npconn *conn;
	Npfid *fid;
	Npfcall *rc;

	rc = NULL;
	conn = req->conn;
	fid = np_fid_find(conn, tc->fid);
	if (!fid) {
		np_werror(Eunknownfid, EIO);
		goto done;
	} else 
		np_fid_incref(fid);

	req->fid = fid;
	if (fid->omode != (u16)~0) {
		np_werror(Ebadusefid, EIO);
		goto done;
	}

	if (fid->type&Qtdir && tc->mode != Oread) {
		np_werror(Eperm, EPERM);
		goto done;
	}

	rc = (*conn->srv->open)(fid, tc->mode);
	fid->omode = tc->mode;
done:
	np_fid_decref(fid);
	return rc;
}
Пример #4
0
/* Create a fid with initial refcount of 1.
 */
Npfid *
np_fid_create (Npconn *conn, u32 fid)
{
	Npsrv *srv = conn->srv;
	Npfidpool *pool = conn->fidpool;
	int hash = fid % pool->size;
	Npfid *f;

	xpthread_mutex_lock(&pool->lock);
	if ((f = _lookup_fid (&pool->htable[hash], fid))) {
		np_logmsg (srv, "np_fid_create: unclunked fid %d (%s): %d refs",
			   f->fid, srv->get_path ? srv->get_path (f) : "<nil>",
			   f->refcount);
		if ((srv->flags & SRV_FLAGS_LOOSEFID)) {
			f->flags |= FID_FLAGS_ZOMBIE;
		} else {
			np_uerror (EEXIST);
			f = NULL;
			goto done;
		}
	}
	if ((f = _create_fid (conn, fid))) {
		np_fid_incref (f);
		_link_fid (&pool->htable[hash], f);
	}
done:
	xpthread_mutex_unlock(&pool->lock);

	return f;
}
Пример #5
0
Npfcall *
np_xattrwalk(Npreq *req, Npfcall *tc)
{
	Npfid *fid = req->fid;
	Npfid *attrfid;
	Npfcall *rc = NULL;

	if (!fid) {
		np_uerror (EIO);
		goto done;
	}
	if (!(attrfid = np_fid_find(req->conn, tc->u.txattrwalk.attrfid))) {
		np_uerror(EIO);
		goto done;
	}
	np_fid_incref(attrfid); /* XXX decref needed? */
	if (fid->type & P9_QTTMP) {
		np_uerror (EPERM);
		goto done;
	} else {
		if (np_setfsid (req, fid->user, -1) < 0)
			goto done;
		if (!req->conn->srv->xattrwalk) {
			np_uerror (ENOSYS);
			goto done;
		}
		rc = (*req->conn->srv->xattrwalk)(fid, attrfid,
						  &tc->u.txattrwalk.name);
	}
done:
	return rc;
}
Пример #6
0
Npfcall *
np_rename(Npreq *req, Npfcall *tc)
{
	Npfid *fid = req->fid;
	Npfid *dfid = NULL;
	Npfcall *rc = NULL;

	if (!fid) {
		np_uerror (EIO);
		goto done;
	}
	if (!(dfid = np_fid_find(req->conn, tc->u.trename.dfid))) {
		np_uerror(EIO);
		goto done;
	}
	np_fid_incref(dfid);
	if (fid->type & P9_QTTMP) {
		np_uerror (EPERM);
		goto done;
	} else {
		if (np_setfsid (req, fid->user, -1) < 0)
			goto done;
		if (!req->conn->srv->rename) {
			np_uerror (ENOSYS);
			goto done;
		}
		rc = (*req->conn->srv->rename)(fid, dfid, &tc->u.trename.name);
	}
done:
	np_fid_decref(dfid);
	return rc;
}
Пример #7
0
static Npfcall *
np_read(Npreq *req, Npfcall *tc)
{
	Npconn *conn;
	Npfid *fid;
	Npfcall *rc;

	rc = NULL;
	conn = req->conn;
	fid = np_fid_find(conn, tc->fid);
	if (!fid) {
		np_werror(Eunknownfid, EIO);
		goto error;
	} else 
		np_fid_incref(fid);

	req->fid = fid;
	if (tc->count+IOHDRSZ > conn->msize) {
		np_werror(Etoolarge, EIO);
		goto error;
	}

	if (fid->type&Qtauth) {
		if (conn->srv->auth)
			rc = conn->srv->auth->read(fid, tc->offset, tc->count);
		else
			np_werror(Ebadusefid, EIO);

		goto error;
	}

	if (fid->omode==(u16)~0 || (fid->omode&3)==Owrite) {
		np_werror(Ebadusefid, EIO);
		goto error;
	}

	if (fid->type&Qtdir && tc->offset != fid->diroffset) {
		np_werror(Ebadoffset, EIO);
		goto error;
	}
		
	rc = (*conn->srv->read)(fid, tc->offset, tc->count, req);

/*
	if (rc && rc->id==Rread && fid->type&Qtdir) {
		fid->diroffset = tc->offset + rc->count;
	}
*/
	if (rc || np_haserror())
		np_fid_decref(fid);

	return rc;

error:
	np_fid_decref(fid);
	return NULL;
}
Пример #8
0
Npfcall *
np_auth(Npreq *req, Npfcall *tc)
{
	Npconn *conn = req->conn;
	Npsrv *srv = conn->srv;
	Npfid *afid = req->fid;
	Npfcall *rc = NULL;
	Npqid aqid;
	char a[128];
	int auth_required = _authrequired(srv, &tc->u.tauth.uname,
					       tc->u.tauth.n_uname,
					       &tc->u.tauth.aname);

	if (tc->u.tauth.n_uname != P9_NONUNAME) {
		snprintf (a, sizeof(a), "auth(%d@%s:%.*s)",
			  tc->u.tauth.n_uname,
			  np_conn_get_client_id (conn), 
			  tc->u.tauth.aname.len, tc->u.tauth.aname.str);
	} else {
		snprintf (a, sizeof(a), "auth(%.*s@%s:%.*s)",
			  tc->u.tauth.uname.len, tc->u.tauth.uname.str,
			  np_conn_get_client_id (conn),
			  tc->u.tauth.aname.len, tc->u.tauth.aname.str);
	}
	if (!auth_required) {
		if (!(rc = np_create_rlerror(0))) {
			np_uerror(ENOMEM);
			np_logerr (srv, "%s: creating response", a);
		}
		goto error;
	}
	if (!afid) {
		np_uerror (EIO);
		np_logerr (srv, "%s: invalid afid (%d)", a, tc->u.tauth.afid);
		goto error;
	}
	np_fid_incref(afid);
	if (!(afid->user = np_attach2user (srv, &tc->u.tauth.uname,
				     		 tc->u.tauth.n_uname))) {
		np_logerr (srv, "%s: user lookup", a);
		goto error;
	}
	afid->type = P9_QTAUTH;
	if (!srv->auth->startauth(afid, afid->aname, &aqid)) {
		np_logerr (srv, "%s: startauth", a);
		goto error;
	}
	assert((aqid.type & P9_QTAUTH));
	if (!(rc = np_create_rauth(&aqid))) {
		np_uerror(ENOMEM);
		np_logerr (srv, "%s: creating response", a);
		goto error;
	}
error:
	return rc;
}
Пример #9
0
static Npfcall *
myattach (Npfid *fid, Npfid *afid, Npstr *aname)
{
    Npqid qid = { 1, 2, 3};
    Npfcall *ret = NULL;

    if (!(ret = np_create_rattach(&qid))) {
        np_uerror (ENOMEM);
        return NULL;
    }
    np_fid_incref (fid);
    return ret;
}
Пример #10
0
/* Find a fid, then refcount++
 */
Npfid *
np_fid_find (Npconn *conn, u32 fid)
{
	Npfidpool *pool = conn->fidpool;
	int hash = fid % pool->size;
	Npfid *f;

	xpthread_mutex_lock (&pool->lock);
	if ((f = _lookup_fid (&pool->htable[hash], fid)))
		np_fid_incref (f);
	xpthread_mutex_unlock (&pool->lock);
	
	return f;
}
Пример #11
0
static Npfcall *
np_write(Npreq *req, Npfcall *tc)
{
	Npconn *conn;
	Npfid *fid;
	Npfcall *rc;

	rc = NULL;
	conn = req->conn;
	fid = np_fid_find(conn, tc->fid);
	if (!fid) {
		np_werror(Eunknownfid, EIO);
		goto error;
	} else 
		np_fid_incref(fid);

	req->fid = fid;
	if (fid->type&Qtauth) {
		if (conn->srv->auth) {
			rc = conn->srv->auth->write(fid, tc->offset, 
				tc->count, tc->data);
			np_fid_decref(fid);
			return rc;
		} else {
			np_werror(Ebadusefid, EIO);
			goto error;
		}
	}

	if (fid->omode==(u16)~0 || fid->type&Qtdir || (fid->omode&3)==Oread) {
		np_werror(Ebadusefid, EIO);
		goto error;
	}

	if (tc->count+IOHDRSZ > conn->msize) {
		np_werror(Etoolarge, EIO);
		goto error;
	}

	rc = (*conn->srv->write)(fid, tc->offset, tc->count, tc->data, req);
	if (rc || np_haserror())
		np_fid_decref(fid);

	return rc;

error:
	np_fid_decref(fid);
	return NULL;
}
Пример #12
0
static Npfcall *
np_create(Npreq *req, Npfcall *tc)
{
	Npconn *conn;
	Npfid *fid;
	Npfcall *rc;

	rc = NULL;
	conn = req->conn;
	fid = np_fid_find(conn, tc->fid);
	if (!fid) {
		np_werror(Eunknownfid, EIO);
		goto done;
	} else 
		np_fid_incref(fid);

	req->fid = fid;
	if (fid->omode != (u16)~0) {
		np_werror(Ebadusefid, EIO);
		goto done;
	}

	if (!fid->type&Qtdir) {
		np_werror(Enotdir, ENOTDIR);
		goto done;
	}

	if (tc->perm&Dmdir && tc->mode!=Oread) {
		np_werror(Eperm, EPERM);
		goto done;
	}

	if (tc->perm&(Dmnamedpipe|Dmsymlink|Dmlink|Dmdevice|Dmsocket)
	&& !fid->conn->dotu) {
		np_werror(Eperm, EPERM);
		goto done;
	}

	rc = (*conn->srv->create)(fid, &tc->name, tc->perm, tc->mode, 
		&tc->extension);
	if (rc && rc->id == Rcreate) {
		fid->omode = tc->mode;
		fid->type = rc->qid.type;
	}

done:
	np_fid_decref(fid);
	return rc;
}
Пример #13
0
Файл: ops.c Проект: eugmes/diod
/* Tattach - attach a new user (fid->user) to aname.
 *   diod_auth.c::diod_checkauth first authenticates/authorizes user
 */
Npfcall*
diod_attach (Npfid *fid, Npfid *afid, Npstr *aname)
{
    Npfcall* ret = NULL;
    Fid *f = NULL;
    Npqid qid;
    struct stat sb;

    if (aname->len == 0 || *aname->str != '/') {
        np_uerror (EPERM);
        goto error;
    }
    if (!(f = _fidalloc ()) || !(f->path = np_strdup (aname))) {
        np_uerror (ENOMEM);
        goto error;
    }
    if (diod_conf_opt_runasuid ()) {
        if (fid->user->uid != diod_conf_get_runasuid ()) {
            np_uerror (EPERM);
            goto error;
        }
    }
    if (!diod_match_exports (f->path, fid->conn, fid->user, &f->xflags))
        goto error;
    if (stat (f->path, &sb) < 0) { /* OK to follow symbolic links */
        np_uerror (errno);
        goto error;
    }
    if (!S_ISDIR (sb.st_mode)) {
        np_uerror (ENOTDIR);
        goto error;
    }
    _ustat2qid (&sb, &qid);
    if ((ret = np_create_rattach (&qid)) == NULL) {
        np_uerror (ENOMEM);
        goto error;
    }
    fid->aux = f;
    np_fid_incref (fid);
    return ret;
error:
    errn (np_rerror (), "diod_attach %s@%s:%.*s", fid->user->uname,
          np_conn_get_client_id (fid->conn), aname->len, aname->str);
    if (f)
        _fidfree (f);
    return NULL;
}
Пример #14
0
static Npfcall *
np_remove(Npreq *req, Npfcall *tc)
{
	Npconn *conn;
	Npfid *fid;
	Npfcall *rc;

	rc = NULL;
	conn = req->conn;
	fid = np_fid_find(conn, tc->fid);
	if (!fid) {
		np_werror(Eunknownfid, EIO);
		goto done;
	} else 
		np_fid_incref(fid);

	req->fid = fid;
	rc = (*conn->srv->remove)(fid);
done:
	np_fid_decref(fid);
	return rc;
}
Пример #15
0
static Npfcall *
np_clunk(Npreq *req, Npfcall *tc)
{
	Npconn *conn;
	Npfid *fid;
	Npfcall *rc;

	rc = NULL;
	conn = req->conn;
	fid = np_fid_find(conn, tc->fid);
	if (!fid) {
		np_werror(Eunknownfid, EIO);
		goto done;
	} else 
		np_fid_incref(fid);

	req->fid = fid;
	if (fid->type&Qtauth) {
		if (conn->srv->auth)
			rc = conn->srv->auth->clunk(fid);
		else
			np_werror(Ebadusefid, EIO);

		goto done;
	}

	if (fid->omode!=(u16)~0 && fid->omode==Orclose) {
		rc = (*conn->srv->remove)(fid);
		if (rc->id == Rerror)
			goto done;
		free(rc);
		rc = np_create_rclunk();
	} else
		rc = (*conn->srv->clunk)(fid);

done:
	np_fid_decref(fid);
	return rc;
}
Пример #16
0
static Npfcall *
np_wstat(Npreq *req, Npfcall *tc)
{
	Npconn *conn;
	Npfid *fid;
	Npfcall *rc;
	Npstat *stat;

	rc = NULL;
	conn = req->conn;
	stat = &tc->stat;
	fid = np_fid_find(conn, tc->fid);
	if (!fid) {
		np_werror(Eunknownfid, EIO);
		goto done;
	} else 
		np_fid_incref(fid);

	req->fid = fid;
	if (stat->type != (u16)~0 || stat->dev != (u32)~0
	|| stat->qid.version != (u32)~0
	|| stat->qid.path != (u64)~0 ) {
                np_werror(Eperm, EPERM);
                goto done;
        }

	if ((fid->type&Qtdir && !stat->mode&Dmdir)
	|| (!fid->type&Qtdir&&stat->mode&Dmdir)) {
		np_werror(Edirchange, EPERM);
		goto done;
	}

	rc = (*conn->srv->wstat)(fid, &tc->stat);
done:
	np_fid_decref(fid);
	return rc;
}
Пример #17
0
Npfcall *
np_walk(Npreq *req, Npfcall *tc)
{
	int i;
	Npconn *conn = req->conn;
	Npfid *fid = req->fid;
	Npfid *newfid = NULL;
	Npfcall *rc = NULL;
	Npqid wqids[P9_MAXWELEM];

	if (!fid) {
		np_uerror (EIO);
		goto done;
	}
#if 0
	if (!(fid->type & P9_QTDIR)) {
		np_uerror(ENOTDIR);
		goto done;
	}
#endif
	/* FIXME: error if fid has been opened */
	if (tc->u.twalk.nwname > P9_MAXWELEM) {
		np_uerror(EIO);
		goto done;
	}

	if (tc->u.twalk.fid != tc->u.twalk.newfid) {
		newfid = np_fid_find(conn, tc->u.twalk.newfid);
		if (newfid) {
			np_uerror(EIO);
			goto done;
		}
		newfid = np_fid_create(conn, tc->u.twalk.newfid, NULL);
		if (!newfid)
			goto done;
		if (fid->type & P9_QTTMP) {
			if (!np_ctl_clone (fid, newfid))
				goto done;
		} else {
			if (!conn->srv->clone)
				goto done;
			if (!(*conn->srv->clone)(fid, newfid))
				goto done;
		}
		np_user_incref(fid->user);
		newfid->user = fid->user;
		np_tpool_incref(fid->tpool);
		newfid->tpool = fid->tpool;
		newfid->type = fid->type;
		if (!(newfid->aname = strdup (fid->aname))) {
			np_uerror (ENOMEM);
			goto done;
		}
	} else
		newfid = fid;

	np_fid_incref(newfid);
	if (!(newfid->type & P9_QTTMP)) {
		if (np_setfsid (req, newfid->user, -1) < 0)
			goto done;
	}
	for(i = 0; i < tc->u.twalk.nwname;) {
		if (newfid->type & P9_QTTMP) {
			if (!np_ctl_walk (newfid, &tc->u.twalk.wnames[i],
					  &wqids[i]))
				break;
		} else {
			if (!conn->srv->walk) {
				np_uerror (ENOSYS);
				break;
			}
			if (!(*conn->srv->walk)(newfid, &tc->u.twalk.wnames[i],
						&wqids[i]))
				break;
		}
		newfid->type = wqids[i].type;
		i++;
		if (i<(tc->u.twalk.nwname) && !(newfid->type & P9_QTDIR))
			break;
	}

	if (i==0 && tc->u.twalk.nwname!=0)
		goto done;

	np_uerror(0);
	if (tc->u.twalk.fid != tc->u.twalk.newfid)
		np_fid_incref(newfid);
	rc = np_create_rwalk(i, wqids);

done:
	np_fid_decref(newfid);
	return rc;
}
Пример #18
0
/* Look up operation's fid and assign it to req->fid.
 * This is done before the request is handed off to a worker, with
 * the plan of using fid data in scheduling work.
 * The fid refcount is incremented here, then decremented in np_respond ().
 */
static void
np_preprocess_request(Npreq *req)
{
	Npfcall *tc = req->tcall;
	Npconn *conn = req->conn;

	switch (tc->type) {
		case P9_TSTATFS:
			req->fid = np_fid_find (conn, tc->u.tstatfs.fid);
			break;
		case P9_TLOPEN:
			req->fid = np_fid_find (conn, tc->u.tlopen.fid);
			break;
		case P9_TLCREATE:
			req->fid = np_fid_find (conn, tc->u.tlcreate.fid);
			break;
		case P9_TSYMLINK:
			req->fid = np_fid_find (conn, tc->u.tsymlink.fid);
			break;
		case P9_TMKNOD:
			req->fid = np_fid_find (conn, tc->u.tmknod.fid);
			break;
		case P9_TRENAME:
			req->fid = np_fid_find (conn, tc->u.trename.fid);
			break;
		case P9_TREADLINK:
			req->fid = np_fid_find (conn, tc->u.treadlink.fid);
			break;
		case P9_TGETATTR:
			req->fid = np_fid_find (conn, tc->u.tgetattr.fid);
			break;
		case P9_TSETATTR:
			req->fid = np_fid_find (conn, tc->u.tsetattr.fid);
			break;
		case P9_TXATTRWALK:
			req->fid = np_fid_find (conn, tc->u.txattrwalk.fid);
			break;
		case P9_TXATTRCREATE:
			req->fid = np_fid_find (conn, tc->u.txattrcreate.fid);
			break;
		case P9_TREADDIR:
			req->fid = np_fid_find (conn, tc->u.treaddir.fid);
			break;
		case P9_TFSYNC:
			req->fid = np_fid_find (conn, tc->u.tfsync.fid);
			break;
		case P9_TLOCK:
			req->fid = np_fid_find (conn, tc->u.tlock.fid);
			break;
		case P9_TGETLOCK:
			req->fid = np_fid_find (conn, tc->u.tgetlock.fid);
			break;
		case P9_TLINK:
			req->fid = np_fid_find (conn, tc->u.tlink.dfid);
			break;
		case P9_TMKDIR:
			req->fid = np_fid_find (conn, tc->u.tmkdir.fid);
			break;
		case P9_TVERSION:
			break;
		case P9_TAUTH:
			if (np_fid_find (conn, tc->u.tauth.afid))
				break;
			req->fid = np_fid_create (conn, tc->u.tauth.afid, NULL);
			if (!req->fid)
				break;
			req->fid->aname = np_strdup (&tc->u.tauth.aname);
			if (!req->fid->aname) {
				np_fid_destroy(req->fid);
				req->fid = NULL;
			}
			/* XXX leave fid->tpool NULL for now as auth
			 * can be handled in the default thread pool
			 * without risk of deadlock.
			 */
			break;
		case P9_TATTACH:
			if (np_fid_find (conn, tc->u.tattach.fid))
				break;
			req->fid = np_fid_create (conn, tc->u.tattach.fid,NULL);
			if (!req->fid)
				break;
			req->fid->aname = np_strdup (&tc->u.tattach.aname);
			if (!req->fid->aname) {
				np_fid_destroy(req->fid);
				req->fid = NULL;
			}
			np_tpool_select (req);
			break;
		case P9_TFLUSH:
			break;
		case P9_TWALK:
			req->fid = np_fid_find (conn, tc->u.twalk.fid);
			break;
		case P9_TREAD:
			req->fid = np_fid_find (conn, tc->u.tread.fid);
			break;
		case P9_TWRITE:
			req->fid = np_fid_find (conn, tc->u.twrite.fid);
			break;
		case P9_TCLUNK:
			req->fid = np_fid_find (conn, tc->u.tclunk.fid);
			break;
		case P9_TREMOVE:
			req->fid = np_fid_find (conn, tc->u.tremove.fid);
			break;
		default:
			break;
	}
	if (req->fid)
		np_fid_incref (req->fid);
}
Пример #19
0
static Npfcall *
np_walk(Npreq *req, Npfcall *tc)
{
	int i;
	Npconn *conn;
	Npfid *fid, *newfid;
	Npfcall *rc;
	Npqid wqids[MAXWELEM];

	rc = NULL;
	conn = req->conn;
	newfid = NULL;
	fid = np_fid_find(conn, tc->fid);
	if (!fid) {
		np_werror(Eunknownfid, EIO);
		goto done;
	} else 
		np_fid_incref(fid);

	req->fid = fid;
	if (!fid->type&Qtdir) {
		np_werror(Enotdir, ENOTDIR);
		goto done;
	}

	if (fid->omode != (u16) ~0) {
		np_werror(Ebadusefid, EIO);
		goto done;
	}

	if (tc->nwname > MAXWELEM) {
		np_werror(Etoomanywnames, EIO);
		goto done;
	}

	if (tc->fid != tc->newfid) {
		newfid = np_fid_find(conn, tc->newfid);
		if (newfid) {
			np_werror(Einuse, EIO);
			goto done;
		}
		newfid = np_fid_create(conn, tc->newfid, NULL);
		if (!newfid) {
			np_werror(Enomem, ENOMEM);
			goto done;
		}

		if (!(*conn->srv->clone)(fid, newfid))
			goto done;

		newfid->user = fid->user;
		newfid->type = fid->type;
	} else
		newfid = fid;

	np_fid_incref(newfid);
	for(i = 0; i < tc->nwname;) {
		if (!(*conn->srv->walk)(newfid, &tc->wnames[i], &wqids[i]))
			break;

		newfid->type = wqids[i].type;
		i++;

		if (i<(tc->nwname) && !newfid->type&Qtdir)
			break;
	}

	if (i==0 && tc->nwname!=0)
		goto done;

	np_werror(NULL, 0);
	if (tc->fid != tc->newfid)
		np_fid_incref(newfid);
	rc = np_create_rwalk(i, wqids);

done:
	np_fid_decref(fid);
	np_fid_decref(newfid);
	return rc;
}
Пример #20
0
Npfcall *
np_attach(Npreq *req, Npfcall *tc)
{
	Npconn *conn = req->conn;
	Npsrv *srv = conn->srv;
	Npfid *fid = req->fid;
	Npfid *afid = NULL;
	Npfcall *rc = NULL;
	char a[128];
	int auth_required = _authrequired(srv, &tc->u.tattach.uname,
					       tc->u.tattach.n_uname,
					       &tc->u.tattach.aname);

	if (tc->u.tattach.n_uname != P9_NONUNAME) {
		snprintf (a, sizeof(a), "attach(%d@%s:%.*s)",
			  tc->u.tattach.n_uname,
			  np_conn_get_client_id (conn), 
			  tc->u.tattach.aname.len, tc->u.tattach.aname.str);
	} else {
		snprintf (a, sizeof(a), "attach(%.*s@%s:%.*s)",
			  tc->u.tattach.uname.len, tc->u.tattach.uname.str,
			  np_conn_get_client_id (conn),
			  tc->u.tattach.aname.len, tc->u.tattach.aname.str);
	}
	if (!fid) {
		np_uerror (EIO);
		np_logerr (srv, "%s: invalid fid (%d)", a, tc->u.tattach.fid);
		goto error;
	}
	if (tc->u.tattach.afid != P9_NOFID) {
		if (!(afid = np_fid_find(conn, tc->u.tattach.afid))) {
			np_uerror(EPERM);
			np_logerr (srv, "%s: invalid afid (%d)", a,
				   tc->u.tattach.afid);
			goto error;
		}
		np_fid_incref(afid);
		if (!(afid->type & P9_QTAUTH)) {
			np_uerror(EPERM);
			np_logerr (srv, "%s: invalid afid type", a);
			goto error;
		}
	}
	if (auth_required) {
		if (afid) {
			fid->user = np_afid2user (afid, &tc->u.tattach.uname,
						  tc->u.tattach.n_uname);
			if (!fid->user) {
				np_logerr (srv, "%s: invalid afid user", a);
				goto error;
			}
			if (srv->auth->checkauth(fid, afid, fid->aname) == 0) {
				np_logerr (srv, "%s: checkauth", a);
				goto error;
			}
			np_conn_set_authuser(conn, fid->user->uid);
		} else {
			u32 uid;

			fid->user = np_attach2user (srv, &tc->u.tattach.uname,
						    tc->u.tattach.n_uname);
			if (!fid->user) {
				np_logerr (srv, "%s: user lookup", a);
				goto error;
			}
			if (!(srv->flags & SRV_FLAGS_AUTHCONN)) {
				np_uerror(EPERM);
				np_logerr (srv, "%s: auth required", a);
				goto error;
			}
			if (np_conn_get_authuser(conn, &uid) < 0) {
				np_uerror(EPERM);
				np_logerr (srv, "%s: prior auth required", a);
				goto error;
			}
			if (uid != 0 && uid != fid->user->uid) {
				np_uerror(EPERM);
				np_logerr (srv, "%s: insufficient auth", a);
				goto error;
			}
		}
	}

	if (srv->remapuser) { /* squash user handling */
		if (srv->remapuser(fid, &tc->u.tattach.uname,
				        tc->u.tattach.n_uname,
				        &tc->u.tattach.aname) < 0) {
			np_logerr (srv, "%s: error remapping user", a);
			goto error;
		}
	}
	if (!fid->user) {
		fid->user = np_attach2user (srv, &tc->u.tattach.uname,
					          tc->u.tattach.n_uname);
		if (!fid->user) {
			np_logerr (srv, "%s: user lookup", a);
			goto error;
		}
	}

	if (!strcmp (fid->aname, "ctl")) {
		rc = np_ctl_attach (fid, afid, fid->aname);
	} else {
		if (!srv->attach) {
			np_uerror (EIO);
			goto error;
		}
		rc = (*srv->attach)(fid, afid, &tc->u.tattach.aname);
	}
error:
	if (afid)
		np_fid_decref(afid);
	return rc;
}