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