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