chap.c revision 134789
1/*-
2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3 *          based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4 *                           Internet Initiative Japan, Inc (IIJ)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/usr.sbin/ppp/chap.c 134789 2004-09-05 01:46:52Z brian $
29 */
30
31#include <sys/param.h>
32#include <netinet/in.h>
33#include <netinet/in_systm.h>
34#include <netinet/ip.h>
35#include <sys/socket.h>
36#include <sys/un.h>
37
38#include <ctype.h>
39#include <errno.h>
40#include <fcntl.h>
41#ifndef NODES
42#include <md4.h>
43#endif
44#include <md5.h>
45#include <paths.h>
46#include <signal.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <sys/wait.h>
51#include <termios.h>
52#include <unistd.h>
53
54#include "layer.h"
55#include "mbuf.h"
56#include "log.h"
57#include "defs.h"
58#include "timer.h"
59#include "fsm.h"
60#include "proto.h"
61#include "lqr.h"
62#include "hdlc.h"
63#include "lcp.h"
64#include "auth.h"
65#include "async.h"
66#include "throughput.h"
67#include "descriptor.h"
68#include "chap.h"
69#include "iplist.h"
70#include "slcompress.h"
71#include "ncpaddr.h"
72#include "ipcp.h"
73#include "filter.h"
74#include "ccp.h"
75#include "link.h"
76#include "physical.h"
77#include "mp.h"
78#ifndef NORADIUS
79#include "radius.h"
80#endif
81#include "ipv6cp.h"
82#include "ncp.h"
83#include "bundle.h"
84#include "chat.h"
85#include "cbcp.h"
86#include "command.h"
87#include "datalink.h"
88#ifndef NODES
89#include "chap_ms.h"
90#include "mppe.h"
91#endif
92#include "id.h"
93
94static const char * const chapcodes[] = {
95  "???", "CHALLENGE", "RESPONSE", "SUCCESS", "FAILURE"
96};
97#define MAXCHAPCODE (sizeof chapcodes / sizeof chapcodes[0] - 1)
98
99static void
100ChapOutput(struct physical *physical, u_int code, u_int id,
101	   const u_char *ptr, int count, const char *text)
102{
103  int plen;
104  struct fsmheader lh;
105  struct mbuf *bp;
106
107  plen = sizeof(struct fsmheader) + count;
108  lh.code = code;
109  lh.id = id;
110  lh.length = htons(plen);
111  bp = m_get(plen, MB_CHAPOUT);
112  memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
113  if (count)
114    memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
115  log_DumpBp(LogDEBUG, "ChapOutput", bp);
116  if (text == NULL)
117    log_Printf(LogPHASE, "Chap Output: %s\n", chapcodes[code]);
118  else
119    log_Printf(LogPHASE, "Chap Output: %s (%s)\n", chapcodes[code], text);
120  link_PushPacket(&physical->link, bp, physical->dl->bundle,
121                  LINK_QUEUES(&physical->link) - 1, PROTO_CHAP);
122}
123
124static char *
125chap_BuildAnswer(char *name, char *key, u_char id, char *challenge
126#ifndef NODES
127		 , u_char type, char *peerchallenge, char *authresponse,
128		 int lanman
129#endif
130                )
131{
132  char *result, *digest;
133  size_t nlen, klen;
134
135  nlen = strlen(name);
136  klen = strlen(key);
137
138#ifndef NODES
139  if (type == 0x80) {
140    char expkey[AUTHLEN << 2];
141    MD4_CTX MD4context;
142    size_t f;
143
144    if ((result = malloc(1 + nlen + MS_CHAP_RESPONSE_LEN)) == NULL)
145      return result;
146
147    digest = result;					/* the response */
148    *digest++ = MS_CHAP_RESPONSE_LEN;			/* 49 */
149    memcpy(digest + MS_CHAP_RESPONSE_LEN, name, nlen);
150    if (lanman) {
151      memset(digest + 24, '\0', 25);
152      mschap_LANMan(digest, challenge + 1, key);	/* LANMan response */
153    } else {
154      memset(digest, '\0', 25);
155      digest += 24;
156
157      for (f = 0; f < klen; f++) {
158        expkey[2*f] = key[f];
159        expkey[2*f+1] = '\0';
160      }
161      /*
162       *           -----------
163       * expkey = | k\0e\0y\0 |
164       *           -----------
165       */
166      MD4Init(&MD4context);
167      MD4Update(&MD4context, expkey, klen << 1);
168      MD4Final(digest, &MD4context);
169
170      /*
171       *           ---- -------- ---------------- ------- ------
172       * result = | 49 | LANMan | 16 byte digest | 9 * ? | name |
173       *           ---- -------- ---------------- ------- ------
174       */
175      mschap_NT(digest, challenge + 1);
176    }
177    /*
178     *           ---- -------- ------------- ----- ------
179     *          |    |  struct MS_ChapResponse24  |      |
180     * result = | 49 | LANMan  |  NT digest | 0/1 | name |
181     *           ---- -------- ------------- ----- ------
182     * where only one of LANMan & NT digest are set.
183     */
184  } else if (type == 0x81) {
185    char expkey[AUTHLEN << 2];
186    char pwdhash[CHAP81_HASH_LEN];
187    char pwdhashhash[CHAP81_HASH_LEN];
188    char *ntresponse;
189    size_t f;
190
191    if ((result = malloc(1 + nlen + CHAP81_RESPONSE_LEN)) == NULL)
192      return result;
193
194    memset(result, 0, 1 + nlen + CHAP81_RESPONSE_LEN);
195
196    digest = result;
197    *digest++ = CHAP81_RESPONSE_LEN;		/* value size */
198
199    /* Copy our challenge */
200    memcpy(digest, peerchallenge + 1, CHAP81_CHALLENGE_LEN);
201
202    /* Expand password to Unicode XXX */
203    for (f = 0; f < klen; f++) {
204      expkey[2*f] = key[f];
205      expkey[2*f+1] = '\0';
206    }
207
208    ntresponse = digest + CHAP81_NTRESPONSE_OFF;
209
210    /* Get some needed hashes */
211    NtPasswordHash(expkey, klen * 2, pwdhash);
212    HashNtPasswordHash(pwdhash, pwdhashhash);
213
214    /* Generate NTRESPONSE to respond on challenge call */
215    GenerateNTResponse(challenge + 1, peerchallenge + 1, name,
216                       expkey, klen * 2, ntresponse);
217
218    /* Generate MPPE MASTERKEY */
219    GetMasterKey(pwdhashhash, ntresponse, MPPE_MasterKey);    /* XXX Global ! */
220
221    /* Generate AUTHRESPONSE to verify on auth success */
222    GenerateAuthenticatorResponse(expkey, klen * 2, ntresponse,
223                                  peerchallenge + 1, challenge + 1, name,
224                                  authresponse);
225
226    authresponse[CHAP81_AUTHRESPONSE_LEN] = 0;
227
228    memcpy(digest + CHAP81_RESPONSE_LEN, name, nlen);
229  } else
230#endif
231  if ((result = malloc(nlen + 17)) != NULL) {
232    /* Normal MD5 stuff */
233    MD5_CTX MD5context;
234
235    digest = result;
236    *digest++ = 16;				/* value size */
237
238    MD5Init(&MD5context);
239    MD5Update(&MD5context, &id, 1);
240    MD5Update(&MD5context, key, klen);
241    MD5Update(&MD5context, challenge + 1, *challenge);
242    MD5Final(digest, &MD5context);
243
244    memcpy(digest + 16, name, nlen);
245    /*
246     *           ---- -------- ------
247     * result = | 16 | digest | name |
248     *           ---- -------- ------
249     */
250  }
251
252  return result;
253}
254
255static void
256chap_StartChild(struct chap *chap, char *prog, const char *name)
257{
258  char *argv[MAXARGS], *nargv[MAXARGS];
259  int argc, fd;
260  int in[2], out[2];
261  pid_t pid;
262
263  if (chap->child.fd != -1) {
264    log_Printf(LogWARN, "Chap: %s: Program already running\n", prog);
265    return;
266  }
267
268  if (pipe(in) == -1) {
269    log_Printf(LogERROR, "Chap: pipe: %s\n", strerror(errno));
270    return;
271  }
272
273  if (pipe(out) == -1) {
274    log_Printf(LogERROR, "Chap: pipe: %s\n", strerror(errno));
275    close(in[0]);
276    close(in[1]);
277    return;
278  }
279
280  pid = getpid();
281  switch ((chap->child.pid = fork())) {
282    case -1:
283      log_Printf(LogERROR, "Chap: fork: %s\n", strerror(errno));
284      close(in[0]);
285      close(in[1]);
286      close(out[0]);
287      close(out[1]);
288      chap->child.pid = 0;
289      return;
290
291    case 0:
292      timer_TermService();
293
294      if ((argc = command_Interpret(prog, strlen(prog), argv)) <= 0) {
295        if (argc < 0) {
296          log_Printf(LogWARN, "CHAP: Invalid command syntax\n");
297          _exit(255);
298        }
299        _exit(0);
300      }
301
302      close(in[1]);
303      close(out[0]);
304      if (out[1] == STDIN_FILENO)
305        out[1] = dup(out[1]);
306      dup2(in[0], STDIN_FILENO);
307      dup2(out[1], STDOUT_FILENO);
308      close(STDERR_FILENO);
309      if (open(_PATH_DEVNULL, O_RDWR) != STDERR_FILENO) {
310        log_Printf(LogALERT, "Chap: Failed to open %s: %s\n",
311                  _PATH_DEVNULL, strerror(errno));
312        exit(1);
313      }
314      for (fd = getdtablesize(); fd > STDERR_FILENO; fd--)
315        fcntl(fd, F_SETFD, 1);
316#ifndef NOSUID
317      setuid(ID0realuid());
318#endif
319      command_Expand(nargv, argc, (char const *const *)argv,
320                     chap->auth.physical->dl->bundle, 0, pid);
321      execvp(nargv[0], nargv);
322      printf("exec() of %s failed: %s\n", nargv[0], strerror(errno));
323      _exit(255);
324
325    default:
326      close(in[0]);
327      close(out[1]);
328      chap->child.fd = out[0];
329      chap->child.buf.len = 0;
330      write(in[1], chap->auth.in.name, strlen(chap->auth.in.name));
331      write(in[1], "\n", 1);
332      write(in[1], chap->challenge.peer + 1, *chap->challenge.peer);
333      write(in[1], "\n", 1);
334      write(in[1], name, strlen(name));
335      write(in[1], "\n", 1);
336      close(in[1]);
337      break;
338  }
339}
340
341static void
342chap_Cleanup(struct chap *chap, int sig)
343{
344  if (chap->child.pid) {
345    int status;
346
347    close(chap->child.fd);
348    chap->child.fd = -1;
349    if (sig)
350      kill(chap->child.pid, SIGTERM);
351    chap->child.pid = 0;
352    chap->child.buf.len = 0;
353
354    if (wait(&status) == -1)
355      log_Printf(LogERROR, "Chap: wait: %s\n", strerror(errno));
356    else if (WIFSIGNALED(status))
357      log_Printf(LogWARN, "Chap: Child received signal %d\n", WTERMSIG(status));
358    else if (WIFEXITED(status) && WEXITSTATUS(status))
359      log_Printf(LogERROR, "Chap: Child exited %d\n", WEXITSTATUS(status));
360  }
361  *chap->challenge.local = *chap->challenge.peer = '\0';
362#ifndef NODES
363  chap->peertries = 0;
364#endif
365}
366
367static void
368chap_Respond(struct chap *chap, char *name, char *key
369#ifndef NODES
370             , u_char type, int lm
371#endif
372            )
373{
374  u_char *ans;
375
376  ans = chap_BuildAnswer(name, key, chap->auth.id, chap->challenge.peer
377#ifndef NODES
378                         , type, chap->challenge.local, chap->authresponse, lm
379#endif
380                        );
381
382  if (ans) {
383    ChapOutput(chap->auth.physical, CHAP_RESPONSE, chap->auth.id,
384               ans, *ans + 1 + strlen(name), name);
385#ifndef NODES
386    chap->NTRespSent = !lm;
387    MPPE_IsServer = 0;		/* XXX Global ! */
388#endif
389    free(ans);
390  } else
391    ChapOutput(chap->auth.physical, CHAP_FAILURE, chap->auth.id,
392               "Out of memory!", 14, NULL);
393}
394
395static int
396chap_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w __unused,
397	       fd_set *e __unused, int *n)
398{
399  struct chap *chap = descriptor2chap(d);
400
401  if (r && chap && chap->child.fd != -1) {
402    FD_SET(chap->child.fd, r);
403    if (*n < chap->child.fd + 1)
404      *n = chap->child.fd + 1;
405    log_Printf(LogTIMER, "Chap: fdset(r) %d\n", chap->child.fd);
406    return 1;
407  }
408
409  return 0;
410}
411
412static int
413chap_IsSet(struct fdescriptor *d, const fd_set *fdset)
414{
415  struct chap *chap = descriptor2chap(d);
416
417  return chap && chap->child.fd != -1 && FD_ISSET(chap->child.fd, fdset);
418}
419
420static void
421chap_Read(struct fdescriptor *d, struct bundle *bundle __unused,
422	  const fd_set *fdset __unused)
423{
424  struct chap *chap = descriptor2chap(d);
425  int got;
426
427  got = read(chap->child.fd, chap->child.buf.ptr + chap->child.buf.len,
428             sizeof chap->child.buf.ptr - chap->child.buf.len - 1);
429  if (got == -1) {
430    log_Printf(LogERROR, "Chap: Read: %s\n", strerror(errno));
431    chap_Cleanup(chap, SIGTERM);
432  } else if (got == 0) {
433    log_Printf(LogWARN, "Chap: Read: Child terminated connection\n");
434    chap_Cleanup(chap, SIGTERM);
435  } else {
436    char *name, *key, *end;
437
438    chap->child.buf.len += got;
439    chap->child.buf.ptr[chap->child.buf.len] = '\0';
440    name = chap->child.buf.ptr;
441    name += strspn(name, " \t");
442    if ((key = strchr(name, '\n')) == NULL)
443      end = NULL;
444    else
445      end = strchr(++key, '\n');
446
447    if (end == NULL) {
448      if (chap->child.buf.len == sizeof chap->child.buf.ptr - 1) {
449        log_Printf(LogWARN, "Chap: Read: Input buffer overflow\n");
450        chap_Cleanup(chap, SIGTERM);
451      }
452    } else {
453#ifndef NODES
454      int lanman = chap->auth.physical->link.lcp.his_authtype == 0x80 &&
455                   ((chap->NTRespSent &&
456                     IsAccepted(chap->auth.physical->link.lcp.cfg.chap80lm)) ||
457                    !IsAccepted(chap->auth.physical->link.lcp.cfg.chap80nt));
458#endif
459
460      while (end >= name && strchr(" \t\r\n", *end))
461        *end-- = '\0';
462      end = key - 1;
463      while (end >= name && strchr(" \t\r\n", *end))
464        *end-- = '\0';
465      key += strspn(key, " \t");
466
467      chap_Respond(chap, name, key
468#ifndef NODES
469                   , chap->auth.physical->link.lcp.his_authtype, lanman
470#endif
471                  );
472      chap_Cleanup(chap, 0);
473    }
474  }
475}
476
477static int
478chap_Write(struct fdescriptor *d __unused, struct bundle *bundle __unused,
479	   const fd_set *fdset __unused)
480{
481  /* We never want to write here ! */
482  log_Printf(LogALERT, "chap_Write: Internal error: Bad call !\n");
483  return 0;
484}
485
486static void
487chap_ChallengeInit(struct authinfo *authp)
488{
489  struct chap *chap = auth2chap(authp);
490  int len, i;
491  char *cp;
492
493  len = strlen(authp->physical->dl->bundle->cfg.auth.name);
494
495  if (!*chap->challenge.local) {
496    randinit();
497    cp = chap->challenge.local;
498
499#ifndef NORADIUS
500    if (*authp->physical->dl->bundle->radius.cfg.file) {
501      /* For radius, our challenge is 16 readable NUL terminated bytes :*/
502      *cp++ = 16;
503      for (i = 0; i < 16; i++)
504        *cp++ = (random() % 10) + '0';
505    } else
506#endif
507    {
508#ifndef NODES
509      if (authp->physical->link.lcp.want_authtype == 0x80)
510        *cp++ = 8;	/* MS does 8 byte callenges :-/ */
511      else if (authp->physical->link.lcp.want_authtype == 0x81)
512        *cp++ = 16;	/* MS-CHAP-V2 does 16 bytes challenges */
513      else
514#endif
515        *cp++ = random() % (CHAPCHALLENGELEN-16) + 16;
516      for (i = 0; i < *chap->challenge.local; i++)
517        *cp++ = random() & 0xff;
518    }
519    memcpy(cp, authp->physical->dl->bundle->cfg.auth.name, len);
520  }
521}
522
523static void
524chap_Challenge(struct authinfo *authp)
525{
526  struct chap *chap = auth2chap(authp);
527  int len;
528
529  log_Printf(LogDEBUG, "CHAP%02X: Challenge\n",
530             authp->physical->link.lcp.want_authtype);
531
532  len = strlen(authp->physical->dl->bundle->cfg.auth.name);
533
534  /* Generate new local challenge value */
535  if (!*chap->challenge.local)
536    chap_ChallengeInit(authp);
537
538#ifndef NODES
539  if (authp->physical->link.lcp.want_authtype == 0x81)
540    ChapOutput(authp->physical, CHAP_CHALLENGE, authp->id,
541             chap->challenge.local, 1 + *chap->challenge.local, NULL);
542  else
543#endif
544    ChapOutput(authp->physical, CHAP_CHALLENGE, authp->id,
545             chap->challenge.local, 1 + *chap->challenge.local + len, NULL);
546}
547
548static void
549chap_Success(struct authinfo *authp)
550{
551  struct bundle *bundle = authp->physical->dl->bundle;
552  const char *msg;
553
554  datalink_GotAuthname(authp->physical->dl, authp->in.name);
555#ifndef NODES
556  if (authp->physical->link.lcp.want_authtype == 0x81) {
557#ifndef NORADIUS
558    if (*bundle->radius.cfg.file && bundle->radius.msrepstr)
559      msg = bundle->radius.msrepstr;
560    else
561#endif
562      msg = auth2chap(authp)->authresponse;
563    MPPE_MasterKeyValid = 1;		/* XXX Global ! */
564  } else
565#endif
566#ifndef NORADIUS
567  if (*bundle->radius.cfg.file && bundle->radius.repstr)
568    msg = bundle->radius.repstr;
569  else
570#endif
571    msg = "Welcome!!";
572
573  ChapOutput(authp->physical, CHAP_SUCCESS, authp->id, msg, strlen(msg),
574             NULL);
575
576  authp->physical->link.lcp.auth_ineed = 0;
577  if (Enabled(bundle, OPT_UTMP))
578    physical_Login(authp->physical, authp->in.name);
579
580  if (authp->physical->link.lcp.auth_iwait == 0)
581    /*
582     * Either I didn't need to authenticate, or I've already been
583     * told that I got the answer right.
584     */
585    datalink_AuthOk(authp->physical->dl);
586}
587
588static void
589chap_Failure(struct authinfo *authp)
590{
591#ifndef NODES
592  char buf[1024], *ptr;
593#endif
594  const char *msg;
595
596#ifndef NORADIUS
597  struct bundle *bundle = authp->physical->link.lcp.fsm.bundle;
598  if (*bundle->radius.cfg.file && bundle->radius.errstr)
599    msg = bundle->radius.errstr;
600  else
601#endif
602#ifndef NODES
603  if (authp->physical->link.lcp.want_authtype == 0x80) {
604    sprintf(buf, "E=691 R=1 M=Invalid!");
605    msg = buf;
606  } else if (authp->physical->link.lcp.want_authtype == 0x81) {
607    int i;
608
609    ptr = buf;
610    ptr += sprintf(buf, "E=691 R=0 C=");
611    for (i=0; i<16; i++)
612      ptr += sprintf(ptr, "%02X", *(auth2chap(authp)->challenge.local+1+i));
613
614    sprintf(ptr, " V=3 M=Invalid!");
615    msg = buf;
616  } else
617#endif
618    msg = "Invalid!!";
619
620  ChapOutput(authp->physical, CHAP_FAILURE, authp->id, msg, strlen(msg) + 1,
621             NULL);
622  datalink_AuthNotOk(authp->physical->dl);
623}
624
625static int
626chap_Cmp(char *myans, int mylen, char *hisans, int hislen
627#ifndef NODES
628         , u_char type, int lm
629#endif
630        )
631{
632  int off;
633
634  if (mylen != hislen)
635    return 0;
636
637  off = 0;
638
639#ifndef NODES
640  if (type == 0x80) {
641    off = lm ? 0 : 24;
642    mylen = 24;
643  }
644#endif
645
646  for (; mylen; off++, mylen--)
647    if (toupper(myans[off]) != toupper(hisans[off]))
648      return 0;
649
650  return 1;
651}
652
653#ifndef NODES
654static int
655chap_HaveAnotherGo(struct chap *chap)
656{
657  if (++chap->peertries < 3) {
658    /* Give the peer another shot */
659    *chap->challenge.local = '\0';
660    chap_Challenge(&chap->auth);
661    return 1;
662  }
663
664  return 0;
665}
666#endif
667
668void
669chap_Init(struct chap *chap, struct physical *p)
670{
671  chap->desc.type = CHAP_DESCRIPTOR;
672  chap->desc.UpdateSet = chap_UpdateSet;
673  chap->desc.IsSet = chap_IsSet;
674  chap->desc.Read = chap_Read;
675  chap->desc.Write = chap_Write;
676  chap->child.pid = 0;
677  chap->child.fd = -1;
678  auth_Init(&chap->auth, p, chap_Challenge, chap_Success, chap_Failure);
679  *chap->challenge.local = *chap->challenge.peer = '\0';
680#ifndef NODES
681  chap->NTRespSent = 0;
682  chap->peertries = 0;
683#endif
684}
685
686void
687chap_ReInit(struct chap *chap)
688{
689  chap_Cleanup(chap, SIGTERM);
690}
691
692struct mbuf *
693chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
694{
695  struct physical *p = link2physical(l);
696  struct chap *chap = &p->dl->chap;
697  char *name, *key, *ans;
698  int len;
699  size_t nlen;
700  u_char alen;
701#ifndef NODES
702  int lanman;
703#endif
704
705  if (p == NULL) {
706    log_Printf(LogERROR, "chap_Input: Not a physical link - dropped\n");
707    m_freem(bp);
708    return NULL;
709  }
710
711  if (bundle_Phase(bundle) != PHASE_NETWORK &&
712      bundle_Phase(bundle) != PHASE_AUTHENTICATE) {
713    log_Printf(LogPHASE, "Unexpected chap input - dropped !\n");
714    m_freem(bp);
715    return NULL;
716  }
717
718  m_settype(bp, MB_CHAPIN);
719  if ((bp = auth_ReadHeader(&chap->auth, bp)) == NULL &&
720      ntohs(chap->auth.in.hdr.length) == 0)
721    log_Printf(LogWARN, "Chap Input: Truncated header !\n");
722  else if (chap->auth.in.hdr.code == 0 || chap->auth.in.hdr.code > MAXCHAPCODE)
723    log_Printf(LogPHASE, "Chap Input: %d: Bad CHAP code !\n",
724               chap->auth.in.hdr.code);
725  else {
726    len = m_length(bp);
727    ans = NULL;
728
729    if (chap->auth.in.hdr.code != CHAP_CHALLENGE &&
730        chap->auth.id != chap->auth.in.hdr.id &&
731        Enabled(bundle, OPT_IDCHECK)) {
732      /* Wrong conversation dude ! */
733      log_Printf(LogPHASE, "Chap Input: %s dropped (got id %d, not %d)\n",
734                 chapcodes[chap->auth.in.hdr.code], chap->auth.in.hdr.id,
735                 chap->auth.id);
736      m_freem(bp);
737      return NULL;
738    }
739    chap->auth.id = chap->auth.in.hdr.id;	/* We respond with this id */
740
741#ifndef NODES
742    lanman = 0;
743#endif
744    switch (chap->auth.in.hdr.code) {
745      case CHAP_CHALLENGE:
746        bp = mbuf_Read(bp, &alen, 1);
747        len -= alen + 1;
748        if (len < 0) {
749          log_Printf(LogERROR, "Chap Input: Truncated challenge !\n");
750          m_freem(bp);
751          return NULL;
752        }
753        *chap->challenge.peer = alen;
754        bp = mbuf_Read(bp, chap->challenge.peer + 1, alen);
755        bp = auth_ReadName(&chap->auth, bp, len);
756#ifndef NODES
757        lanman = p->link.lcp.his_authtype == 0x80 &&
758                 ((chap->NTRespSent && IsAccepted(p->link.lcp.cfg.chap80lm)) ||
759                  !IsAccepted(p->link.lcp.cfg.chap80nt));
760
761        /* Generate local challenge value */
762        chap_ChallengeInit(&chap->auth);
763#endif
764        break;
765
766      case CHAP_RESPONSE:
767        auth_StopTimer(&chap->auth);
768        bp = mbuf_Read(bp, &alen, 1);
769        len -= alen + 1;
770        if (len < 0) {
771          log_Printf(LogERROR, "Chap Input: Truncated response !\n");
772          m_freem(bp);
773          return NULL;
774        }
775        if ((ans = malloc(alen + 1)) == NULL) {
776          log_Printf(LogERROR, "Chap Input: Out of memory !\n");
777          m_freem(bp);
778          return NULL;
779        }
780        *ans = chap->auth.id;
781        bp = mbuf_Read(bp, ans + 1, alen);
782        bp = auth_ReadName(&chap->auth, bp, len);
783#ifndef NODES
784        lanman = p->link.lcp.want_authtype == 0x80 &&
785                 alen == 49 && ans[alen] == 0;
786#endif
787        break;
788
789      case CHAP_SUCCESS:
790      case CHAP_FAILURE:
791        /* chap->auth.in.name is already set up at CHALLENGE time */
792        if ((ans = malloc(len + 1)) == NULL) {
793          log_Printf(LogERROR, "Chap Input: Out of memory !\n");
794          m_freem(bp);
795          return NULL;
796        }
797        bp = mbuf_Read(bp, ans, len);
798        ans[len] = '\0';
799        break;
800    }
801
802    switch (chap->auth.in.hdr.code) {
803      case CHAP_CHALLENGE:
804      case CHAP_RESPONSE:
805        if (*chap->auth.in.name)
806          log_Printf(LogPHASE, "Chap Input: %s (%d bytes from %s%s)\n",
807                     chapcodes[chap->auth.in.hdr.code], alen,
808                     chap->auth.in.name,
809#ifndef NODES
810                     lanman && chap->auth.in.hdr.code == CHAP_RESPONSE ?
811                     " - lanman" :
812#endif
813                     "");
814        else
815          log_Printf(LogPHASE, "Chap Input: %s (%d bytes%s)\n",
816                     chapcodes[chap->auth.in.hdr.code], alen,
817#ifndef NODES
818                     lanman && chap->auth.in.hdr.code == CHAP_RESPONSE ?
819                     " - lanman" :
820#endif
821                     "");
822        break;
823
824      case CHAP_SUCCESS:
825      case CHAP_FAILURE:
826        if (*ans)
827          log_Printf(LogPHASE, "Chap Input: %s (%s)\n",
828                     chapcodes[chap->auth.in.hdr.code], ans);
829        else
830          log_Printf(LogPHASE, "Chap Input: %s\n",
831                     chapcodes[chap->auth.in.hdr.code]);
832        break;
833    }
834
835    switch (chap->auth.in.hdr.code) {
836      case CHAP_CHALLENGE:
837        if (*bundle->cfg.auth.key == '!' && bundle->cfg.auth.key[1] != '!')
838          chap_StartChild(chap, bundle->cfg.auth.key + 1,
839                          bundle->cfg.auth.name);
840        else
841          chap_Respond(chap, bundle->cfg.auth.name, bundle->cfg.auth.key +
842                       (*bundle->cfg.auth.key == '!' ? 1 : 0)
843
844#ifndef NODES
845                       , p->link.lcp.his_authtype, lanman
846#endif
847                      );
848        break;
849
850      case CHAP_RESPONSE:
851        name = chap->auth.in.name;
852        nlen = strlen(name);
853#ifndef NODES
854        if (p->link.lcp.want_authtype == 0x81) {
855          struct MSCHAPv2_resp *resp = (struct MSCHAPv2_resp *)(ans + 1);
856
857          chap->challenge.peer[0] = sizeof resp->PeerChallenge;
858          memcpy(chap->challenge.peer + 1, resp->PeerChallenge,
859                 sizeof resp->PeerChallenge);
860        }
861#endif
862
863#ifndef NORADIUS
864        if (*bundle->radius.cfg.file) {
865          if (!radius_Authenticate(&bundle->radius, &chap->auth,
866                                   chap->auth.in.name, ans, alen + 1,
867                                   chap->challenge.local + 1,
868                                   *chap->challenge.local))
869            chap_Failure(&chap->auth);
870        } else
871#endif
872        {
873          if (p->link.lcp.want_authtype == 0x81 && ans[alen] != '\0' &&
874              alen == sizeof(struct MSCHAPv2_resp)) {
875            struct MSCHAPv2_resp *resp = (struct MSCHAPv2_resp *)(ans + 1);
876
877            log_Printf(LogWARN, "%s: Compensating for corrupt (Win98/WinME?) "
878                       "CHAP81 RESPONSE\n", l->name);
879            resp->Flags = '\0';	/* rfc2759 says it *MUST* be zero */
880          }
881          key = auth_GetSecret(name, nlen);
882          if (key) {
883#ifndef NODES
884            if (p->link.lcp.want_authtype == 0x80 &&
885                lanman && !IsEnabled(p->link.lcp.cfg.chap80lm)) {
886              log_Printf(LogPHASE, "Auth failure: LANMan not enabled\n");
887              if (chap_HaveAnotherGo(chap))
888                break;
889              key = NULL;
890            } else if (p->link.lcp.want_authtype == 0x80 &&
891                !lanman && !IsEnabled(p->link.lcp.cfg.chap80nt)) {
892              log_Printf(LogPHASE, "Auth failure: mschap not enabled\n");
893              if (chap_HaveAnotherGo(chap))
894                break;
895              key = NULL;
896            } else if (p->link.lcp.want_authtype == 0x81 &&
897                !IsEnabled(p->link.lcp.cfg.chap81)) {
898              log_Printf(LogPHASE, "Auth failure: CHAP81 not enabled\n");
899              key = NULL;
900            } else
901#endif
902            {
903              char *myans = chap_BuildAnswer(name, key, chap->auth.id,
904                                             chap->challenge.local
905#ifndef NODES
906					     , p->link.lcp.want_authtype,
907					     chap->challenge.peer,
908					     chap->authresponse, lanman);
909              MPPE_IsServer = 1;		/* XXX Global ! */
910#else
911                                      );
912#endif
913              if (myans == NULL)
914                key = NULL;
915              else {
916                if (!chap_Cmp(myans + 1, *myans, ans + 1, alen
917#ifndef NODES
918                              , p->link.lcp.want_authtype, lanman
919#endif
920                             ))
921                  key = NULL;
922                free(myans);
923              }
924            }
925          }
926
927          if (key)
928            chap_Success(&chap->auth);
929          else
930            chap_Failure(&chap->auth);
931        }
932
933        break;
934
935      case CHAP_SUCCESS:
936        if (p->link.lcp.auth_iwait == PROTO_CHAP) {
937          p->link.lcp.auth_iwait = 0;
938          if (p->link.lcp.auth_ineed == 0) {
939#ifndef NODES
940            if (p->link.lcp.his_authtype == 0x81) {
941              if (strncasecmp(ans, chap->authresponse, 42)) {
942                datalink_AuthNotOk(p->dl);
943	        log_Printf(LogWARN, "CHAP81: AuthenticatorResponse: (%.42s)"
944                           " != ans: (%.42s)\n", chap->authresponse, ans);
945
946              } else {
947                /* Successful login */
948                MPPE_MasterKeyValid = 1;		/* XXX Global ! */
949                datalink_AuthOk(p->dl);
950              }
951            } else
952#endif
953            /*
954             * We've succeeded in our ``login''
955             * If we're not expecting  the peer to authenticate (or he already
956             * has), proceed to network phase.
957             */
958            datalink_AuthOk(p->dl);
959          }
960        }
961        break;
962
963      case CHAP_FAILURE:
964        datalink_AuthNotOk(p->dl);
965        break;
966    }
967    free(ans);
968  }
969
970  m_freem(bp);
971  return NULL;
972}
973