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