Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.
chap.c
00001 /*** WARNING - THIS HAS NEVER BEEN FINISHED ***/ 00002 /***************************************************************************** 00003 * chap.c - Network Challenge Handshake Authentication Protocol program file. 00004 * 00005 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 00006 * portions Copyright (c) 1997 by Global Election Systems Inc. 00007 * 00008 * The authors hereby grant permission to use, copy, modify, distribute, 00009 * and license this software and its documentation for any purpose, provided 00010 * that existing copyright notices are retained in all copies and that this 00011 * notice and the following disclaimer are included verbatim in any 00012 * distributions. No written agreement, license, or royalty fee is required 00013 * for any of the authorized uses. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00017 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00018 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00019 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00020 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00021 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00022 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00023 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00024 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00025 * 00026 ****************************************************************************** 00027 * REVISION HISTORY 00028 * 00029 * 03-01-01 Marc Boucher <marc@mbsi.ca> 00030 * Ported to lwIP. 00031 * 97-12-04 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 00032 * Original based on BSD chap.c. 00033 *****************************************************************************/ 00034 /* 00035 * chap.c - Challenge Handshake Authentication Protocol. 00036 * 00037 * Copyright (c) 1993 The Australian National University. 00038 * All rights reserved. 00039 * 00040 * Redistribution and use in source and binary forms are permitted 00041 * provided that the above copyright notice and this paragraph are 00042 * duplicated in all such forms and that any documentation, 00043 * advertising materials, and other materials related to such 00044 * distribution and use acknowledge that the software was developed 00045 * by the Australian National University. The name of the University 00046 * may not be used to endorse or promote products derived from this 00047 * software without specific prior written permission. 00048 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00049 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00050 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00051 * 00052 * Copyright (c) 1991 Gregory M. Christy. 00053 * All rights reserved. 00054 * 00055 * Redistribution and use in source and binary forms are permitted 00056 * provided that the above copyright notice and this paragraph are 00057 * duplicated in all such forms and that any documentation, 00058 * advertising materials, and other materials related to such 00059 * distribution and use acknowledge that the software was developed 00060 * by Gregory M. Christy. The name of the author may not be used to 00061 * endorse or promote products derived from this software without 00062 * specific prior written permission. 00063 * 00064 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00065 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00066 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00067 */ 00068 00069 #include "lwip/opt.h" 00070 00071 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00072 00073 #if CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00074 00075 #include "ppp.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 /* UNUSED */ 00088 /* 00089 * Command-line options. 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 /* UNUSED */ 00105 00106 /* 00107 * Protocol entry points. 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 /* PPP_ADDITIONAL_CALLBACKS */ 00131 1, 00132 "CHAP", 00133 #if PPP_ADDITIONAL_CALLBACKS 00134 NULL, 00135 NULL, 00136 NULL 00137 #endif /* PPP_ADDITIONAL_CALLBACKS */ 00138 }; 00139 00140 chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */ 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 * ChapInit - Initialize a CHAP unit. 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 /* random number generator is initialized in magic_init */ 00169 } 00170 00171 00172 /* 00173 * ChapAuthWithPeer - Authenticate us with our peer (start client). 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 /* lower layer isn't up - wait until later */ 00187 cstate->clientstate = CHAPCS_PENDING; 00188 return; 00189 } 00190 00191 /* 00192 * We get here as a result of LCP coming up. 00193 * So even if CHAP was open before, we will 00194 * have to re-authenticate ourselves. 00195 */ 00196 cstate->clientstate = CHAPCS_LISTEN; 00197 } 00198 00199 00200 /* 00201 * ChapAuthPeer - Authenticate our peer (start server). 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 /* lower layer isn't up - wait until later */ 00214 cstate->serverstate = CHAPSS_PENDING; 00215 return; 00216 } 00217 00218 ChapGenChallenge(cstate); 00219 ChapSendChallenge(cstate); /* crank it up dude! */ 00220 cstate->serverstate = CHAPSS_INITIAL_CHAL; 00221 } 00222 00223 00224 /* 00225 * ChapChallengeTimeout - Timeout expired on sending challenge. 00226 */ 00227 static void 00228 ChapChallengeTimeout(void *arg) 00229 { 00230 chap_state *cstate = (chap_state *) arg; 00231 00232 /* if we aren't sending challenges, don't worry. then again we */ 00233 /* probably shouldn't be here either */ 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 /* give up on peer */ 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); /* Re-send challenge */ 00248 } 00249 00250 00251 /* 00252 * ChapResponseTimeout - Timeout expired on sending response. 00253 */ 00254 static void 00255 ChapResponseTimeout(void *arg) 00256 { 00257 chap_state *cstate = (chap_state *) arg; 00258 00259 /* if we aren't sending a response, don't worry. */ 00260 if (cstate->clientstate != CHAPCS_RESPONSE) { 00261 return; 00262 } 00263 00264 ChapSendResponse(cstate); /* re-send response */ 00265 } 00266 00267 00268 /* 00269 * ChapRechallenge - Time to challenge the peer again. 00270 */ 00271 static void 00272 ChapRechallenge(void *arg) 00273 { 00274 chap_state *cstate = (chap_state *) arg; 00275 00276 /* if we aren't sending a response, don't worry. */ 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 * ChapLowerUp - The lower layer is up. 00289 * 00290 * Start up if we have pending requests. 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 * ChapLowerDown - The lower layer is down. 00315 * 00316 * Cancel all timeouts. 00317 */ 00318 static void 00319 ChapLowerDown(int unit) 00320 { 00321 chap_state *cstate = &chap[unit]; 00322 00323 /* Timeout(s) pending? Cancel if so. */ 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 * ChapProtocolReject - Peer doesn't grok CHAP. 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); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */ 00354 } 00355 ChapLowerDown(unit); /* shutdown chap */ 00356 } 00357 00358 00359 /* 00360 * ChapInput - Input CHAP packet. 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 * Parse header (code, id and length). 00372 * If packet too short, drop it. 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 * Action depends on code (as in fact it usually does :-). 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: /* Need code reject? */ 00413 CHAPDEBUG(LOG_WARNING, ("Unknown CHAP code (%d) received.\n", code)); 00414 break; 00415 } 00416 } 00417 00418 00419 /* 00420 * ChapReceiveChallenge - Receive Challenge and send Response. 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; /* now name field length */ 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 /* Microsoft doesn't send their name back in the PPP packet */ 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 /* get secret for authenticating ourselves with the specified host */ 00473 if (!get_secret(cstate->unit, cstate->resp_name, rhostname, 00474 secret, &secret_len, 0)) { 00475 secret_len = 0; /* assume null secret if can't find one */ 00476 CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating us to %s\n", 00477 rhostname)); 00478 } 00479 00480 /* cancel response send timeout if necessary */ 00481 if (cstate->clientstate == CHAPCS_RESPONSE) { 00482 UNTIMEOUT(ChapResponseTimeout, cstate); 00483 } 00484 00485 cstate->resp_id = id; 00486 cstate->resp_transmits = 0; 00487 00488 /* generate MD based on negotiated type */ 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 * ChapReceiveResponse - Receive and process response. 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; /* doesn't match ID of last challenge */ 00542 } 00543 00544 /* 00545 * If we have received a duplicate or bogus Response, 00546 * we have to send the same answer (Success/Failure) 00547 * as we did for the first Response we saw. 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); /* get length of MD */ 00563 remmd = inp; /* get pointer to MD */ 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 * Get secret for authenticating them with us, 00585 * do the hash ourselves, and compare the result. 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 /* generate MD based on negotiated type */ 00594 switch (cstate->chal_type) { 00595 00596 case CHAP_DIGEST_MD5: /* only MD5 is defined for now */ 00597 if (remmd_len != MD5_SIGNATURE_SIZE) { 00598 break; /* it's not even the right length */ 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 /* compare local and remote MDs and send the appropriate status */ 00607 if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0) { 00608 code = CHAP_SUCCESS; /* they are the same! */ 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 * ChapReceiveSuccess - Receive Success 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 /* presumably an answer to a duplicate response */ 00649 return; 00650 } 00651 00652 if (cstate->clientstate != CHAPCS_RESPONSE) { 00653 /* don't know what this is */ 00654 CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: in state %d\n", 00655 cstate->clientstate)); 00656 return; 00657 } 00658 00659 UNTIMEOUT(ChapResponseTimeout, cstate); 00660 00661 /* 00662 * Print message. 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 * ChapReceiveFailure - Receive failure. 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 /* don't know what this is */ 00687 CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: in state %d\n", 00688 cstate->clientstate)); 00689 return; 00690 } 00691 00692 UNTIMEOUT(ChapResponseTimeout, cstate); 00693 00694 /* 00695 * Print message. 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); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */ 00703 } 00704 00705 00706 /* 00707 * ChapSendChallenge - Send an Authenticate challenge. 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); /* paste in a CHAP header */ 00722 00723 PUTCHAR(CHAP_CHALLENGE, outp); 00724 PUTCHAR(cstate->chal_id, outp); 00725 PUTSHORT(outlen, outp); 00726 00727 PUTCHAR(chal_len, outp); /* put length of challenge */ 00728 BCOPY(cstate->challenge, outp, chal_len); 00729 INCPTR(chal_len, outp); 00730 00731 BCOPY(cstate->chal_name, outp, name_len); /* append hostname */ 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 * ChapSendStatus - Send a status response (ack or nak). 00744 */ 00745 static void 00746 ChapSendStatus(chap_state *cstate, int code) 00747 { 00748 u_char *outp; 00749 int outlen, msglen; 00750 char msg[256]; /* @todo: this can be a char*, no strcpy needed */ 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); /* paste in a header */ 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 * ChapGenChallenge is used to generate a pseudo-random challenge string of 00776 * a pseudo-random length between min_len and max_len. The challenge 00777 * string and its length are stored in *cstate, and various other fields of 00778 * *cstate are initialized. 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 /* pick a random challenge length between MIN_CHALLENGE_LENGTH and 00789 MAX_CHALLENGE_LENGTH */ 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 /* generate a random string */ 00800 for (i = 0; i < chal_len; i++ ) { 00801 *ptr++ = (char) (magic() & 0xff); 00802 } 00803 } 00804 00805 /* 00806 * ChapSendResponse - send a response packet with values as specified 00807 * in *cstate. 00808 */ 00809 /* ARGSUSED */ 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); /* we are a response */ 00824 PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */ 00825 PUTSHORT(outlen, outp); /* packet length */ 00826 00827 PUTCHAR(md_len, outp); /* length of MD */ 00828 BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */ 00829 INCPTR(md_len, outp); 00830 00831 BCOPY(cstate->resp_name, outp, name_len); /* append our name */ 00832 00833 /* send the packet */ 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 * ChapPrintPkt - print the contents of a CHAP packet. 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 /* PPP_ADDITIONAL_CALLBACKS */ 00905 00906 #endif /* CHAP_SUPPORT */ 00907 00908 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 21:10:24 by 1.7.2