|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <string.h> ! 3: #include <ctype.h> ! 4: #include <sys/types.h> ! 5: #include <time.h> ! 6: #include "auth.h" ! 7: ! 8: #define FIELDSIZE 100 /* maximum field size in the keys file */ ! 9: #define LARGECH 99999 /* largest challenge */ ! 10: ! 11: typedef struct keydesc keydesc; ! 12: ! 13: struct keydesc { ! 14: char name[FIELDSIZE]; ! 15: char type[FIELDSIZE]; ! 16: char key[FIELDSIZE]; ! 17: long expires; ! 18: struct keydesc *next; ! 19: }; ! 20: ! 21: struct keydesc *firstkey; ! 22: struct keydesc *kp; ! 23: enum keytypes kt; ! 24: ! 25: unsigned long challenge = 0; ! 26: time_t now; /* current time, for expiration purposes */ ! 27: ! 28: extern char *keyfile; ! 29: ! 30: ! 31: /* ! 32: * Get challenge string for `login'. `type' is the login type, "" for the ! 33: * first one found. ! 34: */ ! 35: char * ! 36: getchallenge(login, type, echo) ! 37: char *login; ! 38: char *type; ! 39: int *echo; ! 40: { ! 41: static char buf[BUFSIZ]; ! 42: static int inited=0; ! 43: ! 44: for (kp=firstkey; kp; kp = kp->next) ! 45: if (strcmp(kp->name, login) == NULL) ! 46: if (type == NULL || strcmp(type, "") == NULL || ! 47: strcmp(type, kp->type) == NULL) ! 48: break; ! 49: ! 50: if (kp == (keydesc *)0 || (strcmp(kp->type, "passwd") != NULL)) { ! 51: /* ! 52: * atalla entry or illegal user. Generate a challenge. ! 53: */ ! 54: if(!inited) ! 55: srand((int)time((long*)0)); ! 56: challenge = lrand()%LARGECH; ! 57: sprintf(buf, "Enter response code for %lu: ", challenge); ! 58: if (kp == (keydesc *)0) ! 59: kt = NONE; ! 60: else ! 61: kt = ATALLA; ! 62: *echo = TRUE; ! 63: } else { ! 64: kt = PASS; ! 65: strcpy(buf, "Password: "); ! 66: *echo = FALSE; ! 67: } ! 68: return buf; ! 69: } ! 70: ! 71: /* ! 72: * He gave `response'. Return TRUE iff it is the correct ! 73: * response. ! 74: */ ! 75: int ! 76: responseok(response) ! 77: char response[]; ! 78: { ! 79: char b[64]; ! 80: int k[8]; ! 81: char buf[12]; ! 82: int i,j; ! 83: unsigned long bresponse = 0; ! 84: char cresponse[10]; ! 85: ! 86: /* ! 87: * check expiration date. ! 88: */ ! 89: if (kt != NONE && kp->expires < now) { ! 90: fprintf(stderr, "Account `%s' is expired (%d)\n", ! 91: kp->name, kp->expires); ! 92: kt = NONE; ! 93: kp = (keydesc *)0; ! 94: } ! 95: ! 96: switch(kt) { ! 97: case NONE: /* take some time, then say no. */ ! 98: setkey(b); ! 99: encrypt(b, 0); ! 100: return FALSE; ! 101: case PASS: /* the classic password hash */ ! 102: return (strcmp(crypt(response, kp->key), kp->key) == NULL); ! 103: case ATALLA: ! 104: /* ! 105: * set the key ! 106: */ ! 107: sscanf(kp->key, "%o %o %o %o %o %o %o %o", ! 108: &k[0], &k[1], &k[2], &k[3], &k[4], &k[5], &k[6], &k[7]); ! 109: for(i=0; i<8; i++) ! 110: for(j=0; j<8; j++) ! 111: b[8*i+j] = (k[i]>>(7-j))&1; ! 112: setkey(b); ! 113: ! 114: /* ! 115: * compute the proper response. We encrypt the ascii of ! 116: * challenge number, with trailing binary zero fill. ! 117: * This process was derived empirically. ! 118: */ ! 119: for(i=0; i<8; buf[i++] = 0) ! 120: ; ! 121: sprintf(buf, "%lu", challenge); ! 122: for(i=0; i<8; i++) ! 123: for(j=0; j<8; j++) ! 124: b[8*i+j] = (buf[i]>>(7-j))&1; ! 125: encrypt(b, 0); ! 126: for(i=0; i<32; i++) { ! 127: bresponse = (bresponse<<1) | b[i]; ! 128: } ! 129: ! 130: /* ! 131: * check for hex match ! 132: */ ! 133: sprintf(cresponse, "%08x", bresponse); ! 134: for (i=0; response[i]; i++) ! 135: if (isupper(response[i])) ! 136: response[i] = tolower(response[i]); ! 137: if (strcmp(response, cresponse) == 0) ! 138: return TRUE; /* Hex matches */ ! 139: ! 140: /* ! 141: * check for decimal match ! 142: */ ! 143: for (i=0; cresponse[i]; i++) ! 144: if (cresponse[i] == 'a' || cresponse[i] == 'b' || ! 145: cresponse[i] == 'c') ! 146: cresponse[i] = '2'; ! 147: else if (cresponse[i] == 'd' || cresponse[i] == 'e' || ! 148: cresponse[i] == 'f') ! 149: cresponse[i] = '3'; ! 150: return (strcmp(response, cresponse) == NULL); /* Decimal matches */ ! 151: } ! 152: } ! 153: ! 154: ! 155: /* ! 156: * Read in the keys. This won't happen in a secret-server version. ! 157: * ! 158: * key file has the following colon-separated fields: ! 159: * ! 160: * id user's id ! 161: * type entry type (`atalla' is only legal entry at the moment) ! 162: * key the key's value: ! 163: * for atalla: 8 blank-separated octal bytes ! 164: * expire expiration date of this entry [optional] ! 165: * comment [optional] ! 166: */ ! 167: readkeyfile() ! 168: { ! 169: FILE *kf; ! 170: int linenumber = 0; ! 171: char line[BUFSIZE]; ! 172: #define NFLDS 10 ! 173: char *field[NFLDS]; ! 174: keydesc *lastkey = firstkey = (keydesc *)0; ! 175: time_t t = time((long*)0); ! 176: struct tm *tm = localtime(&t); ! 177: ! 178: now = tm->tm_mday + 100*(tm->tm_mon+1) + 10000*(tm->tm_year+1900); ! 179: ! 180: if ((kf = fopen(keyfile, "r")) == NULL) { ! 181: printf("Could not open key file: get help!\n"); ! 182: exit(100); ! 183: } ! 184: setfields(":"); ! 185: while(fgets(line, sizeof(line), kf) != NULL) { ! 186: int i; ! 187: char *cp; ! 188: ! 189: linenumber++; ! 190: for(i=0; line[i] == ' ' || line[i] == '\t'; i++) ! 191: ; ! 192: if(line[i] == '#') ! 193: continue; ! 194: if((cp = strchr(&line[i], '\n')) != NULL) ! 195: *cp = '\0'; ! 196: ! 197: i = getfields(&line[i], field, NFLDS); ! 198: if(i <= 1) /* blank line */ ! 199: continue; ! 200: if (i < 3) { ! 201: fprintf(stderr, "Bad key entry for line %d, ignored\n", ! 202: linenumber); ! 203: continue; ! 204: } ! 205: ! 206: if ((kp = (keydesc *)malloc(sizeof(keydesc))) == (keydesc *)0) { ! 207: printf("Out of memory: get help!\n"); ! 208: fprintf("Out of memory building key table\n"); ! 209: exit(101); ! 210: } ! 211: if (firstkey == (keydesc *)0) ! 212: firstkey = kp; ! 213: if (lastkey) ! 214: lastkey->next = kp; ! 215: strncpy(kp->name, field[0], FIELDSIZE); ! 216: strncpy(kp->type, field[1], FIELDSIZE); ! 217: strncpy(kp->key, field[2], FIELDSIZE); ! 218: if (i >= 4) ! 219: if(strcmp(field[3], "") != 0) { ! 220: kp->expires = atol(field[3]); ! 221: if (kp->expires < 19700101 || ! 222: kp->expires > 99991231) { ! 223: fprintf(stderr, "Bad expiration for line %d, ignored\n", ! 224: linenumber); ! 225: continue; ! 226: } ! 227: } else ! 228: kp->expires = 99991231; ! 229: kp->next = (keydesc *)0; ! 230: lastkey = kp; ! 231: } ! 232: ! 233: } ! 234: ! 235: dumpkeys() ! 236: { ! 237: keydesc *kp; ! 238: ! 239: for (kp=firstkey; kp; kp = kp->next) ! 240: printf("%s/%s/%s/%s/\n", ! 241: kp->name, kp->type, kp->key, kp->expires); ! 242: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.