00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #include "lwip/opt.h"
00070
00071 #if PPP_SUPPORT
00072
00073 #if CHAP_SUPPORT
00074
00075 #include "ppp_impl.h"
00076 #include "pppdebug.h"
00077
00078 #include "magic.h"
00079 #include "randm.h"
00080 #include "auth.h"
00081 #include "md5.h"
00082 #include "chap.h"
00083 #include "chpms.h"
00084
00085 #include <string.h>
00086
00087 #if 0
00088
00089
00090
00091 static option_t chap_option_list[] = {
00092 { "chap-restart", o_int, &chap[0].timeouttime,
00093 "Set timeout for CHAP" },
00094 { "chap-max-challenge", o_int, &chap[0].max_transmits,
00095 "Set max #xmits for challenge" },
00096 { "chap-interval", o_int, &chap[0].chal_interval,
00097 "Set interval for rechallenge" },
00098 #ifdef MSLANMAN
00099 { "ms-lanman", o_bool, &ms_lanman,
00100 "Use LanMan passwd when using MS-CHAP", 1 },
00101 #endif
00102 { NULL }
00103 };
00104 #endif
00105
00106
00107
00108
00109 static void ChapInit (int);
00110 static void ChapLowerUp (int);
00111 static void ChapLowerDown (int);
00112 static void ChapInput (int, u_char *, int);
00113 static void ChapProtocolReject (int);
00114 #if PPP_ADDITIONAL_CALLBACKS
00115 static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *);
00116 #endif
00117
00118 struct protent chap_protent = {
00119 PPP_CHAP,
00120 ChapInit,
00121 ChapInput,
00122 ChapProtocolReject,
00123 ChapLowerUp,
00124 ChapLowerDown,
00125 NULL,
00126 NULL,
00127 #if PPP_ADDITIONAL_CALLBACKS
00128 ChapPrintPkt,
00129 NULL,
00130 #endif
00131 1,
00132 "CHAP",
00133 #if PPP_ADDITIONAL_CALLBACKS
00134 NULL,
00135 NULL,
00136 NULL
00137 #endif
00138 };
00139
00140 chap_state chap[NUM_PPP];
00141
00142 static void ChapChallengeTimeout (void *);
00143 static void ChapResponseTimeout (void *);
00144 static void ChapReceiveChallenge (chap_state *, u_char *, u_char, int);
00145 static void ChapRechallenge (void *);
00146 static void ChapReceiveResponse (chap_state *, u_char *, int, int);
00147 static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len);
00148 static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len);
00149 static void ChapSendStatus (chap_state *, int);
00150 static void ChapSendChallenge (chap_state *);
00151 static void ChapSendResponse (chap_state *);
00152 static void ChapGenChallenge (chap_state *);
00153
00154
00155
00156
00157 static void
00158 ChapInit(int unit)
00159 {
00160 chap_state *cstate = &chap[unit];
00161
00162 BZERO(cstate, sizeof(*cstate));
00163 cstate->unit = unit;
00164 cstate->clientstate = CHAPCS_INITIAL;
00165 cstate->serverstate = CHAPSS_INITIAL;
00166 cstate->timeouttime = CHAP_DEFTIMEOUT;
00167 cstate->max_transmits = CHAP_DEFTRANSMITS;
00168
00169 }
00170
00171
00172
00173
00174
00175
00176 void
00177 ChapAuthWithPeer(int unit, char *our_name, u_char digest)
00178 {
00179 chap_state *cstate = &chap[unit];
00180
00181 cstate->resp_name = our_name;
00182 cstate->resp_type = digest;
00183
00184 if (cstate->clientstate == CHAPCS_INITIAL ||
00185 cstate->clientstate == CHAPCS_PENDING) {
00186
00187 cstate->clientstate = CHAPCS_PENDING;
00188 return;
00189 }
00190
00191
00192
00193
00194
00195
00196 cstate->clientstate = CHAPCS_LISTEN;
00197 }
00198
00199
00200
00201
00202
00203 void
00204 ChapAuthPeer(int unit, char *our_name, u_char digest)
00205 {
00206 chap_state *cstate = &chap[unit];
00207
00208 cstate->chal_name = our_name;
00209 cstate->chal_type = digest;
00210
00211 if (cstate->serverstate == CHAPSS_INITIAL ||
00212 cstate->serverstate == CHAPSS_PENDING) {
00213
00214 cstate->serverstate = CHAPSS_PENDING;
00215 return;
00216 }
00217
00218 ChapGenChallenge(cstate);
00219 ChapSendChallenge(cstate);
00220 cstate->serverstate = CHAPSS_INITIAL_CHAL;
00221 }
00222
00223
00224
00225
00226
00227 static void
00228 ChapChallengeTimeout(void *arg)
00229 {
00230 chap_state *cstate = (chap_state *) arg;
00231
00232
00233
00234 if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
00235 cstate->serverstate != CHAPSS_RECHALLENGE) {
00236 return;
00237 }
00238
00239 if (cstate->chal_transmits >= cstate->max_transmits) {
00240
00241 CHAPDEBUG(LOG_ERR, ("Peer failed to respond to CHAP challenge\n"));
00242 cstate->serverstate = CHAPSS_BADAUTH;
00243 auth_peer_fail(cstate->unit, PPP_CHAP);
00244 return;
00245 }
00246
00247 ChapSendChallenge(cstate);
00248 }
00249
00250
00251
00252
00253
00254 static void
00255 ChapResponseTimeout(void *arg)
00256 {
00257 chap_state *cstate = (chap_state *) arg;
00258
00259
00260 if (cstate->clientstate != CHAPCS_RESPONSE) {
00261 return;
00262 }
00263
00264 ChapSendResponse(cstate);
00265 }
00266
00267
00268
00269
00270
00271 static void
00272 ChapRechallenge(void *arg)
00273 {
00274 chap_state *cstate = (chap_state *) arg;
00275
00276
00277 if (cstate->serverstate != CHAPSS_OPEN) {
00278 return;
00279 }
00280
00281 ChapGenChallenge(cstate);
00282 ChapSendChallenge(cstate);
00283 cstate->serverstate = CHAPSS_RECHALLENGE;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292 static void
00293 ChapLowerUp(int unit)
00294 {
00295 chap_state *cstate = &chap[unit];
00296
00297 if (cstate->clientstate == CHAPCS_INITIAL) {
00298 cstate->clientstate = CHAPCS_CLOSED;
00299 } else if (cstate->clientstate == CHAPCS_PENDING) {
00300 cstate->clientstate = CHAPCS_LISTEN;
00301 }
00302
00303 if (cstate->serverstate == CHAPSS_INITIAL) {
00304 cstate->serverstate = CHAPSS_CLOSED;
00305 } else if (cstate->serverstate == CHAPSS_PENDING) {
00306 ChapGenChallenge(cstate);
00307 ChapSendChallenge(cstate);
00308 cstate->serverstate = CHAPSS_INITIAL_CHAL;
00309 }
00310 }
00311
00312
00313
00314
00315
00316
00317
00318 static void
00319 ChapLowerDown(int unit)
00320 {
00321 chap_state *cstate = &chap[unit];
00322
00323
00324 if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
00325 cstate->serverstate == CHAPSS_RECHALLENGE) {
00326 UNTIMEOUT(ChapChallengeTimeout, cstate);
00327 } else if (cstate->serverstate == CHAPSS_OPEN
00328 && cstate->chal_interval != 0) {
00329 UNTIMEOUT(ChapRechallenge, cstate);
00330 }
00331 if (cstate->clientstate == CHAPCS_RESPONSE) {
00332 UNTIMEOUT(ChapResponseTimeout, cstate);
00333 }
00334 cstate->clientstate = CHAPCS_INITIAL;
00335 cstate->serverstate = CHAPSS_INITIAL;
00336 }
00337
00338
00339
00340
00341
00342 static void
00343 ChapProtocolReject(int unit)
00344 {
00345 chap_state *cstate = &chap[unit];
00346
00347 if (cstate->serverstate != CHAPSS_INITIAL &&
00348 cstate->serverstate != CHAPSS_CLOSED) {
00349 auth_peer_fail(unit, PPP_CHAP);
00350 }
00351 if (cstate->clientstate != CHAPCS_INITIAL &&
00352 cstate->clientstate != CHAPCS_CLOSED) {
00353 auth_withpeer_fail(unit, PPP_CHAP);
00354 }
00355 ChapLowerDown(unit);
00356 }
00357
00358
00359
00360
00361
00362 static void
00363 ChapInput(int unit, u_char *inpacket, int packet_len)
00364 {
00365 chap_state *cstate = &chap[unit];
00366 u_char *inp;
00367 u_char code, id;
00368 int len;
00369
00370
00371
00372
00373
00374 inp = inpacket;
00375 if (packet_len < CHAP_HEADERLEN) {
00376 CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short header.\n"));
00377 return;
00378 }
00379 GETCHAR(code, inp);
00380 GETCHAR(id, inp);
00381 GETSHORT(len, inp);
00382 if (len < CHAP_HEADERLEN) {
00383 CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd illegal length.\n"));
00384 return;
00385 }
00386 if (len > packet_len) {
00387 CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short packet.\n"));
00388 return;
00389 }
00390 len -= CHAP_HEADERLEN;
00391
00392
00393
00394
00395 switch (code) {
00396 case CHAP_CHALLENGE:
00397 ChapReceiveChallenge(cstate, inp, id, len);
00398 break;
00399
00400 case CHAP_RESPONSE:
00401 ChapReceiveResponse(cstate, inp, id, len);
00402 break;
00403
00404 case CHAP_FAILURE:
00405 ChapReceiveFailure(cstate, inp, id, len);
00406 break;
00407
00408 case CHAP_SUCCESS:
00409 ChapReceiveSuccess(cstate, inp, id, len);
00410 break;
00411
00412 default:
00413 CHAPDEBUG(LOG_WARNING, ("Unknown CHAP code (%d) received.\n", code));
00414 break;
00415 }
00416 }
00417
00418
00419
00420
00421
00422 static void
00423 ChapReceiveChallenge(chap_state *cstate, u_char *inp, u_char id, int len)
00424 {
00425 int rchallenge_len;
00426 u_char *rchallenge;
00427 int secret_len;
00428 char secret[MAXSECRETLEN];
00429 char rhostname[256];
00430 MD5_CTX mdContext;
00431 u_char hash[MD5_SIGNATURE_SIZE];
00432
00433 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: Rcvd id %d.\n", id));
00434 if (cstate->clientstate == CHAPCS_CLOSED ||
00435 cstate->clientstate == CHAPCS_PENDING) {
00436 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: in state %d\n",
00437 cstate->clientstate));
00438 return;
00439 }
00440
00441 if (len < 2) {
00442 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
00443 return;
00444 }
00445
00446 GETCHAR(rchallenge_len, inp);
00447 len -= sizeof (u_char) + rchallenge_len;
00448 if (len < 0) {
00449 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
00450 return;
00451 }
00452 rchallenge = inp;
00453 INCPTR(rchallenge_len, inp);
00454
00455 if (len >= (int)sizeof(rhostname)) {
00456 len = sizeof(rhostname) - 1;
00457 }
00458 BCOPY(inp, rhostname, len);
00459 rhostname[len] = '\000';
00460
00461 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: received name field '%s'\n",
00462 rhostname));
00463
00464
00465 if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) {
00466 strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname));
00467 rhostname[sizeof(rhostname) - 1] = 0;
00468 CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: using '%s' as remote name\n",
00469 rhostname));
00470 }
00471
00472
00473 if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
00474 secret, &secret_len, 0)) {
00475 secret_len = 0;
00476 CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating us to %s\n",
00477 rhostname));
00478 }
00479
00480
00481 if (cstate->clientstate == CHAPCS_RESPONSE) {
00482 UNTIMEOUT(ChapResponseTimeout, cstate);
00483 }
00484
00485 cstate->resp_id = id;
00486 cstate->resp_transmits = 0;
00487
00488
00489 switch (cstate->resp_type) {
00490
00491 case CHAP_DIGEST_MD5:
00492 MD5Init(&mdContext);
00493 MD5Update(&mdContext, &cstate->resp_id, 1);
00494 MD5Update(&mdContext, (u_char*)secret, secret_len);
00495 MD5Update(&mdContext, rchallenge, rchallenge_len);
00496 MD5Final(hash, &mdContext);
00497 BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
00498 cstate->resp_length = MD5_SIGNATURE_SIZE;
00499 break;
00500
00501 #if MSCHAP_SUPPORT
00502 case CHAP_MICROSOFT:
00503 ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
00504 break;
00505 #endif
00506
00507 default:
00508 CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->resp_type));
00509 return;
00510 }
00511
00512 BZERO(secret, sizeof(secret));
00513 ChapSendResponse(cstate);
00514 }
00515
00516
00517
00518
00519
00520 static void
00521 ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
00522 {
00523 u_char *remmd, remmd_len;
00524 int secret_len, old_state;
00525 int code;
00526 char rhostname[256];
00527 MD5_CTX mdContext;
00528 char secret[MAXSECRETLEN];
00529 u_char hash[MD5_SIGNATURE_SIZE];
00530
00531 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: Rcvd id %d.\n", id));
00532
00533 if (cstate->serverstate == CHAPSS_CLOSED ||
00534 cstate->serverstate == CHAPSS_PENDING) {
00535 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: in state %d\n",
00536 cstate->serverstate));
00537 return;
00538 }
00539
00540 if (id != cstate->chal_id) {
00541 return;
00542 }
00543
00544
00545
00546
00547
00548
00549 if (cstate->serverstate == CHAPSS_OPEN) {
00550 ChapSendStatus(cstate, CHAP_SUCCESS);
00551 return;
00552 }
00553 if (cstate->serverstate == CHAPSS_BADAUTH) {
00554 ChapSendStatus(cstate, CHAP_FAILURE);
00555 return;
00556 }
00557
00558 if (len < 2) {
00559 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
00560 return;
00561 }
00562 GETCHAR(remmd_len, inp);
00563 remmd = inp;
00564 INCPTR(remmd_len, inp);
00565
00566 len -= sizeof (u_char) + remmd_len;
00567 if (len < 0) {
00568 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
00569 return;
00570 }
00571
00572 UNTIMEOUT(ChapChallengeTimeout, cstate);
00573
00574 if (len >= (int)sizeof(rhostname)) {
00575 len = sizeof(rhostname) - 1;
00576 }
00577 BCOPY(inp, rhostname, len);
00578 rhostname[len] = '\000';
00579
00580 CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: received name field: %s\n",
00581 rhostname));
00582
00583
00584
00585
00586
00587 code = CHAP_FAILURE;
00588 if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
00589 secret, &secret_len, 1)) {
00590 CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating %s\n",
00591 rhostname));
00592 } else {
00593
00594 switch (cstate->chal_type) {
00595
00596 case CHAP_DIGEST_MD5:
00597 if (remmd_len != MD5_SIGNATURE_SIZE) {
00598 break;
00599 }
00600 MD5Init(&mdContext);
00601 MD5Update(&mdContext, &cstate->chal_id, 1);
00602 MD5Update(&mdContext, (u_char*)secret, secret_len);
00603 MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
00604 MD5Final(hash, &mdContext);
00605
00606
00607 if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0) {
00608 code = CHAP_SUCCESS;
00609 }
00610 break;
00611
00612 default:
00613 CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->chal_type));
00614 }
00615 }
00616
00617 BZERO(secret, sizeof(secret));
00618 ChapSendStatus(cstate, code);
00619
00620 if (code == CHAP_SUCCESS) {
00621 old_state = cstate->serverstate;
00622 cstate->serverstate = CHAPSS_OPEN;
00623 if (old_state == CHAPSS_INITIAL_CHAL) {
00624 auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
00625 }
00626 if (cstate->chal_interval != 0) {
00627 TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
00628 }
00629 } else {
00630 CHAPDEBUG(LOG_ERR, ("CHAP peer authentication failed\n"));
00631 cstate->serverstate = CHAPSS_BADAUTH;
00632 auth_peer_fail(cstate->unit, PPP_CHAP);
00633 }
00634 }
00635
00636
00637
00638
00639 static void
00640 ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len)
00641 {
00642 LWIP_UNUSED_ARG(id);
00643 LWIP_UNUSED_ARG(inp);
00644
00645 CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: Rcvd id %d.\n", id));
00646
00647 if (cstate->clientstate == CHAPCS_OPEN) {
00648
00649 return;
00650 }
00651
00652 if (cstate->clientstate != CHAPCS_RESPONSE) {
00653
00654 CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: in state %d\n",
00655 cstate->clientstate));
00656 return;
00657 }
00658
00659 UNTIMEOUT(ChapResponseTimeout, cstate);
00660
00661
00662
00663
00664 if (len > 0) {
00665 PRINTMSG(inp, len);
00666 }
00667
00668 cstate->clientstate = CHAPCS_OPEN;
00669
00670 auth_withpeer_success(cstate->unit, PPP_CHAP);
00671 }
00672
00673
00674
00675
00676
00677 static void
00678 ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len)
00679 {
00680 LWIP_UNUSED_ARG(id);
00681 LWIP_UNUSED_ARG(inp);
00682
00683 CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: Rcvd id %d.\n", id));
00684
00685 if (cstate->clientstate != CHAPCS_RESPONSE) {
00686
00687 CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: in state %d\n",
00688 cstate->clientstate));
00689 return;
00690 }
00691
00692 UNTIMEOUT(ChapResponseTimeout, cstate);
00693
00694
00695
00696
00697 if (len > 0) {
00698 PRINTMSG(inp, len);
00699 }
00700
00701 CHAPDEBUG(LOG_ERR, ("CHAP authentication failed\n"));
00702 auth_withpeer_fail(cstate->unit, PPP_CHAP);
00703 }
00704
00705
00706
00707
00708
00709 static void
00710 ChapSendChallenge(chap_state *cstate)
00711 {
00712 u_char *outp;
00713 int chal_len, name_len;
00714 int outlen;
00715
00716 chal_len = cstate->chal_len;
00717 name_len = (int)strlen(cstate->chal_name);
00718 outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
00719 outp = outpacket_buf[cstate->unit];
00720
00721 MAKEHEADER(outp, PPP_CHAP);
00722
00723 PUTCHAR(CHAP_CHALLENGE, outp);
00724 PUTCHAR(cstate->chal_id, outp);
00725 PUTSHORT(outlen, outp);
00726
00727 PUTCHAR(chal_len, outp);
00728 BCOPY(cstate->challenge, outp, chal_len);
00729 INCPTR(chal_len, outp);
00730
00731 BCOPY(cstate->chal_name, outp, name_len);
00732
00733 pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
00734
00735 CHAPDEBUG(LOG_INFO, ("ChapSendChallenge: Sent id %d.\n", cstate->chal_id));
00736
00737 TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
00738 ++cstate->chal_transmits;
00739 }
00740
00741
00742
00743
00744
00745 static void
00746 ChapSendStatus(chap_state *cstate, int code)
00747 {
00748 u_char *outp;
00749 int outlen, msglen;
00750 char msg[256];
00751
00752 if (code == CHAP_SUCCESS) {
00753 strcpy(msg, "Welcome!");
00754 } else {
00755 strcpy(msg, "I don't like you. Go 'way.");
00756 }
00757 msglen = (int)strlen(msg);
00758
00759 outlen = CHAP_HEADERLEN + msglen;
00760 outp = outpacket_buf[cstate->unit];
00761
00762 MAKEHEADER(outp, PPP_CHAP);
00763
00764 PUTCHAR(code, outp);
00765 PUTCHAR(cstate->chal_id, outp);
00766 PUTSHORT(outlen, outp);
00767 BCOPY(msg, outp, msglen);
00768 pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
00769
00770 CHAPDEBUG(LOG_INFO, ("ChapSendStatus: Sent code %d, id %d.\n", code,
00771 cstate->chal_id));
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781 static void
00782 ChapGenChallenge(chap_state *cstate)
00783 {
00784 int chal_len;
00785 u_char *ptr = cstate->challenge;
00786 int i;
00787
00788
00789
00790 chal_len = (unsigned)
00791 ((((magic() >> 16) *
00792 (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16)
00793 + MIN_CHALLENGE_LENGTH);
00794 LWIP_ASSERT("chal_len <= 0xff", chal_len <= 0xffff);
00795 cstate->chal_len = (u_char)chal_len;
00796 cstate->chal_id = ++cstate->id;
00797 cstate->chal_transmits = 0;
00798
00799
00800 for (i = 0; i < chal_len; i++ ) {
00801 *ptr++ = (char) (magic() & 0xff);
00802 }
00803 }
00804
00805
00806
00807
00808
00809
00810 static void
00811 ChapSendResponse(chap_state *cstate)
00812 {
00813 u_char *outp;
00814 int outlen, md_len, name_len;
00815
00816 md_len = cstate->resp_length;
00817 name_len = (int)strlen(cstate->resp_name);
00818 outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
00819 outp = outpacket_buf[cstate->unit];
00820
00821 MAKEHEADER(outp, PPP_CHAP);
00822
00823 PUTCHAR(CHAP_RESPONSE, outp);
00824 PUTCHAR(cstate->resp_id, outp);
00825 PUTSHORT(outlen, outp);
00826
00827 PUTCHAR(md_len, outp);
00828 BCOPY(cstate->response, outp, md_len);
00829 INCPTR(md_len, outp);
00830
00831 BCOPY(cstate->resp_name, outp, name_len);
00832
00833
00834 pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
00835
00836 cstate->clientstate = CHAPCS_RESPONSE;
00837 TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
00838 ++cstate->resp_transmits;
00839 }
00840
00841 #if PPP_ADDITIONAL_CALLBACKS
00842 static char *ChapCodenames[] = {
00843 "Challenge", "Response", "Success", "Failure"
00844 };
00845
00846
00847
00848 static int
00849 ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
00850 {
00851 int code, id, len;
00852 int clen, nlen;
00853 u_char x;
00854
00855 if (plen < CHAP_HEADERLEN) {
00856 return 0;
00857 }
00858 GETCHAR(code, p);
00859 GETCHAR(id, p);
00860 GETSHORT(len, p);
00861 if (len < CHAP_HEADERLEN || len > plen) {
00862 return 0;
00863 }
00864
00865 if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) {
00866 printer(arg, " %s", ChapCodenames[code-1]);
00867 } else {
00868 printer(arg, " code=0x%x", code);
00869 }
00870 printer(arg, " id=0x%x", id);
00871 len -= CHAP_HEADERLEN;
00872 switch (code) {
00873 case CHAP_CHALLENGE:
00874 case CHAP_RESPONSE:
00875 if (len < 1) {
00876 break;
00877 }
00878 clen = p[0];
00879 if (len < clen + 1) {
00880 break;
00881 }
00882 ++p;
00883 nlen = len - clen - 1;
00884 printer(arg, " <");
00885 for (; clen > 0; --clen) {
00886 GETCHAR(x, p);
00887 printer(arg, "%.2x", x);
00888 }
00889 printer(arg, ">, name = %.*Z", nlen, p);
00890 break;
00891 case CHAP_FAILURE:
00892 case CHAP_SUCCESS:
00893 printer(arg, " %.*Z", len, p);
00894 break;
00895 default:
00896 for (clen = len; clen > 0; --clen) {
00897 GETCHAR(x, p);
00898 printer(arg, " %.2x", x);
00899 }
00900 }
00901
00902 return len + CHAP_HEADERLEN;
00903 }
00904 #endif
00905
00906 #endif
00907
00908 #endif