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