CPU: Wrong CPU Load %.
[tomato.git] / release / src / router / ppp / pppd / chap.c
blobc26db5c2d3a88c2e11211c746bbf140c0f6efb81
1 /*
2 * chap.c - Challenge Handshake Authentication Protocol.
4 * Copyright (c) 1993 The Australian National University.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by the Australian National University. The name of the University
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 * Copyright (c) 1991 Gregory M. Christy.
20 * All rights reserved.
22 * Redistribution and use in source and binary forms are permitted
23 * provided that the above copyright notice and this paragraph are
24 * duplicated in all such forms and that any documentation,
25 * advertising materials, and other materials related to such
26 * distribution and use acknowledge that the software was developed
27 * by Gregory M. Christy. The name of the author may not be used to
28 * endorse or promote products derived from this software without
29 * specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
32 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
33 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
36 #define RCSID "$Id: chap.c,v 1.5 2004/10/06 10:21:52 honor Exp $"
39 * TODO:
42 #include <stdio.h>
43 #include <string.h>
44 #include <stdlib.h>
45 #include <sys/types.h>
46 #include <sys/time.h>
48 #include <pppd.h>
49 #include "chap.h"
50 #include "md5.h"
51 #ifdef CHAPMS
52 #include "chap_ms.h"
53 #endif
55 static const char rcsid[] = RCSID;
58 * Command-line options.
60 static option_t chap_option_list[] = {
61 { "chap-restart", o_int, &chap[0].timeouttime,
62 "Set timeout for CHAP", OPT_PRIO },
63 { "chap-max-challenge", o_int, &chap[0].max_transmits,
64 "Set max #xmits for challenge", OPT_PRIO },
65 { "chap-interval", o_int, &chap[0].chal_interval,
66 "Set interval for rechallenge", OPT_PRIO },
67 #ifdef MSLANMAN
68 { "ms-lanman", o_bool, &ms_lanman,
69 "Use LanMan passwd when using MS-CHAP", 1 },
70 #endif
71 { NULL }
75 * Protocol entry points.
77 static void ChapInit __P((int));
78 static void ChapLowerUp __P((int));
79 static void ChapLowerDown __P((int));
80 static void ChapInput __P((int, u_char *, int));
81 static void ChapProtocolReject __P((int));
82 static int ChapPrintPkt __P((u_char *, int,
83 void (*) __P((void *, char *, ...)), void *));
85 struct protent chap_protent = {
86 PPP_CHAP,
87 ChapInit,
88 ChapInput,
89 ChapProtocolReject,
90 ChapLowerUp,
91 ChapLowerDown,
92 NULL,
93 NULL,
94 ChapPrintPkt,
95 NULL,
97 "CHAP",
98 NULL,
99 chap_option_list,
100 NULL,
101 NULL,
102 NULL
105 chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
107 static void ChapChallengeTimeout __P((void *));
108 static void ChapResponseTimeout __P((void *));
109 static void ChapReceiveChallenge __P((chap_state *, u_char *, int, int));
110 static void ChapRechallenge __P((void *));
111 static void ChapReceiveResponse __P((chap_state *, u_char *, int, int));
112 static void ChapReceiveSuccess __P((chap_state *, u_char *, int, int));
113 static void ChapReceiveFailure __P((chap_state *, u_char *, int, int));
114 static void ChapSendStatus __P((chap_state *, int));
115 static void ChapSendChallenge __P((chap_state *));
116 static void ChapSendResponse __P((chap_state *));
117 static void ChapGenChallenge __P((chap_state *));
119 extern double drand48 __P((void));
120 extern void srand48 __P((long));
123 * ChapInit - Initialize a CHAP unit.
125 static void
126 ChapInit(unit)
127 int unit;
129 chap_state *cstate = &chap[unit];
131 BZERO(cstate, sizeof(*cstate));
132 cstate->unit = unit;
133 cstate->clientstate = CHAPCS_INITIAL;
134 cstate->serverstate = CHAPSS_INITIAL;
135 cstate->timeouttime = CHAP_DEFTIMEOUT;
136 cstate->max_transmits = CHAP_DEFTRANSMITS;
137 /* random number generator is initialized in magic_init */
142 * ChapAuthWithPeer - Authenticate us with our peer (start client).
145 void
146 ChapAuthWithPeer(unit, our_name, digest)
147 int unit;
148 char *our_name;
149 int digest;
151 chap_state *cstate = &chap[unit];
153 cstate->resp_name = our_name;
154 cstate->resp_type = digest;
156 if (cstate->clientstate == CHAPCS_INITIAL ||
157 cstate->clientstate == CHAPCS_PENDING) {
158 /* lower layer isn't up - wait until later */
159 cstate->clientstate = CHAPCS_PENDING;
160 return;
164 * We get here as a result of LCP coming up.
165 * So even if CHAP was open before, we will
166 * have to re-authenticate ourselves.
168 cstate->clientstate = CHAPCS_LISTEN;
173 * ChapAuthPeer - Authenticate our peer (start server).
175 void
176 ChapAuthPeer(unit, our_name, digest)
177 int unit;
178 char *our_name;
179 int digest;
181 chap_state *cstate = &chap[unit];
183 cstate->chal_name = our_name;
184 cstate->chal_type = digest;
186 if (cstate->serverstate == CHAPSS_INITIAL ||
187 cstate->serverstate == CHAPSS_PENDING) {
188 /* lower layer isn't up - wait until later */
189 cstate->serverstate = CHAPSS_PENDING;
190 return;
193 ChapGenChallenge(cstate);
194 ChapSendChallenge(cstate); /* crank it up dude! */
195 cstate->serverstate = CHAPSS_INITIAL_CHAL;
200 * ChapChallengeTimeout - Timeout expired on sending challenge.
202 static void
203 ChapChallengeTimeout(arg)
204 void *arg;
206 chap_state *cstate = (chap_state *) arg;
208 /* if we aren't sending challenges, don't worry. then again we */
209 /* probably shouldn't be here either */
210 if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
211 cstate->serverstate != CHAPSS_RECHALLENGE)
212 return;
214 if (cstate->chal_transmits >= cstate->max_transmits) {
215 /* give up on peer */
217 LOGX_ERROR("Peer failed to respond to CHAP challenge.");
218 error("Peer failed to respond to CHAP challenge");
220 cstate->serverstate = CHAPSS_BADAUTH;
221 auth_peer_fail(cstate->unit, PPP_CHAP);
222 return;
225 ChapSendChallenge(cstate); /* Re-send challenge */
230 * ChapResponseTimeout - Timeout expired on sending response.
232 static void
233 ChapResponseTimeout(arg)
234 void *arg;
236 chap_state *cstate = (chap_state *) arg;
238 /* if we aren't sending a response, don't worry. */
239 if (cstate->clientstate != CHAPCS_RESPONSE)
240 return;
242 ChapSendResponse(cstate); /* re-send response */
247 * ChapRechallenge - Time to challenge the peer again.
249 static void
250 ChapRechallenge(arg)
251 void *arg;
253 chap_state *cstate = (chap_state *) arg;
255 /* if we aren't sending a response, don't worry. */
256 if (cstate->serverstate != CHAPSS_OPEN)
257 return;
259 ChapGenChallenge(cstate);
260 ChapSendChallenge(cstate);
261 cstate->serverstate = CHAPSS_RECHALLENGE;
266 * ChapLowerUp - The lower layer is up.
268 * Start up if we have pending requests.
270 static void
271 ChapLowerUp(unit)
272 int unit;
274 chap_state *cstate = &chap[unit];
276 if (cstate->clientstate == CHAPCS_INITIAL)
277 cstate->clientstate = CHAPCS_CLOSED;
278 else if (cstate->clientstate == CHAPCS_PENDING)
279 cstate->clientstate = CHAPCS_LISTEN;
281 if (cstate->serverstate == CHAPSS_INITIAL)
282 cstate->serverstate = CHAPSS_CLOSED;
283 else if (cstate->serverstate == CHAPSS_PENDING) {
284 ChapGenChallenge(cstate);
285 ChapSendChallenge(cstate);
286 cstate->serverstate = CHAPSS_INITIAL_CHAL;
292 * ChapLowerDown - The lower layer is down.
294 * Cancel all timeouts.
296 static void
297 ChapLowerDown(unit)
298 int unit;
300 chap_state *cstate = &chap[unit];
302 /* Timeout(s) pending? Cancel if so. */
303 if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
304 cstate->serverstate == CHAPSS_RECHALLENGE)
305 UNTIMEOUT(ChapChallengeTimeout, cstate);
306 else if (cstate->serverstate == CHAPSS_OPEN
307 && cstate->chal_interval != 0)
308 UNTIMEOUT(ChapRechallenge, cstate);
309 if (cstate->clientstate == CHAPCS_RESPONSE)
310 UNTIMEOUT(ChapResponseTimeout, cstate);
312 cstate->clientstate = CHAPCS_INITIAL;
313 cstate->serverstate = CHAPSS_INITIAL;
318 * ChapProtocolReject - Peer doesn't grok CHAP.
320 static void
321 ChapProtocolReject(unit)
322 int unit;
324 chap_state *cstate = &chap[unit];
326 if (cstate->serverstate != CHAPSS_INITIAL &&
327 cstate->serverstate != CHAPSS_CLOSED)
328 auth_peer_fail(unit, PPP_CHAP);
329 if (cstate->clientstate != CHAPCS_INITIAL &&
330 cstate->clientstate != CHAPCS_CLOSED)
331 auth_withpeer_fail(unit, PPP_CHAP);
332 ChapLowerDown(unit); /* shutdown chap */
337 * ChapInput - Input CHAP packet.
339 static void
340 ChapInput(unit, inpacket, packet_len)
341 int unit;
342 u_char *inpacket;
343 int packet_len;
345 chap_state *cstate = &chap[unit];
346 u_char *inp;
347 u_char code, id;
348 int len;
351 * Parse header (code, id and length).
352 * If packet too short, drop it.
354 inp = inpacket;
355 if (packet_len < CHAP_HEADERLEN) {
356 CHAPDEBUG(("ChapInput: rcvd short header."));
357 return;
359 GETCHAR(code, inp);
360 GETCHAR(id, inp);
361 GETSHORT(len, inp);
362 if (len < CHAP_HEADERLEN) {
363 CHAPDEBUG(("ChapInput: rcvd illegal length."));
364 return;
366 if (len > packet_len) {
367 CHAPDEBUG(("ChapInput: rcvd short packet."));
368 return;
370 len -= CHAP_HEADERLEN;
373 * Action depends on code (as in fact it usually does :-).
375 switch (code) {
376 case CHAP_CHALLENGE:
377 ChapReceiveChallenge(cstate, inp, id, len);
378 break;
380 case CHAP_RESPONSE:
381 ChapReceiveResponse(cstate, inp, id, len);
382 break;
384 case CHAP_FAILURE:
385 ChapReceiveFailure(cstate, inp, id, len);
386 break;
388 case CHAP_SUCCESS:
389 ChapReceiveSuccess(cstate, inp, id, len);
390 break;
392 default: /* Need code reject? */
393 warn("Unknown CHAP code (%d) received.", code);
394 break;
400 * ChapReceiveChallenge - Receive Challenge and send Response.
402 static void
403 ChapReceiveChallenge(cstate, inp, id, len)
404 chap_state *cstate;
405 u_char *inp;
406 int id;
407 int len;
409 int rchallenge_len;
410 u_char *rchallenge;
411 int secret_len;
412 char secret[MAXSECRETLEN];
413 char rhostname[256];
414 MD5_CTX mdContext;
415 u_char hash[MD5_SIGNATURE_SIZE];
417 if (cstate->clientstate == CHAPCS_CLOSED ||
418 cstate->clientstate == CHAPCS_PENDING) {
419 CHAPDEBUG(("ChapReceiveChallenge: in state %d", cstate->clientstate));
420 return;
423 if (len < 2) {
424 CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet."));
425 return;
428 GETCHAR(rchallenge_len, inp);
429 len -= sizeof (u_char) + rchallenge_len; /* now name field length */
430 if (len < 0) {
431 CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet."));
432 return;
434 rchallenge = inp;
435 INCPTR(rchallenge_len, inp);
437 if (len >= sizeof(rhostname))
438 len = sizeof(rhostname) - 1;
439 BCOPY(inp, rhostname, len);
440 rhostname[len] = '\000';
442 /* Microsoft doesn't send their name back in the PPP packet */
443 if (explicit_remote || (remote_name[0] != 0 && rhostname[0] == 0)) {
444 strlcpy(rhostname, remote_name, sizeof(rhostname));
445 CHAPDEBUG(("ChapReceiveChallenge: using '%q' as remote name",
446 rhostname));
449 /* get secret for authenticating ourselves with the specified host */
450 if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
451 secret, &secret_len, 0)) {
452 secret_len = 0; /* assume null secret if can't find one */
453 warn("No CHAP secret found for authenticating us to %q", rhostname);
456 /* cancel response send timeout if necessary */
457 if (cstate->clientstate == CHAPCS_RESPONSE)
458 UNTIMEOUT(ChapResponseTimeout, cstate);
460 cstate->resp_id = id;
461 cstate->resp_transmits = 0;
463 /* generate MD based on negotiated type */
464 switch (cstate->resp_type) {
466 case CHAP_DIGEST_MD5:
467 MD5Init(&mdContext);
468 MD5Update(&mdContext, &cstate->resp_id, 1);
469 MD5Update(&mdContext, secret, secret_len);
470 MD5Update(&mdContext, rchallenge, rchallenge_len);
471 MD5Final(hash, &mdContext);
472 BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
473 cstate->resp_length = MD5_SIGNATURE_SIZE;
474 break;
476 #ifdef CHAPMS
477 case CHAP_MICROSOFT:
478 ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
479 break;
480 #endif
482 default:
483 CHAPDEBUG(("unknown digest type %d", cstate->resp_type));
484 return;
487 BZERO(secret, sizeof(secret));
488 ChapSendResponse(cstate);
493 * ChapReceiveResponse - Receive and process response.
495 static void
496 ChapReceiveResponse(cstate, inp, id, len)
497 chap_state *cstate;
498 u_char *inp;
499 int id;
500 int len;
502 u_char *remmd, remmd_len;
503 int secret_len, old_state;
504 int code;
505 char rhostname[256];
506 MD5_CTX mdContext;
507 char secret[MAXSECRETLEN];
508 u_char hash[MD5_SIGNATURE_SIZE];
510 if (cstate->serverstate == CHAPSS_CLOSED ||
511 cstate->serverstate == CHAPSS_PENDING) {
512 CHAPDEBUG(("ChapReceiveResponse: in state %d", cstate->serverstate));
513 return;
516 if (id != cstate->chal_id)
517 return; /* doesn't match ID of last challenge */
519 LOGX_INFO("Received CHAP Response.");
522 * If we have received a duplicate or bogus Response,
523 * we have to send the same answer (Success/Failure)
524 * as we did for the first Response we saw.
526 if (cstate->serverstate == CHAPSS_OPEN) {
527 ChapSendStatus(cstate, CHAP_SUCCESS);
528 return;
530 if (cstate->serverstate == CHAPSS_BADAUTH) {
531 ChapSendStatus(cstate, CHAP_FAILURE);
532 return;
535 if (len < 2) {
536 CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
537 return;
539 GETCHAR(remmd_len, inp); /* get length of MD */
540 remmd = inp; /* get pointer to MD */
541 INCPTR(remmd_len, inp);
543 len -= sizeof (u_char) + remmd_len;
544 if (len < 0) {
545 CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
546 return;
549 UNTIMEOUT(ChapChallengeTimeout, cstate);
551 if (len >= sizeof(rhostname))
552 len = sizeof(rhostname) - 1;
553 BCOPY(inp, rhostname, len);
554 rhostname[len] = '\000';
557 * Get secret for authenticating them with us,
558 * do the hash ourselves, and compare the result.
560 code = CHAP_FAILURE;
561 if (!get_secret(cstate->unit, (explicit_remote? remote_name: rhostname),
562 cstate->chal_name, secret, &secret_len, 1)) {
563 warn("No CHAP secret found for authenticating %q", rhostname);
564 } else {
566 /* generate MD based on negotiated type */
567 switch (cstate->chal_type) {
569 case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
570 if (remmd_len != MD5_SIGNATURE_SIZE)
571 break; /* it's not even the right length */
572 MD5Init(&mdContext);
573 MD5Update(&mdContext, &cstate->chal_id, 1);
574 MD5Update(&mdContext, secret, secret_len);
575 MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
576 MD5Final(hash, &mdContext);
578 /* compare local and remote MDs and send the appropriate status */
579 if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0)
580 code = CHAP_SUCCESS; /* they are the same! */
581 break;
583 default:
584 CHAPDEBUG(("unknown digest type %d", cstate->chal_type));
588 BZERO(secret, sizeof(secret));
589 ChapSendStatus(cstate, code);
591 if (code == CHAP_SUCCESS) {
592 old_state = cstate->serverstate;
593 cstate->serverstate = CHAPSS_OPEN;
594 if (old_state == CHAPSS_INITIAL_CHAL) {
595 auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
597 if (cstate->chal_interval != 0)
598 TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
600 LOGX_INFO("CHAP peer authentication succeeded for %s.", rhostname);
601 notice("CHAP peer authentication succeeded for %q", rhostname);
603 } else {
604 LOGX_WARN("CHAP peer authentication failed for remote host %s.", rhostname);
605 error("CHAP peer authentication failed for remote host %q", rhostname);
606 cstate->serverstate = CHAPSS_BADAUTH;
607 auth_peer_fail(cstate->unit, PPP_CHAP);
612 * ChapReceiveSuccess - Receive Success
614 static void
615 ChapReceiveSuccess(cstate, inp, id, len)
616 chap_state *cstate;
617 u_char *inp;
618 u_char id;
619 int len;
622 if (cstate->clientstate == CHAPCS_OPEN)
623 /* presumably an answer to a duplicate response */
624 return;
626 if (cstate->clientstate != CHAPCS_RESPONSE) {
627 /* don't know what this is */
628 CHAPDEBUG(("ChapReceiveSuccess: in state %d\n", cstate->clientstate));
629 return;
632 LOGX_INFO("CHAP authentication succeeded.");
633 UNTIMEOUT(ChapResponseTimeout, cstate);
636 * Print message.
638 if (len > 0)
639 PRINTMSG(inp, len);
641 cstate->clientstate = CHAPCS_OPEN;
643 auth_withpeer_success(cstate->unit, PPP_CHAP);
648 * ChapReceiveFailure - Receive failure.
650 static void
651 ChapReceiveFailure(cstate, inp, id, len)
652 chap_state *cstate;
653 u_char *inp;
654 u_char id;
655 int len;
657 if (cstate->clientstate != CHAPCS_RESPONSE) {
658 /* don't know what this is */
659 CHAPDEBUG(("ChapReceiveFailure: in state %d\n", cstate->clientstate));
660 return;
663 UNTIMEOUT(ChapResponseTimeout, cstate);
666 * Print message.
668 if (len > 0)
669 PRINTMSG(inp, len);
671 LOGX_ERROR("CHAP authentication failed.");
672 error("CHAP authentication failed");
674 //log_to_file("CHAP_AUTH_FAIL");
675 system("ppp_event -t CHAP_AUTH_FAIL &");
677 auth_withpeer_fail(cstate->unit, PPP_CHAP);
682 * ChapSendChallenge - Send an Authenticate challenge.
684 static void
685 ChapSendChallenge(cstate)
686 chap_state *cstate;
688 u_char *outp;
689 int chal_len, name_len;
690 int outlen;
692 LOGX_INFO("Sending CHAP challenge.");
694 chal_len = cstate->chal_len;
695 name_len = strlen(cstate->chal_name);
696 outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
697 outp = outpacket_buf;
699 MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
701 PUTCHAR(CHAP_CHALLENGE, outp);
702 PUTCHAR(cstate->chal_id, outp);
703 PUTSHORT(outlen, outp);
705 PUTCHAR(chal_len, outp); /* put length of challenge */
706 BCOPY(cstate->challenge, outp, chal_len);
707 INCPTR(chal_len, outp);
709 BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
711 output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
713 TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
714 ++cstate->chal_transmits;
719 * ChapSendStatus - Send a status response (ack or nak).
721 static void
722 ChapSendStatus(cstate, code)
723 chap_state *cstate;
724 int code;
726 u_char *outp;
727 int outlen, msglen;
728 char msg[256];
730 LOGX_INFO("Sending CHAP %s.", (code == CHAP_SUCCESS ? "Success" : "Failure"));
732 if (code == CHAP_SUCCESS)
733 slprintf(msg, sizeof(msg), "Welcome to %s.", hostname);
734 else
735 slprintf(msg, sizeof(msg), "I don't like you. Go 'way.");
736 msglen = strlen(msg);
738 outlen = CHAP_HEADERLEN + msglen;
739 outp = outpacket_buf;
741 MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
743 PUTCHAR(code, outp);
744 PUTCHAR(cstate->chal_id, outp);
745 PUTSHORT(outlen, outp);
746 BCOPY(msg, outp, msglen);
747 output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
751 * ChapGenChallenge is used to generate a pseudo-random challenge string of
752 * a pseudo-random length between min_len and max_len. The challenge
753 * string and its length are stored in *cstate, and various other fields of
754 * *cstate are initialized.
757 static void
758 ChapGenChallenge(cstate)
759 chap_state *cstate;
761 int chal_len;
762 u_char *ptr = cstate->challenge;
763 int i;
765 /* pick a random challenge length between MIN_CHALLENGE_LENGTH and
766 MAX_CHALLENGE_LENGTH */
767 chal_len = (unsigned) ((drand48() *
768 (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
769 MIN_CHALLENGE_LENGTH);
770 cstate->chal_len = chal_len;
771 cstate->chal_id = ++cstate->id;
772 cstate->chal_transmits = 0;
774 /* generate a random string */
775 for (i = 0; i < chal_len; i++)
776 *ptr++ = (char) (drand48() * 0xff);
780 * ChapSendResponse - send a response packet with values as specified
781 * in *cstate.
783 /* ARGSUSED */
784 static void
785 ChapSendResponse(cstate)
786 chap_state *cstate;
788 u_char *outp;
789 int outlen, md_len, name_len;
791 md_len = cstate->resp_length;
792 name_len = strlen(cstate->resp_name);
793 outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
794 outp = outpacket_buf;
796 MAKEHEADER(outp, PPP_CHAP);
798 PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
799 PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */
800 PUTSHORT(outlen, outp); /* packet length */
802 PUTCHAR(md_len, outp); /* length of MD */
803 BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
804 INCPTR(md_len, outp);
806 BCOPY(cstate->resp_name, outp, name_len); /* append our name */
808 /* send the packet */
809 output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
811 cstate->clientstate = CHAPCS_RESPONSE;
812 TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
813 ++cstate->resp_transmits;
817 * ChapPrintPkt - print the contents of a CHAP packet.
819 static char *ChapCodenames[] = {
820 "Challenge", "Response", "Success", "Failure"
823 static int
824 ChapPrintPkt(p, plen, printer, arg)
825 u_char *p;
826 int plen;
827 void (*printer) __P((void *, char *, ...));
828 void *arg;
830 int code, id, len;
831 int clen, nlen;
832 u_char x;
834 if (plen < CHAP_HEADERLEN)
835 return 0;
836 GETCHAR(code, p);
837 GETCHAR(id, p);
838 GETSHORT(len, p);
839 if (len < CHAP_HEADERLEN || len > plen)
840 return 0;
842 if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *))
843 printer(arg, " %s", ChapCodenames[code-1]);
844 else
845 printer(arg, " code=0x%x", code);
846 printer(arg, " id=0x%x", id);
847 len -= CHAP_HEADERLEN;
848 switch (code) {
849 case CHAP_CHALLENGE:
850 case CHAP_RESPONSE:
851 if (len < 1)
852 break;
853 clen = p[0];
854 if (len < clen + 1)
855 break;
856 ++p;
857 nlen = len - clen - 1;
858 printer(arg, " <");
859 for (; clen > 0; --clen) {
860 GETCHAR(x, p);
861 printer(arg, "%.2x", x);
863 printer(arg, ">, name = ");
864 print_string((char *)p, nlen, printer, arg);
865 break;
866 case CHAP_FAILURE:
867 case CHAP_SUCCESS:
868 printer(arg, " ");
869 print_string((char *)p, len, printer, arg);
870 break;
871 default:
872 for (clen = len; clen > 0; --clen) {
873 GETCHAR(x, p);
874 printer(arg, " %.2x", x);
878 return len + CHAP_HEADERLEN;