xref: /plan9/sys/src/cmd/auth/lib/netcheck.c (revision f54edc786b9c49b2c7ab1c0695cdc8c698b11f4d)
1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
35979f962SDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include "authcmdlib.h"
5219b2ee8SDavid du Colombier 
6219b2ee8SDavid du Colombier /*
7219b2ee8SDavid du Colombier  * compute the key verification checksum
8219b2ee8SDavid du Colombier  */
9219b2ee8SDavid du Colombier void
checksum(char key[],char csum[])10219b2ee8SDavid du Colombier checksum(char key[], char csum[]) {
11219b2ee8SDavid du Colombier 	uchar buf[8];
12219b2ee8SDavid du Colombier 
13219b2ee8SDavid du Colombier 	memset(buf, 0, 8);
14219b2ee8SDavid du Colombier 	encrypt(key, buf, 8);
157dd7cddfSDavid du Colombier 	sprint(csum, "C %.2ux%.2ux%.2ux%.2ux", buf[0], buf[1], buf[2], buf[3]);
16219b2ee8SDavid du Colombier }
17219b2ee8SDavid du Colombier 
18219b2ee8SDavid du Colombier /*
19219b2ee8SDavid du Colombier  * compute the proper response.  We encrypt the ascii of
20219b2ee8SDavid du Colombier  * challenge number, with trailing binary zero fill.
21219b2ee8SDavid du Colombier  * This process was derived empirically.
22219b2ee8SDavid du Colombier  * this was copied from inet's guard.
23219b2ee8SDavid du Colombier  */
24219b2ee8SDavid du Colombier char *
netresp(char * key,long chal,char * answer)25219b2ee8SDavid du Colombier netresp(char *key, long chal, char *answer)
26219b2ee8SDavid du Colombier {
27219b2ee8SDavid du Colombier 	uchar buf[8];
28219b2ee8SDavid du Colombier 
29219b2ee8SDavid du Colombier 	memset(buf, 0, 8);
30*f54edc78SDavid du Colombier 	snprint((char *)buf, sizeof buf, "%lud", chal);
31219b2ee8SDavid du Colombier 	if(encrypt(key, buf, 8) < 0)
32219b2ee8SDavid du Colombier 		error("can't encrypt response");
33219b2ee8SDavid du Colombier 	chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];
34219b2ee8SDavid du Colombier 	sprint(answer, "%.8lux", chal);
35219b2ee8SDavid du Colombier 
36219b2ee8SDavid du Colombier 	return answer;
37219b2ee8SDavid du Colombier }
38219b2ee8SDavid du Colombier 
39219b2ee8SDavid du Colombier char *
netdecimal(char * answer)40219b2ee8SDavid du Colombier netdecimal(char *answer)
41219b2ee8SDavid du Colombier {
42219b2ee8SDavid du Colombier 	int i;
43219b2ee8SDavid du Colombier 
44219b2ee8SDavid du Colombier 	for(i = 0; answer[i]; i++)
45219b2ee8SDavid du Colombier 		switch(answer[i]){
46219b2ee8SDavid du Colombier 		case 'a': case 'b': case 'c':
47219b2ee8SDavid du Colombier 			answer[i] = '2';
48219b2ee8SDavid du Colombier 			break;
49219b2ee8SDavid du Colombier 		case 'd': case 'e': case 'f':
50219b2ee8SDavid du Colombier 			answer[i] = '3';
51219b2ee8SDavid du Colombier 			break;
52219b2ee8SDavid du Colombier 		}
53219b2ee8SDavid du Colombier 	return answer;
54219b2ee8SDavid du Colombier }
55219b2ee8SDavid du Colombier 
56219b2ee8SDavid du Colombier int
netcheck(void * key,long chal,char * response)57219b2ee8SDavid du Colombier netcheck(void *key, long chal, char *response)
58219b2ee8SDavid du Colombier {
59219b2ee8SDavid du Colombier 	char answer[32], *p;
60219b2ee8SDavid du Colombier 	int i;
61219b2ee8SDavid du Colombier 
62219b2ee8SDavid du Colombier 	if(smartcheck(key, chal, response))
63219b2ee8SDavid du Colombier 		return 1;
64219b2ee8SDavid du Colombier 
65219b2ee8SDavid du Colombier 	if(p = strchr(response, '\n'))
66219b2ee8SDavid du Colombier 		*p = '\0';
67219b2ee8SDavid du Colombier 	netresp(key, chal, answer);
68219b2ee8SDavid du Colombier 
69219b2ee8SDavid du Colombier 	/*
70219b2ee8SDavid du Colombier 	 * check for hex response -- securenet mode 1 or 5
71219b2ee8SDavid du Colombier 	 */
72219b2ee8SDavid du Colombier 	for(i = 0; response[i]; i++)
73219b2ee8SDavid du Colombier 		if(response[i] >= 'A' && response[i] <= 'Z')
74219b2ee8SDavid du Colombier 			response[i] -= 'A' - 'a';
75219b2ee8SDavid du Colombier 	if(strcmp(answer, response) == 0)
76219b2ee8SDavid du Colombier 		return 1;
77219b2ee8SDavid du Colombier 
78219b2ee8SDavid du Colombier 	/*
79219b2ee8SDavid du Colombier 	 * check for decimal response -- securenet mode 0 or 4
80219b2ee8SDavid du Colombier 	 */
81219b2ee8SDavid du Colombier 	return strcmp(netdecimal(answer), response) == 0;
82219b2ee8SDavid du Colombier }
83219b2ee8SDavid du Colombier 
84219b2ee8SDavid du Colombier int
smartcheck(void * key,long chal,char * response)85219b2ee8SDavid du Colombier smartcheck(void *key, long chal, char *response)
86219b2ee8SDavid du Colombier {
87219b2ee8SDavid du Colombier 	uchar buf[2*8];
88219b2ee8SDavid du Colombier 	int i, c, cslo, cshi;
89219b2ee8SDavid du Colombier 
90*f54edc78SDavid du Colombier 	snprint((char*)buf, sizeof buf, "%lud        ", chal);
91219b2ee8SDavid du Colombier 	cslo = 0x52;
92219b2ee8SDavid du Colombier 	cshi = cslo;
93219b2ee8SDavid du Colombier 	for(i = 0; i < 8; i++){
94219b2ee8SDavid du Colombier 		c = buf[i];
95219b2ee8SDavid du Colombier 		if(c >= '0' && c <= '9')
96219b2ee8SDavid du Colombier 			c -= '0';
97219b2ee8SDavid du Colombier 		cslo += c;
98219b2ee8SDavid du Colombier 		if(cslo > 0xff)
99219b2ee8SDavid du Colombier 			cslo -= 0xff;
100219b2ee8SDavid du Colombier 		cshi += cslo;
101219b2ee8SDavid du Colombier 		if(cshi > 0xff)
102219b2ee8SDavid du Colombier 			cshi -= 0xff;
103219b2ee8SDavid du Colombier 		buf[i] = c | (cshi & 0xf0);
104219b2ee8SDavid du Colombier 	}
105219b2ee8SDavid du Colombier 
106219b2ee8SDavid du Colombier 	encrypt(key, buf, 8);
107219b2ee8SDavid du Colombier 	for(i = 0; i < 8; i++)
108219b2ee8SDavid du Colombier 		if(response[i] != buf[i] % 10 + '0')
109219b2ee8SDavid du Colombier 			return 0;
110219b2ee8SDavid du Colombier 	return 1;
111219b2ee8SDavid du Colombier }
112