Deleted Added
full compact
chap.c (43743) chap.c (43888)
1/*
2 * PPP CHAP Module
3 *
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc. The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
1/*
2 * PPP CHAP Module
3 *
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc. The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id: chap.c,v 1.41 1999/02/07 13:48:38 brian Exp $
20 * $Id: chap.c,v 1.42 1999/02/07 13:56:29 brian Exp $
21 *
22 * TODO:
23 */
24#include <sys/param.h>
25#include <netinet/in.h>
26#include <netinet/in_systm.h>
27#include <netinet/ip.h>
28#include <sys/un.h>
29
21 *
22 * TODO:
23 */
24#include <sys/param.h>
25#include <netinet/in.h>
26#include <netinet/in_systm.h>
27#include <netinet/ip.h>
28#include <sys/un.h>
29
30#include <errno.h>
31#include <fcntl.h>
30#ifdef HAVE_DES
31#include <md4.h>
32#include <string.h>
33#endif
34#include <md5.h>
32#ifdef HAVE_DES
33#include <md4.h>
34#include <string.h>
35#endif
36#include <md5.h>
37#include <paths.h>
38#include <signal.h>
35#include <stdlib.h>
39#include <stdlib.h>
40#include <sys/wait.h>
36#include <termios.h>
41#include <termios.h>
42#include <unistd.h>
37
38#include "mbuf.h"
39#include "log.h"
40#include "defs.h"
41#include "timer.h"
42#include "fsm.h"
43#include "lcpproto.h"
44#include "lcp.h"
45#include "lqr.h"
46#include "hdlc.h"
47#include "auth.h"
43
44#include "mbuf.h"
45#include "log.h"
46#include "defs.h"
47#include "timer.h"
48#include "fsm.h"
49#include "lcpproto.h"
50#include "lcp.h"
51#include "lqr.h"
52#include "hdlc.h"
53#include "auth.h"
48#include "chap.h"
49#include "async.h"
50#include "throughput.h"
51#include "descriptor.h"
54#include "async.h"
55#include "throughput.h"
56#include "descriptor.h"
57#include "chap.h"
52#include "iplist.h"
53#include "slcompress.h"
54#include "ipcp.h"
55#include "filter.h"
56#include "ccp.h"
57#include "link.h"
58#include "physical.h"
59#include "mp.h"
60#ifndef NORADIUS
61#include "radius.h"
62#endif
63#include "bundle.h"
64#include "chat.h"
65#include "cbcp.h"
58#include "iplist.h"
59#include "slcompress.h"
60#include "ipcp.h"
61#include "filter.h"
62#include "ccp.h"
63#include "link.h"
64#include "physical.h"
65#include "mp.h"
66#ifndef NORADIUS
67#include "radius.h"
68#endif
69#include "bundle.h"
70#include "chat.h"
71#include "cbcp.h"
72#include "command.h"
66#include "datalink.h"
67#ifdef HAVE_DES
68#include "chap_ms.h"
69#endif
70
71static const char *chapcodes[] = {
72 "???", "CHALLENGE", "RESPONSE", "SUCCESS", "FAILURE"
73};

--- 96 unchanged lines hidden (view full) ---

170 * ---- -------- ------
171 */
172 }
173
174 return result;
175}
176
177static void
73#include "datalink.h"
74#ifdef HAVE_DES
75#include "chap_ms.h"
76#endif
77
78static const char *chapcodes[] = {
79 "???", "CHALLENGE", "RESPONSE", "SUCCESS", "FAILURE"
80};

--- 96 unchanged lines hidden (view full) ---

