xref: /plan9-contrib/sys/src/cmd/disk/kfs/auth.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
1 /*
2  * Network listening authentication.
3  * This and all the other network-related
4  * code is due to Richard Miller.
5  */
6 #include	"all.h"
7 
8 int allownone;
9 
10 /*
11  *  create a challenge for a fid space
12  */
13 void
14 mkchallenge(Chan *cp)
15 {
16 	int i;
17 
18 	srand(truerand());
19 	for(i = 0; i < CHALLEN; i++)
20 		cp->chal[i] = nrand(256);
21 
22 	cp->idoffset = 0;
23 	cp->idvec = 0;
24 }
25 
26 /*
27  *  match a challenge from an attach
28  */
29 int
30 authorize(Chan *cp, Fcall *in, Fcall *ou)
31 {
32 	Ticket t;
33 	Authenticator a;
34 	int x;
35 	ulong bit;
36 
37 	if (cp == cons.srvchan)               /* local channel already safe */
38 		return 1;
39 
40 	if(noauth || wstatallow)		/* set to allow entry during boot */
41 		return 1;
42 
43 	if(strcmp(in->uname, "none") == 0)
44 		return allownone || cp->auth;
45 
46 	if(in->type == Toattach)
47 		return 0;
48 
49 	/* decrypt and unpack ticket */
50 	convM2T(in->ticket, &t, nvr.authkey);
51 	if(t.num != AuthTs){
52 print("bad AuthTs num\n");
53 		return 0;
54 	}
55 
56 	/* decrypt and unpack authenticator */
57 	convM2A(in->auth, &a, t.key);
58 	if(a.num != AuthAc){
59 print("bad AuthAc num\n");
60 		return 0;
61 	}
62 
63 	/* challenges must match */
64 	if(memcmp(a.chal, cp->chal, sizeof(a.chal)) != 0){
65 print("bad challenge\n");
66 		return 0;
67 	}
68 
69 	/*
70 	 *  the id must be in a valid range.  the range is specified by a
71 	 *  lower bount (idoffset) and a bit vector (idvec) where a
72 	 *  bit set to 1 means unusable
73 	 */
74 	lock(&cp->idlock);
75 	x = a.id - cp->idoffset;
76 	bit = 1<<x;
77 	if(x < 0 || x > 31 || (bit&cp->idvec)){
78 		unlock(&cp->idlock);
79 print("id out of range: idoff %ld idvec %lux id %ld\n", cp->idoffset, cp->idvec, a.id);
80 		return 0;
81 	}
82 	cp->idvec |= bit;
83 
84 	/* normalize the vector */
85 	while(cp->idvec&0xffff0001){
86 		cp->idvec >>= 1;
87 		cp->idoffset++;
88 	}
89 	unlock(&cp->idlock);
90 
91 	/* ticket name and attach name must match */
92 	if(memcmp(in->uname, t.cuid, sizeof(in->uname)) != 0){
93 print("names don't match\n");
94 		return 0;
95 	}
96 
97 	/* copy translated name into input record */
98 	memmove(in->uname, t.suid, sizeof(in->uname));
99 
100 	/* craft a reply */
101 	a.num = AuthAs;
102 	memmove(a.chal, cp->rchal, CHALLEN);
103 	convA2M(&a, ou->rauth, t.key);
104 
105 	cp->auth = 1;
106 	return 1;
107 }
108