15926Smckusick /* Copyright (c) 1982 Regents of the University of California */
25926Smckusick 
3*8455Ssam static char sccsid[] = "@(#)ruserpass.c 4.2 10/10/82";
45926Smckusick 
55926Smckusick #include <stdio.h>
65926Smckusick #include <utmp.h>
75926Smckusick #include <ctype.h>
85926Smckusick #include <sys/types.h>
95926Smckusick #include <sys/stat.h>
10*8455Ssam #include <errno.h>
115926Smckusick 
125926Smckusick char	*renvlook(), *malloc(), *index(), *getenv(), *getpass(), *getlogin();
135926Smckusick struct	utmp *getutmp();
145926Smckusick static	FILE *cfile;
155926Smckusick 
165926Smckusick ruserpass(host, aname, apass)
175926Smckusick 	char *host, **aname, **apass;
185926Smckusick {
195926Smckusick 
205926Smckusick 	renv(host, aname, apass);
215926Smckusick 	if (*aname == 0 || *apass == 0)
225926Smckusick 		rnetrc(host, aname, apass);
235926Smckusick 	if (*aname == 0) {
245926Smckusick 		char *myname = getlogin();
255926Smckusick 		*aname = malloc(16);
265926Smckusick 		printf("Name (%s:%s): ", host, myname);
275926Smckusick 		fflush(stdout);
285926Smckusick 		if (read(2, *aname, 16) <= 0)
295926Smckusick 			exit(1);
305926Smckusick 		if ((*aname)[0] == '\n')
315926Smckusick 			*aname = myname;
325926Smckusick 		else
335926Smckusick 			if (index(*aname, '\n'))
345926Smckusick 				*index(*aname, '\n') = 0;
355926Smckusick 	}
365926Smckusick 	if (*aname && *apass == 0) {
375926Smckusick 		printf("Password (%s:%s): ", host, *aname);
385926Smckusick 		fflush(stdout);
395926Smckusick 		*apass = getpass("");
405926Smckusick 	}
415926Smckusick }
425926Smckusick 
435926Smckusick static
445926Smckusick renv(host, aname, apass)
455926Smckusick 	char *host, **aname, **apass;
465926Smckusick {
475926Smckusick 	register char *cp;
485926Smckusick 	char *stemp, fgetlogin, *comma;
495926Smckusick 
505926Smckusick 	cp = renvlook(host);
515926Smckusick 	if (cp == NULL)
525926Smckusick 		return;
535926Smckusick 	if (!isalpha(cp[0]))
545926Smckusick 		return;
555926Smckusick 	comma = index(cp, ',');
565926Smckusick 	if (comma == 0)
575926Smckusick 		return;
585926Smckusick 	if (*aname == 0) {
595926Smckusick 		*aname = malloc(comma - cp + 1);
605926Smckusick 		strncpy(*aname, cp, comma - cp);
615926Smckusick 	} else
625926Smckusick 		if (strncmp(*aname, cp, comma - cp))
635926Smckusick 			return;
645926Smckusick 	comma++;
655926Smckusick 	cp = malloc(strlen(comma)+1);
665926Smckusick 	strcpy(cp, comma);
675926Smckusick 	*apass = malloc(16);
685926Smckusick 	mkpwclear(cp, host[0], *apass);
695926Smckusick }
705926Smckusick 
715926Smckusick static
725926Smckusick char *
735926Smckusick renvlook(host)
745926Smckusick 	char *host;
755926Smckusick {
765926Smckusick 	register char *cp, **env;
775926Smckusick 	extern char **environ;
785926Smckusick 
795926Smckusick 	env = environ;
805926Smckusick 	for (env = environ; *env != NULL; env++)
815926Smckusick 		if (!strncmp(*env, "MACH", 4)) {
825926Smckusick 			cp = index(*env, '=');
835926Smckusick 			if (cp == 0)
845926Smckusick 				continue;
855926Smckusick 			if (strncmp(*env+4, host, cp-(*env+4)))
865926Smckusick 				continue;
875926Smckusick 			return (cp+1);
885926Smckusick 		}
895926Smckusick 	return (NULL);
905926Smckusick }
915926Smckusick 
925926Smckusick #define	DEFAULT	1
935926Smckusick #define	LOGIN	2
945926Smckusick #define	PASSWD	3
955926Smckusick #define	NOTIFY	4
965926Smckusick #define	WRITE	5
975926Smckusick #define	YES	6
985926Smckusick #define	NO	7
995926Smckusick #define	COMMAND	8
1005926Smckusick #define	FORCE	9
1015926Smckusick #define	ID	10
1025926Smckusick #define	MACHINE	11
1035926Smckusick 
1045926Smckusick static char tokval[100];
1055926Smckusick 
1065926Smckusick static struct toktab {
1075926Smckusick 	char *tokstr;
1085926Smckusick 	int tval;
1095926Smckusick } toktab[]= {
1105926Smckusick 	"default",	DEFAULT,
1115926Smckusick 	"login",	LOGIN,
1125926Smckusick 	"password",	PASSWD,
1135926Smckusick 	"notify",	NOTIFY,
1145926Smckusick 	"write",	WRITE,
1155926Smckusick 	"yes",		YES,
1165926Smckusick 	"y",		YES,
1175926Smckusick 	"no",		NO,
1185926Smckusick 	"n",		NO,
1195926Smckusick 	"command",	COMMAND,
1205926Smckusick 	"force",	FORCE,
1215926Smckusick 	"machine",	MACHINE,
1225926Smckusick 	0,		0
1235926Smckusick };
1245926Smckusick 
1255926Smckusick static
1265926Smckusick rnetrc(host, aname, apass)
1275926Smckusick 	char *host, **aname, **apass;
1285926Smckusick {
1295926Smckusick 	char *hdir, buf[BUFSIZ];
1305926Smckusick 	int t;
1315926Smckusick 	struct stat stb;
132*8455Ssam 	extern int errno;
1335926Smckusick 
1345926Smckusick 	hdir = getenv("HOME");
1355926Smckusick 	if (hdir == NULL)
1365926Smckusick 		hdir = ".";
1375926Smckusick 	sprintf(buf, "%s/.netrc", hdir);
1385926Smckusick 	cfile = fopen(buf, "r");
1395926Smckusick 	if (cfile == NULL) {
140*8455Ssam 		if (errno != ENOENT)
141*8455Ssam 			perror(buf);
1425926Smckusick 		return;
1435926Smckusick 	}
1445926Smckusick next:
1455926Smckusick 	while ((t = token())) switch(t) {
1465926Smckusick 
1475926Smckusick 	case DEFAULT:
1485926Smckusick 		(void) token();
1495926Smckusick 		continue;
1505926Smckusick 
1515926Smckusick 	case MACHINE:
1525926Smckusick 		if (token() != ID || strcmp(host, tokval))
1535926Smckusick 			continue;
1545926Smckusick 		while ((t = token()) && t != MACHINE) switch(t) {
1555926Smckusick 
1565926Smckusick 		case LOGIN:
1575926Smckusick 			if (token())
1585926Smckusick 				if (*aname == 0) {
1595926Smckusick 					*aname = malloc(strlen(tokval) + 1);
1605926Smckusick 					strcpy(*aname, tokval);
1615926Smckusick 				} else {
1625926Smckusick 					if (strcmp(*aname, tokval))
1635926Smckusick 						goto next;
1645926Smckusick 				}
1655926Smckusick 			break;
1665926Smckusick 		case PASSWD:
1675926Smckusick 			if (fstat(fileno(cfile), &stb) >= 0
1685926Smckusick 			    && (stb.st_mode & 077) != 0) {
1695926Smckusick 	fprintf(stderr, "Error - .netrc file not correct mode.\n");
1705926Smckusick 	fprintf(stderr, "Remove password or correct mode.\n");
1715926Smckusick 				exit(1);
1725926Smckusick 			}
1735926Smckusick 			if (token() && *apass == 0) {
1745926Smckusick 				*apass = malloc(strlen(tokval) + 1);
1755926Smckusick 				strcpy(*apass, tokval);
1765926Smckusick 			}
1775926Smckusick 			break;
1785926Smckusick 		case COMMAND:
1795926Smckusick 		case NOTIFY:
1805926Smckusick 		case WRITE:
1815926Smckusick 		case FORCE:
1825926Smckusick 			(void) token();
1835926Smckusick 			break;
1845926Smckusick 		default:
1855926Smckusick 	fprintf(stderr, "Unknown .netrc option %s\n", tokval);
1865926Smckusick 			break;
1875926Smckusick 		}
1885926Smckusick 		goto done;
1895926Smckusick 	}
1905926Smckusick done:
1915926Smckusick 	fclose(cfile);
1925926Smckusick }
1935926Smckusick 
1945926Smckusick static
1955926Smckusick token()
1965926Smckusick {
1975926Smckusick 	char *cp;
1985926Smckusick 	int c;
1995926Smckusick 	struct toktab *t;
2005926Smckusick 
2015926Smckusick 	if (feof(cfile))
2025926Smckusick 		return (0);
2035926Smckusick 	while ((c = getc(cfile)) != EOF &&
2045926Smckusick 	    (c == '\n' || c == '\t' || c == ' ' || c == ','))
2055926Smckusick 		continue;
2065926Smckusick 	if (c == EOF)
2075926Smckusick 		return (0);
2085926Smckusick 	cp = tokval;
2095926Smckusick 	if (c == '"') {
2105926Smckusick 		while ((c = getc(cfile)) != EOF && c != '"') {
2115926Smckusick 			if (c == '\\')
2125926Smckusick 				c = getc(cfile);
2135926Smckusick 			*cp++ = c;
2145926Smckusick 		}
2155926Smckusick 	} else {
2165926Smckusick 		*cp++ = c;
2175926Smckusick 		while ((c = getc(cfile)) != EOF
2185926Smckusick 		    && c != '\n' && c != '\t' && c != ' ' && c != ',') {
2195926Smckusick 			if (c == '\\')
2205926Smckusick 				c = getc(cfile);
2215926Smckusick 			*cp++ = c;
2225926Smckusick 		}
2235926Smckusick 	}
2245926Smckusick 	*cp = 0;
2255926Smckusick 	if (tokval[0] == 0)
2265926Smckusick 		return (0);
2275926Smckusick 	for (t = toktab; t->tokstr; t++)
2285926Smckusick 		if (!strcmp(t->tokstr, tokval))
2295926Smckusick 			return (t->tval);
2305926Smckusick 	return (ID);
2315926Smckusick }
2325926Smckusick /* rest is nbs.c stolen from berknet */
2335926Smckusick 
2345926Smckusick char *deblknot(), *deblkclr();
2355926Smckusick char *nbs8decrypt(), *nbs8encrypt();
2365926Smckusick static char	E[48];
2375926Smckusick 
2385926Smckusick /*
2395926Smckusick  * The E bit-selection table.
2405926Smckusick  */
2415926Smckusick static char	e[] = {
2425926Smckusick 	32, 1, 2, 3, 4, 5,
2435926Smckusick 	 4, 5, 6, 7, 8, 9,
2445926Smckusick 	 8, 9,10,11,12,13,
2455926Smckusick 	12,13,14,15,16,17,
2465926Smckusick 	16,17,18,19,20,21,
2475926Smckusick 	20,21,22,23,24,25,
2485926Smckusick 	24,25,26,27,28,29,
2495926Smckusick 	28,29,30,31,32, 1,
2505926Smckusick };
2515926Smckusick static
2525926Smckusick char *nbsencrypt(str,key,result)
2535926Smckusick   char *result;
2545926Smckusick   char *str, *key; {
2555926Smckusick 	static char buf[20],oldbuf[20];
2565926Smckusick 	register int j;
2575926Smckusick 	result[0] = 0;
2585926Smckusick 	strcpy(oldbuf,key);
2595926Smckusick 	while(*str){
2605926Smckusick 		for(j=0;j<10;j++)buf[j] = 0;
2615926Smckusick 		for(j=0;j<8 && *str;j++)buf[j] = *str++;
2625926Smckusick 		strcat(result,nbs8encrypt(buf,oldbuf));
2635926Smckusick 		strcat(result,"$");
2645926Smckusick 		strcpy(oldbuf,buf);
2655926Smckusick 		}
2665926Smckusick 	return(result);
2675926Smckusick 	}
2685926Smckusick static
2695926Smckusick char *nbsdecrypt(cpt,key,result)
2705926Smckusick   char *result;
2715926Smckusick   char *cpt,*key; {
2725926Smckusick 	char *s;
2735926Smckusick 	char c,oldbuf[20];
2745926Smckusick 	result[0] = 0;
2755926Smckusick 	strcpy(oldbuf,key);
2765926Smckusick 	while(*cpt){
2775926Smckusick 		for(s = cpt;*s && *s != '$';s++);
2785926Smckusick 		c = *s;
2795926Smckusick 		*s = 0;
2805926Smckusick 		strcpy(oldbuf,nbs8decrypt(cpt,oldbuf));
2815926Smckusick 		strcat(result,oldbuf);
2825926Smckusick 		if(c == 0)break;
2835926Smckusick 		cpt = s + 1;
2845926Smckusick 		}
2855926Smckusick 	return(result);
2865926Smckusick 	}
2875926Smckusick 
2885926Smckusick static
2895926Smckusick char *nbs8encrypt(str,key)
2905926Smckusick char *str, *key; {
2915926Smckusick 	static char keyblk[100], blk[100];
2925926Smckusick 	register int i;
2935926Smckusick 
2945926Smckusick 	enblkclr(keyblk,key);
2955926Smckusick 	nbssetkey(keyblk);
2965926Smckusick 
2975926Smckusick 	for(i=0;i<48;i++) E[i] = e[i];
2985926Smckusick 	enblkclr(blk,str);
2995926Smckusick 	blkencrypt(blk,0);			/* forward dir */
3005926Smckusick 
3015926Smckusick 	return(deblknot(blk));
3025926Smckusick }
3035926Smckusick 
3045926Smckusick static
3055926Smckusick char *nbs8decrypt(crp,key)
3065926Smckusick char *crp, *key; {
3075926Smckusick 	static char keyblk[100], blk[100];
3085926Smckusick 	register int i;
3095926Smckusick 
3105926Smckusick 	enblkclr(keyblk,key);
3115926Smckusick 	nbssetkey(keyblk);
3125926Smckusick 
3135926Smckusick 	for(i=0;i<48;i++) E[i] = e[i];
3145926Smckusick 	enblknot(blk,crp);
3155926Smckusick 	blkencrypt(blk,1);			/* backward dir */
3165926Smckusick 
3175926Smckusick 	return(deblkclr(blk));
3185926Smckusick }
3195926Smckusick 
3205926Smckusick static
3215926Smckusick enblkclr(blk,str)		/* ignores top bit of chars in string str */
3225926Smckusick char *blk,*str; {
3235926Smckusick 	register int i,j;
3245926Smckusick 	char c;
3255926Smckusick 	for(i=0;i<70;i++)blk[i] = 0;
3265926Smckusick 	for(i=0; (c= *str) && i<64; str++){
3275926Smckusick 		for(j=0; j<7; j++, i++)
3285926Smckusick 			blk[i] = (c>>(6-j)) & 01;
3295926Smckusick 		i++;
3305926Smckusick 		}
3315926Smckusick 	}
3325926Smckusick 
3335926Smckusick static
3345926Smckusick char *deblkclr(blk)
3355926Smckusick char *blk; {
3365926Smckusick 	register int i,j;
3375926Smckusick 	char c;
3385926Smckusick 	static char iobuf[30];
3395926Smckusick 	for(i=0; i<10; i++){
3405926Smckusick 		c = 0;
3415926Smckusick 		for(j=0; j<7; j++){
3425926Smckusick 			c <<= 1;
3435926Smckusick 			c |= blk[8*i+j];
3445926Smckusick 			}
3455926Smckusick 		iobuf[i] = c;
3465926Smckusick 	}
3475926Smckusick 	iobuf[i] = 0;
3485926Smckusick 	return(iobuf);
3495926Smckusick 	}
3505926Smckusick 
3515926Smckusick static
3525926Smckusick enblknot(blk,crp)
3535926Smckusick char *blk;
3545926Smckusick char *crp; {
3555926Smckusick 	register int i,j;
3565926Smckusick 	char c;
3575926Smckusick 	for(i=0;i<70;i++)blk[i] = 0;
3585926Smckusick 	for(i=0; (c= *crp) && i<64; crp++){
3595926Smckusick 		if(c>'Z') c -= 6;
3605926Smckusick 		if(c>'9') c -= 7;
3615926Smckusick 		c -= '.';
3625926Smckusick 		for(j=0; j<6; j++, i++)
3635926Smckusick 			blk[i] = (c>>(5-j)) & 01;
3645926Smckusick 		}
3655926Smckusick 	}
3665926Smckusick 
3675926Smckusick static
3685926Smckusick char *deblknot(blk)
3695926Smckusick char *blk; {
3705926Smckusick 	register int i,j;
3715926Smckusick 	char c;
3725926Smckusick 	static char iobuf[30];
3735926Smckusick 	for(i=0; i<11; i++){
3745926Smckusick 		c = 0;
3755926Smckusick 		for(j=0; j<6; j++){
3765926Smckusick 			c <<= 1;
3775926Smckusick 			c |= blk[6*i+j];
3785926Smckusick 			}
3795926Smckusick 		c += '.';
3805926Smckusick 		if(c > '9')c += 7;
3815926Smckusick 		if(c > 'Z')c += 6;
3825926Smckusick 		iobuf[i] = c;
3835926Smckusick 	}
3845926Smckusick 	iobuf[i] = 0;
3855926Smckusick 	return(iobuf);
3865926Smckusick }
3875926Smckusick 
3885926Smckusick /*
3895926Smckusick  * This program implements the
3905926Smckusick  * Proposed Federal Information Processing
3915926Smckusick  *  Data Encryption Standard.
3925926Smckusick  * See Federal Register, March 17, 1975 (40FR12134)
3935926Smckusick  */
3945926Smckusick 
3955926Smckusick /*
3965926Smckusick  * Initial permutation,
3975926Smckusick  */
3985926Smckusick static	char	IP[] = {
3995926Smckusick 	58,50,42,34,26,18,10, 2,
4005926Smckusick 	60,52,44,36,28,20,12, 4,
4015926Smckusick 	62,54,46,38,30,22,14, 6,
4025926Smckusick 	64,56,48,40,32,24,16, 8,
4035926Smckusick 	57,49,41,33,25,17, 9, 1,
4045926Smckusick 	59,51,43,35,27,19,11, 3,
4055926Smckusick 	61,53,45,37,29,21,13, 5,
4065926Smckusick 	63,55,47,39,31,23,15, 7,
4075926Smckusick };
4085926Smckusick 
4095926Smckusick /*
4105926Smckusick  * Final permutation, FP = IP^(-1)
4115926Smckusick  */
4125926Smckusick static	char	FP[] = {
4135926Smckusick 	40, 8,48,16,56,24,64,32,
4145926Smckusick 	39, 7,47,15,55,23,63,31,
4155926Smckusick 	38, 6,46,14,54,22,62,30,
4165926Smckusick 	37, 5,45,13,53,21,61,29,
4175926Smckusick 	36, 4,44,12,52,20,60,28,
4185926Smckusick 	35, 3,43,11,51,19,59,27,
4195926Smckusick 	34, 2,42,10,50,18,58,26,
4205926Smckusick 	33, 1,41, 9,49,17,57,25,
4215926Smckusick };
4225926Smckusick 
4235926Smckusick /*
4245926Smckusick  * Permuted-choice 1 from the key bits
4255926Smckusick  * to yield C and D.
4265926Smckusick  * Note that bits 8,16... are left out:
4275926Smckusick  * They are intended for a parity check.
4285926Smckusick  */
4295926Smckusick static	char	PC1_C[] = {
4305926Smckusick 	57,49,41,33,25,17, 9,
4315926Smckusick 	 1,58,50,42,34,26,18,
4325926Smckusick 	10, 2,59,51,43,35,27,
4335926Smckusick 	19,11, 3,60,52,44,36,
4345926Smckusick };
4355926Smckusick 
4365926Smckusick static	char	PC1_D[] = {
4375926Smckusick 	63,55,47,39,31,23,15,
4385926Smckusick 	 7,62,54,46,38,30,22,
4395926Smckusick 	14, 6,61,53,45,37,29,
4405926Smckusick 	21,13, 5,28,20,12, 4,
4415926Smckusick };
4425926Smckusick 
4435926Smckusick /*
4445926Smckusick  * Sequence of shifts used for the key schedule.
4455926Smckusick */
4465926Smckusick static	char	shifts[] = {
4475926Smckusick 	1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
4485926Smckusick };
4495926Smckusick 
4505926Smckusick /*
4515926Smckusick  * Permuted-choice 2, to pick out the bits from
4525926Smckusick  * the CD array that generate the key schedule.
4535926Smckusick  */
4545926Smckusick static	char	PC2_C[] = {
4555926Smckusick 	14,17,11,24, 1, 5,
4565926Smckusick 	 3,28,15, 6,21,10,
4575926Smckusick 	23,19,12, 4,26, 8,
4585926Smckusick 	16, 7,27,20,13, 2,
4595926Smckusick };
4605926Smckusick 
4615926Smckusick static	char	PC2_D[] = {
4625926Smckusick 	41,52,31,37,47,55,
4635926Smckusick 	30,40,51,45,33,48,
4645926Smckusick 	44,49,39,56,34,53,
4655926Smckusick 	46,42,50,36,29,32,
4665926Smckusick };
4675926Smckusick 
4685926Smckusick /*
4695926Smckusick  * The C and D arrays used to calculate the key schedule.
4705926Smckusick  */
4715926Smckusick 
4725926Smckusick static	char	C[28];
4735926Smckusick static	char	D[28];
4745926Smckusick /*
4755926Smckusick  * The key schedule.
4765926Smckusick  * Generated from the key.
4775926Smckusick  */
4785926Smckusick static	char	KS[16][48];
4795926Smckusick 
4805926Smckusick /*
4815926Smckusick  * Set up the key schedule from the key.
4825926Smckusick  */
4835926Smckusick 
4845926Smckusick static
4855926Smckusick nbssetkey(key)
4865926Smckusick char *key;
4875926Smckusick {
4885926Smckusick 	register i, j, k;
4895926Smckusick 	int t;
4905926Smckusick 
4915926Smckusick 	/*
4925926Smckusick 	 * First, generate C and D by permuting
4935926Smckusick 	 * the key.  The low order bit of each
4945926Smckusick 	 * 8-bit char is not used, so C and D are only 28
4955926Smckusick 	 * bits apiece.
4965926Smckusick 	 */
4975926Smckusick 	for (i=0; i<28; i++) {
4985926Smckusick 		C[i] = key[PC1_C[i]-1];
4995926Smckusick 		D[i] = key[PC1_D[i]-1];
5005926Smckusick 	}
5015926Smckusick 	/*
5025926Smckusick 	 * To generate Ki, rotate C and D according
5035926Smckusick 	 * to schedule and pick up a permutation
5045926Smckusick 	 * using PC2.
5055926Smckusick 	 */
5065926Smckusick 	for (i=0; i<16; i++) {
5075926Smckusick 		/*
5085926Smckusick 		 * rotate.
5095926Smckusick 		 */
5105926Smckusick 		for (k=0; k<shifts[i]; k++) {
5115926Smckusick 			t = C[0];
5125926Smckusick 			for (j=0; j<28-1; j++)
5135926Smckusick 				C[j] = C[j+1];
5145926Smckusick 			C[27] = t;
5155926Smckusick 			t = D[0];
5165926Smckusick 			for (j=0; j<28-1; j++)
5175926Smckusick 				D[j] = D[j+1];
5185926Smckusick 			D[27] = t;
5195926Smckusick 		}
5205926Smckusick 		/*
5215926Smckusick 		 * get Ki. Note C and D are concatenated.
5225926Smckusick 		 */
5235926Smckusick 		for (j=0; j<24; j++) {
5245926Smckusick 			KS[i][j] = C[PC2_C[j]-1];
5255926Smckusick 			KS[i][j+24] = D[PC2_D[j]-28-1];
5265926Smckusick 		}
5275926Smckusick 	}
5285926Smckusick }
5295926Smckusick 
5305926Smckusick 
5315926Smckusick /*
5325926Smckusick  * The 8 selection functions.
5335926Smckusick  * For some reason, they give a 0-origin
5345926Smckusick  * index, unlike everything else.
5355926Smckusick  */
5365926Smckusick static	char	S[8][64] = {
5375926Smckusick 	14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
5385926Smckusick 	 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
5395926Smckusick 	 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
5405926Smckusick 	15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
5415926Smckusick 
5425926Smckusick 	15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
5435926Smckusick 	 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
5445926Smckusick 	 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
5455926Smckusick 	13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
5465926Smckusick 
5475926Smckusick 	10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
5485926Smckusick 	13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
5495926Smckusick 	13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
5505926Smckusick 	 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
5515926Smckusick 
5525926Smckusick 	 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
5535926Smckusick 	13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
5545926Smckusick 	10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
5555926Smckusick 	 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
5565926Smckusick 
5575926Smckusick 	 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
5585926Smckusick 	14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
5595926Smckusick 	 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
5605926Smckusick 	11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
5615926Smckusick 
5625926Smckusick 	12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
5635926Smckusick 	10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
5645926Smckusick 	 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
5655926Smckusick 	 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
5665926Smckusick 
5675926Smckusick 	 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
5685926Smckusick 	13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
5695926Smckusick 	 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
5705926Smckusick 	 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
5715926Smckusick 
5725926Smckusick 	13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
5735926Smckusick 	 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
5745926Smckusick 	 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
5755926Smckusick 	 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
5765926Smckusick };
5775926Smckusick 
5785926Smckusick /*
5795926Smckusick  * P is a permutation on the selected combination
5805926Smckusick  * of the current L and key.
5815926Smckusick  */
5825926Smckusick static	char	P[] = {
5835926Smckusick 	16, 7,20,21,
5845926Smckusick 	29,12,28,17,
5855926Smckusick 	 1,15,23,26,
5865926Smckusick 	 5,18,31,10,
5875926Smckusick 	 2, 8,24,14,
5885926Smckusick 	32,27, 3, 9,
5895926Smckusick 	19,13,30, 6,
5905926Smckusick 	22,11, 4,25,
5915926Smckusick };
5925926Smckusick 
5935926Smckusick /*
5945926Smckusick  * The current block, divided into 2 halves.
5955926Smckusick  */
5965926Smckusick static	char	L[32], R[32];
5975926Smckusick static	char	tempL[32];
5985926Smckusick static	char	f[32];
5995926Smckusick 
6005926Smckusick /*
6015926Smckusick  * The combination of the key and the input, before selection.
6025926Smckusick  */
6035926Smckusick static	char	preS[48];
6045926Smckusick 
6055926Smckusick /*
6065926Smckusick  * The payoff: encrypt a block.
6075926Smckusick  */
6085926Smckusick 
6095926Smckusick static
6105926Smckusick blkencrypt(block, edflag)
6115926Smckusick char *block;
6125926Smckusick {
6135926Smckusick 	int i, ii;
6145926Smckusick 	register t, j, k;
6155926Smckusick 
6165926Smckusick 	/*
6175926Smckusick 	 * First, permute the bits in the input
6185926Smckusick 	 */
6195926Smckusick 	for (j=0; j<64; j++)
6205926Smckusick 		L[j] = block[IP[j]-1];
6215926Smckusick 	/*
6225926Smckusick 	 * Perform an encryption operation 16 times.
6235926Smckusick 	 */
6245926Smckusick 	for (ii=0; ii<16; ii++) {
6255926Smckusick 		/*
6265926Smckusick 		 * Set direction
6275926Smckusick 		 */
6285926Smckusick 		if (edflag)
6295926Smckusick 			i = 15-ii;
6305926Smckusick 		else
6315926Smckusick 			i = ii;
6325926Smckusick 		/*
6335926Smckusick 		 * Save the R array,
6345926Smckusick 		 * which will be the new L.
6355926Smckusick 		 */
6365926Smckusick 		for (j=0; j<32; j++)
6375926Smckusick 			tempL[j] = R[j];
6385926Smckusick 		/*
6395926Smckusick 		 * Expand R to 48 bits using the E selector;
6405926Smckusick 		 * exclusive-or with the current key bits.
6415926Smckusick 		 */
6425926Smckusick 		for (j=0; j<48; j++)
6435926Smckusick 			preS[j] = R[E[j]-1] ^ KS[i][j];
6445926Smckusick 		/*
6455926Smckusick 		 * The pre-select bits are now considered
6465926Smckusick 		 * in 8 groups of 6 bits each.
6475926Smckusick 		 * The 8 selection functions map these
6485926Smckusick 		 * 6-bit quantities into 4-bit quantities
6495926Smckusick 		 * and the results permuted
6505926Smckusick 		 * to make an f(R, K).
6515926Smckusick 		 * The indexing into the selection functions
6525926Smckusick 		 * is peculiar; it could be simplified by
6535926Smckusick 		 * rewriting the tables.
6545926Smckusick 		 */
6555926Smckusick 		for (j=0; j<8; j++) {
6565926Smckusick 			t = 6*j;
6575926Smckusick 			k = S[j][(preS[t+0]<<5)+
6585926Smckusick 				(preS[t+1]<<3)+
6595926Smckusick 				(preS[t+2]<<2)+
6605926Smckusick 				(preS[t+3]<<1)+
6615926Smckusick 				(preS[t+4]<<0)+
6625926Smckusick 				(preS[t+5]<<4)];
6635926Smckusick 			t = 4*j;
6645926Smckusick 			f[t+0] = (k>>3)&01;
6655926Smckusick 			f[t+1] = (k>>2)&01;
6665926Smckusick 			f[t+2] = (k>>1)&01;
6675926Smckusick 			f[t+3] = (k>>0)&01;
6685926Smckusick 		}
6695926Smckusick 		/*
6705926Smckusick 		 * The new R is L ^ f(R, K).
6715926Smckusick 		 * The f here has to be permuted first, though.
6725926Smckusick 		 */
6735926Smckusick 		for (j=0; j<32; j++)
6745926Smckusick 			R[j] = L[j] ^ f[P[j]-1];
6755926Smckusick 		/*
6765926Smckusick 		 * Finally, the new L (the original R)
6775926Smckusick 		 * is copied back.
6785926Smckusick 		 */
6795926Smckusick 		for (j=0; j<32; j++)
6805926Smckusick 			L[j] = tempL[j];
6815926Smckusick 	}
6825926Smckusick 	/*
6835926Smckusick 	 * The output L and R are reversed.
6845926Smckusick 	 */
6855926Smckusick 	for (j=0; j<32; j++) {
6865926Smckusick 		t = L[j];
6875926Smckusick 		L[j] = R[j];
6885926Smckusick 		R[j] = t;
6895926Smckusick 	}
6905926Smckusick 	/*
6915926Smckusick 	 * The final output
6925926Smckusick 	 * gets the inverse permutation of the very original.
6935926Smckusick 	 */
6945926Smckusick 	for (j=0; j<64; j++)
6955926Smckusick 		block[j] = L[FP[j]-1];
6965926Smckusick }
6975926Smckusick /*
6985926Smckusick 	getutmp()
6995926Smckusick 	return a pointer to the system utmp structure associated with
7005926Smckusick 	terminal sttyname, e.g. "/dev/tty3"
7015926Smckusick 	Is version independent-- will work on v6 systems
7025926Smckusick 	return NULL if error
7035926Smckusick */
7045926Smckusick static
7055926Smckusick struct utmp *getutmp(sttyname)
7065926Smckusick char *sttyname;
7075926Smckusick {
7085926Smckusick 	static struct utmp utmpstr;
7095926Smckusick 	FILE *fdutmp;
7105926Smckusick 
7115926Smckusick 	if(sttyname == NULL || sttyname[0] == 0)return(NULL);
7125926Smckusick 
7135926Smckusick 	fdutmp = fopen("/etc/utmp","r");
7145926Smckusick 	if(fdutmp == NULL)return(NULL);
7155926Smckusick 
7165926Smckusick 	while(fread(&utmpstr,1,sizeof utmpstr,fdutmp) == sizeof utmpstr)
7175926Smckusick 		if(strcmp(utmpstr.ut_line,sttyname+5) == 0){
7185926Smckusick 			fclose(fdutmp);
7195926Smckusick 			return(&utmpstr);
7205926Smckusick 		}
7215926Smckusick 	fclose(fdutmp);
7225926Smckusick 	return(NULL);
7235926Smckusick }
7245926Smckusick 
7255926Smckusick static
7265926Smckusick sreverse(sto, sfrom)
7275926Smckusick 	register char *sto, *sfrom;
7285926Smckusick {
7295926Smckusick 	register int i;
7305926Smckusick 
7315926Smckusick 	i = strlen(sfrom);
7325926Smckusick 	while (i >= 0)
7335926Smckusick 		*sto++ = sfrom[i--];
7345926Smckusick }
7355926Smckusick 
7365926Smckusick static
7375926Smckusick char *mkenvkey(mch)
7385926Smckusick 	char mch;
7395926Smckusick {
7405926Smckusick 	static char skey[40];
7415926Smckusick 	register struct utmp *putmp;
7425926Smckusick 	char stemp[40], stemp1[40], sttyname[30];
7435926Smckusick 	register char *sk,*p;
7445926Smckusick 
7455926Smckusick 	if (isatty(2))
7465926Smckusick 		strcpy(sttyname,ttyname(2));
7475926Smckusick 	else if (isatty(0))
7485926Smckusick 		strcpy(sttyname,ttyname(0));
7495926Smckusick 	else if (isatty(1))
7505926Smckusick 		strcpy(sttyname,ttyname(1));
7515926Smckusick 	else
7525926Smckusick 		return (NULL);
7535926Smckusick 	putmp = getutmp(sttyname);
7545926Smckusick 	if (putmp == NULL)
7555926Smckusick 		return (NULL);
7565926Smckusick 	sk = skey;
7575926Smckusick 	p = putmp->ut_line;
7585926Smckusick 	while (*p)
7595926Smckusick 		*sk++ = *p++;
7605926Smckusick 	*sk++ = mch;
7615926Smckusick 	sprintf(stemp, "%ld", putmp->ut_time);
7625926Smckusick 	sreverse(stemp1, stemp);
7635926Smckusick 	p = stemp1;
7645926Smckusick 	while (*p)
7655926Smckusick 		*sk++ = *p++;
7665926Smckusick 	*sk = 0;
7675926Smckusick 	return (skey);
7685926Smckusick }
7695926Smckusick 
7705926Smckusick mkpwunclear(spasswd,mch,sencpasswd)
7715926Smckusick 	char mch, *spasswd, *sencpasswd;
7725926Smckusick {
7735926Smckusick 	register char *skey;
7745926Smckusick 
7755926Smckusick 	if (spasswd[0] == 0) {
7765926Smckusick 		sencpasswd[0] = 0;
7775926Smckusick 		return;
7785926Smckusick 	}
7795926Smckusick 	skey = mkenvkey(mch);
7805926Smckusick 	if (skey == NULL) {
7815926Smckusick 		fprintf(stderr, "Can't make key\n");
7825926Smckusick 		exit(1);
7835926Smckusick 	}
7845926Smckusick 	nbsencrypt(spasswd, skey, sencpasswd);
7855926Smckusick }
7865926Smckusick 
7875926Smckusick mkpwclear(sencpasswd,mch,spasswd)
7885926Smckusick 	char mch, *spasswd, *sencpasswd;
7895926Smckusick {
7905926Smckusick 	register char *skey;
7915926Smckusick 
7925926Smckusick 	if (sencpasswd[0] == 0) {
7935926Smckusick 		spasswd[0] = 0;
7945926Smckusick 		return;
7955926Smckusick 	}
7965926Smckusick 	skey = mkenvkey(mch);
7975926Smckusick 	if (skey == NULL) {
7985926Smckusick 		fprintf(stderr, "Can't make key\n");
7995926Smckusick 		exit(1);
8005926Smckusick 	}
8015926Smckusick 	nbsdecrypt(sencpasswd, skey, spasswd);
8025926Smckusick }
803