1*5926Smckusick /* Copyright (c) 1982 Regents of the University of California */
2*5926Smckusick 
3*5926Smckusick static char sccsid[] = "@(#)ruserpass.c 4.1 02/21/82";
4*5926Smckusick 
5*5926Smckusick #include <stdio.h>
6*5926Smckusick #include <utmp.h>
7*5926Smckusick #include <ctype.h>
8*5926Smckusick #include <sys/types.h>
9*5926Smckusick #include <sys/stat.h>
10*5926Smckusick 
11*5926Smckusick char	*renvlook(), *malloc(), *index(), *getenv(), *getpass(), *getlogin();
12*5926Smckusick struct	utmp *getutmp();
13*5926Smckusick static	FILE *cfile;
14*5926Smckusick 
15*5926Smckusick ruserpass(host, aname, apass)
16*5926Smckusick 	char *host, **aname, **apass;
17*5926Smckusick {
18*5926Smckusick 
19*5926Smckusick 	renv(host, aname, apass);
20*5926Smckusick 	if (*aname == 0 || *apass == 0)
21*5926Smckusick 		rnetrc(host, aname, apass);
22*5926Smckusick 	if (*aname == 0) {
23*5926Smckusick 		char *myname = getlogin();
24*5926Smckusick 		*aname = malloc(16);
25*5926Smckusick 		printf("Name (%s:%s): ", host, myname);
26*5926Smckusick 		fflush(stdout);
27*5926Smckusick 		if (read(2, *aname, 16) <= 0)
28*5926Smckusick 			exit(1);
29*5926Smckusick 		if ((*aname)[0] == '\n')
30*5926Smckusick 			*aname = myname;
31*5926Smckusick 		else
32*5926Smckusick 			if (index(*aname, '\n'))
33*5926Smckusick 				*index(*aname, '\n') = 0;
34*5926Smckusick 	}
35*5926Smckusick 	if (*aname && *apass == 0) {
36*5926Smckusick 		printf("Password (%s:%s): ", host, *aname);
37*5926Smckusick 		fflush(stdout);
38*5926Smckusick 		*apass = getpass("");
39*5926Smckusick 	}
40*5926Smckusick }
41*5926Smckusick 
42*5926Smckusick static
43*5926Smckusick renv(host, aname, apass)
44*5926Smckusick 	char *host, **aname, **apass;
45*5926Smckusick {
46*5926Smckusick 	register char *cp;
47*5926Smckusick 	char *stemp, fgetlogin, *comma;
48*5926Smckusick 
49*5926Smckusick 	cp = renvlook(host);
50*5926Smckusick 	if (cp == NULL)
51*5926Smckusick 		return;
52*5926Smckusick 	if (!isalpha(cp[0]))
53*5926Smckusick 		return;
54*5926Smckusick 	comma = index(cp, ',');
55*5926Smckusick 	if (comma == 0)
56*5926Smckusick 		return;
57*5926Smckusick 	if (*aname == 0) {
58*5926Smckusick 		*aname = malloc(comma - cp + 1);
59*5926Smckusick 		strncpy(*aname, cp, comma - cp);
60*5926Smckusick 	} else
61*5926Smckusick 		if (strncmp(*aname, cp, comma - cp))
62*5926Smckusick 			return;
63*5926Smckusick 	comma++;
64*5926Smckusick 	cp = malloc(strlen(comma)+1);
65*5926Smckusick 	strcpy(cp, comma);
66*5926Smckusick 	*apass = malloc(16);
67*5926Smckusick 	mkpwclear(cp, host[0], *apass);
68*5926Smckusick }
69*5926Smckusick 
70*5926Smckusick static
71*5926Smckusick char *
72*5926Smckusick renvlook(host)
73*5926Smckusick 	char *host;
74*5926Smckusick {
75*5926Smckusick 	register char *cp, **env;
76*5926Smckusick 	extern char **environ;
77*5926Smckusick 
78*5926Smckusick 	env = environ;
79*5926Smckusick 	for (env = environ; *env != NULL; env++)
80*5926Smckusick 		if (!strncmp(*env, "MACH", 4)) {
81*5926Smckusick 			cp = index(*env, '=');
82*5926Smckusick 			if (cp == 0)
83*5926Smckusick 				continue;
84*5926Smckusick 			if (strncmp(*env+4, host, cp-(*env+4)))
85*5926Smckusick 				continue;
86*5926Smckusick 			return (cp+1);
87*5926Smckusick 		}
88*5926Smckusick 	return (NULL);
89*5926Smckusick }
90*5926Smckusick 
91*5926Smckusick #define	DEFAULT	1
92*5926Smckusick #define	LOGIN	2
93*5926Smckusick #define	PASSWD	3
94*5926Smckusick #define	NOTIFY	4
95*5926Smckusick #define	WRITE	5
96*5926Smckusick #define	YES	6
97*5926Smckusick #define	NO	7
98*5926Smckusick #define	COMMAND	8
99*5926Smckusick #define	FORCE	9
100*5926Smckusick #define	ID	10
101*5926Smckusick #define	MACHINE	11
102*5926Smckusick 
103*5926Smckusick static char tokval[100];
104*5926Smckusick 
105*5926Smckusick static struct toktab {
106*5926Smckusick 	char *tokstr;
107*5926Smckusick 	int tval;
108*5926Smckusick } toktab[]= {
109*5926Smckusick 	"default",	DEFAULT,
110*5926Smckusick 	"login",	LOGIN,
111*5926Smckusick 	"password",	PASSWD,
112*5926Smckusick 	"notify",	NOTIFY,
113*5926Smckusick 	"write",	WRITE,
114*5926Smckusick 	"yes",		YES,
115*5926Smckusick 	"y",		YES,
116*5926Smckusick 	"no",		NO,
117*5926Smckusick 	"n",		NO,
118*5926Smckusick 	"command",	COMMAND,
119*5926Smckusick 	"force",	FORCE,
120*5926Smckusick 	"machine",	MACHINE,
121*5926Smckusick 	0,		0
122*5926Smckusick };
123*5926Smckusick 
124*5926Smckusick static
125*5926Smckusick rnetrc(host, aname, apass)
126*5926Smckusick 	char *host, **aname, **apass;
127*5926Smckusick {
128*5926Smckusick 	char *hdir, buf[BUFSIZ];
129*5926Smckusick 	int t;
130*5926Smckusick 	struct stat stb;
131*5926Smckusick 
132*5926Smckusick 	hdir = getenv("HOME");
133*5926Smckusick 	if (hdir == NULL)
134*5926Smckusick 		hdir = ".";
135*5926Smckusick 	sprintf(buf, "%s/.netrc", hdir);
136*5926Smckusick 	cfile = fopen(buf, "r");
137*5926Smckusick 	if (cfile == NULL) {
138*5926Smckusick 		perror(buf);
139*5926Smckusick 		return;
140*5926Smckusick 	}
141*5926Smckusick next:
142*5926Smckusick 	while ((t = token())) switch(t) {
143*5926Smckusick 
144*5926Smckusick 	case DEFAULT:
145*5926Smckusick 		(void) token();
146*5926Smckusick 		continue;
147*5926Smckusick 
148*5926Smckusick 	case MACHINE:
149*5926Smckusick 		if (token() != ID || strcmp(host, tokval))
150*5926Smckusick 			continue;
151*5926Smckusick 		while ((t = token()) && t != MACHINE) switch(t) {
152*5926Smckusick 
153*5926Smckusick 		case LOGIN:
154*5926Smckusick 			if (token())
155*5926Smckusick 				if (*aname == 0) {
156*5926Smckusick 					*aname = malloc(strlen(tokval) + 1);
157*5926Smckusick 					strcpy(*aname, tokval);
158*5926Smckusick 				} else {
159*5926Smckusick 					if (strcmp(*aname, tokval))
160*5926Smckusick 						goto next;
161*5926Smckusick 				}
162*5926Smckusick 			break;
163*5926Smckusick 		case PASSWD:
164*5926Smckusick 			if (fstat(fileno(cfile), &stb) >= 0
165*5926Smckusick 			    && (stb.st_mode & 077) != 0) {
166*5926Smckusick 	fprintf(stderr, "Error - .netrc file not correct mode.\n");
167*5926Smckusick 	fprintf(stderr, "Remove password or correct mode.\n");
168*5926Smckusick 				exit(1);
169*5926Smckusick 			}
170*5926Smckusick 			if (token() && *apass == 0) {
171*5926Smckusick 				*apass = malloc(strlen(tokval) + 1);
172*5926Smckusick 				strcpy(*apass, tokval);
173*5926Smckusick 			}
174*5926Smckusick 			break;
175*5926Smckusick 		case COMMAND:
176*5926Smckusick 		case NOTIFY:
177*5926Smckusick 		case WRITE:
178*5926Smckusick 		case FORCE:
179*5926Smckusick 			(void) token();
180*5926Smckusick 			break;
181*5926Smckusick 		default:
182*5926Smckusick 	fprintf(stderr, "Unknown .netrc option %s\n", tokval);
183*5926Smckusick 			break;
184*5926Smckusick 		}
185*5926Smckusick 		goto done;
186*5926Smckusick 	}
187*5926Smckusick done:
188*5926Smckusick 	fclose(cfile);
189*5926Smckusick }
190*5926Smckusick 
191*5926Smckusick static
192*5926Smckusick token()
193*5926Smckusick {
194*5926Smckusick 	char *cp;
195*5926Smckusick 	int c;
196*5926Smckusick 	struct toktab *t;
197*5926Smckusick 
198*5926Smckusick 	if (feof(cfile))
199*5926Smckusick 		return (0);
200*5926Smckusick 	while ((c = getc(cfile)) != EOF &&
201*5926Smckusick 	    (c == '\n' || c == '\t' || c == ' ' || c == ','))
202*5926Smckusick 		continue;
203*5926Smckusick 	if (c == EOF)
204*5926Smckusick 		return (0);
205*5926Smckusick 	cp = tokval;
206*5926Smckusick 	if (c == '"') {
207*5926Smckusick 		while ((c = getc(cfile)) != EOF && c != '"') {
208*5926Smckusick 			if (c == '\\')
209*5926Smckusick 				c = getc(cfile);
210*5926Smckusick 			*cp++ = c;
211*5926Smckusick 		}
212*5926Smckusick 	} else {
213*5926Smckusick 		*cp++ = c;
214*5926Smckusick 		while ((c = getc(cfile)) != EOF
215*5926Smckusick 		    && c != '\n' && c != '\t' && c != ' ' && c != ',') {
216*5926Smckusick 			if (c == '\\')
217*5926Smckusick 				c = getc(cfile);
218*5926Smckusick 			*cp++ = c;
219*5926Smckusick 		}
220*5926Smckusick 	}
221*5926Smckusick 	*cp = 0;
222*5926Smckusick 	if (tokval[0] == 0)
223*5926Smckusick 		return (0);
224*5926Smckusick 	for (t = toktab; t->tokstr; t++)
225*5926Smckusick 		if (!strcmp(t->tokstr, tokval))
226*5926Smckusick 			return (t->tval);
227*5926Smckusick 	return (ID);
228*5926Smckusick }
229*5926Smckusick /* rest is nbs.c stolen from berknet */
230*5926Smckusick 
231*5926Smckusick char *deblknot(), *deblkclr();
232*5926Smckusick char *nbs8decrypt(), *nbs8encrypt();
233*5926Smckusick static char	E[48];
234*5926Smckusick 
235*5926Smckusick /*
236*5926Smckusick  * The E bit-selection table.
237*5926Smckusick  */
238*5926Smckusick static char	e[] = {
239*5926Smckusick 	32, 1, 2, 3, 4, 5,
240*5926Smckusick 	 4, 5, 6, 7, 8, 9,
241*5926Smckusick 	 8, 9,10,11,12,13,
242*5926Smckusick 	12,13,14,15,16,17,
243*5926Smckusick 	16,17,18,19,20,21,
244*5926Smckusick 	20,21,22,23,24,25,
245*5926Smckusick 	24,25,26,27,28,29,
246*5926Smckusick 	28,29,30,31,32, 1,
247*5926Smckusick };
248*5926Smckusick static
249*5926Smckusick char *nbsencrypt(str,key,result)
250*5926Smckusick   char *result;
251*5926Smckusick   char *str, *key; {
252*5926Smckusick 	static char buf[20],oldbuf[20];
253*5926Smckusick 	register int j;
254*5926Smckusick 	result[0] = 0;
255*5926Smckusick 	strcpy(oldbuf,key);
256*5926Smckusick 	while(*str){
257*5926Smckusick 		for(j=0;j<10;j++)buf[j] = 0;
258*5926Smckusick 		for(j=0;j<8 && *str;j++)buf[j] = *str++;
259*5926Smckusick 		strcat(result,nbs8encrypt(buf,oldbuf));
260*5926Smckusick 		strcat(result,"$");
261*5926Smckusick 		strcpy(oldbuf,buf);
262*5926Smckusick 		}
263*5926Smckusick 	return(result);
264*5926Smckusick 	}
265*5926Smckusick static
266*5926Smckusick char *nbsdecrypt(cpt,key,result)
267*5926Smckusick   char *result;
268*5926Smckusick   char *cpt,*key; {
269*5926Smckusick 	char *s;
270*5926Smckusick 	char c,oldbuf[20];
271*5926Smckusick 	result[0] = 0;
272*5926Smckusick 	strcpy(oldbuf,key);
273*5926Smckusick 	while(*cpt){
274*5926Smckusick 		for(s = cpt;*s && *s != '$';s++);
275*5926Smckusick 		c = *s;
276*5926Smckusick 		*s = 0;
277*5926Smckusick 		strcpy(oldbuf,nbs8decrypt(cpt,oldbuf));
278*5926Smckusick 		strcat(result,oldbuf);
279*5926Smckusick 		if(c == 0)break;
280*5926Smckusick 		cpt = s + 1;
281*5926Smckusick 		}
282*5926Smckusick 	return(result);
283*5926Smckusick 	}
284*5926Smckusick 
285*5926Smckusick static
286*5926Smckusick char *nbs8encrypt(str,key)
287*5926Smckusick char *str, *key; {
288*5926Smckusick 	static char keyblk[100], blk[100];
289*5926Smckusick 	register int i;
290*5926Smckusick 
291*5926Smckusick 	enblkclr(keyblk,key);
292*5926Smckusick 	nbssetkey(keyblk);
293*5926Smckusick 
294*5926Smckusick 	for(i=0;i<48;i++) E[i] = e[i];
295*5926Smckusick 	enblkclr(blk,str);
296*5926Smckusick 	blkencrypt(blk,0);			/* forward dir */
297*5926Smckusick 
298*5926Smckusick 	return(deblknot(blk));
299*5926Smckusick }
300*5926Smckusick 
301*5926Smckusick static
302*5926Smckusick char *nbs8decrypt(crp,key)
303*5926Smckusick char *crp, *key; {
304*5926Smckusick 	static char keyblk[100], blk[100];
305*5926Smckusick 	register int i;
306*5926Smckusick 
307*5926Smckusick 	enblkclr(keyblk,key);
308*5926Smckusick 	nbssetkey(keyblk);
309*5926Smckusick 
310*5926Smckusick 	for(i=0;i<48;i++) E[i] = e[i];
311*5926Smckusick 	enblknot(blk,crp);
312*5926Smckusick 	blkencrypt(blk,1);			/* backward dir */
313*5926Smckusick 
314*5926Smckusick 	return(deblkclr(blk));
315*5926Smckusick }
316*5926Smckusick 
317*5926Smckusick static
318*5926Smckusick enblkclr(blk,str)		/* ignores top bit of chars in string str */
319*5926Smckusick char *blk,*str; {
320*5926Smckusick 	register int i,j;
321*5926Smckusick 	char c;
322*5926Smckusick 	for(i=0;i<70;i++)blk[i] = 0;
323*5926Smckusick 	for(i=0; (c= *str) && i<64; str++){
324*5926Smckusick 		for(j=0; j<7; j++, i++)
325*5926Smckusick 			blk[i] = (c>>(6-j)) & 01;
326*5926Smckusick 		i++;
327*5926Smckusick 		}
328*5926Smckusick 	}
329*5926Smckusick 
330*5926Smckusick static
331*5926Smckusick char *deblkclr(blk)
332*5926Smckusick char *blk; {
333*5926Smckusick 	register int i,j;
334*5926Smckusick 	char c;
335*5926Smckusick 	static char iobuf[30];
336*5926Smckusick 	for(i=0; i<10; i++){
337*5926Smckusick 		c = 0;
338*5926Smckusick 		for(j=0; j<7; j++){
339*5926Smckusick 			c <<= 1;
340*5926Smckusick 			c |= blk[8*i+j];
341*5926Smckusick 			}
342*5926Smckusick 		iobuf[i] = c;
343*5926Smckusick 	}
344*5926Smckusick 	iobuf[i] = 0;
345*5926Smckusick 	return(iobuf);
346*5926Smckusick 	}
347*5926Smckusick 
348*5926Smckusick static
349*5926Smckusick enblknot(blk,crp)
350*5926Smckusick char *blk;
351*5926Smckusick char *crp; {
352*5926Smckusick 	register int i,j;
353*5926Smckusick 	char c;
354*5926Smckusick 	for(i=0;i<70;i++)blk[i] = 0;
355*5926Smckusick 	for(i=0; (c= *crp) && i<64; crp++){
356*5926Smckusick 		if(c>'Z') c -= 6;
357*5926Smckusick 		if(c>'9') c -= 7;
358*5926Smckusick 		c -= '.';
359*5926Smckusick 		for(j=0; j<6; j++, i++)
360*5926Smckusick 			blk[i] = (c>>(5-j)) & 01;
361*5926Smckusick 		}
362*5926Smckusick 	}
363*5926Smckusick 
364*5926Smckusick static
365*5926Smckusick char *deblknot(blk)
366*5926Smckusick char *blk; {
367*5926Smckusick 	register int i,j;
368*5926Smckusick 	char c;
369*5926Smckusick 	static char iobuf[30];
370*5926Smckusick 	for(i=0; i<11; i++){
371*5926Smckusick 		c = 0;
372*5926Smckusick 		for(j=0; j<6; j++){
373*5926Smckusick 			c <<= 1;
374*5926Smckusick 			c |= blk[6*i+j];
375*5926Smckusick 			}
376*5926Smckusick 		c += '.';
377*5926Smckusick 		if(c > '9')c += 7;
378*5926Smckusick 		if(c > 'Z')c += 6;
379*5926Smckusick 		iobuf[i] = c;
380*5926Smckusick 	}
381*5926Smckusick 	iobuf[i] = 0;
382*5926Smckusick 	return(iobuf);
383*5926Smckusick }
384*5926Smckusick 
385*5926Smckusick /*
386*5926Smckusick  * This program implements the
387*5926Smckusick  * Proposed Federal Information Processing
388*5926Smckusick  *  Data Encryption Standard.
389*5926Smckusick  * See Federal Register, March 17, 1975 (40FR12134)
390*5926Smckusick  */
391*5926Smckusick 
392*5926Smckusick /*
393*5926Smckusick  * Initial permutation,
394*5926Smckusick  */
395*5926Smckusick static	char	IP[] = {
396*5926Smckusick 	58,50,42,34,26,18,10, 2,
397*5926Smckusick 	60,52,44,36,28,20,12, 4,
398*5926Smckusick 	62,54,46,38,30,22,14, 6,
399*5926Smckusick 	64,56,48,40,32,24,16, 8,
400*5926Smckusick 	57,49,41,33,25,17, 9, 1,
401*5926Smckusick 	59,51,43,35,27,19,11, 3,
402*5926Smckusick 	61,53,45,37,29,21,13, 5,
403*5926Smckusick 	63,55,47,39,31,23,15, 7,
404*5926Smckusick };
405*5926Smckusick 
406*5926Smckusick /*
407*5926Smckusick  * Final permutation, FP = IP^(-1)
408*5926Smckusick  */
409*5926Smckusick static	char	FP[] = {
410*5926Smckusick 	40, 8,48,16,56,24,64,32,
411*5926Smckusick 	39, 7,47,15,55,23,63,31,
412*5926Smckusick 	38, 6,46,14,54,22,62,30,
413*5926Smckusick 	37, 5,45,13,53,21,61,29,
414*5926Smckusick 	36, 4,44,12,52,20,60,28,
415*5926Smckusick 	35, 3,43,11,51,19,59,27,
416*5926Smckusick 	34, 2,42,10,50,18,58,26,
417*5926Smckusick 	33, 1,41, 9,49,17,57,25,
418*5926Smckusick };
419*5926Smckusick 
420*5926Smckusick /*
421*5926Smckusick  * Permuted-choice 1 from the key bits
422*5926Smckusick  * to yield C and D.
423*5926Smckusick  * Note that bits 8,16... are left out:
424*5926Smckusick  * They are intended for a parity check.
425*5926Smckusick  */
426*5926Smckusick static	char	PC1_C[] = {
427*5926Smckusick 	57,49,41,33,25,17, 9,
428*5926Smckusick 	 1,58,50,42,34,26,18,
429*5926Smckusick 	10, 2,59,51,43,35,27,
430*5926Smckusick 	19,11, 3,60,52,44,36,
431*5926Smckusick };
432*5926Smckusick 
433*5926Smckusick static	char	PC1_D[] = {
434*5926Smckusick 	63,55,47,39,31,23,15,
435*5926Smckusick 	 7,62,54,46,38,30,22,
436*5926Smckusick 	14, 6,61,53,45,37,29,
437*5926Smckusick 	21,13, 5,28,20,12, 4,
438*5926Smckusick };
439*5926Smckusick 
440*5926Smckusick /*
441*5926Smckusick  * Sequence of shifts used for the key schedule.
442*5926Smckusick */
443*5926Smckusick static	char	shifts[] = {
444*5926Smckusick 	1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
445*5926Smckusick };
446*5926Smckusick 
447*5926Smckusick /*
448*5926Smckusick  * Permuted-choice 2, to pick out the bits from
449*5926Smckusick  * the CD array that generate the key schedule.
450*5926Smckusick  */
451*5926Smckusick static	char	PC2_C[] = {
452*5926Smckusick 	14,17,11,24, 1, 5,
453*5926Smckusick 	 3,28,15, 6,21,10,
454*5926Smckusick 	23,19,12, 4,26, 8,
455*5926Smckusick 	16, 7,27,20,13, 2,
456*5926Smckusick };
457*5926Smckusick 
458*5926Smckusick static	char	PC2_D[] = {
459*5926Smckusick 	41,52,31,37,47,55,
460*5926Smckusick 	30,40,51,45,33,48,
461*5926Smckusick 	44,49,39,56,34,53,
462*5926Smckusick 	46,42,50,36,29,32,
463*5926Smckusick };
464*5926Smckusick 
465*5926Smckusick /*
466*5926Smckusick  * The C and D arrays used to calculate the key schedule.
467*5926Smckusick  */
468*5926Smckusick 
469*5926Smckusick static	char	C[28];
470*5926Smckusick static	char	D[28];
471*5926Smckusick /*
472*5926Smckusick  * The key schedule.
473*5926Smckusick  * Generated from the key.
474*5926Smckusick  */
475*5926Smckusick static	char	KS[16][48];
476*5926Smckusick 
477*5926Smckusick /*
478*5926Smckusick  * Set up the key schedule from the key.
479*5926Smckusick  */
480*5926Smckusick 
481*5926Smckusick static
482*5926Smckusick nbssetkey(key)
483*5926Smckusick char *key;
484*5926Smckusick {
485*5926Smckusick 	register i, j, k;
486*5926Smckusick 	int t;
487*5926Smckusick 
488*5926Smckusick 	/*
489*5926Smckusick 	 * First, generate C and D by permuting
490*5926Smckusick 	 * the key.  The low order bit of each
491*5926Smckusick 	 * 8-bit char is not used, so C and D are only 28
492*5926Smckusick 	 * bits apiece.
493*5926Smckusick 	 */
494*5926Smckusick 	for (i=0; i<28; i++) {
495*5926Smckusick 		C[i] = key[PC1_C[i]-1];
496*5926Smckusick 		D[i] = key[PC1_D[i]-1];
497*5926Smckusick 	}
498*5926Smckusick 	/*
499*5926Smckusick 	 * To generate Ki, rotate C and D according
500*5926Smckusick 	 * to schedule and pick up a permutation
501*5926Smckusick 	 * using PC2.
502*5926Smckusick 	 */
503*5926Smckusick 	for (i=0; i<16; i++) {
504*5926Smckusick 		/*
505*5926Smckusick 		 * rotate.
506*5926Smckusick 		 */
507*5926Smckusick 		for (k=0; k<shifts[i]; k++) {
508*5926Smckusick 			t = C[0];
509*5926Smckusick 			for (j=0; j<28-1; j++)
510*5926Smckusick 				C[j] = C[j+1];
511*5926Smckusick 			C[27] = t;
512*5926Smckusick 			t = D[0];
513*5926Smckusick 			for (j=0; j<28-1; j++)
514*5926Smckusick 				D[j] = D[j+1];
515*5926Smckusick 			D[27] = t;
516*5926Smckusick 		}
517*5926Smckusick 		/*
518*5926Smckusick 		 * get Ki. Note C and D are concatenated.
519*5926Smckusick 		 */
520*5926Smckusick 		for (j=0; j<24; j++) {
521*5926Smckusick 			KS[i][j] = C[PC2_C[j]-1];
522*5926Smckusick 			KS[i][j+24] = D[PC2_D[j]-28-1];
523*5926Smckusick 		}
524*5926Smckusick 	}
525*5926Smckusick }
526*5926Smckusick 
527*5926Smckusick 
528*5926Smckusick /*
529*5926Smckusick  * The 8 selection functions.
530*5926Smckusick  * For some reason, they give a 0-origin
531*5926Smckusick  * index, unlike everything else.
532*5926Smckusick  */
533*5926Smckusick static	char	S[8][64] = {
534*5926Smckusick 	14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
535*5926Smckusick 	 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
536*5926Smckusick 	 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
537*5926Smckusick 	15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
538*5926Smckusick 
539*5926Smckusick 	15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
540*5926Smckusick 	 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
541*5926Smckusick 	 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
542*5926Smckusick 	13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
543*5926Smckusick 
544*5926Smckusick 	10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
545*5926Smckusick 	13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
546*5926Smckusick 	13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
547*5926Smckusick 	 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
548*5926Smckusick 
549*5926Smckusick 	 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
550*5926Smckusick 	13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
551*5926Smckusick 	10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
552*5926Smckusick 	 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
553*5926Smckusick 
554*5926Smckusick 	 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
555*5926Smckusick 	14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
556*5926Smckusick 	 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
557*5926Smckusick 	11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
558*5926Smckusick 
559*5926Smckusick 	12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
560*5926Smckusick 	10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
561*5926Smckusick 	 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
562*5926Smckusick 	 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
563*5926Smckusick 
564*5926Smckusick 	 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
565*5926Smckusick 	13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
566*5926Smckusick 	 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
567*5926Smckusick 	 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
568*5926Smckusick 
569*5926Smckusick 	13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
570*5926Smckusick 	 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
571*5926Smckusick 	 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
572*5926Smckusick 	 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
573*5926Smckusick };
574*5926Smckusick 
575*5926Smckusick /*
576*5926Smckusick  * P is a permutation on the selected combination
577*5926Smckusick  * of the current L and key.
578*5926Smckusick  */
579*5926Smckusick static	char	P[] = {
580*5926Smckusick 	16, 7,20,21,
581*5926Smckusick 	29,12,28,17,
582*5926Smckusick 	 1,15,23,26,
583*5926Smckusick 	 5,18,31,10,
584*5926Smckusick 	 2, 8,24,14,
585*5926Smckusick 	32,27, 3, 9,
586*5926Smckusick 	19,13,30, 6,
587*5926Smckusick 	22,11, 4,25,
588*5926Smckusick };
589*5926Smckusick 
590*5926Smckusick /*
591*5926Smckusick  * The current block, divided into 2 halves.
592*5926Smckusick  */
593*5926Smckusick static	char	L[32], R[32];
594*5926Smckusick static	char	tempL[32];
595*5926Smckusick static	char	f[32];
596*5926Smckusick 
597*5926Smckusick /*
598*5926Smckusick  * The combination of the key and the input, before selection.
599*5926Smckusick  */
600*5926Smckusick static	char	preS[48];
601*5926Smckusick 
602*5926Smckusick /*
603*5926Smckusick  * The payoff: encrypt a block.
604*5926Smckusick  */
605*5926Smckusick 
606*5926Smckusick static
607*5926Smckusick blkencrypt(block, edflag)
608*5926Smckusick char *block;
609*5926Smckusick {
610*5926Smckusick 	int i, ii;
611*5926Smckusick 	register t, j, k;
612*5926Smckusick 
613*5926Smckusick 	/*
614*5926Smckusick 	 * First, permute the bits in the input
615*5926Smckusick 	 */
616*5926Smckusick 	for (j=0; j<64; j++)
617*5926Smckusick 		L[j] = block[IP[j]-1];
618*5926Smckusick 	/*
619*5926Smckusick 	 * Perform an encryption operation 16 times.
620*5926Smckusick 	 */
621*5926Smckusick 	for (ii=0; ii<16; ii++) {
622*5926Smckusick 		/*
623*5926Smckusick 		 * Set direction
624*5926Smckusick 		 */
625*5926Smckusick 		if (edflag)
626*5926Smckusick 			i = 15-ii;
627*5926Smckusick 		else
628*5926Smckusick 			i = ii;
629*5926Smckusick 		/*
630*5926Smckusick 		 * Save the R array,
631*5926Smckusick 		 * which will be the new L.
632*5926Smckusick 		 */
633*5926Smckusick 		for (j=0; j<32; j++)
634*5926Smckusick 			tempL[j] = R[j];
635*5926Smckusick 		/*
636*5926Smckusick 		 * Expand R to 48 bits using the E selector;
637*5926Smckusick 		 * exclusive-or with the current key bits.
638*5926Smckusick 		 */
639*5926Smckusick 		for (j=0; j<48; j++)
640*5926Smckusick 			preS[j] = R[E[j]-1] ^ KS[i][j];
641*5926Smckusick 		/*
642*5926Smckusick 		 * The pre-select bits are now considered
643*5926Smckusick 		 * in 8 groups of 6 bits each.
644*5926Smckusick 		 * The 8 selection functions map these
645*5926Smckusick 		 * 6-bit quantities into 4-bit quantities
646*5926Smckusick 		 * and the results permuted
647*5926Smckusick 		 * to make an f(R, K).
648*5926Smckusick 		 * The indexing into the selection functions
649*5926Smckusick 		 * is peculiar; it could be simplified by
650*5926Smckusick 		 * rewriting the tables.
651*5926Smckusick 		 */
652*5926Smckusick 		for (j=0; j<8; j++) {
653*5926Smckusick 			t = 6*j;
654*5926Smckusick 			k = S[j][(preS[t+0]<<5)+
655*5926Smckusick 				(preS[t+1]<<3)+
656*5926Smckusick 				(preS[t+2]<<2)+
657*5926Smckusick 				(preS[t+3]<<1)+
658*5926Smckusick 				(preS[t+4]<<0)+
659*5926Smckusick 				(preS[t+5]<<4)];
660*5926Smckusick 			t = 4*j;
661*5926Smckusick 			f[t+0] = (k>>3)&01;
662*5926Smckusick 			f[t+1] = (k>>2)&01;
663*5926Smckusick 			f[t+2] = (k>>1)&01;
664*5926Smckusick 			f[t+3] = (k>>0)&01;
665*5926Smckusick 		}
666*5926Smckusick 		/*
667*5926Smckusick 		 * The new R is L ^ f(R, K).
668*5926Smckusick 		 * The f here has to be permuted first, though.
669*5926Smckusick 		 */
670*5926Smckusick 		for (j=0; j<32; j++)
671*5926Smckusick 			R[j] = L[j] ^ f[P[j]-1];
672*5926Smckusick 		/*
673*5926Smckusick 		 * Finally, the new L (the original R)
674*5926Smckusick 		 * is copied back.
675*5926Smckusick 		 */
676*5926Smckusick 		for (j=0; j<32; j++)
677*5926Smckusick 			L[j] = tempL[j];
678*5926Smckusick 	}
679*5926Smckusick 	/*
680*5926Smckusick 	 * The output L and R are reversed.
681*5926Smckusick 	 */
682*5926Smckusick 	for (j=0; j<32; j++) {
683*5926Smckusick 		t = L[j];
684*5926Smckusick 		L[j] = R[j];
685*5926Smckusick 		R[j] = t;
686*5926Smckusick 	}
687*5926Smckusick 	/*
688*5926Smckusick 	 * The final output
689*5926Smckusick 	 * gets the inverse permutation of the very original.
690*5926Smckusick 	 */
691*5926Smckusick 	for (j=0; j<64; j++)
692*5926Smckusick 		block[j] = L[FP[j]-1];
693*5926Smckusick }
694*5926Smckusick /*
695*5926Smckusick 	getutmp()
696*5926Smckusick 	return a pointer to the system utmp structure associated with
697*5926Smckusick 	terminal sttyname, e.g. "/dev/tty3"
698*5926Smckusick 	Is version independent-- will work on v6 systems
699*5926Smckusick 	return NULL if error
700*5926Smckusick */
701*5926Smckusick static
702*5926Smckusick struct utmp *getutmp(sttyname)
703*5926Smckusick char *sttyname;
704*5926Smckusick {
705*5926Smckusick 	static struct utmp utmpstr;
706*5926Smckusick 	FILE *fdutmp;
707*5926Smckusick 
708*5926Smckusick 	if(sttyname == NULL || sttyname[0] == 0)return(NULL);
709*5926Smckusick 
710*5926Smckusick 	fdutmp = fopen("/etc/utmp","r");
711*5926Smckusick 	if(fdutmp == NULL)return(NULL);
712*5926Smckusick 
713*5926Smckusick 	while(fread(&utmpstr,1,sizeof utmpstr,fdutmp) == sizeof utmpstr)
714*5926Smckusick 		if(strcmp(utmpstr.ut_line,sttyname+5) == 0){
715*5926Smckusick 			fclose(fdutmp);
716*5926Smckusick 			return(&utmpstr);
717*5926Smckusick 		}
718*5926Smckusick 	fclose(fdutmp);
719*5926Smckusick 	return(NULL);
720*5926Smckusick }
721*5926Smckusick 
722*5926Smckusick static
723*5926Smckusick sreverse(sto, sfrom)
724*5926Smckusick 	register char *sto, *sfrom;
725*5926Smckusick {
726*5926Smckusick 	register int i;
727*5926Smckusick 
728*5926Smckusick 	i = strlen(sfrom);
729*5926Smckusick 	while (i >= 0)
730*5926Smckusick 		*sto++ = sfrom[i--];
731*5926Smckusick }
732*5926Smckusick 
733*5926Smckusick static
734*5926Smckusick char *mkenvkey(mch)
735*5926Smckusick 	char mch;
736*5926Smckusick {
737*5926Smckusick 	static char skey[40];
738*5926Smckusick 	register struct utmp *putmp;
739*5926Smckusick 	char stemp[40], stemp1[40], sttyname[30];
740*5926Smckusick 	register char *sk,*p;
741*5926Smckusick 
742*5926Smckusick 	if (isatty(2))
743*5926Smckusick 		strcpy(sttyname,ttyname(2));
744*5926Smckusick 	else if (isatty(0))
745*5926Smckusick 		strcpy(sttyname,ttyname(0));
746*5926Smckusick 	else if (isatty(1))
747*5926Smckusick 		strcpy(sttyname,ttyname(1));
748*5926Smckusick 	else
749*5926Smckusick 		return (NULL);
750*5926Smckusick 	putmp = getutmp(sttyname);
751*5926Smckusick 	if (putmp == NULL)
752*5926Smckusick 		return (NULL);
753*5926Smckusick 	sk = skey;
754*5926Smckusick 	p = putmp->ut_line;
755*5926Smckusick 	while (*p)
756*5926Smckusick 		*sk++ = *p++;
757*5926Smckusick 	*sk++ = mch;
758*5926Smckusick 	sprintf(stemp, "%ld", putmp->ut_time);
759*5926Smckusick 	sreverse(stemp1, stemp);
760*5926Smckusick 	p = stemp1;
761*5926Smckusick 	while (*p)
762*5926Smckusick 		*sk++ = *p++;
763*5926Smckusick 	*sk = 0;
764*5926Smckusick 	return (skey);
765*5926Smckusick }
766*5926Smckusick 
767*5926Smckusick mkpwunclear(spasswd,mch,sencpasswd)
768*5926Smckusick 	char mch, *spasswd, *sencpasswd;
769*5926Smckusick {
770*5926Smckusick 	register char *skey;
771*5926Smckusick 
772*5926Smckusick 	if (spasswd[0] == 0) {
773*5926Smckusick 		sencpasswd[0] = 0;
774*5926Smckusick 		return;
775*5926Smckusick 	}
776*5926Smckusick 	skey = mkenvkey(mch);
777*5926Smckusick 	if (skey == NULL) {
778*5926Smckusick 		fprintf(stderr, "Can't make key\n");
779*5926Smckusick 		exit(1);
780*5926Smckusick 	}
781*5926Smckusick 	nbsencrypt(spasswd, skey, sencpasswd);
782*5926Smckusick }
783*5926Smckusick 
784*5926Smckusick mkpwclear(sencpasswd,mch,spasswd)
785*5926Smckusick 	char mch, *spasswd, *sencpasswd;
786*5926Smckusick {
787*5926Smckusick 	register char *skey;
788*5926Smckusick 
789*5926Smckusick 	if (sencpasswd[0] == 0) {
790*5926Smckusick 		spasswd[0] = 0;
791*5926Smckusick 		return;
792*5926Smckusick 	}
793*5926Smckusick 	skey = mkenvkey(mch);
794*5926Smckusick 	if (skey == NULL) {
795*5926Smckusick 		fprintf(stderr, "Can't make key\n");
796*5926Smckusick 		exit(1);
797*5926Smckusick 	}
798*5926Smckusick 	nbsdecrypt(sencpasswd, skey, spasswd);
799*5926Smckusick }
800