xref: /csrg-svn/lib/libcompat/4.3/ruserpass.c (revision 34818)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #if defined(LIBC_SCCS) && !defined(lint)
19 static char sccsid[] = "@(#)ruserpass.c	5.5 (Berkeley) 06/27/88";
20 #endif /* LIBC_SCCS and not lint */
21 
22 #include <stdio.h>
23 #include <utmp.h>
24 #include <ctype.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <errno.h>
28 
29 char	*renvlook(), *malloc(), *index(), *getenv(), *getpass(), *getlogin();
30 struct	utmp *getutmp();
31 static	FILE *cfile;
32 
33 ruserpass(host, aname, apass)
34 	char *host, **aname, **apass;
35 {
36 
37 	renv(host, aname, apass);
38 	if (*aname == 0 || *apass == 0)
39 		rnetrc(host, aname, apass);
40 	if (*aname == 0) {
41 		char *myname = getlogin();
42 		*aname = malloc(16);
43 		printf("Name (%s:%s): ", host, myname);
44 		fflush(stdout);
45 		if (read(2, *aname, 16) <= 0)
46 			exit(1);
47 		if ((*aname)[0] == '\n')
48 			*aname = myname;
49 		else
50 			if (index(*aname, '\n'))
51 				*index(*aname, '\n') = 0;
52 	}
53 	if (*aname && *apass == 0) {
54 		printf("Password (%s:%s): ", host, *aname);
55 		fflush(stdout);
56 		*apass = getpass("");
57 	}
58 }
59 
60 static
61 renv(host, aname, apass)
62 	char *host, **aname, **apass;
63 {
64 	register char *cp;
65 	char *stemp, fgetlogin, *comma;
66 
67 	cp = renvlook(host);
68 	if (cp == NULL)
69 		return;
70 	if (!isalpha(cp[0]))
71 		return;
72 	comma = index(cp, ',');
73 	if (comma == 0)
74 		return;
75 	if (*aname == 0) {
76 		*aname = malloc(comma - cp + 1);
77 		strncpy(*aname, cp, comma - cp);
78 	} else
79 		if (strncmp(*aname, cp, comma - cp))
80 			return;
81 	comma++;
82 	cp = malloc(strlen(comma)+1);
83 	strcpy(cp, comma);
84 	*apass = malloc(16);
85 	mkpwclear(cp, host[0], *apass);
86 }
87 
88 static
89 char *
90 renvlook(host)
91 	char *host;
92 {
93 	register char *cp, **env;
94 	extern char **environ;
95 
96 	env = environ;
97 	for (env = environ; *env != NULL; env++)
98 		if (!strncmp(*env, "MACH", 4)) {
99 			cp = index(*env, '=');
100 			if (cp == 0)
101 				continue;
102 			if (strncmp(*env+4, host, cp-(*env+4)))
103 				continue;
104 			return (cp+1);
105 		}
106 	return (NULL);
107 }
108 
109 #define	DEFAULT	1
110 #define	LOGIN	2
111 #define	PASSWD	3
112 #define	NOTIFY	4
113 #define	WRITE	5
114 #define	YES	6
115 #define	NO	7
116 #define	COMMAND	8
117 #define	FORCE	9
118 #define	ID	10
119 #define	MACHINE	11
120 
121 static char tokval[100];
122 
123 static struct toktab {
124 	char *tokstr;
125 	int tval;
126 } toktab[]= {
127 	"default",	DEFAULT,
128 	"login",	LOGIN,
129 	"password",	PASSWD,
130 	"notify",	NOTIFY,
131 	"write",	WRITE,
132 	"yes",		YES,
133 	"y",		YES,
134 	"no",		NO,
135 	"n",		NO,
136 	"command",	COMMAND,
137 	"force",	FORCE,
138 	"machine",	MACHINE,
139 	0,		0
140 };
141 
142 static
143 rnetrc(host, aname, apass)
144 	char *host, **aname, **apass;
145 {
146 	char *hdir, buf[BUFSIZ];
147 	int t;
148 	struct stat stb;
149 	extern int errno;
150 
151 	hdir = getenv("HOME");
152 	if (hdir == NULL)
153 		hdir = ".";
154 	(void)sprintf(buf, "%s/.netrc", hdir);
155 	cfile = fopen(buf, "r");
156 	if (cfile == NULL) {
157 		if (errno != ENOENT)
158 			perror(buf);
159 		return;
160 	}
161 next:
162 	while ((t = token())) switch(t) {
163 
164 	case DEFAULT:
165 		(void) token();
166 		continue;
167 
168 	case MACHINE:
169 		if (token() != ID || strcmp(host, tokval))
170 			continue;
171 		while ((t = token()) && t != MACHINE) switch(t) {
172 
173 		case LOGIN:
174 			if (token())
175 				if (*aname == 0) {
176 					*aname = malloc(strlen(tokval) + 1);
177 					strcpy(*aname, tokval);
178 				} else {
179 					if (strcmp(*aname, tokval))
180 						goto next;
181 				}
182 			break;
183 		case PASSWD:
184 			if (fstat(fileno(cfile), &stb) >= 0
185 			    && (stb.st_mode & 077) != 0) {
186 	fprintf(stderr, "Error - .netrc file not correct mode.\n");
187 	fprintf(stderr, "Remove password or correct mode.\n");
188 				exit(1);
189 			}
190 			if (token() && *apass == 0) {
191 				*apass = malloc(strlen(tokval) + 1);
192 				strcpy(*apass, tokval);
193 			}
194 			break;
195 		case COMMAND:
196 		case NOTIFY:
197 		case WRITE:
198 		case FORCE:
199 			(void) token();
200 			break;
201 		default:
202 	fprintf(stderr, "Unknown .netrc option %s\n", tokval);
203 			break;
204 		}
205 		goto done;
206 	}
207 done:
208 	fclose(cfile);
209 }
210 
211 static
212 token()
213 {
214 	char *cp;
215 	int c;
216 	struct toktab *t;
217 
218 	if (feof(cfile))
219 		return (0);
220 	while ((c = getc(cfile)) != EOF &&
221 	    (c == '\n' || c == '\t' || c == ' ' || c == ','))
222 		continue;
223 	if (c == EOF)
224 		return (0);
225 	cp = tokval;
226 	if (c == '"') {
227 		while ((c = getc(cfile)) != EOF && c != '"') {
228 			if (c == '\\')
229 				c = getc(cfile);
230 			*cp++ = c;
231 		}
232 	} else {
233 		*cp++ = c;
234 		while ((c = getc(cfile)) != EOF
235 		    && c != '\n' && c != '\t' && c != ' ' && c != ',') {
236 			if (c == '\\')
237 				c = getc(cfile);
238 			*cp++ = c;
239 		}
240 	}
241 	*cp = 0;
242 	if (tokval[0] == 0)
243 		return (0);
244 	for (t = toktab; t->tokstr; t++)
245 		if (!strcmp(t->tokstr, tokval))
246 			return (t->tval);
247 	return (ID);
248 }
249 /* rest is nbs.c stolen from berknet */
250 
251 char *deblknot(), *deblkclr();
252 char *nbs8decrypt(), *nbs8encrypt();
253 static char	E[48];
254 
255 /*
256  * The E bit-selection table.
257  */
258 static char	e[] = {
259 	32, 1, 2, 3, 4, 5,
260 	 4, 5, 6, 7, 8, 9,
261 	 8, 9,10,11,12,13,
262 	12,13,14,15,16,17,
263 	16,17,18,19,20,21,
264 	20,21,22,23,24,25,
265 	24,25,26,27,28,29,
266 	28,29,30,31,32, 1,
267 };
268 static
269 char *nbsencrypt(str,key,result)
270   char *result;
271   char *str, *key; {
272 	static char buf[20],oldbuf[20];
273 	register int j;
274 	result[0] = 0;
275 	strcpy(oldbuf,key);
276 	while(*str){
277 		for(j=0;j<10;j++)buf[j] = 0;
278 		for(j=0;j<8 && *str;j++)buf[j] = *str++;
279 		strcat(result,nbs8encrypt(buf,oldbuf));
280 		strcat(result,"$");
281 		strcpy(oldbuf,buf);
282 		}
283 	return(result);
284 	}
285 static
286 char *nbsdecrypt(cpt,key,result)
287   char *result;
288   char *cpt,*key; {
289 	char *s;
290 	char c,oldbuf[20];
291 	result[0] = 0;
292 	strcpy(oldbuf,key);
293 	while(*cpt){
294 		for(s = cpt;*s && *s != '$';s++);
295 		c = *s;
296 		*s = 0;
297 		strcpy(oldbuf,nbs8decrypt(cpt,oldbuf));
298 		strcat(result,oldbuf);
299 		if(c == 0)break;
300 		cpt = s + 1;
301 		}
302 	return(result);
303 	}
304 
305 static
306 char *nbs8encrypt(str,key)
307 char *str, *key; {
308 	static char keyblk[100], blk[100];
309 	register int i;
310 
311 	enblkclr(keyblk,key);
312 	nbssetkey(keyblk);
313 
314 	for(i=0;i<48;i++) E[i] = e[i];
315 	enblkclr(blk,str);
316 	blkencrypt(blk,0);			/* forward dir */
317 
318 	return(deblknot(blk));
319 }
320 
321 static
322 char *nbs8decrypt(crp,key)
323 char *crp, *key; {
324 	static char keyblk[100], blk[100];
325 	register int i;
326 
327 	enblkclr(keyblk,key);
328 	nbssetkey(keyblk);
329 
330 	for(i=0;i<48;i++) E[i] = e[i];
331 	enblknot(blk,crp);
332 	blkencrypt(blk,1);			/* backward dir */
333 
334 	return(deblkclr(blk));
335 }
336 
337 static
338 enblkclr(blk,str)		/* ignores top bit of chars in string str */
339 char *blk,*str; {
340 	register int i,j;
341 	char c;
342 	for(i=0;i<70;i++)blk[i] = 0;
343 	for(i=0; (c= *str) && i<64; str++){
344 		for(j=0; j<7; j++, i++)
345 			blk[i] = (c>>(6-j)) & 01;
346 		i++;
347 		}
348 	}
349 
350 static
351 char *deblkclr(blk)
352 char *blk; {
353 	register int i,j;
354 	char c;
355 	static char iobuf[30];
356 	for(i=0; i<10; i++){
357 		c = 0;
358 		for(j=0; j<7; j++){
359 			c <<= 1;
360 			c |= blk[8*i+j];
361 			}
362 		iobuf[i] = c;
363 	}
364 	iobuf[i] = 0;
365 	return(iobuf);
366 	}
367 
368 static
369 enblknot(blk,crp)
370 char *blk;
371 char *crp; {
372 	register int i,j;
373 	char c;
374 	for(i=0;i<70;i++)blk[i] = 0;
375 	for(i=0; (c= *crp) && i<64; crp++){
376 		if(c>'Z') c -= 6;
377 		if(c>'9') c -= 7;
378 		c -= '.';
379 		for(j=0; j<6; j++, i++)
380 			blk[i] = (c>>(5-j)) & 01;
381 		}
382 	}
383 
384 static
385 char *deblknot(blk)
386 char *blk; {
387 	register int i,j;
388 	char c;
389 	static char iobuf[30];
390 	for(i=0; i<11; i++){
391 		c = 0;
392 		for(j=0; j<6; j++){
393 			c <<= 1;
394 			c |= blk[6*i+j];
395 			}
396 		c += '.';
397 		if(c > '9')c += 7;
398 		if(c > 'Z')c += 6;
399 		iobuf[i] = c;
400 	}
401 	iobuf[i] = 0;
402 	return(iobuf);
403 }
404 
405 /*
406  * This program implements the
407  * Proposed Federal Information Processing
408  *  Data Encryption Standard.
409  * See Federal Register, March 17, 1975 (40FR12134)
410  */
411 
412 /*
413  * Initial permutation,
414  */
415 static	char	IP[] = {
416 	58,50,42,34,26,18,10, 2,
417 	60,52,44,36,28,20,12, 4,
418 	62,54,46,38,30,22,14, 6,
419 	64,56,48,40,32,24,16, 8,
420 	57,49,41,33,25,17, 9, 1,
421 	59,51,43,35,27,19,11, 3,
422 	61,53,45,37,29,21,13, 5,
423 	63,55,47,39,31,23,15, 7,
424 };
425 
426 /*
427  * Final permutation, FP = IP^(-1)
428  */
429 static	char	FP[] = {
430 	40, 8,48,16,56,24,64,32,
431 	39, 7,47,15,55,23,63,31,
432 	38, 6,46,14,54,22,62,30,
433 	37, 5,45,13,53,21,61,29,
434 	36, 4,44,12,52,20,60,28,
435 	35, 3,43,11,51,19,59,27,
436 	34, 2,42,10,50,18,58,26,
437 	33, 1,41, 9,49,17,57,25,
438 };
439 
440 /*
441  * Permuted-choice 1 from the key bits
442  * to yield C and D.
443  * Note that bits 8,16... are left out:
444  * They are intended for a parity check.
445  */
446 static	char	PC1_C[] = {
447 	57,49,41,33,25,17, 9,
448 	 1,58,50,42,34,26,18,
449 	10, 2,59,51,43,35,27,
450 	19,11, 3,60,52,44,36,
451 };
452 
453 static	char	PC1_D[] = {
454 	63,55,47,39,31,23,15,
455 	 7,62,54,46,38,30,22,
456 	14, 6,61,53,45,37,29,
457 	21,13, 5,28,20,12, 4,
458 };
459 
460 /*
461  * Sequence of shifts used for the key schedule.
462 */
463 static	char	shifts[] = {
464 	1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
465 };
466 
467 /*
468  * Permuted-choice 2, to pick out the bits from
469  * the CD array that generate the key schedule.
470  */
471 static	char	PC2_C[] = {
472 	14,17,11,24, 1, 5,
473 	 3,28,15, 6,21,10,
474 	23,19,12, 4,26, 8,
475 	16, 7,27,20,13, 2,
476 };
477 
478 static	char	PC2_D[] = {
479 	41,52,31,37,47,55,
480 	30,40,51,45,33,48,
481 	44,49,39,56,34,53,
482 	46,42,50,36,29,32,
483 };
484 
485 /*
486  * The C and D arrays used to calculate the key schedule.
487  */
488 
489 static	char	C[28];
490 static	char	D[28];
491 /*
492  * The key schedule.
493  * Generated from the key.
494  */
495 static	char	KS[16][48];
496 
497 /*
498  * Set up the key schedule from the key.
499  */
500 
501 static
502 nbssetkey(key)
503 char *key;
504 {
505 	register i, j, k;
506 	int t;
507 
508 	/*
509 	 * First, generate C and D by permuting
510 	 * the key.  The low order bit of each
511 	 * 8-bit char is not used, so C and D are only 28
512 	 * bits apiece.
513 	 */
514 	for (i=0; i<28; i++) {
515 		C[i] = key[PC1_C[i]-1];
516 		D[i] = key[PC1_D[i]-1];
517 	}
518 	/*
519 	 * To generate Ki, rotate C and D according
520 	 * to schedule and pick up a permutation
521 	 * using PC2.
522 	 */
523 	for (i=0; i<16; i++) {
524 		/*
525 		 * rotate.
526 		 */
527 		for (k=0; k<shifts[i]; k++) {
528 			t = C[0];
529 			for (j=0; j<28-1; j++)
530 				C[j] = C[j+1];
531 			C[27] = t;
532 			t = D[0];
533 			for (j=0; j<28-1; j++)
534 				D[j] = D[j+1];
535 			D[27] = t;
536 		}
537 		/*
538 		 * get Ki. Note C and D are concatenated.
539 		 */
540 		for (j=0; j<24; j++) {
541 			KS[i][j] = C[PC2_C[j]-1];
542 			KS[i][j+24] = D[PC2_D[j]-28-1];
543 		}
544 	}
545 }
546 
547 
548 /*
549  * The 8 selection functions.
550  * For some reason, they give a 0-origin
551  * index, unlike everything else.
552  */
553 static	char	S[8][64] = {
554 	14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
555 	 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
556 	 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
557 	15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
558 
559 	15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
560 	 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
561 	 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
562 	13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
563 
564 	10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
565 	13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
566 	13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
567 	 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
568 
569 	 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
570 	13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
571 	10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
572 	 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
573 
574 	 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
575 	14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
576 	 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
577 	11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
578 
579 	12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
580 	10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
581 	 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
582 	 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
583 
584 	 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
585 	13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
586 	 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
587 	 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
588 
589 	13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
590 	 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
591 	 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
592 	 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
593 };
594 
595 /*
596  * P is a permutation on the selected combination
597  * of the current L and key.
598  */
599 static	char	P[] = {
600 	16, 7,20,21,
601 	29,12,28,17,
602 	 1,15,23,26,
603 	 5,18,31,10,
604 	 2, 8,24,14,
605 	32,27, 3, 9,
606 	19,13,30, 6,
607 	22,11, 4,25,
608 };
609 
610 /*
611  * The current block, divided into 2 halves.
612  */
613 static	char	L[32], R[32];
614 static	char	tempL[32];
615 static	char	f[32];
616 
617 /*
618  * The combination of the key and the input, before selection.
619  */
620 static	char	preS[48];
621 
622 /*
623  * The payoff: encrypt a block.
624  */
625 
626 static
627 blkencrypt(block, edflag)
628 char *block;
629 {
630 	int i, ii;
631 	register t, j, k;
632 
633 	/*
634 	 * First, permute the bits in the input
635 	 */
636 	for (j=0; j<64; j++)
637 		L[j] = block[IP[j]-1];
638 	/*
639 	 * Perform an encryption operation 16 times.
640 	 */
641 	for (ii=0; ii<16; ii++) {
642 		/*
643 		 * Set direction
644 		 */
645 		if (edflag)
646 			i = 15-ii;
647 		else
648 			i = ii;
649 		/*
650 		 * Save the R array,
651 		 * which will be the new L.
652 		 */
653 		for (j=0; j<32; j++)
654 			tempL[j] = R[j];
655 		/*
656 		 * Expand R to 48 bits using the E selector;
657 		 * exclusive-or with the current key bits.
658 		 */
659 		for (j=0; j<48; j++)
660 			preS[j] = R[E[j]-1] ^ KS[i][j];
661 		/*
662 		 * The pre-select bits are now considered
663 		 * in 8 groups of 6 bits each.
664 		 * The 8 selection functions map these
665 		 * 6-bit quantities into 4-bit quantities
666 		 * and the results permuted
667 		 * to make an f(R, K).
668 		 * The indexing into the selection functions
669 		 * is peculiar; it could be simplified by
670 		 * rewriting the tables.
671 		 */
672 		for (j=0; j<8; j++) {
673 			t = 6*j;
674 			k = S[j][(preS[t+0]<<5)+
675 				(preS[t+1]<<3)+
676 				(preS[t+2]<<2)+
677 				(preS[t+3]<<1)+
678 				(preS[t+4]<<0)+
679 				(preS[t+5]<<4)];
680 			t = 4*j;
681 			f[t+0] = (k>>3)&01;
682 			f[t+1] = (k>>2)&01;
683 			f[t+2] = (k>>1)&01;
684 			f[t+3] = (k>>0)&01;
685 		}
686 		/*
687 		 * The new R is L ^ f(R, K).
688 		 * The f here has to be permuted first, though.
689 		 */
690 		for (j=0; j<32; j++)
691 			R[j] = L[j] ^ f[P[j]-1];
692 		/*
693 		 * Finally, the new L (the original R)
694 		 * is copied back.
695 		 */
696 		for (j=0; j<32; j++)
697 			L[j] = tempL[j];
698 	}
699 	/*
700 	 * The output L and R are reversed.
701 	 */
702 	for (j=0; j<32; j++) {
703 		t = L[j];
704 		L[j] = R[j];
705 		R[j] = t;
706 	}
707 	/*
708 	 * The final output
709 	 * gets the inverse permutation of the very original.
710 	 */
711 	for (j=0; j<64; j++)
712 		block[j] = L[FP[j]-1];
713 }
714 /*
715 	getutmp()
716 	return a pointer to the system utmp structure associated with
717 	terminal sttyname, e.g. "/dev/tty3"
718 	Is version independent-- will work on v6 systems
719 	return NULL if error
720 */
721 static
722 struct utmp *getutmp(sttyname)
723 char *sttyname;
724 {
725 	static struct utmp utmpstr;
726 	FILE *fdutmp;
727 
728 	if(sttyname == NULL || sttyname[0] == 0)return(NULL);
729 
730 	fdutmp = fopen("/etc/utmp","r");
731 	if(fdutmp == NULL)return(NULL);
732 
733 	while(fread(&utmpstr,1,sizeof utmpstr,fdutmp) == sizeof utmpstr)
734 		if(strcmp(utmpstr.ut_line,sttyname+5) == 0){
735 			fclose(fdutmp);
736 			return(&utmpstr);
737 		}
738 	fclose(fdutmp);
739 	return(NULL);
740 }
741 
742 static
743 sreverse(sto, sfrom)
744 	register char *sto, *sfrom;
745 {
746 	register int i;
747 
748 	i = strlen(sfrom);
749 	while (i >= 0)
750 		*sto++ = sfrom[i--];
751 }
752 
753 static
754 char *mkenvkey(mch)
755 	char mch;
756 {
757 	static char skey[40];
758 	register struct utmp *putmp;
759 	char stemp[40], stemp1[40], sttyname[30];
760 	register char *sk,*p;
761 
762 	if (isatty(2))
763 		strcpy(sttyname,ttyname(2));
764 	else if (isatty(0))
765 		strcpy(sttyname,ttyname(0));
766 	else if (isatty(1))
767 		strcpy(sttyname,ttyname(1));
768 	else
769 		return (NULL);
770 	putmp = getutmp(sttyname);
771 	if (putmp == NULL)
772 		return (NULL);
773 	sk = skey;
774 	p = putmp->ut_line;
775 	while (*p)
776 		*sk++ = *p++;
777 	*sk++ = mch;
778 	(void)sprintf(stemp, "%ld", putmp->ut_time);
779 	sreverse(stemp1, stemp);
780 	p = stemp1;
781 	while (*p)
782 		*sk++ = *p++;
783 	*sk = 0;
784 	return (skey);
785 }
786 
787 mkpwunclear(spasswd,mch,sencpasswd)
788 	char mch, *spasswd, *sencpasswd;
789 {
790 	register char *skey;
791 
792 	if (spasswd[0] == 0) {
793 		sencpasswd[0] = 0;
794 		return;
795 	}
796 	skey = mkenvkey(mch);
797 	if (skey == NULL) {
798 		fprintf(stderr, "Can't make key\n");
799 		exit(1);
800 	}
801 	nbsencrypt(spasswd, skey, sencpasswd);
802 }
803 
804 mkpwclear(sencpasswd,mch,spasswd)
805 	char mch, *spasswd, *sencpasswd;
806 {
807 	register char *skey;
808 
809 	if (sencpasswd[0] == 0) {
810 		spasswd[0] = 0;
811 		return;
812 	}
813 	skey = mkenvkey(mch);
814 	if (skey == NULL) {
815 		fprintf(stderr, "Can't make key\n");
816 		exit(1);
817 	}
818 	nbsdecrypt(sencpasswd, skey, spasswd);
819 }
820