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