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