101a344a2SDavid du Colombier #include "all.h"
201a344a2SDavid du Colombier #include "io.h"
301a344a2SDavid du Colombier #include <authsrv.h>
401a344a2SDavid du Colombier
501a344a2SDavid du Colombier Nvrsafe nvr;
601a344a2SDavid du Colombier
701a344a2SDavid du Colombier static int gotnvr; /* flag: nvr contains nvram; it could be bad */
801a344a2SDavid du Colombier
901a344a2SDavid du Colombier char*
nvrgetconfig(void)1001a344a2SDavid du Colombier nvrgetconfig(void)
1101a344a2SDavid du Colombier {
1201a344a2SDavid du Colombier return conf.confdev;
1301a344a2SDavid du Colombier }
1401a344a2SDavid du Colombier
1501a344a2SDavid du Colombier /*
1601a344a2SDavid du Colombier * we shouldn't be writing nvram any more.
1701a344a2SDavid du Colombier * the secstore/config field is now just secstore key.
1801a344a2SDavid du Colombier * we still use authid, authdom and machkey for authentication.
1901a344a2SDavid du Colombier */
2001a344a2SDavid du Colombier
2101a344a2SDavid du Colombier int
nvrcheck(void)2201a344a2SDavid du Colombier nvrcheck(void)
2301a344a2SDavid du Colombier {
2401a344a2SDavid du Colombier uchar csum;
2501a344a2SDavid du Colombier
2601a344a2SDavid du Colombier if (readnvram(&nvr, NVread) < 0) {
2701a344a2SDavid du Colombier print("nvrcheck: can't read nvram\n");
2801a344a2SDavid du Colombier return 1;
2901a344a2SDavid du Colombier } else
3001a344a2SDavid du Colombier gotnvr = 1;
3101a344a2SDavid du Colombier print("nvr read\n");
3201a344a2SDavid du Colombier
3301a344a2SDavid du Colombier csum = nvcsum(nvr.machkey, sizeof nvr.machkey);
3401a344a2SDavid du Colombier if(csum != nvr.machsum) {
3501a344a2SDavid du Colombier print("\n\n ** NVR key checksum is incorrect **\n");
3601a344a2SDavid du Colombier print(" ** set password to allow attaches **\n\n");
3701a344a2SDavid du Colombier memset(nvr.machkey, 0, sizeof nvr.machkey);
3801a344a2SDavid du Colombier return 1;
3901a344a2SDavid du Colombier }
4001a344a2SDavid du Colombier
4101a344a2SDavid du Colombier return 0;
4201a344a2SDavid du Colombier }
4301a344a2SDavid du Colombier
4401a344a2SDavid du Colombier int
nvrsetconfig(char * word)4501a344a2SDavid du Colombier nvrsetconfig(char* word)
4601a344a2SDavid du Colombier {
4701a344a2SDavid du Colombier /* config block is on device `word' */
4801a344a2SDavid du Colombier USED(word);
4901a344a2SDavid du Colombier return 0;
5001a344a2SDavid du Colombier }
5101a344a2SDavid du Colombier
5201a344a2SDavid du Colombier int
conslock(void)5301a344a2SDavid du Colombier conslock(void)
5401a344a2SDavid du Colombier {
5501a344a2SDavid du Colombier char *ln;
5601a344a2SDavid du Colombier char nkey1[DESKEYLEN];
5701a344a2SDavid du Colombier static char zeroes[DESKEYLEN];
5801a344a2SDavid du Colombier
5901a344a2SDavid du Colombier if(memcmp(nvr.machkey, zeroes, DESKEYLEN) == 0) {
6001a344a2SDavid du Colombier print("no password set\n");
6101a344a2SDavid du Colombier return 0;
6201a344a2SDavid du Colombier }
6301a344a2SDavid du Colombier
6401a344a2SDavid du Colombier for(;;) {
6501a344a2SDavid du Colombier print("%s password:", service);
6601a344a2SDavid du Colombier /* could turn off echo here */
6701a344a2SDavid du Colombier
6801a344a2SDavid du Colombier if ((ln = Brdline(&bin, '\n')) == nil)
6901a344a2SDavid du Colombier return 0;
7001a344a2SDavid du Colombier ln[Blinelen(&bin)-1] = '\0';
7101a344a2SDavid du Colombier
7201a344a2SDavid du Colombier /* could turn on echo here */
7301a344a2SDavid du Colombier memset(nkey1, 0, DESKEYLEN);
7401a344a2SDavid du Colombier passtokey(nkey1, ln);
7501a344a2SDavid du Colombier if(memcmp(nkey1, nvr.machkey, DESKEYLEN) == 0) {
7601a344a2SDavid du Colombier prdate();
7701a344a2SDavid du Colombier break;
7801a344a2SDavid du Colombier }
7901a344a2SDavid du Colombier
8001a344a2SDavid du Colombier print("Bad password\n");
8101a344a2SDavid du Colombier delay(1000);
8201a344a2SDavid du Colombier }
8301a344a2SDavid du Colombier return 1;
8401a344a2SDavid du Colombier }
8501a344a2SDavid du Colombier
8601a344a2SDavid du Colombier /*
8701a344a2SDavid du Colombier * authentication specific to 9P2000
8801a344a2SDavid du Colombier */
8901a344a2SDavid du Colombier
9001a344a2SDavid du Colombier /* authentication states */
9101a344a2SDavid du Colombier enum
9201a344a2SDavid du Colombier {
9301a344a2SDavid du Colombier HaveProtos=1,
9401a344a2SDavid du Colombier NeedProto,
9501a344a2SDavid du Colombier HaveOK,
9601a344a2SDavid du Colombier NeedCchal,
9701a344a2SDavid du Colombier HaveSinfo,
9801a344a2SDavid du Colombier NeedTicket,
9901a344a2SDavid du Colombier HaveSauthenticator,
10001a344a2SDavid du Colombier SSuccess,
10101a344a2SDavid du Colombier };
10201a344a2SDavid du Colombier
10301a344a2SDavid du Colombier char *phasename[] =
10401a344a2SDavid du Colombier {
10501a344a2SDavid du Colombier [HaveProtos] "HaveProtos",
10601a344a2SDavid du Colombier [NeedProto] "NeedProto",
10701a344a2SDavid du Colombier [HaveOK] "HaveOK",
10801a344a2SDavid du Colombier [NeedCchal] "NeedCchal",
10901a344a2SDavid du Colombier [HaveSinfo] "HaveSinfo",
11001a344a2SDavid du Colombier [NeedTicket] "NeedTicket",
11101a344a2SDavid du Colombier [HaveSauthenticator] "HaveSauthenticator",
11201a344a2SDavid du Colombier [SSuccess] "SSuccess",
11301a344a2SDavid du Colombier };
11401a344a2SDavid du Colombier
11501a344a2SDavid du Colombier /* authentication structure */
11601a344a2SDavid du Colombier struct Auth
11701a344a2SDavid du Colombier {
11801a344a2SDavid du Colombier int inuse;
11901a344a2SDavid du Colombier char uname[NAMELEN]; /* requestor's remote user name */
12001a344a2SDavid du Colombier char aname[NAMELEN]; /* requested aname */
12101a344a2SDavid du Colombier Userid uid; /* uid decided on */
12201a344a2SDavid du Colombier int phase;
12301a344a2SDavid du Colombier char cchal[CHALLEN];
12401a344a2SDavid du Colombier char tbuf[TICKETLEN+AUTHENTLEN]; /* server ticket */
12501a344a2SDavid du Colombier Ticket t;
12601a344a2SDavid du Colombier Ticketreq tr;
12701a344a2SDavid du Colombier };
12801a344a2SDavid du Colombier
12901a344a2SDavid du Colombier Auth* auths;
13001a344a2SDavid du Colombier Lock authlock;
13101a344a2SDavid du Colombier
13201a344a2SDavid du Colombier void
authinit(void)13301a344a2SDavid du Colombier authinit(void)
13401a344a2SDavid du Colombier {
13501a344a2SDavid du Colombier auths = malloc(conf.nauth * sizeof(*auths));
13601a344a2SDavid du Colombier }
13701a344a2SDavid du Colombier
13801a344a2SDavid du Colombier static int
failure(Auth * s,char * why)13901a344a2SDavid du Colombier failure(Auth *s, char *why)
14001a344a2SDavid du Colombier {
14101a344a2SDavid du Colombier int i;
14201a344a2SDavid du Colombier
14301a344a2SDavid du Colombier if(*why)print("authentication failed: %s: %s\n", phasename[s->phase], why);
144*223a0358SDavid du Colombier srand((uintptr)s + time(nil));
14501a344a2SDavid du Colombier for(i = 0; i < CHALLEN; i++)
14601a344a2SDavid du Colombier s->tr.chal[i] = nrand(256);
14701a344a2SDavid du Colombier s->uid = -1;
14801a344a2SDavid du Colombier strncpy(s->tr.authid, nvr.authid, NAMELEN);
14901a344a2SDavid du Colombier strncpy(s->tr.authdom, nvr.authdom, DOMLEN);
15001a344a2SDavid du Colombier memmove(s->cchal, s->tr.chal, sizeof(s->cchal));
15101a344a2SDavid du Colombier s->phase = HaveProtos;
15201a344a2SDavid du Colombier return -1;
15301a344a2SDavid du Colombier }
15401a344a2SDavid du Colombier
15501a344a2SDavid du Colombier Auth*
authnew(char * uname,char * aname)15601a344a2SDavid du Colombier authnew(char *uname, char *aname)
15701a344a2SDavid du Colombier {
15801a344a2SDavid du Colombier static int si = 0;
15901a344a2SDavid du Colombier int i, nwrap;
16001a344a2SDavid du Colombier Auth *s;
16101a344a2SDavid du Colombier
16201a344a2SDavid du Colombier i = si;
16301a344a2SDavid du Colombier nwrap = 0;
16401a344a2SDavid du Colombier for(;;){
16501a344a2SDavid du Colombier if(i < 0 || i >= conf.nauth){
16601a344a2SDavid du Colombier if(++nwrap > 1)
16701a344a2SDavid du Colombier return nil;
16801a344a2SDavid du Colombier i = 0;
16901a344a2SDavid du Colombier }
17001a344a2SDavid du Colombier s = &auths[i++];
17101a344a2SDavid du Colombier if(s->inuse)
17201a344a2SDavid du Colombier continue;
17301a344a2SDavid du Colombier lock(&authlock);
17401a344a2SDavid du Colombier if(s->inuse == 0){
17501a344a2SDavid du Colombier s->inuse = 1;
17601a344a2SDavid du Colombier strncpy(s->uname, uname, NAMELEN-1);
17701a344a2SDavid du Colombier strncpy(s->aname, aname, NAMELEN-1);
17801a344a2SDavid du Colombier failure(s, "");
17901a344a2SDavid du Colombier si = i;
18001a344a2SDavid du Colombier unlock(&authlock);
18101a344a2SDavid du Colombier break;
18201a344a2SDavid du Colombier }
18301a344a2SDavid du Colombier unlock(&authlock);
18401a344a2SDavid du Colombier }
18501a344a2SDavid du Colombier return s;
18601a344a2SDavid du Colombier }
18701a344a2SDavid du Colombier
18801a344a2SDavid du Colombier void
authfree(Auth * s)18901a344a2SDavid du Colombier authfree(Auth *s)
19001a344a2SDavid du Colombier {
19101a344a2SDavid du Colombier if(s != nil)
19201a344a2SDavid du Colombier s->inuse = 0;
19301a344a2SDavid du Colombier }
19401a344a2SDavid du Colombier
19501a344a2SDavid du Colombier int
authread(File * file,uchar * data,int n)19601a344a2SDavid du Colombier authread(File* file, uchar* data, int n)
19701a344a2SDavid du Colombier {
19801a344a2SDavid du Colombier Auth *s;
19901a344a2SDavid du Colombier int m;
20001a344a2SDavid du Colombier
20101a344a2SDavid du Colombier s = file->auth;
20201a344a2SDavid du Colombier if(s == nil)
20301a344a2SDavid du Colombier return -1;
20401a344a2SDavid du Colombier
20501a344a2SDavid du Colombier switch(s->phase){
20601a344a2SDavid du Colombier default:
20701a344a2SDavid du Colombier return failure(s, "unexpected phase");
20801a344a2SDavid du Colombier case HaveProtos:
20901a344a2SDavid du Colombier m = snprint((char*)data, n, "v.2 p9sk1@%s", nvr.authdom) + 1;
21001a344a2SDavid du Colombier s->phase = NeedProto;
21101a344a2SDavid du Colombier break;
21201a344a2SDavid du Colombier case HaveOK:
21301a344a2SDavid du Colombier m = 3;
21401a344a2SDavid du Colombier if(n < m)
21501a344a2SDavid du Colombier return failure(s, "read too short");
21601a344a2SDavid du Colombier strcpy((char*)data, "OK");
21701a344a2SDavid du Colombier s->phase = NeedCchal;
21801a344a2SDavid du Colombier break;
21901a344a2SDavid du Colombier case HaveSinfo:
22001a344a2SDavid du Colombier m = TICKREQLEN;
22101a344a2SDavid du Colombier if(n < m)
22201a344a2SDavid du Colombier return failure(s, "read too short");
22301a344a2SDavid du Colombier convTR2M(&s->tr, (char*)data);
22401a344a2SDavid du Colombier s->phase = NeedTicket;
22501a344a2SDavid du Colombier break;
22601a344a2SDavid du Colombier case HaveSauthenticator:
22701a344a2SDavid du Colombier m = AUTHENTLEN;
22801a344a2SDavid du Colombier if(n < m)
22901a344a2SDavid du Colombier return failure(s, "read too short");
23001a344a2SDavid du Colombier memmove(data, s->tbuf+TICKETLEN, m);
23101a344a2SDavid du Colombier s->phase = SSuccess;
23201a344a2SDavid du Colombier break;
23301a344a2SDavid du Colombier }
23401a344a2SDavid du Colombier return m;
23501a344a2SDavid du Colombier }
23601a344a2SDavid du Colombier
23701a344a2SDavid du Colombier int
authwrite(File * file,uchar * data,int n)23801a344a2SDavid du Colombier authwrite(File* file, uchar *data, int n)
23901a344a2SDavid du Colombier {
24001a344a2SDavid du Colombier Auth *s;
24101a344a2SDavid du Colombier int m;
24201a344a2SDavid du Colombier char *p, *d;
24301a344a2SDavid du Colombier Authenticator a;
24401a344a2SDavid du Colombier
24501a344a2SDavid du Colombier s = file->auth;
24601a344a2SDavid du Colombier if(s == nil)
24701a344a2SDavid du Colombier return -1;
24801a344a2SDavid du Colombier
24901a344a2SDavid du Colombier switch(s->phase){
25001a344a2SDavid du Colombier default:
25101a344a2SDavid du Colombier return failure(s, "unknown phase");
25201a344a2SDavid du Colombier case NeedProto:
25301a344a2SDavid du Colombier p = (char*)data;
25401a344a2SDavid du Colombier if(p[n-1] != 0)
25501a344a2SDavid du Colombier return failure(s, "proto missing terminator");
25601a344a2SDavid du Colombier d = strchr(p, ' ');
25701a344a2SDavid du Colombier if(d == nil)
25801a344a2SDavid du Colombier return failure(s, "proto missing separator");
25901a344a2SDavid du Colombier *d++ = 0;
26001a344a2SDavid du Colombier if(strcmp(p, "p9sk1") != 0)
26101a344a2SDavid du Colombier return failure(s, "unknown proto");
26201a344a2SDavid du Colombier if(strcmp(d, nvr.authdom) != 0)
26301a344a2SDavid du Colombier return failure(s, "unknown domain");
26401a344a2SDavid du Colombier s->phase = HaveOK;
26501a344a2SDavid du Colombier m = n;
26601a344a2SDavid du Colombier break;
26701a344a2SDavid du Colombier case NeedCchal:
26801a344a2SDavid du Colombier m = CHALLEN;
26901a344a2SDavid du Colombier if(n < m)
27001a344a2SDavid du Colombier return failure(s, "client challenge too short");
27101a344a2SDavid du Colombier memmove(s->cchal, data, sizeof(s->cchal));
27201a344a2SDavid du Colombier s->phase = HaveSinfo;
27301a344a2SDavid du Colombier break;
27401a344a2SDavid du Colombier case NeedTicket:
27501a344a2SDavid du Colombier m = TICKETLEN+AUTHENTLEN;
27601a344a2SDavid du Colombier if(n < m)
27701a344a2SDavid du Colombier return failure(s, "ticket+auth too short");
27801a344a2SDavid du Colombier
27901a344a2SDavid du Colombier convM2T((char*)data, &s->t, nvr.machkey);
28001a344a2SDavid du Colombier if(s->t.num != AuthTs
28101a344a2SDavid du Colombier || memcmp(s->t.chal, s->tr.chal, sizeof(s->t.chal)) != 0)
28201a344a2SDavid du Colombier return failure(s, "bad ticket");
28301a344a2SDavid du Colombier
28401a344a2SDavid du Colombier convM2A((char*)data+TICKETLEN, &a, s->t.key);
28501a344a2SDavid du Colombier if(a.num != AuthAc
28601a344a2SDavid du Colombier || memcmp(a.chal, s->tr.chal, sizeof(a.chal)) != 0
28701a344a2SDavid du Colombier || a.id != 0)
28801a344a2SDavid du Colombier return failure(s, "bad authenticator");
28901a344a2SDavid du Colombier
29001a344a2SDavid du Colombier /* at this point, we're convinced */
29101a344a2SDavid du Colombier s->uid = strtouid(s->t.suid);
29201a344a2SDavid du Colombier if(s->uid < 0)
29301a344a2SDavid du Colombier return failure(s, "unknown user");
29401a344a2SDavid du Colombier if(cons.flags & authdebugflag)
29501a344a2SDavid du Colombier print("user %s = %d authenticated\n",
29601a344a2SDavid du Colombier s->t.suid, s->uid);
29701a344a2SDavid du Colombier
29801a344a2SDavid du Colombier /* create an authenticator to send back */
29901a344a2SDavid du Colombier a.num = AuthAs;
30001a344a2SDavid du Colombier memmove(a.chal, s->cchal, sizeof(a.chal));
30101a344a2SDavid du Colombier a.id = 0;
30201a344a2SDavid du Colombier convA2M(&a, s->tbuf+TICKETLEN, s->t.key);
30301a344a2SDavid du Colombier
30401a344a2SDavid du Colombier s->phase = HaveSauthenticator;
30501a344a2SDavid du Colombier break;
30601a344a2SDavid du Colombier }
30701a344a2SDavid du Colombier return m;
30801a344a2SDavid du Colombier }
30901a344a2SDavid du Colombier
31001a344a2SDavid du Colombier int
authuid(Auth * s)31101a344a2SDavid du Colombier authuid(Auth* s)
31201a344a2SDavid du Colombier {
31301a344a2SDavid du Colombier return s->uid;
31401a344a2SDavid du Colombier }
31501a344a2SDavid du Colombier
31601a344a2SDavid du Colombier char*
authaname(Auth * s)31701a344a2SDavid du Colombier authaname(Auth* s)
31801a344a2SDavid du Colombier {
31901a344a2SDavid du Colombier return s->aname;
32001a344a2SDavid du Colombier }
32101a344a2SDavid du Colombier
32201a344a2SDavid du Colombier char*
authuname(Auth * s)32301a344a2SDavid du Colombier authuname(Auth* s)
32401a344a2SDavid du Colombier {
32501a344a2SDavid du Colombier return s->uname;
32601a344a2SDavid du Colombier }
327