ReactOS 0.4.15-dev-8614-gbc76250
chap.c
Go to the documentation of this file.
1/*** WARNING - THIS HAS NEVER BEEN FINISHED ***/
2/*****************************************************************************
3* chap.c - Network Challenge Handshake Authentication Protocol program file.
4*
5* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
6* portions Copyright (c) 1997 by Global Election Systems Inc.
7*
8* The authors hereby grant permission to use, copy, modify, distribute,
9* and license this software and its documentation for any purpose, provided
10* that existing copyright notices are retained in all copies and that this
11* notice and the following disclaimer are included verbatim in any
12* distributions. No written agreement, license, or royalty fee is required
13* for any of the authorized uses.
14*
15* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
16* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*
26******************************************************************************
27* REVISION HISTORY
28*
29* 03-01-01 Marc Boucher <marc@mbsi.ca>
30* Ported to lwIP.
31* 97-12-04 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
32* Original based on BSD chap.c.
33*****************************************************************************/
34/*
35 * chap.c - Challenge Handshake Authentication Protocol.
36 *
37 * Copyright (c) 1993 The Australian National University.
38 * All rights reserved.
39 *
40 * Redistribution and use in source and binary forms are permitted
41 * provided that the above copyright notice and this paragraph are
42 * duplicated in all such forms and that any documentation,
43 * advertising materials, and other materials related to such
44 * distribution and use acknowledge that the software was developed
45 * by the Australian National University. The name of the University
46 * may not be used to endorse or promote products derived from this
47 * software without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
49 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
50 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
51 *
52 * Copyright (c) 1991 Gregory M. Christy.
53 * All rights reserved.
54 *
55 * Redistribution and use in source and binary forms are permitted
56 * provided that the above copyright notice and this paragraph are
57 * duplicated in all such forms and that any documentation,
58 * advertising materials, and other materials related to such
59 * distribution and use acknowledge that the software was developed
60 * by Gregory M. Christy. The name of the author may not be used to
61 * endorse or promote products derived from this software without
62 * specific prior written permission.
63 *
64 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
65 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
66 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
67 */
68
69#include "lwip/opt.h"
70
71#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
72
73#if CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
74
75#include "ppp_impl.h"
76#include "pppdebug.h"
77
78#include "magic.h"
79#include "randm.h"
80#include "auth.h"
81#include "md5.h"
82#include "chap.h"
83#include "chpms.h"
84
85#include <string.h>
86
87#if 0 /* UNUSED */
88/*
89 * Command-line options.
90 */
91static option_t chap_option_list[] = {
92 { "chap-restart", o_int, &chap[0].timeouttime,
93 "Set timeout for CHAP" },
94 { "chap-max-challenge", o_int, &chap[0].max_transmits,
95 "Set max #xmits for challenge" },
96 { "chap-interval", o_int, &chap[0].chal_interval,
97 "Set interval for rechallenge" },
98#ifdef MSLANMAN
99 { "ms-lanman", o_bool, &ms_lanman,
100 "Use LanMan passwd when using MS-CHAP", 1 },
101#endif
102 { NULL }
103};
104#endif /* UNUSED */
105
106/*
107 * Protocol entry points.
108 */
109static void ChapInit (int);
110static void ChapLowerUp (int);
111static void ChapLowerDown (int);
112static void ChapInput (int, u_char *, int);
113static void ChapProtocolReject (int);
114#if PPP_ADDITIONAL_CALLBACKS
115static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *);
116#endif
117
118struct protent chap_protent = {
119 PPP_CHAP,
120 ChapInit,
121 ChapInput,
122 ChapProtocolReject,
123 ChapLowerUp,
124 ChapLowerDown,
125 NULL,
126 NULL,
127#if PPP_ADDITIONAL_CALLBACKS
128 ChapPrintPkt,
129 NULL,
130#endif /* PPP_ADDITIONAL_CALLBACKS */
131 1,
132 "CHAP",
133#if PPP_ADDITIONAL_CALLBACKS
134 NULL,
135 NULL,
136 NULL
137#endif /* PPP_ADDITIONAL_CALLBACKS */
138};
139
140chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
141
142static void ChapChallengeTimeout (void *);
143static void ChapResponseTimeout (void *);
144static void ChapReceiveChallenge (chap_state *, u_char *, u_char, int);
145static void ChapRechallenge (void *);
146static void ChapReceiveResponse (chap_state *, u_char *, int, int);
147static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len);
148static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len);
149static void ChapSendStatus (chap_state *, int);
150static void ChapSendChallenge (chap_state *);
151static void ChapSendResponse (chap_state *);
152static void ChapGenChallenge (chap_state *);
153
154/*
155 * ChapInit - Initialize a CHAP unit.
156 */
157static void
158ChapInit(int unit)
159{
161
162 BZERO(cstate, sizeof(*cstate));
163 cstate->unit = unit;
164 cstate->clientstate = CHAPCS_INITIAL;
165 cstate->serverstate = CHAPSS_INITIAL;
166 cstate->timeouttime = CHAP_DEFTIMEOUT;
167 cstate->max_transmits = CHAP_DEFTRANSMITS;
168 /* random number generator is initialized in magic_init */
169}
170
171
172/*
173 * ChapAuthWithPeer - Authenticate us with our peer (start client).
174 *
175 */
176void
177ChapAuthWithPeer(int unit, char *our_name, u_char digest)
178{
180
181 cstate->resp_name = our_name;
182 cstate->resp_type = digest;
183
184 if (cstate->clientstate == CHAPCS_INITIAL ||
185 cstate->clientstate == CHAPCS_PENDING) {
186 /* lower layer isn't up - wait until later */
187 cstate->clientstate = CHAPCS_PENDING;
188 return;
189 }
190
191 /*
192 * We get here as a result of LCP coming up.
193 * So even if CHAP was open before, we will
194 * have to re-authenticate ourselves.
195 */
196 cstate->clientstate = CHAPCS_LISTEN;
197}
198
199
200/*
201 * ChapAuthPeer - Authenticate our peer (start server).
202 */
203void
204ChapAuthPeer(int unit, char *our_name, u_char digest)
205{
207
208 cstate->chal_name = our_name;
209 cstate->chal_type = digest;
210
211 if (cstate->serverstate == CHAPSS_INITIAL ||
212 cstate->serverstate == CHAPSS_PENDING) {
213 /* lower layer isn't up - wait until later */
214 cstate->serverstate = CHAPSS_PENDING;
215 return;
216 }
217
218 ChapGenChallenge(cstate);
219 ChapSendChallenge(cstate); /* crank it up dude! */
220 cstate->serverstate = CHAPSS_INITIAL_CHAL;
221}
222
223
224/*
225 * ChapChallengeTimeout - Timeout expired on sending challenge.
226 */
227static void
228ChapChallengeTimeout(void *arg)
229{
231
232 /* if we aren't sending challenges, don't worry. then again we */
233 /* probably shouldn't be here either */
234 if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
235 cstate->serverstate != CHAPSS_RECHALLENGE) {
236 return;
237 }
238
239 if (cstate->chal_transmits >= cstate->max_transmits) {
240 /* give up on peer */
241 CHAPDEBUG(LOG_ERR, ("Peer failed to respond to CHAP challenge\n"));
242 cstate->serverstate = CHAPSS_BADAUTH;
243 auth_peer_fail(cstate->unit, PPP_CHAP);
244 return;
245 }
246
247 ChapSendChallenge(cstate); /* Re-send challenge */
248}
249
250
251/*
252 * ChapResponseTimeout - Timeout expired on sending response.
253 */
254static void
255ChapResponseTimeout(void *arg)
256{
258
259 /* if we aren't sending a response, don't worry. */
260 if (cstate->clientstate != CHAPCS_RESPONSE) {
261 return;
262 }
263
264 ChapSendResponse(cstate); /* re-send response */
265}
266
267
268/*
269 * ChapRechallenge - Time to challenge the peer again.
270 */
271static void
272ChapRechallenge(void *arg)
273{
275
276 /* if we aren't sending a response, don't worry. */
277 if (cstate->serverstate != CHAPSS_OPEN) {
278 return;
279 }
280
281 ChapGenChallenge(cstate);
282 ChapSendChallenge(cstate);
283 cstate->serverstate = CHAPSS_RECHALLENGE;
284}
285
286
287/*
288 * ChapLowerUp - The lower layer is up.
289 *
290 * Start up if we have pending requests.
291 */
292static void
293ChapLowerUp(int unit)
294{
296
297 if (cstate->clientstate == CHAPCS_INITIAL) {
298 cstate->clientstate = CHAPCS_CLOSED;
299 } else if (cstate->clientstate == CHAPCS_PENDING) {
300 cstate->clientstate = CHAPCS_LISTEN;
301 }
302
303 if (cstate->serverstate == CHAPSS_INITIAL) {
304 cstate->serverstate = CHAPSS_CLOSED;
305 } else if (cstate->serverstate == CHAPSS_PENDING) {
306 ChapGenChallenge(cstate);
307 ChapSendChallenge(cstate);
308 cstate->serverstate = CHAPSS_INITIAL_CHAL;
309 }
310}
311
312
313/*
314 * ChapLowerDown - The lower layer is down.
315 *
316 * Cancel all timeouts.
317 */
318static void
319ChapLowerDown(int unit)
320{
322
323 /* Timeout(s) pending? Cancel if so. */
324 if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
325 cstate->serverstate == CHAPSS_RECHALLENGE) {
326 UNTIMEOUT(ChapChallengeTimeout, cstate);
327 } else if (cstate->serverstate == CHAPSS_OPEN
328 && cstate->chal_interval != 0) {
329 UNTIMEOUT(ChapRechallenge, cstate);
330 }
331 if (cstate->clientstate == CHAPCS_RESPONSE) {
332 UNTIMEOUT(ChapResponseTimeout, cstate);
333 }
334 cstate->clientstate = CHAPCS_INITIAL;
335 cstate->serverstate = CHAPSS_INITIAL;
336}
337
338
339/*
340 * ChapProtocolReject - Peer doesn't grok CHAP.
341 */
342static void
343ChapProtocolReject(int unit)
344{
346
347 if (cstate->serverstate != CHAPSS_INITIAL &&
348 cstate->serverstate != CHAPSS_CLOSED) {
349 auth_peer_fail(unit, PPP_CHAP);
350 }
351 if (cstate->clientstate != CHAPCS_INITIAL &&
352 cstate->clientstate != CHAPCS_CLOSED) {
353 auth_withpeer_fail(unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */
354 }
355 ChapLowerDown(unit); /* shutdown chap */
356}
357
358
359/*
360 * ChapInput - Input CHAP packet.
361 */
362static void
363ChapInput(int unit, u_char *inpacket, int packet_len)
364{
366 u_char *inp;
367 u_char code, id;
368 int len;
369
370 /*
371 * Parse header (code, id and length).
372 * If packet too short, drop it.
373 */
374 inp = inpacket;
375 if (packet_len < CHAP_HEADERLEN) {
376 CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short header.\n"));
377 return;
378 }
379 GETCHAR(code, inp);
380 GETCHAR(id, inp);
381 GETSHORT(len, inp);
382 if (len < CHAP_HEADERLEN) {
383 CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd illegal length.\n"));
384 return;
385 }
386 if (len > packet_len) {
387 CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short packet.\n"));
388 return;
389 }
391
392 /*
393 * Action depends on code (as in fact it usually does :-).
394 */
395 switch (code) {
396 case CHAP_CHALLENGE:
397 ChapReceiveChallenge(cstate, inp, id, len);
398 break;
399
400 case CHAP_RESPONSE:
401 ChapReceiveResponse(cstate, inp, id, len);
402 break;
403
404 case CHAP_FAILURE:
405 ChapReceiveFailure(cstate, inp, id, len);
406 break;
407
408 case CHAP_SUCCESS:
409 ChapReceiveSuccess(cstate, inp, id, len);
410 break;
411
412 default: /* Need code reject? */
413 CHAPDEBUG(LOG_WARNING, ("Unknown CHAP code (%d) received.\n", code));
414 break;
415 }
416}
417
418
419/*
420 * ChapReceiveChallenge - Receive Challenge and send Response.
421 */
422static void
423ChapReceiveChallenge(chap_state *cstate, u_char *inp, u_char id, int len)
424{
425 int rchallenge_len;
426 u_char *rchallenge;
427 int secret_len;
428 char secret[MAXSECRETLEN];
429 char rhostname[256];
430 MD5_CTX mdContext;
432
433 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: Rcvd id %d.\n", id));
434 if (cstate->clientstate == CHAPCS_CLOSED ||
435 cstate->clientstate == CHAPCS_PENDING) {
436 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: in state %d\n",
437 cstate->clientstate));
438 return;
439 }
440
441 if (len < 2) {
442 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
443 return;
444 }
445
446 GETCHAR(rchallenge_len, inp);
447 len -= sizeof (u_char) + rchallenge_len; /* now name field length */
448 if (len < 0) {
449 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
450 return;
451 }
452 rchallenge = inp;
453 INCPTR(rchallenge_len, inp);
454
455 if (len >= (int)sizeof(rhostname)) {
456 len = sizeof(rhostname) - 1;
457 }
458 BCOPY(inp, rhostname, len);
459 rhostname[len] = '\000';
460
461 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: received name field '%s'\n",
462 rhostname));
463
464 /* Microsoft doesn't send their name back in the PPP packet */
465 if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) {
466 strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname));
467 rhostname[sizeof(rhostname) - 1] = 0;
468 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: using '%s' as remote name\n",
469 rhostname));
470 }
471
472 /* get secret for authenticating ourselves with the specified host */
473 if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
474 secret, &secret_len, 0)) {
475 secret_len = 0; /* assume null secret if can't find one */
476 CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating us to %s\n",
477 rhostname));
478 }
479
480 /* cancel response send timeout if necessary */
481 if (cstate->clientstate == CHAPCS_RESPONSE) {
482 UNTIMEOUT(ChapResponseTimeout, cstate);
483 }
484
485 cstate->resp_id = id;
486 cstate->resp_transmits = 0;
487
488 /* generate MD based on negotiated type */
489 switch (cstate->resp_type) {
490
491 case CHAP_DIGEST_MD5:
492 MD5Init(&mdContext);
493 MD5Update(&mdContext, &cstate->resp_id, 1);
494 MD5Update(&mdContext, (u_char*)secret, secret_len);
495 MD5Update(&mdContext, rchallenge, rchallenge_len);
496 MD5Final(hash, &mdContext);
497 BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
498 cstate->resp_length = MD5_SIGNATURE_SIZE;
499 break;
500
501#if MSCHAP_SUPPORT
502 case CHAP_MICROSOFT:
503 ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
504 break;
505#endif
506
507 default:
508 CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->resp_type));
509 return;
510 }
511
512 BZERO(secret, sizeof(secret));
513 ChapSendResponse(cstate);
514}
515
516
517/*
518 * ChapReceiveResponse - Receive and process response.
519 */
520static void
521ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
522{
523 u_char *remmd, remmd_len;
524 int secret_len, old_state;
525 int code;
526 char rhostname[256];
527 MD5_CTX mdContext;
528 char secret[MAXSECRETLEN];
530
531 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: Rcvd id %d.\n", id));
532
533 if (cstate->serverstate == CHAPSS_CLOSED ||
534 cstate->serverstate == CHAPSS_PENDING) {
535 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: in state %d\n",
536 cstate->serverstate));
537 return;
538 }
539
540 if (id != cstate->chal_id) {
541 return; /* doesn't match ID of last challenge */
542 }
543
544 /*
545 * If we have received a duplicate or bogus Response,
546 * we have to send the same answer (Success/Failure)
547 * as we did for the first Response we saw.
548 */
549 if (cstate->serverstate == CHAPSS_OPEN) {
550 ChapSendStatus(cstate, CHAP_SUCCESS);
551 return;
552 }
553 if (cstate->serverstate == CHAPSS_BADAUTH) {
554 ChapSendStatus(cstate, CHAP_FAILURE);
555 return;
556 }
557
558 if (len < 2) {
559 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
560 return;
561 }
562 GETCHAR(remmd_len, inp); /* get length of MD */
563 remmd = inp; /* get pointer to MD */
564 INCPTR(remmd_len, inp);
565
566 len -= sizeof (u_char) + remmd_len;
567 if (len < 0) {
568 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
569 return;
570 }
571
572 UNTIMEOUT(ChapChallengeTimeout, cstate);
573
574 if (len >= (int)sizeof(rhostname)) {
575 len = sizeof(rhostname) - 1;
576 }
577 BCOPY(inp, rhostname, len);
578 rhostname[len] = '\000';
579
580 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: received name field: %s\n",
581 rhostname));
582
583 /*
584 * Get secret for authenticating them with us,
585 * do the hash ourselves, and compare the result.
586 */
588 if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
589 secret, &secret_len, 1)) {
590 CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating %s\n",
591 rhostname));
592 } else {
593 /* generate MD based on negotiated type */
594 switch (cstate->chal_type) {
595
596 case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
597 if (remmd_len != MD5_SIGNATURE_SIZE) {
598 break; /* it's not even the right length */
599 }
600 MD5Init(&mdContext);
601 MD5Update(&mdContext, &cstate->chal_id, 1);
602 MD5Update(&mdContext, (u_char*)secret, secret_len);
603 MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
604 MD5Final(hash, &mdContext);
605
606 /* compare local and remote MDs and send the appropriate status */
607 if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0) {
608 code = CHAP_SUCCESS; /* they are the same! */
609 }
610 break;
611
612 default:
613 CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->chal_type));
614 }
615 }
616
617 BZERO(secret, sizeof(secret));
618 ChapSendStatus(cstate, code);
619
620 if (code == CHAP_SUCCESS) {
621 old_state = cstate->serverstate;
622 cstate->serverstate = CHAPSS_OPEN;
623 if (old_state == CHAPSS_INITIAL_CHAL) {
624 auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
625 }
626 if (cstate->chal_interval != 0) {
627 TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
628 }
629 } else {
630 CHAPDEBUG(LOG_ERR, ("CHAP peer authentication failed\n"));
631 cstate->serverstate = CHAPSS_BADAUTH;
632 auth_peer_fail(cstate->unit, PPP_CHAP);
633 }
634}
635
636/*
637 * ChapReceiveSuccess - Receive Success
638 */
639static void
640ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len)
641{
642 LWIP_UNUSED_ARG(id);
643 LWIP_UNUSED_ARG(inp);
644
645 CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: Rcvd id %d.\n", id));
646
647 if (cstate->clientstate == CHAPCS_OPEN) {
648 /* presumably an answer to a duplicate response */
649 return;
650 }
651
652 if (cstate->clientstate != CHAPCS_RESPONSE) {
653 /* don't know what this is */
654 CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: in state %d\n",
655 cstate->clientstate));
656 return;
657 }
658
659 UNTIMEOUT(ChapResponseTimeout, cstate);
660
661 /*
662 * Print message.
663 */
664 if (len > 0) {
665 PRINTMSG(inp, len);
666 }
667
668 cstate->clientstate = CHAPCS_OPEN;
669
670 auth_withpeer_success(cstate->unit, PPP_CHAP);
671}
672
673
674/*
675 * ChapReceiveFailure - Receive failure.
676 */
677static void
678ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len)
679{
680 LWIP_UNUSED_ARG(id);
681 LWIP_UNUSED_ARG(inp);
682
683 CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: Rcvd id %d.\n", id));
684
685 if (cstate->clientstate != CHAPCS_RESPONSE) {
686 /* don't know what this is */
687 CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: in state %d\n",
688 cstate->clientstate));
689 return;
690 }
691
692 UNTIMEOUT(ChapResponseTimeout, cstate);
693
694 /*
695 * Print message.
696 */
697 if (len > 0) {
698 PRINTMSG(inp, len);
699 }
700
701 CHAPDEBUG(LOG_ERR, ("CHAP authentication failed\n"));
702 auth_withpeer_fail(cstate->unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */
703}
704
705
706/*
707 * ChapSendChallenge - Send an Authenticate challenge.
708 */
709static void
710ChapSendChallenge(chap_state *cstate)
711{
712 u_char *outp;
713 int chal_len, name_len;
714 int outlen;
715
716 chal_len = cstate->chal_len;
717 name_len = (int)strlen(cstate->chal_name);
718 outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
719 outp = outpacket_buf[cstate->unit];
720
721 MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
722
723 PUTCHAR(CHAP_CHALLENGE, outp);
724 PUTCHAR(cstate->chal_id, outp);
725 PUTSHORT(outlen, outp);
726
727 PUTCHAR(chal_len, outp); /* put length of challenge */
728 BCOPY(cstate->challenge, outp, chal_len);
729 INCPTR(chal_len, outp);
730
731 BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
732
733 pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
734
735 CHAPDEBUG(LOG_INFO, ("ChapSendChallenge: Sent id %d.\n", cstate->chal_id));
736
737 TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
738 ++cstate->chal_transmits;
739}
740
741
742/*
743 * ChapSendStatus - Send a status response (ack or nak).
744 */
745static void
746ChapSendStatus(chap_state *cstate, int code)
747{
748 u_char *outp;
749 int outlen, msglen;
750 char msg[256]; /* @todo: this can be a char*, no strcpy needed */
751
752 if (code == CHAP_SUCCESS) {
753 strcpy(msg, "Welcome!");
754 } else {
755 strcpy(msg, "I don't like you. Go 'way.");
756 }
757 msglen = (int)strlen(msg);
758
759 outlen = CHAP_HEADERLEN + msglen;
760 outp = outpacket_buf[cstate->unit];
761
762 MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
763
764 PUTCHAR(code, outp);
765 PUTCHAR(cstate->chal_id, outp);
766 PUTSHORT(outlen, outp);
767 BCOPY(msg, outp, msglen);
768 pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
769
770 CHAPDEBUG(LOG_INFO, ("ChapSendStatus: Sent code %d, id %d.\n", code,
771 cstate->chal_id));
772}
773
774/*
775 * ChapGenChallenge is used to generate a pseudo-random challenge string of
776 * a pseudo-random length between min_len and max_len. The challenge
777 * string and its length are stored in *cstate, and various other fields of
778 * *cstate are initialized.
779 */
780
781static void
782ChapGenChallenge(chap_state *cstate)
783{
784 int chal_len;
785 u_char *ptr = cstate->challenge;
786 int i;
787
788 /* pick a random challenge length between MIN_CHALLENGE_LENGTH and
789 MAX_CHALLENGE_LENGTH */
790 chal_len = (unsigned)
791 ((((magic() >> 16) *
794 LWIP_ASSERT("chal_len <= 0xff", chal_len <= 0xffff);
795 cstate->chal_len = (u_char)chal_len;
796 cstate->chal_id = ++cstate->id;
797 cstate->chal_transmits = 0;
798
799 /* generate a random string */
800 for (i = 0; i < chal_len; i++ ) {
801 *ptr++ = (char) (magic() & 0xff);
802 }
803}
804
805/*
806 * ChapSendResponse - send a response packet with values as specified
807 * in *cstate.
808 */
809/* ARGSUSED */
810static void
811ChapSendResponse(chap_state *cstate)
812{
813 u_char *outp;
814 int outlen, md_len, name_len;
815
816 md_len = cstate->resp_length;
817 name_len = (int)strlen(cstate->resp_name);
818 outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
819 outp = outpacket_buf[cstate->unit];
820
821 MAKEHEADER(outp, PPP_CHAP);
822
823 PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
824 PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */
825 PUTSHORT(outlen, outp); /* packet length */
826
827 PUTCHAR(md_len, outp); /* length of MD */
828 BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
829 INCPTR(md_len, outp);
830
831 BCOPY(cstate->resp_name, outp, name_len); /* append our name */
832
833 /* send the packet */
834 pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
835
836 cstate->clientstate = CHAPCS_RESPONSE;
837 TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
838 ++cstate->resp_transmits;
839}
840
841#if PPP_ADDITIONAL_CALLBACKS
842static char *ChapCodenames[] = {
843 "Challenge", "Response", "Success", "Failure"
844};
845/*
846 * ChapPrintPkt - print the contents of a CHAP packet.
847 */
848static int
849ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
850{
851 int code, id, len;
852 int clen, nlen;
853 u_char x;
854
855 if (plen < CHAP_HEADERLEN) {
856 return 0;
857 }
858 GETCHAR(code, p);
859 GETCHAR(id, p);
860 GETSHORT(len, p);
861 if (len < CHAP_HEADERLEN || len > plen) {
862 return 0;
863 }
864
865 if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) {
866 printer(arg, " %s", ChapCodenames[code-1]);
867 } else {
868 printer(arg, " code=0x%x", code);
869 }
870 printer(arg, " id=0x%x", id);
872 switch (code) {
873 case CHAP_CHALLENGE:
874 case CHAP_RESPONSE:
875 if (len < 1) {
876 break;
877 }
878 clen = p[0];
879 if (len < clen + 1) {
880 break;
881 }
882 ++p;
883 nlen = len - clen - 1;
884 printer(arg, " <");
885 for (; clen > 0; --clen) {
886 GETCHAR(x, p);
887 printer(arg, "%.2x", x);
888 }
889 printer(arg, ">, name = %.*Z", nlen, p);
890 break;
891 case CHAP_FAILURE:
892 case CHAP_SUCCESS:
893 printer(arg, " %.*Z", len, p);
894 break;
895 default:
896 for (clen = len; clen > 0; --clen) {
897 GETCHAR(x, p);
898 printer(arg, " %.2x", x);
899 }
900 }
901
902 return len + CHAP_HEADERLEN;
903}
904#endif /* PPP_ADDITIONAL_CALLBACKS */
905
906#endif /* CHAP_SUPPORT */
907
908#endif /* PPP_SUPPORT */
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
#define msg(x)
Definition: auth_time.c:54
struct protent chap_protent
#define CHAP_RESPONSE
Definition: chap.h:84
#define CHAPCS_PENDING
Definition: chap.h:127
#define CHAPCS_LISTEN
Definition: chap.h:128
chap_state chap[]
void ChapAuthPeer(int, char *, u_char)
#define MIN_CHALLENGE_LENGTH
Definition: chap.h:91
#define CHAPSS_INITIAL_CHAL
Definition: chap.h:138
#define CHAP_CHALLENGE
Definition: chap.h:83
#define CHAPSS_BADAUTH
Definition: chap.h:141
#define CHAP_HEADERLEN
Definition: chap.h:72
#define CHAPSS_CLOSED
Definition: chap.h:136
#define MD5_SIGNATURE_SIZE
Definition: chap.h:79
#define CHAPCS_OPEN
Definition: chap.h:130
#define CHAPSS_RECHALLENGE
Definition: chap.h:140
void ChapAuthWithPeer(int, char *, u_char)
#define CHAPSS_INITIAL
Definition: chap.h:135
#define CHAP_DIGEST_MD5
Definition: chap.h:78
#define CHAP_MICROSOFT
Definition: chap.h:80
#define CHAP_SUCCESS
Definition: chap.h:85
#define CHAPCS_RESPONSE
Definition: chap.h:129
#define CHAPCS_INITIAL
Definition: chap.h:125
#define CHAPCS_CLOSED
Definition: chap.h:126
#define CHAPSS_OPEN
Definition: chap.h:139
#define MAX_CHALLENGE_LENGTH
Definition: chap.h:92
#define CHAPSS_PENDING
Definition: chap.h:137
#define CHAP_FAILURE
Definition: chap.h:86
void ChapMS(chap_state *, char *, int, char *, int)
#define NULL
Definition: types.h:112
UCHAR u_char
Definition: types.h:80
VOID WINAPI MD5Final(MD5_CTX *)
Definition: md5.c:113
VOID WINAPI MD5Init(MD5_CTX *)
Definition: md5.c:45
VOID WINAPI MD5Update(MD5_CTX *, const unsigned char *, unsigned int)
Definition: md5.c:59
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned char
Definition: typeof.h:29
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:66
void auth_peer_success(int, u16_t, char *, int)
void auth_peer_fail(int, u16_t)
void auth_withpeer_fail(int, u16_t)
int get_secret(int, char *, char *, char *, int *, int)
void auth_withpeer_success(int, u16_t)
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static PVOID ptr
Definition: dispmode.c:27
static DATA_BLOB CRYPTPROTECT_PROMPTSTRUCT DATA_BLOB *static LPWSTR DATA_BLOB CRYPTPROTECT_PROMPTSTRUCT DATA_BLOB *static char secret[]
Definition: protectdata.c:33
static unsigned(__cdecl *hash_bstr)(bstr_t s)
u32_t magic(void)
#define TIMEOUT
Definition: ntpclient.c:12
png_const_structrp png_const_inforp int * unit
Definition: png.h:2159
#define CHAPDEBUG(a, b)
Definition: pppdebug.h:68
Definition: msi.c:4013
int max_transmits
Definition: chap.h:111
int chal_interval
Definition: chap.h:109
int timeouttime
Definition: chap.h:110
Definition: inflate.c:139
Definition: vj.h:105
Definition: _hash_fun.h:40
#define LOG_ERR
Definition: syslog.h:48
#define LOG_WARNING
Definition: syslog.h:49
#define LOG_INFO
Definition: syslog.h:51