/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)ruserpass.c 5.5 (Berkeley) 6/27/88"; #endif /* LIBC_SCCS and not lint */ #include "inetprivate.h" #include #include #include #include static void renv(const char *host, char **aname, char **apass); static char * renvlook(const char *host); static struct utmp *getutmp(char *sttyname); static FILE *cfile; static void rnetrc(const char *host, char **aname, char **apass); static void mkpwclear(char *spasswd, char mch, char *sencpasswd); static int token(); #if NLS #include "nl_types.h" #endif void ruserpass(const char *host, char **aname, char **apass) { static char namebuf [256]; struct hostent *hp; char name[256]; /* a temp name buffer to avoid overlayyed */ #if NLS libc_nls_init(); #endif strncpy(name, host, sizeof(name) - 1); if (hp = gethostbyname (name)) strncpy(name,hp->h_name, sizeof(name) - 1); renv(name, aname, apass); if (*aname == 0 || *apass == 0) rnetrc(name, aname, apass); /*rnetrc would call gethostbyname */ if (*aname == 0) { *aname = getlogin(); if (*aname == NULL) { struct passwd *pp = getpwuid(getuid()); if (pp != NULL) *aname = pp->pw_name; } #if NLS printf("%s (%s:%s): ", catgets(_libc_cat, NetMiscSet, NetMiscName, "Name"), host, *aname); #else printf("Name (%s:%s): ", host, *aname); #endif fflush(stdout); if (read(2, namebuf, sizeof (namebuf)) <= 0) { perror ("read"); exit(1); } if (namebuf [0] != '\n') { char *ptr; *aname = namebuf; namebuf [sizeof (namebuf) - 1] = '0'; if (ptr = index(namebuf, '\n')) *ptr = 0; } } if (*aname && *apass == 0) { #if NLS printf("%s (%s:%s): ", catgets(_libc_cat, NetMiscSet, NetMiscPassword, "Password"), host, *aname); #else printf("Password (%s:%s): ", host, *aname); #endif fflush(stdout); *apass = getpass(""); } } static void renv(const char *host, char **aname, char **apass) { register char *cp; char *comma; cp = renvlook(host); if (cp == NULL) return; if (!isalpha(cp[0])) return; comma = index(cp, ','); if (comma == 0) return; if (*aname == 0) { *aname = malloc(comma - cp + 1); strncpy(*aname, cp, comma - cp); } else if (strncmp(*aname, cp, comma - cp)) return; comma++; cp = malloc(strlen(comma)+1); strcpy(cp, comma); *apass = malloc(16); mkpwclear(cp, host[0], *apass); } static char * renvlook(const char *host) { register char *cp, **env; extern char **environ; env = environ; for (env = environ; *env != NULL; env++) if (!strncmp(*env, "MACH", 4)) { cp = index(*env, '='); if (cp == 0) continue; if (strncmp(*env+4, host, cp-(*env+4))) continue; return (cp+1); } return (NULL); } #define DEFAULT 1 #define LOGIN 2 #define PASSWD 3 #define NOTIFY 4 #define WRITE 5 #define YES 6 #define NO 7 #define COMMAND 8 #define FORCE 9 #define ID 10 #define MACHINE 11 static char tokval[100]; static struct toktab { char *tokstr; int tval; } toktab[]= { "default", DEFAULT, "login", LOGIN, "password", PASSWD, "notify", NOTIFY, "write", WRITE, "yes", YES, "y", YES, "no", NO, "n", NO, "command", COMMAND, "force", FORCE, "machine", MACHINE, 0, 0 }; static void rnetrc(const char *host, char **aname, char **apass) { char *hdir, buf[BUFSIZ]; int t; struct stat stb; extern int errno; struct hostent *hp; #if NLS libc_nls_init(); #endif hdir = getenv("HOME"); if (hdir == NULL) hdir = "."; (void)sprintf(buf, "%s/.netrc", hdir); cfile = fopen(buf, "r"); if (cfile == NULL) { if (errno != ENOENT) perror(buf); return; } next: while ((t = token())) switch(t) { case DEFAULT: (void) token(); continue; case MACHINE: if (token() != ID) continue; if(hp = gethostbyname (tokval)) { if (strcmp(host, hp->h_name)) continue; } else if (strcmp(host, tokval)) continue; while ((t = token()) && t != MACHINE) switch(t) { case LOGIN: if (token()) if (*aname == 0) { *aname = malloc(strlen(tokval) + 1); strcpy(*aname, tokval); } else { if (strcmp(*aname, tokval)) goto next; } break; case PASSWD: if (fstat(fileno(cfile), &stb) >= 0 && (stb.st_mode & 077) != 0) { #if NLS fprintf(stderr, "%s\n", catgets(_libc_cat, NetMiscSet, NetMiscNetrcWrongPasswordMode, "Error - .netrc file not correct mode.\n\ Remove password or correct mode.")); #else fprintf(stderr, "Error - .netrc file not correct mode.\n"); fprintf(stderr, "Remove password or correct mode.\n"); #endif exit(1); } if (token() && *apass == 0) { *apass = malloc(strlen(tokval) + 1); strcpy(*apass, tokval); } break; case COMMAND: case NOTIFY: case WRITE: case FORCE: (void) token(); break; default: #if NLS fprintf(stderr, "%s %s\n", catgets(_libc_cat, NetMiscSet, NetMiscUnknownNetrcOption, "Unknown .netrc option"), tokval); #else fprintf(stderr, "Unknown .netrc option %s\n", tokval); #endif break; } goto done; } done: fclose(cfile); } static int token() { char *cp; int c; struct toktab *t; if (feof(cfile)) return (0); while ((c = getc(cfile)) != EOF && (c == '\n' || c == '\t' || c == ' ' || c == ',')) continue; if (c == EOF) return (0); cp = tokval; if (c == '"') { while ((c = getc(cfile)) != EOF && c != '"') { if (c == '\\') c = getc(cfile); *cp++ = c; } } else { *cp++ = c; while ((c = getc(cfile)) != EOF && c != '\n' && c != '\t' && c != ' ' && c != ',') { if (c == '\\') c = getc(cfile); *cp++ = c; } } *cp = 0; if (tokval[0] == 0) return (0); for (t = toktab; t->tokstr; t++) if (!strcmp(t->tokstr, tokval)) return (t->tval); return (ID); } /* rest is nbs.c stolen from berknet */ #if 0 static char *nbsencrypt(char *str, char *key, char *result); static char *nbs8encrypt(char *str, char *key); static char *deblknot(char *blk); #endif static char *nbsdecrypt(char *cpt, char *key, char *result); static char *nbs8decrypt(char *crp, char *key); static void enblkclr(char *blk, char *str); static char *deblkclr(char *blk); static void enblknot(char *blk, char *crp); static void nbssetkey(char *key); static void blkencrypt(char *block, int edflag); static char E[48]; /* * The E bit-selection table. */ static char e[] = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9,10,11,12,13, 12,13,14,15,16,17, 16,17,18,19,20,21, 20,21,22,23,24,25, 24,25,26,27,28,29, 28,29,30,31,32, 1, }; #if 0 static char *nbsencrypt(str,key,result) char *str, *key; char *result; { static char buf[20],oldbuf[20]; register int j; result[0] = 0; strcpy(oldbuf,key); while(*str){ for(j=0;j<10;j++)buf[j] = 0; for(j=0;j<8 && *str;j++)buf[j] = *str++; strcat(result,nbs8encrypt(buf,oldbuf)); strcat(result,"$"); strcpy(oldbuf,buf); } return(result); } #endif static char *nbsdecrypt(cpt,key,result) char *cpt,*key; char *result; { char *s; char c,oldbuf[20]; result[0] = 0; strcpy(oldbuf,key); while(*cpt){ for(s = cpt;*s && *s != '$';s++); c = *s; *s = 0; strcpy(oldbuf,nbs8decrypt(cpt,oldbuf)); strcat(result,oldbuf); if(c == 0)break; cpt = s + 1; } return(result); } #if 0 static char *nbs8encrypt(str,key) char *str, *key; { static char keyblk[100], blk[100]; register int i; enblkclr(keyblk,key); nbssetkey(keyblk); for(i=0;i<48;i++) E[i] = e[i]; enblkclr(blk,str); blkencrypt(blk,0); /* forward dir */ return(deblknot(blk)); } #endif static char *nbs8decrypt(crp,key) char *crp, *key; { static char keyblk[100], blk[100]; register int i; enblkclr(keyblk,key); nbssetkey(keyblk); for(i=0;i<48;i++) E[i] = e[i]; enblknot(blk,crp); blkencrypt(blk,1); /* backward dir */ return(deblkclr(blk)); } static void enblkclr(blk,str) /* ignores top bit of chars in string str */ char *blk,*str; { register int i,j; char c; for(i=0;i<70;i++)blk[i] = 0; for(i=0; (c= *str) && i<64; str++){ for(j=0; j<7; j++, i++) blk[i] = (c>>(6-j)) & 01; i++; } } static char *deblkclr(blk) char *blk; { register int i,j; char c; static char iobuf[30]; for(i=0; i<10; i++){ c = 0; for(j=0; j<7; j++){ c <<= 1; c |= blk[8*i+j]; } iobuf[i] = c; } iobuf[i] = 0; return(iobuf); } static void enblknot(blk,crp) char *blk; char *crp; { register int i,j; char c; for(i=0;i<70;i++)blk[i] = 0; for(i=0; (c= *crp) && i<64; crp++){ if(c>'Z') c -= 6; if(c>'9') c -= 7; c -= '.'; for(j=0; j<6; j++, i++) blk[i] = (c>>(5-j)) & 01; } } #if 0 static char *deblknot(blk) char *blk; { register int i,j; char c; static char iobuf[30]; for(i=0; i<11; i++){ c = 0; for(j=0; j<6; j++){ c <<= 1; c |= blk[6*i+j]; } c += '.'; if(c > '9')c += 7; if(c > 'Z')c += 6; iobuf[i] = c; } iobuf[i] = 0; return(iobuf); } #endif /* * This program implements the * Proposed Federal Information Processing * Data Encryption Standard. * See Federal Register, March 17, 1975 (40FR12134) */ /* * Initial permutation, */ static char IP[] = { 58,50,42,34,26,18,10, 2, 60,52,44,36,28,20,12, 4, 62,54,46,38,30,22,14, 6, 64,56,48,40,32,24,16, 8, 57,49,41,33,25,17, 9, 1, 59,51,43,35,27,19,11, 3, 61,53,45,37,29,21,13, 5, 63,55,47,39,31,23,15, 7, }; /* * Final permutation, FP = IP^(-1) */ static char FP[] = { 40, 8,48,16,56,24,64,32, 39, 7,47,15,55,23,63,31, 38, 6,46,14,54,22,62,30, 37, 5,45,13,53,21,61,29, 36, 4,44,12,52,20,60,28, 35, 3,43,11,51,19,59,27, 34, 2,42,10,50,18,58,26, 33, 1,41, 9,49,17,57,25, }; /* * Permuted-choice 1 from the key bits * to yield C and D. * Note that bits 8,16... are left out: * They are intended for a parity check. */ static char PC1_C[] = { 57,49,41,33,25,17, 9, 1,58,50,42,34,26,18, 10, 2,59,51,43,35,27, 19,11, 3,60,52,44,36, }; static char PC1_D[] = { 63,55,47,39,31,23,15, 7,62,54,46,38,30,22, 14, 6,61,53,45,37,29, 21,13, 5,28,20,12, 4, }; /* * Sequence of shifts used for the key schedule. */ static char shifts[] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1, }; /* * Permuted-choice 2, to pick out the bits from * the CD array that generate the key schedule. */ static char PC2_C[] = { 14,17,11,24, 1, 5, 3,28,15, 6,21,10, 23,19,12, 4,26, 8, 16, 7,27,20,13, 2, }; static char PC2_D[] = { 41,52,31,37,47,55, 30,40,51,45,33,48, 44,49,39,56,34,53, 46,42,50,36,29,32, }; /* * The C and D arrays used to calculate the key schedule. */ static char C[28]; static char D[28]; /* * The key schedule. * Generated from the key. */ static char KS[16][48]; /* * Set up the key schedule from the key. */ static void nbssetkey(key) char *key; { register i, j, k; int t; /* * First, generate C and D by permuting * the key. The low order bit of each * 8-bit char is not used, so C and D are only 28 * bits apiece. */ for (i=0; i<28; i++) { C[i] = key[PC1_C[i]-1]; D[i] = key[PC1_D[i]-1]; } /* * To generate Ki, rotate C and D according * to schedule and pick up a permutation * using PC2. */ for (i=0; i<16; i++) { /* * rotate. */ for (k=0; k>3)&01; f[t+1] = (k>>2)&01; f[t+2] = (k>>1)&01; f[t+3] = (k>>0)&01; } /* * The new R is L ^ f(R, K). * The f here has to be permuted first, though. */ for (j=0; j<32; j++) R[j] = L[j] ^ f[P[j]-1]; /* * Finally, the new L (the original R) * is copied back. */ for (j=0; j<32; j++) L[j] = tempL[j]; } /* * The output L and R are reversed. */ for (j=0; j<32; j++) { t = L[j]; L[j] = R[j]; R[j] = t; } /* * The final output * gets the inverse permutation of the very original. */ for (j=0; j<64; j++) block[j] = L[FP[j]-1]; } /* getutmp() return a pointer to the system utmp structure associated with terminal sttyname, e.g. "/dev/tty3" Is version independent-- will work on v6 systems return NULL if error */ static struct utmp *getutmp(char *sttyname) { static struct utmp utmpstr; FILE *fdutmp; if(sttyname == NULL || sttyname[0] == 0)return(NULL); fdutmp = fopen(_PATH_UTMP,"r"); if(fdutmp == NULL)return(NULL); while(fread(&utmpstr,1,sizeof utmpstr,fdutmp) == sizeof utmpstr) if(strcmp(utmpstr.ut_line,sttyname+5) == 0){ fclose(fdutmp); return(&utmpstr); } fclose(fdutmp); return(NULL); } static void sreverse(sto, sfrom) register char *sto, *sfrom; { register int i; i = strlen(sfrom); while (i >= 0) *sto++ = sfrom[i--]; } static char *mkenvkey(char mch) { static char skey[40]; register struct utmp *putmp; char stemp[40], stemp1[40], sttyname[30]; register char *sk,*p; if (isatty(2)) strcpy(sttyname,ttyname(2)); else if (isatty(0)) strcpy(sttyname,ttyname(0)); else if (isatty(1)) strcpy(sttyname,ttyname(1)); else return (NULL); putmp = getutmp(sttyname); if (putmp == NULL) return (NULL); sk = skey; p = putmp->ut_line; while (*p) *sk++ = *p++; *sk++ = mch; (void)sprintf(stemp, "%ld", putmp->ut_time); sreverse(stemp1, stemp); p = stemp1; while (*p) *sk++ = *p++; *sk = 0; return (skey); } #if 0 static void mkpwunclear(spasswd,mch,sencpasswd) char *spasswd, mch, *sencpasswd; { register char *skey; if (spasswd[0] == 0) { sencpasswd[0] = 0; return; } skey = mkenvkey(mch); if (skey == NULL) { fprintf(stderr, "Can't make key\n"); exit(1); } nbsencrypt(spasswd, skey, sencpasswd); } #endif static void mkpwclear(sencpasswd,mch,spasswd) char *spasswd, mch, *sencpasswd; { register char *skey; if (sencpasswd[0] == 0) { spasswd[0] = 0; return; } skey = mkenvkey(mch); if (skey == NULL) { fprintf(stderr, "Can't make key\n"); exit(1); } nbsdecrypt(sencpasswd, skey, spasswd); }