aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/fossil/9auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/fossil/9auth.c')
-rw-r--r--src/cmd/fossil/9auth.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/src/cmd/fossil/9auth.c b/src/cmd/fossil/9auth.c
new file mode 100644
index 00000000..72b1f016
--- /dev/null
+++ b/src/cmd/fossil/9auth.c
@@ -0,0 +1,175 @@
+#include "stdinc.h"
+#include "9.h"
+
+int
+authRead(Fid* afid, void* data, int count)
+{
+ AuthInfo *ai;
+ AuthRpc *rpc;
+
+ if((rpc = afid->rpc) == nil){
+ vtSetError("not an auth fid");
+ return -1;
+ }
+
+ switch(auth_rpc(rpc, "read", nil, 0)){
+ default:
+ vtSetError("fossil authRead: auth protocol not finished");
+ return -1;
+ case ARdone:
+ if((ai = auth_getinfo(rpc)) == nil){
+ vtSetError("%r");
+ break;
+ }
+ if(ai->cuid == nil || *ai->cuid == '\0'){
+ vtSetError("auth with no cuid");
+ auth_freeAI(ai);
+ break;
+ }
+ assert(afid->cuname == nil);
+ afid->cuname = vtStrDup(ai->cuid);
+ auth_freeAI(ai);
+ if(Dflag)
+ fprint(2, "authRead cuname %s\n", afid->cuname);
+ assert(afid->uid == nil);
+ if((afid->uid = uidByUname(afid->cuname)) == nil){
+ vtSetError("unknown user %#q", afid->cuname);
+ break;
+ }
+ return 0;
+ case ARok:
+ if(count < rpc->narg){
+ vtSetError("not enough data in auth read");
+ break;
+ }
+ memmove(data, rpc->arg, rpc->narg);
+ return rpc->narg;
+ case ARphase:
+ vtSetError("%r");
+ break;
+ }
+ return -1;
+}
+
+int
+authWrite(Fid* afid, void* data, int count)
+{
+ assert(afid->rpc != nil);
+ if(auth_rpc(afid->rpc, "write", data, count) != ARok)
+ return -1;
+ return count;
+}
+
+int
+authCheck(Fcall* t, Fid* fid, Fsys* fsys)
+{
+ Con *con;
+ Fid *afid;
+ uchar buf[1];
+
+ /*
+ * Can't lookup with FidWlock here as there may be
+ * protocol to do. Use a separate lock to protect altering
+ * the auth information inside afid.
+ */
+ con = fid->con;
+ if(t->afid == NOFID){
+ /*
+ * If no authentication is asked for, allow
+ * "none" provided the connection has already
+ * been authenticatated.
+ *
+ * The console is allowed to attach without
+ * authentication.
+ */
+ vtRLock(con->alock);
+ if(con->isconsole){
+ /* anything goes */
+ }else if((con->flags&ConNoneAllow) || con->aok){
+ static int noneprint;
+
+ if(noneprint++ < 10)
+ consPrint("attach %s as %s: allowing as none\n",
+ fsysGetName(fsys), fid->uname);
+ vtMemFree(fid->uname);
+ fid->uname = vtStrDup(unamenone);
+ }else{
+ vtRUnlock(con->alock);
+ consPrint("attach %s as %s: connection not authenticated, not console\n",
+ fsysGetName(fsys), fid->uname);
+ vtSetError("cannot attach as none before authentication");
+ return 0;
+ }
+ vtRUnlock(con->alock);
+
+ if((fid->uid = uidByUname(fid->uname)) == nil){
+ consPrint("attach %s as %s: unknown uname\n",
+ fsysGetName(fsys), fid->uname);
+ vtSetError("unknown user");
+ return 0;
+ }
+ return 1;
+ }
+
+ if((afid = fidGet(con, t->afid, 0)) == nil){
+ consPrint("attach %s as %s: bad afid\n",
+ fsysGetName(fsys), fid->uname);
+ vtSetError("bad authentication fid");
+ return 0;
+ }
+
+ /*
+ * Check valid afid;
+ * check uname and aname match.
+ */
+ if(!(afid->qid.type & QTAUTH)){
+ consPrint("attach %s as %s: afid not an auth file\n",
+ fsysGetName(fsys), fid->uname);
+ fidPut(afid);
+ vtSetError("bad authentication fid");
+ return 0;
+ }
+ if(strcmp(afid->uname, fid->uname) != 0 || afid->fsys != fsys){
+ consPrint("attach %s as %s: afid is for %s as %s\n",
+ fsysGetName(fsys), fid->uname,
+ fsysGetName(afid->fsys), afid->uname);
+ fidPut(afid);
+ vtSetError("attach/auth mismatch");
+ return 0;
+ }
+
+ vtLock(afid->alock);
+ if(afid->cuname == nil){
+ if(authRead(afid, buf, 0) != 0 || afid->cuname == nil){
+ vtUnlock(afid->alock);
+ consPrint("attach %s as %s: %R\n",
+ fsysGetName(fsys), fid->uname);
+ fidPut(afid);
+ vtSetError("fossil authCheck: auth protocol not finished");
+ return 0;
+ }
+ }
+ vtUnlock(afid->alock);
+
+ assert(fid->uid == nil);
+ if((fid->uid = uidByUname(afid->cuname)) == nil){
+ consPrint("attach %s as %s: unknown cuname %s\n",
+ fsysGetName(fsys), fid->uname, afid->cuname);
+ fidPut(afid);
+ vtSetError("unknown user");
+ return 0;
+ }
+
+ vtMemFree(fid->uname);
+ fid->uname = vtStrDup(afid->cuname);
+ fidPut(afid);
+
+ /*
+ * Allow "none" once the connection has been authenticated.
+ */
+ vtLock(con->alock);
+ con->aok = 1;
+ vtUnlock(con->alock);
+
+ return 1;
+}