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