159cc4ca5SDavid du Colombier /*
259cc4ca5SDavid du Colombier * Network listening authentication.
359cc4ca5SDavid du Colombier * This and all the other network-related
459cc4ca5SDavid du Colombier * code is due to Richard Miller.
559cc4ca5SDavid du Colombier */
659cc4ca5SDavid du Colombier #include "all.h"
79a747e4fSDavid du Colombier #include "9p1.h"
859cc4ca5SDavid du Colombier
959cc4ca5SDavid du Colombier int allownone;
109a747e4fSDavid du Colombier Nvrsafe nvr;
119a747e4fSDavid du Colombier int didread;
1259cc4ca5SDavid du Colombier
1359cc4ca5SDavid du Colombier /*
1459cc4ca5SDavid du Colombier * create a challenge for a fid space
1559cc4ca5SDavid du Colombier */
1659cc4ca5SDavid du Colombier void
mkchallenge(Chan * cp)1759cc4ca5SDavid du Colombier mkchallenge(Chan *cp)
1859cc4ca5SDavid du Colombier {
1959cc4ca5SDavid du Colombier int i;
2059cc4ca5SDavid du Colombier
219a747e4fSDavid du Colombier if(!didread && readnvram(&nvr, 0) >= 0)
229a747e4fSDavid du Colombier didread = 1;
239a747e4fSDavid du Colombier
2459cc4ca5SDavid du Colombier srand(truerand());
2559cc4ca5SDavid du Colombier for(i = 0; i < CHALLEN; i++)
2659cc4ca5SDavid du Colombier cp->chal[i] = nrand(256);
2759cc4ca5SDavid du Colombier
2859cc4ca5SDavid du Colombier cp->idoffset = 0;
2959cc4ca5SDavid du Colombier cp->idvec = 0;
3059cc4ca5SDavid du Colombier }
3159cc4ca5SDavid du Colombier
3259cc4ca5SDavid du Colombier /*
3359cc4ca5SDavid du Colombier * match a challenge from an attach
3459cc4ca5SDavid du Colombier */
359a747e4fSDavid du Colombier Nvrsafe nvr;
369a747e4fSDavid du Colombier
3759cc4ca5SDavid du Colombier int
authorize(Chan * cp,Oldfcall * in,Oldfcall * ou)389a747e4fSDavid du Colombier authorize(Chan *cp, Oldfcall *in, Oldfcall *ou)
3959cc4ca5SDavid du Colombier {
4059cc4ca5SDavid du Colombier Ticket t;
4159cc4ca5SDavid du Colombier Authenticator a;
4259cc4ca5SDavid du Colombier int x;
4359cc4ca5SDavid du Colombier ulong bit;
4459cc4ca5SDavid du Colombier
4559cc4ca5SDavid du Colombier if (cp == cons.srvchan) /* local channel already safe */
4659cc4ca5SDavid du Colombier return 1;
4759cc4ca5SDavid du Colombier
489a747e4fSDavid du Colombier if(wstatallow) /* set to allow entry during boot */
4959cc4ca5SDavid du Colombier return 1;
5059cc4ca5SDavid du Colombier
5159cc4ca5SDavid du Colombier if(strcmp(in->uname, "none") == 0)
529a747e4fSDavid du Colombier return allownone || cp->authed;
5359cc4ca5SDavid du Colombier
549a747e4fSDavid du Colombier if(in->type == Toattach9p1)
559a747e4fSDavid du Colombier return 0;
569a747e4fSDavid du Colombier
579a747e4fSDavid du Colombier if(!didread)
5859cc4ca5SDavid du Colombier return 0;
5959cc4ca5SDavid du Colombier
6059cc4ca5SDavid du Colombier /* decrypt and unpack ticket */
61*d9306527SDavid du Colombier convM2T(in->ticket, &t, nvr.machkey);
6259cc4ca5SDavid du Colombier if(t.num != AuthTs){
6359cc4ca5SDavid du Colombier print("bad AuthTs num\n");
6459cc4ca5SDavid du Colombier return 0;
6559cc4ca5SDavid du Colombier }
6659cc4ca5SDavid du Colombier
6759cc4ca5SDavid du Colombier /* decrypt and unpack authenticator */
6859cc4ca5SDavid du Colombier convM2A(in->auth, &a, t.key);
6959cc4ca5SDavid du Colombier if(a.num != AuthAc){
7059cc4ca5SDavid du Colombier print("bad AuthAc num\n");
7159cc4ca5SDavid du Colombier return 0;
7259cc4ca5SDavid du Colombier }
7359cc4ca5SDavid du Colombier
7459cc4ca5SDavid du Colombier /* challenges must match */
7559cc4ca5SDavid du Colombier if(memcmp(a.chal, cp->chal, sizeof(a.chal)) != 0){
7659cc4ca5SDavid du Colombier print("bad challenge\n");
7759cc4ca5SDavid du Colombier return 0;
7859cc4ca5SDavid du Colombier }
7959cc4ca5SDavid du Colombier
8059cc4ca5SDavid du Colombier /*
8159cc4ca5SDavid du Colombier * the id must be in a valid range. the range is specified by a
8259cc4ca5SDavid du Colombier * lower bount (idoffset) and a bit vector (idvec) where a
8359cc4ca5SDavid du Colombier * bit set to 1 means unusable
8459cc4ca5SDavid du Colombier */
8559cc4ca5SDavid du Colombier lock(&cp->idlock);
8659cc4ca5SDavid du Colombier x = a.id - cp->idoffset;
8759cc4ca5SDavid du Colombier bit = 1<<x;
8859cc4ca5SDavid du Colombier if(x < 0 || x > 31 || (bit&cp->idvec)){
8959cc4ca5SDavid du Colombier unlock(&cp->idlock);
9059cc4ca5SDavid du Colombier return 0;
9159cc4ca5SDavid du Colombier }
9259cc4ca5SDavid du Colombier cp->idvec |= bit;
9359cc4ca5SDavid du Colombier
9459cc4ca5SDavid du Colombier /* normalize the vector */
9559cc4ca5SDavid du Colombier while(cp->idvec&0xffff0001){
9659cc4ca5SDavid du Colombier cp->idvec >>= 1;
9759cc4ca5SDavid du Colombier cp->idoffset++;
9859cc4ca5SDavid du Colombier }
9959cc4ca5SDavid du Colombier unlock(&cp->idlock);
10059cc4ca5SDavid du Colombier
10159cc4ca5SDavid du Colombier /* ticket name and attach name must match */
10259cc4ca5SDavid du Colombier if(memcmp(in->uname, t.cuid, sizeof(in->uname)) != 0){
10359cc4ca5SDavid du Colombier print("names don't match\n");
10459cc4ca5SDavid du Colombier return 0;
10559cc4ca5SDavid du Colombier }
10659cc4ca5SDavid du Colombier
10759cc4ca5SDavid du Colombier /* copy translated name into input record */
10859cc4ca5SDavid du Colombier memmove(in->uname, t.suid, sizeof(in->uname));
10959cc4ca5SDavid du Colombier
11059cc4ca5SDavid du Colombier /* craft a reply */
11159cc4ca5SDavid du Colombier a.num = AuthAs;
11259cc4ca5SDavid du Colombier memmove(a.chal, cp->rchal, CHALLEN);
11359cc4ca5SDavid du Colombier convA2M(&a, ou->rauth, t.key);
11459cc4ca5SDavid du Colombier
1159a747e4fSDavid du Colombier cp->authed = 1;
11659cc4ca5SDavid du Colombier return 1;
11759cc4ca5SDavid du Colombier }
118