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