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