diff options
Diffstat (limited to 'lib9p/srv.c')
-rw-r--r-- | lib9p/srv.c | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/lib9p/srv.c b/lib9p/srv.c index f25fe09..1510a4a 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -14,6 +14,12 @@ /* structs ********************************************************************/ +#define NAME fidmap +#define KEY_T uint32_t +#define VAL_T struct lib9p_srv_file +#define CAP CONFIG_9P_MAX_FIDS +#include "map.h" + /* The hierarchy of concepts is: * * server -> connection -> session -> request @@ -40,6 +46,7 @@ struct lib9p_sess { /* mutable */ bool initialized; unsigned int refcount; + struct fidmap fids; }; struct lib9p_req { @@ -48,7 +55,7 @@ struct lib9p_req { uint16_t tag; /* mutable */ uint8_t *net_bytes; /* CONFIG_9P_MAX_MSG_SIZE-sized */ - struct lib9p_ctx ctx; + struct lib9p_reqctx ctx; }; /* base utilities *************************************************************/ @@ -195,6 +202,8 @@ COROUTINE lib9p_srv_read_cr(void *_srv) { /* write coroutine ************************************************************/ static void handle_Tversion(struct lib9p_req *ctx, struct lib9p_msg_Tversion *req, struct lib9p_msg_Rversion *resp); +static void handle_Tauth(struct lib9p_req *ctx, struct lib9p_msg_Tauth *req, struct lib9p_msg_Rauth *resp); +static void handle_Tattach(struct lib9p_req *ctx, struct lib9p_msg_Tattach *req, struct lib9p_msg_Rattach *resp); COROUTINE lib9p_srv_write_cr(void *_srv) { uint8_t net[CONFIG_9P_MAX_MSG_SIZE]; @@ -287,7 +296,7 @@ COROUTINE lib9p_srv_write_cr(void *_srv) { } write: - if (req.ctx.err_num || req.ctx.err_msg[0]) + if (lib9p_ctx_has_error(&req.ctx)) respond_error(&req); else { if (lib9p_marshal(&req.ctx, typ+1, req.tag, host_resp, net)) @@ -335,3 +344,66 @@ static void handle_Tversion(struct lib9p_req *ctx, struct lib9p_msg_Tversion *re ? CONFIG_9P_MAX_MSG_SIZE : req->max_msg_size; } + +static void handle_Tauth(struct lib9p_req *ctx, struct lib9p_msg_Tauth *UNUSED(req), struct lib9p_msg_Rauth *UNUSED(resp)) { + if (!ctx->parent_sess->parent_conn->parent_srv->auth) { + lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "authentication not required"); + return; + } + ctx->ctx.uid = req->uid; + ctx->ctx.uname = req->uname.utf8; + lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "TODO: auth not implemented"); + return; +} + +static void handle_Tattach(struct lib9p_req *ctx, struct lib9p_msg_Tattach *req, struct lib9p_msg_Rattach *resp) { + ctx->ctx.uid = req->uid; + ctx->ctx.uname = req->uname.utf8; + if (ctx->parent_sess->parent_conn->parent_srv->auth) { + /* + struct lib9p_srv_filehandle *fh = fidmap_get(req->afid); + if (!fh) + lib9p_error(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file is not a valid FID"); + else if (fh->type != FH_AUTH) + lib9p_error(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file is not an auth-file"); + else if (strcmp(fh->data.auth.uname, req->uname.utf8) != 0) + lib9p_errorf(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file is for user=\"%s\" and cannot be used for user=\"%s\"", + fh->data.auth.uname, req->uname.utf8); + else if (strcmp(fh->data.auth.aname, req->aname.utf8) != 0) + lib9p_errorf(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file is for tree=\"%s\" and cannot be used for tree=\"%s\"", + fh->data.auth.aname, req->aname.utf8); + else if (!fh->data.auth.authenticated) + lib9p_error(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file has not completed authentication"); + fh->refcount--; + if (lib9p_ctx_has_error(&ctx->ctx)) + return; + */ + lib9p_error(&ctx->ctx, LINUX_EOPNOTSUPP, "TODO: auth not implemented"); + return; + } else { + if (req->afid != LIB9P_NOFID) { + lib9p_error(&ctx->ctx, LINUX_EACCES, "FID provided as auth-file, but no auth-file is required"); + return; + } + } + + if (fidmap_load(&ctx->parent_sess->fids, req->fid)) { + lib9p_error(&ctx->ctx, LINUX_EBADF, "FID already in use"); + return; + } + + struct lib9p_srv_file rootdir = ctx->parent_sess->parent_conn->parent_srv->rootdir(&ctx->ctx, req->aname.utf8); + if (lib9p_ctx_has_error(&ctx->ctx.ctx)) + return; + + struct lib9p_srv_file *rootdir_ptr = fidmap_store(&ctx->parent_sess->fids, req->fid, rootdir); + if (!rootdir_ptr) { + lib9p_error(&ctx->ctx, LINUX_EMFILE, "too many open files"); + if (rootdir.free) + rootdir.free(ctx, rootdir.impldata); + return; + } + + resp->qid = rootdir.qid; + return; +} |