summaryrefslogtreecommitdiff
path: root/sys/src/cmd/cwfs/auth.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/cwfs/auth.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/cwfs/auth.c')
-rwxr-xr-xsys/src/cmd/cwfs/auth.c326
1 files changed, 326 insertions, 0 deletions
diff --git a/sys/src/cmd/cwfs/auth.c b/sys/src/cmd/cwfs/auth.c
new file mode 100755
index 000000000..4fba59ca8
--- /dev/null
+++ b/sys/src/cmd/cwfs/auth.c
@@ -0,0 +1,326 @@
+#include "all.h"
+#include "io.h"
+#include <authsrv.h>
+
+Nvrsafe nvr;
+
+static int gotnvr; /* flag: nvr contains nvram; it could be bad */
+
+char*
+nvrgetconfig(void)
+{
+ return conf.confdev;
+}
+
+/*
+ * we shouldn't be writing nvram any more.
+ * the secstore/config field is now just secstore key.
+ * we still use authid, authdom and machkey for authentication.
+ */
+
+int
+nvrcheck(void)
+{
+ uchar csum;
+
+ if (readnvram(&nvr, NVread) < 0) {
+ print("nvrcheck: can't read nvram\n");
+ return 1;
+ } else
+ gotnvr = 1;
+ print("nvr read\n");
+
+ csum = nvcsum(nvr.machkey, sizeof nvr.machkey);
+ if(csum != nvr.machsum) {
+ print("\n\n ** NVR key checksum is incorrect **\n");
+ print(" ** set password to allow attaches **\n\n");
+ memset(nvr.machkey, 0, sizeof nvr.machkey);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+nvrsetconfig(char* word)
+{
+ /* config block is on device `word' */
+ USED(word);
+ return 0;
+}
+
+int
+conslock(void)
+{
+ char *ln;
+ char nkey1[DESKEYLEN];
+ static char zeroes[DESKEYLEN];
+
+ if(memcmp(nvr.machkey, zeroes, DESKEYLEN) == 0) {
+ print("no password set\n");
+ return 0;
+ }
+
+ for(;;) {
+ print("%s password:", service);
+ /* could turn off echo here */
+
+ if ((ln = Brdline(&bin, '\n')) == nil)
+ return 0;
+ ln[Blinelen(&bin)-1] = '\0';
+
+ /* could turn on echo here */
+ memset(nkey1, 0, DESKEYLEN);
+ passtokey(nkey1, ln);
+ if(memcmp(nkey1, nvr.machkey, DESKEYLEN) == 0) {
+ prdate();
+ break;
+ }
+
+ print("Bad password\n");
+ delay(1000);
+ }
+ return 1;
+}
+
+/*
+ * authentication specific to 9P2000
+ */
+
+/* authentication states */
+enum
+{
+ HaveProtos=1,
+ NeedProto,
+ HaveOK,
+ NeedCchal,
+ HaveSinfo,
+ NeedTicket,
+ HaveSauthenticator,
+ SSuccess,
+};
+
+char *phasename[] =
+{
+[HaveProtos] "HaveProtos",
+[NeedProto] "NeedProto",
+[HaveOK] "HaveOK",
+[NeedCchal] "NeedCchal",
+[HaveSinfo] "HaveSinfo",
+[NeedTicket] "NeedTicket",
+[HaveSauthenticator] "HaveSauthenticator",
+[SSuccess] "SSuccess",
+};
+
+/* authentication structure */
+struct Auth
+{
+ int inuse;
+ char uname[NAMELEN]; /* requestor's remote user name */
+ char aname[NAMELEN]; /* requested aname */
+ Userid uid; /* uid decided on */
+ int phase;
+ char cchal[CHALLEN];
+ char tbuf[TICKETLEN+AUTHENTLEN]; /* server ticket */
+ Ticket t;
+ Ticketreq tr;
+};
+
+Auth* auths;
+Lock authlock;
+
+void
+authinit(void)
+{
+ auths = malloc(conf.nauth * sizeof(*auths));
+}
+
+static int
+failure(Auth *s, char *why)
+{
+ int i;
+
+if(*why)print("authentication failed: %s: %s\n", phasename[s->phase], why);
+ srand((uintptr)s + time(nil));
+ for(i = 0; i < CHALLEN; i++)
+ s->tr.chal[i] = nrand(256);
+ s->uid = -1;
+ strncpy(s->tr.authid, nvr.authid, NAMELEN);
+ strncpy(s->tr.authdom, nvr.authdom, DOMLEN);
+ memmove(s->cchal, s->tr.chal, sizeof(s->cchal));
+ s->phase = HaveProtos;
+ return -1;
+}
+
+Auth*
+authnew(char *uname, char *aname)
+{
+ static int si = 0;
+ int i, nwrap;
+ Auth *s;
+
+ i = si;
+ nwrap = 0;
+ for(;;){
+ if(i < 0 || i >= conf.nauth){
+ if(++nwrap > 1)
+ return nil;
+ i = 0;
+ }
+ s = &auths[i++];
+ if(s->inuse)
+ continue;
+ lock(&authlock);
+ if(s->inuse == 0){
+ s->inuse = 1;
+ strncpy(s->uname, uname, NAMELEN-1);
+ strncpy(s->aname, aname, NAMELEN-1);
+ failure(s, "");
+ si = i;
+ unlock(&authlock);
+ break;
+ }
+ unlock(&authlock);
+ }
+ return s;
+}
+
+void
+authfree(Auth *s)
+{
+ if(s != nil)
+ s->inuse = 0;
+}
+
+int
+authread(File* file, uchar* data, int n)
+{
+ Auth *s;
+ int m;
+
+ s = file->auth;
+ if(s == nil)
+ return -1;
+
+ switch(s->phase){
+ default:
+ return failure(s, "unexpected phase");
+ case HaveProtos:
+ m = snprint((char*)data, n, "v.2 p9sk1@%s", nvr.authdom) + 1;
+ s->phase = NeedProto;
+ break;
+ case HaveOK:
+ m = 3;
+ if(n < m)
+ return failure(s, "read too short");
+ strcpy((char*)data, "OK");
+ s->phase = NeedCchal;
+ break;
+ case HaveSinfo:
+ m = TICKREQLEN;
+ if(n < m)
+ return failure(s, "read too short");
+ convTR2M(&s->tr, (char*)data);
+ s->phase = NeedTicket;
+ break;
+ case HaveSauthenticator:
+ m = AUTHENTLEN;
+ if(n < m)
+ return failure(s, "read too short");
+ memmove(data, s->tbuf+TICKETLEN, m);
+ s->phase = SSuccess;
+ break;
+ }
+ return m;
+}
+
+int
+authwrite(File* file, uchar *data, int n)
+{
+ Auth *s;
+ int m;
+ char *p, *d;
+ Authenticator a;
+
+ s = file->auth;
+ if(s == nil)
+ return -1;
+
+ switch(s->phase){
+ default:
+ return failure(s, "unknown phase");
+ case NeedProto:
+ p = (char*)data;
+ if(p[n-1] != 0)
+ return failure(s, "proto missing terminator");
+ d = strchr(p, ' ');
+ if(d == nil)
+ return failure(s, "proto missing separator");
+ *d++ = 0;
+ if(strcmp(p, "p9sk1") != 0)
+ return failure(s, "unknown proto");
+ if(strcmp(d, nvr.authdom) != 0)
+ return failure(s, "unknown domain");
+ s->phase = HaveOK;
+ m = n;
+ break;
+ case NeedCchal:
+ m = CHALLEN;
+ if(n < m)
+ return failure(s, "client challenge too short");
+ memmove(s->cchal, data, sizeof(s->cchal));
+ s->phase = HaveSinfo;
+ break;
+ case NeedTicket:
+ m = TICKETLEN+AUTHENTLEN;
+ if(n < m)
+ return failure(s, "ticket+auth too short");
+
+ convM2T((char*)data, &s->t, nvr.machkey);
+ if(s->t.num != AuthTs
+ || memcmp(s->t.chal, s->tr.chal, sizeof(s->t.chal)) != 0)
+ return failure(s, "bad ticket");
+
+ convM2A((char*)data+TICKETLEN, &a, s->t.key);
+ if(a.num != AuthAc
+ || memcmp(a.chal, s->tr.chal, sizeof(a.chal)) != 0
+ || a.id != 0)
+ return failure(s, "bad authenticator");
+
+ /* at this point, we're convinced */
+ s->uid = strtouid(s->t.suid);
+ if(s->uid < 0)
+ return failure(s, "unknown user");
+ if(cons.flags & authdebugflag)
+ print("user %s = %d authenticated\n",
+ s->t.suid, s->uid);
+
+ /* create an authenticator to send back */
+ a.num = AuthAs;
+ memmove(a.chal, s->cchal, sizeof(a.chal));
+ a.id = 0;
+ convA2M(&a, s->tbuf+TICKETLEN, s->t.key);
+
+ s->phase = HaveSauthenticator;
+ break;
+ }
+ return m;
+}
+
+int
+authuid(Auth* s)
+{
+ return s->uid;
+}
+
+char*
+authaname(Auth* s)
+{
+ return s->aname;
+}
+
+char*
+authuname(Auth* s)
+{
+ return s->uname;
+}