Deleted Added
full compact
generator.c (59121) generator.c (92914)
1/* generator.c: The opiegenerator() library function.
2
3%%% portions-copyright-cmetz-96
1/* generator.c: The opiegenerator() library function.
2
3%%% portions-copyright-cmetz-96
4Portions of this software are Copyright 1996-1998 by Craig Metz, All Rights
4Portions of this software are Copyright 1996-1999 by Craig Metz, All Rights
5Reserved. The Inner Net License Version 2 applies to these portions of
6the software.
7You should have received a copy of the license with this software. If
8you didn't get a copy, you may request one from <license@inner.net>.
9
10 History:
11
5Reserved. The Inner Net License Version 2 applies to these portions of
6the software.
7You should have received a copy of the license with this software. If
8you didn't get a copy, you may request one from <license@inner.net>.
9
10 History:
11
12 Modified by cmetz for OPIE 2.4. Added opieauto code based on
13 previously released test code. Renamed buffer to challenge.
14 Use struct opie_otpkey for keys.
12 Modified by cmetz for OPIE 2.32. If secret=NULL, always return
13 as if opieauto returned "get the secret". Renamed
14 _opieparsechallenge() to __opieparsechallenge(). Check
15 challenge for extended response support and don't send
16 an init-hex response if extended response support isn't
17 indicated in the challenge.
18 Modified by cmetz for OPIE 2.31. Renamed "init" to "init-hex".
19 Removed active attack protection support. Fixed fairly
20 bug in how init response was computed (i.e., dead wrong).
21 Modified by cmetz for OPIE 2.3. Use _opieparsechallenge(). ifdef
22 around string.h. Output hex responses by default, output
23 OTP re-init extended responses (same secret) if sequence
24 number falls below 10.
25 Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
26 Bug fixes.
27 Created at NRL for OPIE 2.2.
28
15 Modified by cmetz for OPIE 2.32. If secret=NULL, always return
16 as if opieauto returned "get the secret". Renamed
17 _opieparsechallenge() to __opieparsechallenge(). Check
18 challenge for extended response support and don't send
19 an init-hex response if extended response support isn't
20 indicated in the challenge.
21 Modified by cmetz for OPIE 2.31. Renamed "init" to "init-hex".
22 Removed active attack protection support. Fixed fairly
23 bug in how init response was computed (i.e., dead wrong).
24 Modified by cmetz for OPIE 2.3. Use _opieparsechallenge(). ifdef
25 around string.h. Output hex responses by default, output
26 OTP re-init extended responses (same secret) if sequence
27 number falls below 10.
28 Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
29 Bug fixes.
30 Created at NRL for OPIE 2.2.
31
29$FreeBSD: head/contrib/opie/libopie/generator.c 59121 2000-04-10 11:18:54Z kris $
32$FreeBSD: head/contrib/opie/libopie/generator.c 92914 2002-03-21 23:42:52Z markm $
30*/
31
32#include "opie_cfg.h"
33#if HAVE_STRING_H
34#include <string.h>
35#endif /* HAVE_STRING_H */
33*/
34
35#include "opie_cfg.h"
36#if HAVE_STRING_H
37#include <string.h>
38#endif /* HAVE_STRING_H */
39#if OPIEAUTO
40#include <errno.h>
41#if HAVE_STDLIB_H
42#include <stdlib.h>
43#endif /* HAVE_STDLIB_H */
44#include <sys/stat.h>
45
46#include <sys/socket.h>
47#include <sys/un.h>
48#endif /* OPIEAUTO */
49#if DEBUG
50#include <syslog.h>
51#endif /* DEBUG */
36#include "opie.h"
37
38static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
39
52#include "opie.h"
53
54static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" };
55
40int opiegenerator FUNCTION((buffer, secret, response), char *buffer AND char *secret AND char *response)
56#if OPIEAUTO
57#ifndef max
58#define max(x, y) (((x) > (y)) ? (x) : (y))
59#endif /* max */
60
61static int opieauto_connect FUNCTION_NOARGS
41{
62{
63 int s;
64 struct sockaddr_un sun;
65 char buffer[1024];
66 char *c, *c2 ="/.opieauto";
67 uid_t myuid = getuid(), myeuid = geteuid();
68
69 if (!myuid || !myeuid || (myuid != myeuid)) {
70#if DEBUG
71 syslog(LOG_DEBUG, "opieauto_connect: superuser and/or setuid not allowed");
72#endif /* DEBUG */
73 return -1;
74 };
75
76 memset(&sun, 0, sizeof(struct sockaddr_un));
77 sun.sun_family = AF_UNIX;
78
79 if (!(c = getenv("HOME"))) {
80#if DEBUG
81 syslog(LOG_DEBUG, "opieauto_connect: no HOME variable?");
82#endif /* DEBUG */
83 return -1;
84 };
85
86 if (strlen(c) > (sizeof(sun.sun_path) - strlen(c2) - 1)) {
87#if DEBUG
88 syslog(LOG_DEBUG, "opieauto_connect: HOME is too long: %s", c);
89#endif /* DEBUG */
90 return -1;
91 };
92
93 strcpy(sun.sun_path, c);
94 strcat(sun.sun_path, c2);
95
96 if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
97#if DEBUG
98 syslog(LOG_DEBUG, "opieauto_connect: socket: %s(%d)", strerror(errno), errno);
99#endif /* DEBUG */
100 return -1;
101 };
102
103 {
104 struct stat st;
105
106 if (stat(sun.sun_path, &st) < 0) {
107#if DEBUG
108 syslog(LOG_DEBUG, "opieauto_connect: stat: %s(%d)\n", strerror(errno), errno);
109#endif /* DEBUG */
110 goto ret;
111 };
112
113 if (connect(s, (struct sockaddr *)&sun, sizeof(struct sockaddr_un))) {
114#if DEBUG
115 syslog(LOG_DEBUG, "opieauto_connect: connect: %s(%d)\n", strerror(errno), errno);
116#endif /* DEBUG */
117 goto ret;
118 };
119
120 if ((st.st_uid != myuid) || (!S_ISSOCK(st.st_mode)) || ((st.st_mode & 07777) != 0600)) {
121#if DEBUG
122 syslog(LOG_DEBUG, "opieauto_connect: something's fishy about the socket\n");
123#endif /* DEBUG */
124 goto ret;
125 };
126 };
127
128 return s;
129
130ret:
131 close(s);
132 return -1;
133};
134#endif /* OPIEAUTO */
135
136int opiegenerator FUNCTION((challenge, secret, response), char *challenge AND char *secret AND char *response)
137{
42 int algorithm;
43 int sequence;
44 char *seed;
138 int algorithm;
139 int sequence;
140 char *seed;
45 char key[8];
141 struct opie_otpkey key;
46 int i;
47 int exts;
142 int i;
143 int exts;
144#if OPIEAUTO
145 int s;
146 int window;
147 char cmd[1+1+1+1+4+1+OPIE_SEED_MAX+1+4+1+4+1+4+1+4+1];
148 char *c;
149#endif /* OPIEAUTO */
48
150
49 if (!(buffer = strstr(buffer, "otp-")))
151 if (!(challenge = strstr(challenge, "otp-")))
50 return 1;
51
152 return 1;
153
52 buffer += 4;
154 challenge += 4;
53
155
54 if (__opieparsechallenge(buffer, &algorithm, &sequence, &seed, &exts))
156 if (__opieparsechallenge(challenge, &algorithm, &sequence, &seed, &exts))
55 return 1;
56
57 if ((sequence < 2) || (sequence > 9999))
58 return 1;
59
157 return 1;
158
159 if ((sequence < 2) || (sequence > 9999))
160 return 1;
161
60 if (!secret[0])
61 return 2;
162 if (*secret) {
163 if (opiepasscheck(secret))
164 return -2;
62
165
63 if (opiepasscheck(secret))
64 return -2;
166 if (i = opiekeycrunch(algorithm, &key, seed, secret))
167 return i;
65
168
66 if (i = opiekeycrunch(algorithm, key, seed, secret))
67 return i;
169 if (sequence <= OPIE_SEQUENCE_RESTRICT) {
170 if (!(exts & 1))
171 return 1;
68
172
69 if (sequence < 10) {
70 if (!(exts & 1))
71 return 1;
173 {
174 char newseed[OPIE_SEED_MAX + 1];
175 struct opie_otpkey newkey;
176 char *c;
177 char buf[OPIE_SEED_MAX + 48 + 1];
72
178
179 while (sequence-- != 0)
180 opiehash(&key, algorithm);
181
182 if (opienewseed(strcpy(newseed, seed)) < 0)
183 return -1;
184
185 if (opiekeycrunch(algorithm, &newkey, newseed, secret))
186 return -1;
187
188 for (i = 0; i < 499; i++)
189 opiehash(&newkey, algorithm);
190
191 strcpy(response, "init-hex:");
192 strcat(response, opiebtoh(buf, &key));
193 if (snprintf(buf, sizeof(buf), ":%s 499 %s:", algids[algorithm],
194 newseed) >= sizeof(buf)) {
195#ifdef DEBUG
196 syslog(LOG_DEBUG, "opiegenerator: snprintf truncation at init-hex");
197#endif /* DEBUG */
198 return -1;
199 }
200 strcat(response, buf);
201 strcat(response, opiebtoh(buf, &newkey));
202 };
203 };
204 };
205
206#if OPIEAUTO
207 if ((s = opieauto_connect()) >= 0) {
208 if ((i = read(s, cmd, sizeof(cmd)-1)) < 0) {
209#if DEBUG
210 syslog(LOG_DEBUG, "opiegenerator: read: %s(%d)\n", strerror(errno), errno);
211#endif /* DEBUG */
212 close(s);
213 s = -1;
214 goto l0;
215 };
216 cmd[i] = 0;
217 if ((cmd[0] != 'C') || (cmd[1] != '+') || (cmd[2] != ' ')) {
218#if DEBUG
219 syslog(LOG_DEBUG, "opiegenerator: got invalid/failing C+ response: %s\n", cmd);
220#endif /* DEBUG */
221 close(s);
222 s = -1;
223 goto l0;
224 };
225
226 window = strtoul(&cmd[3], &c, 10);
227 if (!window || (window >= (OPIE_SEQUENCE_MAX - OPIE_SEQUENCE_RESTRICT)) || !isspace(*c)) {
228#if DEBUG
229 syslog(LOG_DEBUG, "opiegenerator: got bogus option response: %s\n", cmd);
230#endif /* DEBUG */
231 close(s);
232 s = -1;
233 goto l0;
234 };
235 };
236
237l0:
238 if (*secret) {
239 int j;
240
241 if (s < 0) {
242 j = 0;
243 goto l1;
244 };
245
246 j = max(sequence - window + 1, OPIE_SEQUENCE_RESTRICT);
247
248 for (i = j; i > 0; i--)
249 opiehash(&key, algorithm);
250
73 {
251 {
74 char newseed[OPIE_SEED_MAX + 1];
75 char newkey[8];
76 char *c;
77 char buf[OPIE_SEED_MAX + 48 + 1];
252 char buf[16+1];
78
253
79 while (sequence-- != 0)
80 opiehash(key, algorithm);
254 opiebtoa8(buf, &key);
81
255
82 if (opienewseed(strcpy(newseed, seed)) < 0)
83 return -1;
256 if (snprintf(cmd, sizeof(cmd), "S= %d %d %s %s\n", algorithm, sequence,
257 seed, buf) >= sizeof(cmd)) {
258#if DEBUG
259 syslog(LOG_DEBUG, "opiegenerator: snprintf truncation at S=\n");
260#endif /* DEBUG */
261 goto l1;
262 }
263 }
84
264
85 if (opiekeycrunch(algorithm, newkey, newseed, secret))
86 return -1;
265 if (write(s, cmd, i = strlen(cmd)) != i) {
266#if DEBUG
267 syslog(LOG_DEBUG, "opiegenerator: write: %s(%d)\n", strerror(errno), errno);
268#endif /* DEBUG */
269 goto l1;
270 };
87
271
88 for (i = 0; i < 499; i++)
89 opiehash(newkey, algorithm);
272 if ((i = read(s, cmd, sizeof(cmd))) < 0) {
273#if DEBUG
274 syslog(LOG_DEBUG, "opiegenerator: read: %s(%d)\n", strerror(errno), errno);
275#endif /* DEBUG */
276 };
277 close(s);
90
278
91 strcpy(response, "init-hex:");
92 strcat(response, opiebtoh(buf, key));
93 sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed);
94 strcat(response, buf);
95 strcat(response, opiebtoh(buf, newkey));
279 cmd[i] = 0;
280 i = strlen(seed);
281 if ((cmd[0] != 'S') || (cmd[1] != '+') || (cmd[2] != ' ') || (strtoul(&cmd[3], &c, 10) != algorithm) || (strtoul(c + 1, &c, 10) != sequence) || strncmp(++c, seed, i) || (*(c + i) != '\n')) {
282#if DEBUG
283 syslog(LOG_DEBUG, "opiegenerator: got invalid/failing S+ response: %s\n", cmd);
284#endif /* DEBUG */
96 };
285 };
286
287l1:
288 for (i = sequence - j; i > 0; i--)
289 opiehash(&key, algorithm);
290
291 opiebtoh(response, &key);
97 } else {
292 } else {
293 if (s < 0)
294 goto l2;
295
296 if ((snprintf(cmd, sizeof(cmd), "s= %d %d %s\n", algorithm, sequence,
297 seed) >= sizeof(cmd))) {
298#if DEBUG
299 syslog(LOG_DEBUG, "opiegenerator: snprintf truncation at s=\n");
300#endif /* DEBUG */
301 goto l2;
302 }
303
304 if (write(s, cmd, i = strlen(cmd)) != i) {
305#if DEBUG
306 syslog(LOG_DEBUG, "opiegenerator: write: %s(%d)\n", strerror(errno), errno);
307#endif /* DEBUG */
308 goto l2;
309 };
310
311 if ((i = read(s, cmd, sizeof(cmd))) < 0) {
312#if DEBUG
313 syslog(LOG_DEBUG, "opiegenerator: read: %s(%d)\n", strerror(errno), errno);
314#endif /* DEBUG */
315 goto l2;
316 };
317 close(s);
318
319 i = strlen(seed);
320
321 if ((cmd[0] != 's') || (cmd[2] != ' ') || (strtoul(&cmd[3], &c, 10) != algorithm) || (strtoul(c + 1, &c, 10) != sequence) || strncmp(++c, seed, i)) {
322#if DEBUG
323 if (c)
324 *c = 0;
325 else
326 cmd[3] = 0;
327
328 syslog(LOG_DEBUG, "opiegenerator: got bogus/invalid s response: %s\n", cmd);
329#endif /* DEBUG */
330 goto l2;
331 };
332
333 c += i;
334
335 if (cmd[1] == '-') {
336#if DEBUG
337 if (*c != '\n') {
338 *c = 0;
339 syslog(LOG_DEBUG, "opiegenerator: got invalid s- response: %s\n", cmd);
340 };
341#endif /* DEBUG */
342 goto l2;
343 };
344
345 if (cmd[1] != '+') {
346#if DEBUG
347 *c = 0;
348 syslog(LOG_DEBUG, "opiegenerator: got invalid s response: %s\n", cmd);
349#endif /* DEBUG */
350 goto l2;
351 };
352
353 {
354 char *c2;
355
356 if (!(c2 = strchr(++c, '\n'))) {
357#if DEBUG
358 *c = 0;
359 syslog(LOG_DEBUG, "opiegenerator: got invalid s+ response: %s\n", cmd);
360#endif /* DEBUG */
361 goto l2;
362 };
363
364 *c2++ = 0;
365 };
366
367 if (!opieatob8(&key, c))
368 goto l2;
369
370 opiebtoh(response, &key);
371 };
372
373 if (s >= 0)
374 close(s);
375#else /* OPIEAUTO */
376 if (*secret) {
98 while (sequence-- != 0)
377 while (sequence-- != 0)
99 opiehash(key, algorithm);
378 opiehash(&key, algorithm);
100
379
101 opiebtoh(response, key);
102 }
380 opiebtoh(response, &key);
381 } else
382 return -2;
383#endif /* OPIEAUTO */
103
104 return 0;
384
385 return 0;
105}
386
387#if OPIEAUTO
388l2:
389#if DEBUG
390 syslog(LOG_DEBUG, "opiegenerator: no opieauto response available.\n");
391#endif /* DEBUG */
392 if (s >= 0)
393 close(s);
394
395 return -2;
396#endif /* OPIEAUTO */
397};