2 * chap.c - Challenge Handshake Authentication Protocol.
4 * Copyright (c) 1993 The Australian National University.
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.2 2006/05/31 09:34:26 andylin Exp $"
44 #include <sys/types.h>
50 /*wilson add for MS-CHAPv2, 05/26/2005*/
58 static const char rcsid[] = RCSID;
59 extern int authfailcount;
61 * Command-line options.
63 static option_t chap_option_list[] = {
64 { "chap-restart", o_int, &chap[0].timeouttime,
65 "Set timeout for CHAP", OPT_PRIO },
66 { "chap-max-challenge", o_int, &chap[0].max_transmits,
67 "Set max #xmits for challenge", OPT_PRIO },
68 { "chap-interval", o_int, &chap[0].chal_interval,
69 "Set interval for rechallenge", OPT_PRIO },
71 { "ms-lanman", o_bool, &ms_lanman,
72 "Use LanMan passwd when using MS-CHAP", 1 },
74 /*wilson add for MS-CHAPv2, 05/26/2005*/
76 { "chapms-strip-domain", o_bool, &chapms_strip_domain,
77 "Strip the domain prefix before the Username", 1 },
84 * Protocol entry points.
86 static void ChapInit __P((int));
87 static void ChapLowerUp __P((int));
88 static void ChapLowerDown __P((int));
89 static void ChapInput __P((int, u_char *, int));
90 static void ChapProtocolReject __P((int));
91 static int ChapPrintPkt __P((u_char *, int,
92 void (*) __P((void *, char *, ...)), void *));
94 struct protent chap_protent = {
114 chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
116 static void ChapChallengeTimeout __P((void *));
117 static void ChapResponseTimeout __P((void *));
118 static void ChapReceiveChallenge __P((chap_state *, u_char *, int, int));
119 static void ChapRechallenge __P((void *));
120 static void ChapReceiveResponse __P((chap_state *, u_char *, int, int));
121 static void ChapReceiveSuccess __P((chap_state *, u_char *, int, int));
122 static void ChapReceiveFailure __P((chap_state *, u_char *, int, int));
123 static void ChapSendStatus __P((chap_state *, int));
124 static void ChapSendChallenge __P((chap_state *));
125 static void ChapSendResponse __P((chap_state *));
126 /*wilson modify for MS-CHAPv2, 05/26/2005*/
127 //static void ChapGenChallenge __P((chap_state *));
128 void ChapGenChallenge __P((chap_state *));
129 /*wilson modify end*/
131 extern double drand48 __P((void));
132 extern void srand48 __P((long));
135 * ChapInit - Initialize a CHAP unit.
141 chap_state *cstate = &chap[unit];
143 BZERO(cstate, sizeof(*cstate));
145 cstate->clientstate = CHAPCS_INITIAL;
146 cstate->serverstate = CHAPSS_INITIAL;
147 cstate->timeouttime = CHAP_DEFTIMEOUT;
148 cstate->max_transmits = CHAP_DEFTRANSMITS;
149 #if defined(ODM_LANG_LLL)
152 //cstate->retries = CHAP_AUTH_RETRIES;
155 /* random number generator is initialized in magic_init */
160 * ChapAuthWithPeer - Authenticate us with our peer (start client).
164 ChapAuthWithPeer(unit, our_name, digest)
169 chap_state *cstate = &chap[unit];
171 cstate->resp_name = our_name;
172 cstate->resp_type = digest;
174 if (cstate->clientstate == CHAPCS_INITIAL || cstate->clientstate == CHAPCS_PENDING) {
175 /* lower layer isn't up - wait until later */
176 cstate->clientstate = CHAPCS_PENDING;
181 * We get here as a result of LCP coming up.
182 * So even if CHAP was open before, we will
183 * have to re-authenticate ourselves.
185 cstate->clientstate = CHAPCS_LISTEN;
190 * ChapAuthPeer - Authenticate our peer (start server).
193 ChapAuthPeer(unit, our_name, digest)
198 chap_state *cstate = &chap[unit];
200 cstate->chal_name = our_name;
201 cstate->chal_type = digest;
203 if (cstate->serverstate == CHAPSS_INITIAL || cstate->serverstate == CHAPSS_PENDING) {
204 /* lower layer isn't up - wait until later */
205 cstate->serverstate = CHAPSS_PENDING;
209 ChapGenChallenge(cstate);
210 ChapSendChallenge(cstate); /* crank it up dude! */
211 cstate->serverstate = CHAPSS_INITIAL_CHAL;
216 * ChapChallengeTimeout - Timeout expired on sending challenge.
219 ChapChallengeTimeout(arg)
222 chap_state *cstate = (chap_state *) arg;
224 /* if we aren't sending challenges, don't worry. then again we */
225 /* probably shouldn't be here either */
226 if (cstate->serverstate != CHAPSS_INITIAL_CHAL && cstate->serverstate != CHAPSS_RECHALLENGE)
229 if (cstate->chal_transmits >= cstate->max_transmits) {
230 /* give up on peer */
231 error("Peer failed to respond to CHAP challenge");
232 cstate->serverstate = CHAPSS_BADAUTH;
233 auth_peer_fail(cstate->unit, PPP_CHAP);
237 ChapSendChallenge(cstate); /* Re-send challenge */
242 * ChapResponseTimeout - Timeout expired on sending response.
245 ChapResponseTimeout(arg)
248 chap_state *cstate = (chap_state *) arg;
250 /* if we aren't sending a response, don't worry. */
251 if (cstate->clientstate != CHAPCS_RESPONSE)
255 ChapSendResponse(cstate); /* re-send response */
260 * ChapRechallenge - Time to challenge the peer again.
266 chap_state *cstate = (chap_state *) arg;
268 /* if we aren't sending a response, don't worry. */
269 if (cstate->serverstate != CHAPSS_OPEN)
272 ChapGenChallenge(cstate);
273 ChapSendChallenge(cstate);
274 cstate->serverstate = CHAPSS_RECHALLENGE;
279 * ChapLowerUp - The lower layer is up.
281 * Start up if we have pending requests.
287 chap_state *cstate = &chap[unit];
289 if (cstate->clientstate == CHAPCS_INITIAL)
290 cstate->clientstate = CHAPCS_CLOSED;
291 else if (cstate->clientstate == CHAPCS_PENDING)
292 cstate->clientstate = CHAPCS_LISTEN;
294 if (cstate->serverstate == CHAPSS_INITIAL)
295 cstate->serverstate = CHAPSS_CLOSED;
296 else if (cstate->serverstate == CHAPSS_PENDING) {
297 ChapGenChallenge(cstate);
298 ChapSendChallenge(cstate);
299 cstate->serverstate = CHAPSS_INITIAL_CHAL;
305 * ChapLowerDown - The lower layer is down.
307 * Cancel all timeouts.
313 chap_state *cstate = &chap[unit];
315 /* Timeout(s) pending? Cancel if so. */
316 if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
317 cstate->serverstate == CHAPSS_RECHALLENGE)
318 UNTIMEOUT(ChapChallengeTimeout, cstate);
319 else if (cstate->serverstate == CHAPSS_OPEN
320 && cstate->chal_interval != 0)
321 UNTIMEOUT(ChapRechallenge, cstate);
322 if (cstate->clientstate == CHAPCS_RESPONSE)
323 UNTIMEOUT(ChapResponseTimeout, cstate);
325 cstate->clientstate = CHAPCS_INITIAL;
326 cstate->serverstate = CHAPSS_INITIAL;
331 * ChapProtocolReject - Peer doesn't grok CHAP.
334 ChapProtocolReject(unit)
337 chap_state *cstate = &chap[unit];
339 if (cstate->serverstate != CHAPSS_INITIAL && cstate->serverstate != CHAPSS_CLOSED)
340 auth_peer_fail(unit, PPP_CHAP);
342 if (cstate->clientstate != CHAPCS_INITIAL && cstate->clientstate != CHAPCS_CLOSED) {
345 auth_withpeer_fail(unit, PPP_CHAP);
347 ChapLowerDown(unit); /* shutdown chap */
352 * ChapInput - Input CHAP packet.
355 ChapInput(unit, inpacket, packet_len)
360 chap_state *cstate = &chap[unit];
366 * Parse header (code, id and length).
367 * If packet too short, drop it.
370 if (packet_len < CHAP_HEADERLEN) {
371 CHAPDEBUG(("ChapInput: rcvd short header."));
377 if (len < CHAP_HEADERLEN) {
378 CHAPDEBUG(("ChapInput: rcvd illegal length."));
381 if (len > packet_len) {
382 CHAPDEBUG(("ChapInput: rcvd short packet."));
385 len -= CHAP_HEADERLEN;
388 * Action depends on code (as in fact it usually does :-).
392 ChapReceiveChallenge(cstate, inp, id, len);
396 ChapReceiveResponse(cstate, inp, id, len);
400 ChapReceiveFailure(cstate, inp, id, len);
404 ChapReceiveSuccess(cstate, inp, id, len);
407 default: /* Need code reject? */
408 warn("Unknown CHAP code (%d) received.", code);
415 * ChapReceiveChallenge - Receive Challenge and send Response.
418 ChapReceiveChallenge(cstate, inp, id, len)
427 char secret[MAXSECRETLEN];
430 u_char hash[MD5_SIGNATURE_SIZE];
432 if (cstate->clientstate == CHAPCS_CLOSED || cstate->clientstate == CHAPCS_PENDING) {
433 CHAPDEBUG(("ChapReceiveChallenge: in state %d", cstate->clientstate));
438 CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet."));
442 GETCHAR(rchallenge_len, inp);
443 len -= sizeof (u_char) + rchallenge_len; /* now name field length */
445 CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet."));
449 INCPTR(rchallenge_len, inp);
451 if (len >= sizeof(rhostname))
452 len = sizeof(rhostname) - 1;
453 BCOPY(inp, rhostname, len);
454 rhostname[len] = '\000';
456 /* Microsoft doesn't send their name back in the PPP packet */
457 if (explicit_remote || (remote_name[0] != 0 && rhostname[0] == 0)) {
458 strlcpy(rhostname, remote_name, sizeof(rhostname));
459 CHAPDEBUG(("ChapReceiveChallenge: using '%q' as remote name", rhostname));
462 /* get secret for authenticating ourselves with the specified host */
463 if (!get_secret(cstate->unit, cstate->resp_name, rhostname, secret, &secret_len, 0)) {
464 secret_len = 0; /* assume null secret if can't find one */
465 warn("No CHAP secret found for authenticating us to %q", rhostname);
468 /* cancel response send timeout if necessary */
469 if (cstate->clientstate == CHAPCS_RESPONSE)
470 UNTIMEOUT(ChapResponseTimeout, cstate);
472 cstate->resp_id = id;
473 cstate->resp_transmits = 0;
475 /* generate MD based on negotiated type */
476 switch (cstate->resp_type) {
478 case CHAP_DIGEST_MD5:
480 MD5Update(&mdContext, &cstate->resp_id, 1);
481 MD5Update(&mdContext, secret, secret_len);
482 MD5Update(&mdContext, rchallenge, rchallenge_len);
483 MD5Final(hash, &mdContext);
484 BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
485 cstate->resp_length = MD5_SIGNATURE_SIZE;
489 /*wilson modify for MS-CHAPv2, 05/26/2005*/
491 CHAPDEBUG(("ChapReceiveChallenge: rcvd type MS-CHAP-V1."));
492 if(rchallenge_len != 8)
494 CHAPDEBUG(("Invalid challenge length for MS-CHAP-V1"));
497 ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
500 case CHAP_MICROSOFT_V2:
501 CHAPDEBUG(("ChapReceiveChallenge: rcvd type MS-CHAP-V2."));
502 if(rchallenge_len != 16)
504 CHAPDEBUG(("Invalid challenge length for MS-CHAP-V2"));
507 ChapMS_v2(cstate, rchallenge, rchallenge_len, secret, secret_len);
509 /*wilson modify end*/
513 CHAPDEBUG(("unknown digest type %d", cstate->resp_type));
517 #if defined(ODM_LANG_LLL)
518 if ((strlen(rhostname))>0){
520 sprintf(cmd, "echo %s > /var/pppoebasname", rhostname);
525 BZERO(secret, sizeof(secret));
526 ChapSendResponse(cstate);
531 * ChapReceiveResponse - Receive and process response.
534 ChapReceiveResponse(cstate, inp, id, len)
540 u_char *remmd, remmd_len;
541 int secret_len, old_state;
545 char secret[MAXSECRETLEN];
546 u_char hash[MD5_SIGNATURE_SIZE];
548 if (cstate->serverstate == CHAPSS_CLOSED || cstate->serverstate == CHAPSS_PENDING) {
549 CHAPDEBUG(("ChapReceiveResponse: in state %d", cstate->serverstate));
553 if (id != cstate->chal_id)
554 return; /* doesn't match ID of last challenge */
557 * If we have received a duplicate or bogus Response,
558 * we have to send the same answer (Success/Failure)
559 * as we did for the first Response we saw.
561 if (cstate->serverstate == CHAPSS_OPEN) {
562 /*wilson modify for MS-CHAPv2, 05/26/2005*/
563 //ChapSendStatus(cstate, CHAP_SUCCESS);
564 ChapSendStatus(cstate, cstate->chal_type == CHAP_MICROSOFT_V2 ? CHAP_SUCCESS_R : CHAP_SUCCESS);
565 /*wilson modify end*/
568 if (cstate->serverstate == CHAPSS_BADAUTH) {
569 ChapSendStatus(cstate, CHAP_FAILURE);
574 CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
577 GETCHAR(remmd_len, inp); /* get length of MD */
578 remmd = inp; /* get pointer to MD */
579 INCPTR(remmd_len, inp);
581 len -= sizeof (u_char) + remmd_len;
583 CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
587 UNTIMEOUT(ChapChallengeTimeout, cstate);
589 if (len >= sizeof(rhostname))
590 len = sizeof(rhostname) - 1;
591 BCOPY(inp, rhostname, len);
592 rhostname[len] = '\000';
594 /*wilson add for MS-CHAPv2, 05/26/2005*/
595 if (chapms_strip_domain) {
597 if ((q = strrchr(rhostname, '\\'))) {
599 for (p = rhostname; *q; *p++ = *q++) ;
606 * Get secret for authenticating them with us,
607 * do the hash ourselves, and compare the result.
610 if (!get_secret(cstate->unit, (explicit_remote? remote_name: rhostname), cstate->chal_name, secret, &secret_len, 1)) {
611 warn("No CHAP secret found for authenticating %q", rhostname);
614 /* generate MD based on negotiated type */
615 switch (cstate->chal_type) {
617 case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
618 if (remmd_len != MD5_SIGNATURE_SIZE)
619 break; /* it's not even the right length */
621 MD5Update(&mdContext, &cstate->chal_id, 1);
622 MD5Update(&mdContext, secret, secret_len);
623 MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
624 MD5Final(hash, &mdContext);
626 /* compare local and remote MDs and send the appropriate status */
627 if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0)
628 code = CHAP_SUCCESS; /* they are the same! */
631 /*wilson add for MS-CHAPv2, 05/26/2005*/
634 CHAPDEBUG(("ChapReceiveResponse: rcvd type MS-CHAP-V1"));
635 if(remmd_len != MS_CHAP_RESPONSE_LEN)
637 if(ChapMS_Resp(cstate, secret, secret_len, remmd) == 0)
641 case CHAP_MICROSOFT_V2:
642 CHAPDEBUG(("ChapReceiveResponse: rcvd type MS-CHAP-V2"));
643 if(remmd_len != MS_CHAP_RESPONSE_LEN)
645 if(ChapMS_v2_Resp(cstate,secret,secret_len,remmd,rhostname) == 0)
647 code = CHAP_SUCCESS_R;
648 ChapMS_v2_Auth(cstate, secret, secret_len, remmd, rhostname);
654 CHAPDEBUG(("unknown digest type %d", cstate->chal_type));
658 BZERO(secret, sizeof(secret));
659 ChapSendStatus(cstate, code);
661 if ((code == CHAP_SUCCESS) || (code == CHAP_SUCCESS_R)) { /*wilson modify for MS-CHAPv2, 05/26/2005*/
662 old_state = cstate->serverstate;
663 cstate->serverstate = CHAPSS_OPEN;
664 if (old_state == CHAPSS_INITIAL_CHAL) {
665 auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
667 if (cstate->chal_interval != 0)
668 TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
669 /*wilson modify for MS-CHAPv2, 05/26/2005*/
670 //notice("CHAP peer authentication succeeded for %q", rhostname);
671 switch (cstate->chal_type) {
672 case CHAP_DIGEST_MD5:
673 notice("CHAP peer authentication succeeded for %q", rhostname);
677 notice("MSCHAP peer authentication succeeded for %q", rhostname);
679 case CHAP_MICROSOFT_V2:
680 notice("MSCHAP-v2 peer authentication succeeded for %q", rhostname);
684 notice("CHAP (unknown) peer authentication succeeded for %q",
688 /*wilson modify end*/
690 /*wilson modify for MS-CHAPv2, 05/26/2005*/
691 switch (cstate->chal_type) {
692 case CHAP_DIGEST_MD5:
693 error("CHAP peer authentication failed for remote host %q",
698 error("MSCHAP peer authentication failed for remote host %q",
701 case CHAP_MICROSOFT_V2:
702 error("MSCHAP-v2 peer authentication failed for remote host %q",
707 error("CHAP (unknown) peer authentication failed for remote host %q", rhostname);
710 //error("CHAP peer authentication failed for remote host %q", rhostname);
711 /*wilson modify end*/
712 cstate->serverstate = CHAPSS_BADAUTH;
713 auth_peer_fail(cstate->unit, PPP_CHAP);
718 * ChapReceiveSuccess - Receive Success
721 ChapReceiveSuccess(cstate, inp, id, len)
728 if (cstate->clientstate == CHAPCS_OPEN)
729 /* presumably an answer to a duplicate response */
732 if (cstate->clientstate != CHAPCS_RESPONSE) {
733 /* don't know what this is */
734 CHAPDEBUG(("ChapReceiveSuccess: in state %d\n", cstate->clientstate));
738 UNTIMEOUT(ChapResponseTimeout, cstate);
746 cstate->clientstate = CHAPCS_OPEN;
747 #if defined(ODM_LANG_LLL)
751 //cstate->retries = CHAP_AUTH_RETRIES;
755 auth_withpeer_success(cstate->unit, PPP_CHAP);
760 * ChapReceiveFailure - Receive failure.
763 ChapReceiveFailure(cstate, inp, id, len)
769 if (cstate->clientstate != CHAPCS_RESPONSE) {
770 /* don't know what this is */
771 CHAPDEBUG(("ChapReceiveFailure: in state %d\n", cstate->clientstate));
775 UNTIMEOUT(ChapResponseTimeout, cstate);
784 error("CHAP authentication failed");
788 auth_withpeer_fail(cstate->unit, PPP_CHAP);
793 * ChapSendChallenge - Send an Authenticate challenge.
796 ChapSendChallenge(cstate)
800 int chal_len, name_len;
803 chal_len = cstate->chal_len;
804 name_len = strlen(cstate->chal_name);
805 outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
806 outp = outpacket_buf;
808 MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
810 PUTCHAR(CHAP_CHALLENGE, outp);
811 PUTCHAR(cstate->chal_id, outp);
812 PUTSHORT(outlen, outp);
814 PUTCHAR(chal_len, outp); /* put length of challenge */
815 BCOPY(cstate->challenge, outp, chal_len);
816 INCPTR(chal_len, outp);
818 BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
820 output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
822 TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
823 ++cstate->chal_transmits;
828 * ChapSendStatus - Send a status response (ack or nak).
831 ChapSendStatus(cstate, code)
839 /*wilson modify for MS-CHAPv2, 05/26/2005*/
840 if (code == CHAP_SUCCESS)
841 slprintf(msg, sizeof(msg), "Welcome to %s.", hostname);
842 else if(code == CHAP_SUCCESS_R)
843 strcpy(msg, cstate->response);
845 slprintf(msg, sizeof(msg), "I don't like you. Go 'way.");
846 /*wilson modify end*/
847 msglen = strlen(msg);
849 outlen = CHAP_HEADERLEN + msglen;
850 outp = outpacket_buf;
852 MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
854 /*wilson modify for MS-CHAPv2, 05/26/2005*/
855 PUTCHAR(code == CHAP_SUCCESS_R ? CHAP_SUCCESS : code, outp);
856 //PUTCHAR(code, outp);
857 /*wilson modify end*/
858 PUTCHAR(cstate->chal_id, outp);
859 PUTSHORT(outlen, outp);
860 BCOPY(msg, outp, msglen);
861 output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
865 * ChapGenChallenge is used to generate a pseudo-random challenge string of
866 * a pseudo-random length between min_len and max_len. The challenge
867 * string and its length are stored in *cstate, and various other fields of
868 * *cstate are initialized.
871 //static void /*wilson modify for MS-CHAPv2, 05/26/2005*/
873 ChapGenChallenge(cstate)
877 u_char *ptr = cstate->challenge;
880 /*wilson modify for MS-CHAPv2, 05/26/2005*/
882 if(cstate->chal_type == CHAP_MICROSOFT)
884 else if(cstate->chal_type == CHAP_MICROSOFT_V2)
888 /*wilson modify end*/
889 /* pick a random challenge length between MIN_CHALLENGE_LENGTH and
890 MAX_CHALLENGE_LENGTH */
891 chal_len = (unsigned) ((drand48() *
892 (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
893 MIN_CHALLENGE_LENGTH);
894 cstate->chal_len = chal_len;
895 cstate->chal_id = ++cstate->id;
896 cstate->chal_transmits = 0;
898 /* generate a random string */
899 for (i = 0; i < chal_len; i++)
900 *ptr++ = (char) (drand48() * 0xff);
904 * ChapSendResponse - send a response packet with values as specified
909 ChapSendResponse(cstate)
913 int outlen, md_len, name_len;
915 md_len = cstate->resp_length;
916 name_len = strlen(cstate->resp_name);
917 outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
918 outp = outpacket_buf;
920 MAKEHEADER(outp, PPP_CHAP);
922 PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
923 PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */
924 PUTSHORT(outlen, outp); /* packet length */
926 PUTCHAR(md_len, outp); /* length of MD */
927 BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
928 INCPTR(md_len, outp);
930 BCOPY(cstate->resp_name, outp, name_len); /* append our name */
932 /* send the packet */
933 output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
935 cstate->clientstate = CHAPCS_RESPONSE;
936 TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
937 ++cstate->resp_transmits;
941 * ChapPrintPkt - print the contents of a CHAP packet.
943 static char *ChapCodenames[] = {
944 "Challenge", "Response", "Success", "Failure"
948 ChapPrintPkt(p, plen, printer, arg)
951 void (*printer) __P((void *, char *, ...));
958 if (plen < CHAP_HEADERLEN)
963 if (len < CHAP_HEADERLEN || len > plen)
966 if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *))
967 printer(arg, " %s", ChapCodenames[code-1]);
969 printer(arg, " code=0x%x", code);
970 printer(arg, " id=0x%x", id);
971 len -= CHAP_HEADERLEN;
981 nlen = len - clen - 1;
983 for (; clen > 0; --clen) {
985 printer(arg, "%.2x", x);
987 printer(arg, ">, name = ");
988 print_string((char *)p, nlen, printer, arg);
993 print_string((char *)p, len, printer, arg);
996 for (clen = len; clen > 0; --clen) {
998 printer(arg, " %.2x", x);
1002 return len + CHAP_HEADERLEN;
1005 /*wilson add for MS-CHAPv2, 05/26/2005*/
1010 lcp_wantoptions[0].neg_chap = 1;
1011 lcp_wantoptions[0].use_digest = 1;