home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / inet / ruserpass.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-31  |  17.7 KB  |  914 lines

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