xref: /plan9/sys/src/cmd/auth/lib/netcheck.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier #include <u.h>
2*219b2ee8SDavid du Colombier #include <libc.h>
3*219b2ee8SDavid du Colombier #include <auth.h>
4*219b2ee8SDavid du Colombier #include "authsrv.h"
5*219b2ee8SDavid du Colombier 
6*219b2ee8SDavid du Colombier /*
7*219b2ee8SDavid du Colombier  * compute the key verification checksum
8*219b2ee8SDavid du Colombier  */
9*219b2ee8SDavid du Colombier void
10*219b2ee8SDavid du Colombier checksum(char key[], char csum[]) {
11*219b2ee8SDavid du Colombier 	uchar buf[8];
12*219b2ee8SDavid du Colombier 
13*219b2ee8SDavid du Colombier 	memset(buf, 0, 8);
14*219b2ee8SDavid du Colombier 	encrypt(key, buf, 8);
15*219b2ee8SDavid du Colombier 	sprint(csum, "C %.2ux%.2ux%.2ux", buf[0], buf[1], buf[2], buf[3]);
16*219b2ee8SDavid du Colombier }
17*219b2ee8SDavid du Colombier 
18*219b2ee8SDavid du Colombier /*
19*219b2ee8SDavid du Colombier  * compute the proper response.  We encrypt the ascii of
20*219b2ee8SDavid du Colombier  * challenge number, with trailing binary zero fill.
21*219b2ee8SDavid du Colombier  * This process was derived empirically.
22*219b2ee8SDavid du Colombier  * this was copied from inet's guard.
23*219b2ee8SDavid du Colombier  */
24*219b2ee8SDavid du Colombier char *
25*219b2ee8SDavid du Colombier netresp(char *key, long chal, char *answer)
26*219b2ee8SDavid du Colombier {
27*219b2ee8SDavid du Colombier 	uchar buf[8];
28*219b2ee8SDavid du Colombier 
29*219b2ee8SDavid du Colombier 	memset(buf, 0, 8);
30*219b2ee8SDavid du Colombier 	sprint((char *)buf, "%lud", chal);
31*219b2ee8SDavid du Colombier 	if(encrypt(key, buf, 8) < 0)
32*219b2ee8SDavid du Colombier 		error("can't encrypt response");
33*219b2ee8SDavid du Colombier 	chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];
34*219b2ee8SDavid du Colombier 	sprint(answer, "%.8lux", chal);
35*219b2ee8SDavid du Colombier 
36*219b2ee8SDavid du Colombier 	return answer;
37*219b2ee8SDavid du Colombier }
38*219b2ee8SDavid du Colombier 
39*219b2ee8SDavid du Colombier char *
40*219b2ee8SDavid du Colombier netdecimal(char *answer)
41*219b2ee8SDavid du Colombier {
42*219b2ee8SDavid du Colombier 	int i;
43*219b2ee8SDavid du Colombier 
44*219b2ee8SDavid du Colombier 	for(i = 0; answer[i]; i++)
45*219b2ee8SDavid du Colombier 		switch(answer[i]){
46*219b2ee8SDavid du Colombier 		case 'a': case 'b': case 'c':
47*219b2ee8SDavid du Colombier 			answer[i] = '2';
48*219b2ee8SDavid du Colombier 			break;
49*219b2ee8SDavid du Colombier 		case 'd': case 'e': case 'f':
50*219b2ee8SDavid du Colombier 			answer[i] = '3';
51*219b2ee8SDavid du Colombier 			break;
52*219b2ee8SDavid du Colombier 		}
53*219b2ee8SDavid du Colombier 	return answer;
54*219b2ee8SDavid du Colombier }
55*219b2ee8SDavid du Colombier 
56*219b2ee8SDavid du Colombier int
57*219b2ee8SDavid du Colombier netcheck(void *key, long chal, char *response)
58*219b2ee8SDavid du Colombier {
59*219b2ee8SDavid du Colombier 	char answer[32], *p;
60*219b2ee8SDavid du Colombier 	int i;
61*219b2ee8SDavid du Colombier 
62*219b2ee8SDavid du Colombier 	if(smartcheck(key, chal, response))
63*219b2ee8SDavid du Colombier 		return 1;
64*219b2ee8SDavid du Colombier 
65*219b2ee8SDavid du Colombier 	if(p = strchr(response, '\n'))
66*219b2ee8SDavid du Colombier 		*p = '\0';
67*219b2ee8SDavid du Colombier 	netresp(key, chal, answer);
68*219b2ee8SDavid du Colombier 
69*219b2ee8SDavid du Colombier 	/*
70*219b2ee8SDavid du Colombier 	 * check for hex response -- securenet mode 1 or 5
71*219b2ee8SDavid du Colombier 	 */
72*219b2ee8SDavid du Colombier 	for(i = 0; response[i]; i++)
73*219b2ee8SDavid du Colombier 		if(response[i] >= 'A' && response[i] <= 'Z')
74*219b2ee8SDavid du Colombier 			response[i] -= 'A' - 'a';
75*219b2ee8SDavid du Colombier 	if(strcmp(answer, response) == 0)
76*219b2ee8SDavid du Colombier 		return 1;
77*219b2ee8SDavid du Colombier 
78*219b2ee8SDavid du Colombier 	/*
79*219b2ee8SDavid du Colombier 	 * check for decimal response -- securenet mode 0 or 4
80*219b2ee8SDavid du Colombier 	 */
81*219b2ee8SDavid du Colombier 	return strcmp(netdecimal(answer), response) == 0;
82*219b2ee8SDavid du Colombier }
83*219b2ee8SDavid du Colombier 
84*219b2ee8SDavid du Colombier int
85*219b2ee8SDavid du Colombier smartcheck(void *key, long chal, char *response)
86*219b2ee8SDavid du Colombier {
87*219b2ee8SDavid du Colombier 	uchar buf[2*8];
88*219b2ee8SDavid du Colombier 	int i, c, cslo, cshi;
89*219b2ee8SDavid du Colombier 
90*219b2ee8SDavid du Colombier 	sprint((char*)buf, "%lud        ", chal);
91*219b2ee8SDavid du Colombier 	cslo = 0x52;
92*219b2ee8SDavid du Colombier 	cshi = cslo;
93*219b2ee8SDavid du Colombier 	for(i = 0; i < 8; i++){
94*219b2ee8SDavid du Colombier 		c = buf[i];
95*219b2ee8SDavid du Colombier 		if(c >= '0' && c <= '9')
96*219b2ee8SDavid du Colombier 			c -= '0';
97*219b2ee8SDavid du Colombier 		cslo += c;
98*219b2ee8SDavid du Colombier 		if(cslo > 0xff)
99*219b2ee8SDavid du Colombier 			cslo -= 0xff;
100*219b2ee8SDavid du Colombier 		cshi += cslo;
101*219b2ee8SDavid du Colombier 		if(cshi > 0xff)
102*219b2ee8SDavid du Colombier 			cshi -= 0xff;
103*219b2ee8SDavid du Colombier 		buf[i] = c | (cshi & 0xf0);
104*219b2ee8SDavid du Colombier 	}
105*219b2ee8SDavid du Colombier 
106*219b2ee8SDavid du Colombier 	encrypt(key, buf, 8);
107*219b2ee8SDavid du Colombier 	for(i = 0; i < 8; i++)
108*219b2ee8SDavid du Colombier 		if(response[i] != buf[i] % 10 + '0')
109*219b2ee8SDavid du Colombier 			return 0;
110*219b2ee8SDavid du Colombier 	return 1;
111*219b2ee8SDavid du Colombier }
112