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