177 * ---- -------- ------
178 */
179 }
180
181 return result;
182}
183
184static void
185chap_StartChild(struct chap *chap, char *prog, const char *name)
186{
187 char *argv[MAXARGS], *nargv[MAXARGS];
188 int argc, fd;
189 int in[2], out[2];
190
191 if (chap->child.fd != -1) {
192 log_Printf(LogWARN, "Chap: %s: Program already running\n", prog);
193 return;
194 }
195
196 if (pipe(in) == -1) {
197 log_Printf(LogERROR, "Chap: pipe: %s\n", strerror(errno));
198 return;
199 }
200
201 if (pipe(out) == -1) {
202 log_Printf(LogERROR, "Chap: pipe: %s\n", strerror(errno));
203 close(in[0]);
204 close(in[1]);
205 return;
206 }
207
208 switch ((chap->child.pid = fork())) {
209 case -1:
210 log_Printf(LogERROR, "Chap: fork: %s\n", strerror(errno));
211 close(in[0]);
212 close(in[1]);
213 close(out[0]);
214 close(out[1]);
215 chap->child.pid = 0;
216 return;
217
218 case 0:
219 timer_TermService();
220 close(in[1]);
221 close(out[0]);
222 if (out[1] == STDIN_FILENO) {
223 fd = dup(out[1]);
224 close(out[1]);
225 out[1] = fd;
226 }
227 dup2(in[0], STDIN_FILENO);
228 dup2(out[1], STDOUT_FILENO);
229 if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
230 log_Printf(LogALERT, "Chap: Failed to open %s: %s\n",
231 _PATH_DEVNULL, strerror(errno));
232 exit(1);
233 }
234 dup2(fd, STDERR_FILENO);
235 fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */
236
237 setuid(geteuid());
238 argc = command_Interpret(prog, strlen(prog), argv);
239 command_Expand(nargv, argc, (char const *const *)argv,
240 chap->auth.physical->dl->bundle, 0);
241 execvp(nargv[0], nargv);
242
243 log_Printf(LogWARN, "exec() of %s failed: %s\n",
244 nargv[0], strerror(errno));
245 exit(255);
246
247 default:
248 close(in[0]);
249 close(out[1]);
250 chap->child.fd = out[0];
251 chap->child.buf.len = 0;
252 write(in[1], chap->auth.in.name, strlen(chap->auth.in.name));
253 write(in[1], "\n", 1);
254 write(in[1], chap->challenge + 1, *chap->challenge);
255 write(in[1], "\n", 1);
256 write(in[1], name, strlen(name));
257 write(in[1], "\n", 1);
258 close(in[1]);
259 break;
260 }
261}
262
263static void
264chap_Cleanup(struct chap *chap, int sig)
265{
266 if (chap->child.pid) {
267 int status;
268
269 close(chap->child.fd);
270 chap->child.fd = -1;
271 if (sig)
272 kill(chap->child.pid, SIGTERM);
273 chap->child.pid = 0;
274 chap->child.buf.len = 0;
275
276 if (wait(&status) == -1)
277 log_Printf(LogERROR, "Chap: wait: %s\n", strerror(errno));
278 else if (WIFSIGNALED(status))
279 log_Printf(LogWARN, "Chap: Child received signal %d\n", WTERMSIG(status));
280 else if (WIFEXITED(status) && WEXITSTATUS(status))
281 log_Printf(LogERROR, "Chap: Child exited %d\n", WEXITSTATUS(status));
282 }
283 *chap->challenge = 0;
284}
285
286static void
287chap_SendResponse(struct chap *chap, char *name, char *key)
288{
289 char *ans;
290
291 ans = chap_BuildAnswer(name, key, chap->auth.id, chap->challenge, 0);
292
293 if (ans) {
294 ChapOutput(chap->auth.physical, CHAP_RESPONSE, chap->auth.id,
295 ans, *ans + 1 + strlen(name), name);
296 free(ans);
297 } else
298 ChapOutput(chap->auth.physical, CHAP_FAILURE, chap->auth.id,
299 "Out of memory!", 14, NULL);
300}
301
302static int
303chap_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
304{
305 struct chap *chap = descriptor2chap(d);
306
307 if (r && chap && chap->child.fd != -1) {
308 FD_SET(chap->child.fd, r);
309 if (*n < chap->child.fd + 1)
310 *n = chap->child.fd + 1;
311 log_Printf(LogTIMER, "Chap: fdset(r) %d\n", chap->child.fd);
312 return 1;
313 }
314
315 return 0;
316}
317
318static int
319chap_IsSet(struct descriptor *d, const fd_set *fdset)
320{
321 struct chap *chap = descriptor2chap(d);
322
323 return chap && chap->child.fd != -1 && FD_ISSET(chap->child.fd, fdset);
324}
325
326static void
327chap_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
328{
329 struct chap *chap = descriptor2chap(d);
330 int got;
331
332 got = read(chap->child.fd, chap->child.buf.ptr + chap->child.buf.len,
333 sizeof chap->child.buf.ptr - chap->child.buf.len - 1);
334 if (got == -1) {
335 log_Printf(LogERROR, "Chap: Read: %s\n", strerror(errno));
336 chap_Cleanup(chap, SIGTERM);
337 } else if (got == 0) {
338 log_Printf(LogWARN, "Chap: Read: Child terminated connection\n");
339 chap_Cleanup(chap, SIGTERM);
340 } else {
341 char *name, *key, *end;
342
343 chap->child.buf.len += got;
344 chap->child.buf.ptr[chap->child.buf.len] = '\0';
345 name = chap->child.buf.ptr;
346 name += strspn(name, " \t");
347 if ((key = strchr(name, '\n')) == NULL)
348 end = NULL;
349 else
350 end = strchr(++key, '\n');
351
352 if (end == NULL) {
353 if (chap->child.buf.len == sizeof chap->child.buf.ptr - 1) {
354 log_Printf(LogWARN, "Chap: Read: Input buffer overflow\n");
355 chap_Cleanup(chap, SIGTERM);
356 }
357 } else {
358 while (end >= name && strchr(" \t\r\n", *end))
359 *end-- = '\0';
360 end = key - 1;
361 while (end >= name && strchr(" \t\r\n", *end))
362 *end-- = '\0';
363 key += strspn(key, " \t");
364
365 chap_SendResponse(chap, name, key);
366 chap_Cleanup(chap, 0);
367 }
368 }
369}
370
371static int
372chap_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
373{
374 /* We never want to write here ! */
375 log_Printf(LogALERT, "chap_Write: Internal error: Bad call !\n");
376 return 0;
377}
378
379static void
178chap_Challenge(struct authinfo *authp)
179{
180 struct chap *chap = auth2chap(authp);
181 int len, i;
182 char *cp;
183
380chap_Challenge(struct authinfo *authp)
381{
382 struct chap *chap = auth2chap(authp);
383 int len, i;
384 char *cp;
385
184 randinit();
185 cp = chap->challenge;
386 len = strlen(authp->physical->dl->bundle->cfg.auth.name);
186
387
388 if (!*chap->challenge) {
389 randinit();
390 cp = chap->challenge;
391
187#ifndef NORADIUS
392#ifndef NORADIUS
188 if (*authp->physical->dl->bundle->radius.cfg.file) {
189 /* For radius, our challenge is 16 readable NUL terminated bytes :*/
190 *cp++ = 16;
191 for (i = 0; i < 16; i++)
192 *cp++ = (random() % 10) + '0';
193 } else
393 if (*authp->physical->dl->bundle->radius.cfg.file) {
394 /* For radius, our challenge is 16 readable NUL terminated bytes :*/
395 *cp++ = 16;
396 for (i = 0; i < 16; i++)
397 *cp++ = (random() % 10) + '0';
398 } else
194#endif
399#endif
195 {
196 *cp++ = random() % (CHAPCHALLENGELEN-16) + 16;
197 for (i = 0; i < *chap->challenge; i++)
198 *cp++ = random() & 0xff;
400 {
401 *cp++ = random() % (CHAPCHALLENGELEN-16) + 16;
402 for (i = 0; i < *chap->challenge; i++)
403 *cp++ = random() & 0xff;
404 }
405 memcpy(cp, authp->physical->dl->bundle->cfg.auth.name, len);
199 }
406 }
200
201 len = strlen(authp->physical->dl->bundle->cfg.auth.name);
202 memcpy(cp, authp->physical->dl->bundle->cfg.auth.name, len);
203 cp += len;
204 ChapOutput(authp->physical, CHAP_CHALLENGE, authp->id, chap->challenge,
407 ChapOutput(authp->physical, CHAP_CHALLENGE, authp->id, chap->challenge,
205 cp - chap->challenge, NULL);
408 1 + *chap->challenge + len, NULL);
206}
207
208static void
209chap_Success(struct authinfo *authp)
210{
211 datalink_GotAuthname(authp->physical->dl, authp->in.name);
212 ChapOutput(authp->physical, CHAP_SUCCESS, authp->id, "Welcome!!", 10, NULL);
213 authp->physical->link.lcp.auth_ineed = 0;

--- 13 unchanged lines hidden (view full) ---

227{
228 ChapOutput(authp->physical, CHAP_FAILURE, authp->id, "Invalid!!", 9, NULL);
229 datalink_AuthNotOk(authp->physical->dl);
230}
231
232void
233chap_Init(struct chap *chap, struct physical *p)
234{
409}
410
411static void
412chap_Success(struct authinfo *authp)
413{
414 datalink_GotAuthname(authp->physical->dl, authp->in.name);
415 ChapOutput(authp->physical, CHAP_SUCCESS, authp->id, "Welcome!!", 10, NULL);
416 authp->physical->link.lcp.auth_ineed = 0;

--- 13 unchanged lines hidden (view full) ---

430{
431 ChapOutput(authp->physical, CHAP_FAILURE, authp->id, "Invalid!!", 9, NULL);
432 datalink_AuthNotOk(authp->physical->dl);
433}
434
435void
436chap_Init(struct chap *chap, struct physical *p)
437{
438 chap->desc.type = CHAP_DESCRIPTOR;
439 chap->desc.UpdateSet = chap_UpdateSet;
440 chap->desc.IsSet = chap_IsSet;
441 chap->desc.Read = chap_Read;
442 chap->desc.Write = chap_Write;
443 chap->child.pid = 0;
444 chap->child.fd = -1;
235 auth_Init(&chap->auth, p, chap_Challenge, chap_Success, chap_Failure);
236 *chap->challenge = 0;
237 chap->using_MSChap = 0;
238}
239
240void
445 auth_Init(&chap->auth, p, chap_Challenge, chap_Success, chap_Failure);
446 *chap->challenge = 0;
447 chap->using_MSChap = 0;
448}
449
450void
451chap_ReInit(struct chap *chap)
452{
453 chap_Cleanup(chap, SIGTERM);
454}
455
456void
241chap_Input(struct physical *p, struct mbuf *bp)
242{
243 struct chap *chap = &p->dl->chap;
244 char *name, *key, *ans, *myans;
245 int len, nlen;
246 u_char alen;
247
248 if ((bp = auth_ReadHeader(&chap->auth, bp)) == NULL)

--- 82 unchanged lines hidden (view full) ---

331 else
332 log_Printf(LogPHASE, "Chap Input: %s\n",
333 chapcodes[chap->auth.in.hdr.code]);
334 break;
335 }
336
337 switch (chap->auth.in.hdr.code) {
338 case CHAP_CHALLENGE:
457chap_Input(struct physical *p, struct mbuf *bp)
458{
459 struct chap *chap = &p->dl->chap;
460 char *name, *key, *ans, *myans;
461 int len, nlen;
462 u_char alen;
463
464 if ((bp = auth_ReadHeader(&chap->auth, bp)) == NULL)

--- 82 unchanged lines hidden (view full) ---

547 else
548 log_Printf(LogPHASE, "Chap Input: %s\n",
549 chapcodes[chap->auth.in.hdr.code]);
550 break;
551 }
552
553 switch (chap->auth.in.hdr.code) {
554 case CHAP_CHALLENGE:
339 name = p->dl->bundle->cfg.auth.name;
340 nlen = strlen(name);
341 key = p->dl->bundle->cfg.auth.key;
342 myans = chap_BuildAnswer(name, key, chap->auth.id, chap->challenge, 0);
343 if (myans) {
344 ChapOutput(p, CHAP_RESPONSE, chap->auth.id, myans,
345 *myans + 1 + nlen, name);
346 free(myans);
347 } else
348 ChapOutput(p, CHAP_FAILURE, chap->auth.id, "Out of memory!",
349 14, NULL);
555 if (*p->dl->bundle->cfg.auth.key == '!')
556 chap_StartChild(chap, p->dl->bundle->cfg.auth.key + 1,
557 p->dl->bundle->cfg.auth.name);
558 else
559 chap_SendResponse(chap, p->dl->bundle->cfg.auth.name,
560 p->dl->bundle->cfg.auth.key);
350 break;
351
352 case CHAP_RESPONSE:
353 name = chap->auth.in.name;
354 nlen = strlen(name);
355#ifndef NORADIUS
356 if (*p->dl->bundle->radius.cfg.file) {
357 chap->challenge[*chap->challenge+1] = '\0';

--- 48 unchanged lines hidden ---
561 break;
562
563 case CHAP_RESPONSE:
564 name = chap->auth.in.name;
565 nlen = strlen(name);
566#ifndef NORADIUS
567 if (*p->dl->bundle->radius.cfg.file) {
568 chap->challenge[*chap->challenge+1] = '\0';

--- 48 unchanged lines hidden ---