|
|
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.