Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
chap.c
00001 /** 00002 * @file chap.c 00003 * @brief CHAP (Challenge Handshake Authentication Protocol) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL PPP_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include "core/net.h" 00034 #include "ppp/ppp_debug.h" 00035 #include "ppp/lcp.h" 00036 #include "ppp/ipcp.h" 00037 #include "ppp/ipv6cp.h" 00038 #include "ppp/chap.h" 00039 #include "debug.h" 00040 00041 //Check TCP/IP stack configuration 00042 #if (PPP_SUPPORT == ENABLED && CHAP_SUPPORT == ENABLED) 00043 00044 //Additional dependencies 00045 #include "crypto.h" 00046 #include "md5.h" 00047 00048 00049 /** 00050 * @brief Start CHAP authentication 00051 * @param[in] context PPP context 00052 * @return Error code 00053 **/ 00054 00055 error_t chapStartAuth(PppContext *context) 00056 { 00057 //Debug message 00058 TRACE_INFO("\r\nStarting CHAP authentication...\r\n"); 00059 00060 //Check whether the other end of the PPP link is being authenticated 00061 if(context->localConfig.authProtocol == PPP_PROTOCOL_CHAP) 00062 { 00063 //Initialize restart counter 00064 context->chapFsm.restartCounter = CHAP_MAX_CHALLENGES; 00065 //Send a Challenge packet 00066 chapSendChallenge(context); 00067 //Switch to the Challenge-Sent state 00068 context->chapFsm.localState = CHAP_STATE_2_CHALLENGE_SENT; 00069 } 00070 00071 //Check whether the other end of the PPP link is the authenticator 00072 if(context->peerConfig.authProtocol == PPP_PROTOCOL_CHAP) 00073 { 00074 //Switch to the Started state 00075 context->chapFsm.peerState = CHAP_STATE_1_STARTED; 00076 } 00077 00078 //Successful processing 00079 return NO_ERROR; 00080 } 00081 00082 00083 /** 00084 * @brief Abort CHAP authentication 00085 * @param[in] context PPP context 00086 * @return Error code 00087 **/ 00088 00089 error_t chapAbortAuth(PppContext *context) 00090 { 00091 //Debug message 00092 TRACE_INFO("\r\nAborting CHAP authentication...\r\n"); 00093 00094 //Abort CHAP authentication process 00095 context->chapFsm.localState = CHAP_STATE_0_INITIAL; 00096 context->chapFsm.peerState = CHAP_STATE_0_INITIAL; 00097 00098 //Successful processing 00099 return NO_ERROR; 00100 } 00101 00102 00103 /** 00104 * @brief CHAP timer handler 00105 * @param[in] context PPP context 00106 **/ 00107 00108 void chapTick(PppContext *context) 00109 { 00110 //Check whether the restart timer is running 00111 if(context->chapFsm.localState == CHAP_STATE_2_CHALLENGE_SENT) 00112 { 00113 //Get current time 00114 systime_t time = osGetSystemTime(); 00115 00116 //Check restart timer 00117 if((time - context->chapFsm.timestamp) >= CHAP_RESTART_TIMER) 00118 { 00119 //Debug message 00120 TRACE_INFO("\r\nCHAP Timeout event\r\n"); 00121 00122 //Check whether the restart counter is greater than zero 00123 if(context->chapFsm.restartCounter > 0) 00124 { 00125 //Retransmit the Challenge packet 00126 chapSendChallenge(context); 00127 } 00128 else 00129 { 00130 //Abort CHAP authentication 00131 context->chapFsm.localState = CHAP_STATE_0_INITIAL; 00132 //Authentication failed 00133 lcpClose(context); 00134 } 00135 } 00136 } 00137 } 00138 00139 00140 /** 00141 * @brief Process an incoming CHAP packet 00142 * @param[in] context PPP context 00143 * @param[in] packet CHAP packet received from the peer 00144 * @param[in] length Length of the packet, in bytes 00145 **/ 00146 00147 void chapProcessPacket(PppContext *context, 00148 const PppPacket *packet, size_t length) 00149 { 00150 //Ensure the length of the incoming CHAP packet is valid 00151 if(length < sizeof(PppPacket)) 00152 return; 00153 00154 //Check the length field 00155 if(ntohs(packet->length) > length) 00156 return; 00157 if(ntohs(packet->length) < sizeof(PppPacket)) 00158 return; 00159 00160 //Save the length of the CHAP packet 00161 length = ntohs(packet->length); 00162 00163 //Debug message 00164 TRACE_INFO("CHAP packet received (%" PRIuSIZE " bytes)...\r\n", length); 00165 //Dump CHAP packet contents for debugging purpose 00166 pppDumpPacket(packet, length, PPP_PROTOCOL_CHAP); 00167 00168 //CHAP is done at initial link establishment, and could also be 00169 //requested after link establishment 00170 if(context->pppPhase != PPP_PHASE_AUTHENTICATE && 00171 context->pppPhase != PPP_PHASE_NETWORK) 00172 { 00173 //Any packets received during any other phase must be silently discarded 00174 return; 00175 } 00176 00177 //Check CHAP code field 00178 switch(packet->code) 00179 { 00180 //Challenge packet? 00181 case CHAP_CODE_CHALLENGE: 00182 //Process Challenge packet 00183 chapProcessChallenge(context, (ChapChallengePacket *) packet, length); 00184 break; 00185 //Response packet? 00186 case CHAP_CODE_RESPONSE: 00187 //Process Response packet 00188 chapProcessResponse(context, (ChapResponsePacket *) packet, length); 00189 break; 00190 //Success packet? 00191 case CHAP_CODE_SUCCESS: 00192 //Process Success packet 00193 chapProcessSuccess(context, (ChapSuccessPacket *) packet, length); 00194 break; 00195 //Failure packet? 00196 case CHAP_CODE_FAILURE: 00197 //Process Failure packet 00198 chapProcessFailure(context, (ChapFailurePacket *) packet, length); 00199 break; 00200 //Unknown code field 00201 default: 00202 //Silently drop the incoming packet 00203 break; 00204 } 00205 } 00206 00207 00208 /** 00209 * @brief Process Challenge packet 00210 * @param[in] context PPP context 00211 * @param[in] challengePacket Packet received from the peer 00212 * @param[in] length Length of the packet, in bytes 00213 * @return Error code 00214 **/ 00215 00216 error_t chapProcessChallenge(PppContext *context, 00217 const ChapChallengePacket *challengePacket, size_t length) 00218 { 00219 size_t n; 00220 Md5Context md5Context; 00221 00222 //Debug message 00223 TRACE_INFO("\r\nCHAP Challenge packet received\r\n"); 00224 00225 //Make sure the Challenge packet is acceptable 00226 if(context->peerConfig.authProtocol != PPP_PROTOCOL_CHAP) 00227 return ERROR_FAILURE; 00228 00229 //Check the length of the packet 00230 if(length < sizeof(ChapChallengePacket)) 00231 return ERROR_INVALID_LENGTH; 00232 00233 //Malformed Challenge packet? 00234 if(length < (sizeof(ChapChallengePacket) + challengePacket->valueSize)) 00235 return ERROR_INVALID_LENGTH; 00236 00237 //Save the Identifier field 00238 context->chapFsm.peerIdentifier = challengePacket->identifier; 00239 00240 //Retrieve the length of the password 00241 n = strlen(context->password); 00242 00243 //The response value is the one-way hash calculated over a stream 00244 //of octets consisting of the identifier, followed by the secret, 00245 //followed by the challenge value 00246 md5Init(&md5Context); 00247 md5Update(&md5Context, &challengePacket->identifier, sizeof(uint8_t)); 00248 md5Update(&md5Context, context->password, n); 00249 md5Update(&md5Context, challengePacket->value, challengePacket->valueSize); 00250 md5Final(&md5Context, NULL); 00251 00252 //Whenever a Challenge packet is received, the peer must send a Response packet 00253 chapSendResponse(context, md5Context.digest); 00254 00255 //Switch to the Response-Sent state 00256 context->chapFsm.peerState = CHAP_STATE_4_RESPONSE_SENT; 00257 00258 //Successful processing 00259 return NO_ERROR; 00260 } 00261 00262 00263 /** 00264 * @brief Process Response packet 00265 * @param[in] context PPP context 00266 * @param[in] responsePacket Packet received from the peer 00267 * @param[in] length Length of the packet, in bytes 00268 * @return Error code 00269 **/ 00270 00271 error_t chapProcessResponse(PppContext *context, 00272 const ChapResponsePacket *responsePacket, size_t length) 00273 { 00274 bool_t status; 00275 const uint8_t *p; 00276 00277 //Debug message 00278 TRACE_INFO("\r\nCHAP Response packet received\r\n"); 00279 00280 //Make sure the Response packet is acceptable 00281 if(context->localConfig.authProtocol != PPP_PROTOCOL_CHAP) 00282 return ERROR_FAILURE; 00283 00284 //Check the length of the packet 00285 if(length < sizeof(ChapResponsePacket)) 00286 return ERROR_INVALID_LENGTH; 00287 00288 //When a packet is received with an invalid Identifier field, the 00289 //packet is silently discarded without affecting the automaton 00290 if(responsePacket->identifier != context->chapFsm.localIdentifier) 00291 return ERROR_WRONG_IDENTIFIER; 00292 00293 //Malformed Response packet? 00294 if(length < (sizeof(ChapResponsePacket) + responsePacket->valueSize)) 00295 return ERROR_INVALID_LENGTH; 00296 00297 //The length of the response value depends upon the hash algorithm used 00298 if(responsePacket->valueSize != MD5_DIGEST_SIZE) 00299 return ERROR_INVALID_LENGTH; 00300 00301 //Retrieve the response value 00302 context->chapFsm.response = responsePacket->value; 00303 00304 //Point to the Name field 00305 p = responsePacket->value + responsePacket->valueSize; 00306 //Retrieve the length of the Name field 00307 length -= sizeof(ChapResponsePacket) + responsePacket->valueSize; 00308 00309 //Limit the length of the string 00310 length = MIN(length, PPP_MAX_USERNAME_LEN); 00311 //Copy the name of the peer to be identified 00312 memcpy(context->peerName, p, length); 00313 //Properly terminate the string with a NULL character 00314 context->peerName[length] = '\0'; 00315 00316 //Invoke user-defined callback, if any 00317 if(context->settings.authCallback != NULL) 00318 { 00319 //Perfom username and password verification 00320 status = context->settings.authCallback(context->interface, 00321 context->peerName); 00322 } 00323 else 00324 { 00325 //Unable to perform authentication... 00326 status = FALSE; 00327 } 00328 00329 //Whenever a Response packet is received, the authenticator compares the 00330 //Response Value with its own calculation of the expected value. Based on 00331 //this comparison, the authenticator must send a Success or Failure packet 00332 if(status) 00333 { 00334 //Send a Success packet 00335 chapSendSuccess(context); 00336 00337 //Switch to the Success-Sent state 00338 context->chapFsm.localState = CHAP_STATE_6_SUCCESS_SENT; 00339 //The user has been successfully authenticated 00340 context->localAuthDone = TRUE; 00341 00342 //Check whether PPP authentication is complete 00343 if(context->localAuthDone && context->peerAuthDone) 00344 { 00345 //Check current PPP phase 00346 if(context->pppPhase == PPP_PHASE_AUTHENTICATE) 00347 { 00348 //Advance to the Network phase 00349 context->pppPhase = PPP_PHASE_NETWORK; 00350 00351 #if (IPV4_SUPPORT == ENABLED) 00352 //IPCP Open event 00353 ipcpOpen(context); 00354 #endif 00355 #if (IPV6_SUPPORT == ENABLED) 00356 //IPV6CP Open event 00357 ipv6cpOpen(context); 00358 #endif 00359 } 00360 } 00361 } 00362 else 00363 { 00364 //Send a Failure packet 00365 chapSendFailure(context); 00366 00367 //Switch to the Failure-Sent state 00368 context->chapFsm.localState = CHAP_STATE_8_FAILURE_SENT; 00369 //The authenticator should take action to terminate the link 00370 lcpClose(context); 00371 } 00372 00373 //Successful processing 00374 return NO_ERROR; 00375 } 00376 00377 00378 /** 00379 * @brief Process Success packet 00380 * @param[in] context PPP context 00381 * @param[in] successPacket Packet received from the peer 00382 * @param[in] length Length of the packet, in bytes 00383 * @return Error code 00384 **/ 00385 00386 error_t chapProcessSuccess(PppContext *context, 00387 const ChapSuccessPacket *successPacket, size_t length) 00388 { 00389 //Debug message 00390 TRACE_INFO("\r\nCHAP Success packet received\r\n"); 00391 00392 //Make sure the Success packet is acceptable 00393 if(context->peerConfig.authProtocol != PPP_PROTOCOL_CHAP) 00394 return ERROR_FAILURE; 00395 00396 //Check the length of the packet 00397 if(length < sizeof(ChapSuccessPacket)) 00398 return ERROR_INVALID_LENGTH; 00399 00400 //When a packet is received with an invalid Identifier field, the 00401 //packet is silently discarded without affecting the automaton 00402 if(successPacket->identifier != context->chapFsm.peerIdentifier) 00403 return ERROR_WRONG_IDENTIFIER; 00404 00405 //Switch to the Success-Rcvd state 00406 context->chapFsm.peerState = CHAP_STATE_7_SUCCESS_RCVD; 00407 //The user name has been accepted by the authenticator 00408 context->peerAuthDone = TRUE; 00409 00410 //Check whether PPP authentication is complete 00411 if(context->localAuthDone && context->peerAuthDone) 00412 { 00413 //Check current PPP phase 00414 if(context->pppPhase == PPP_PHASE_AUTHENTICATE) 00415 { 00416 //Advance to the Network phase 00417 context->pppPhase = PPP_PHASE_NETWORK; 00418 00419 #if (IPV4_SUPPORT == ENABLED) 00420 //IPCP Open event 00421 ipcpOpen(context); 00422 #endif 00423 #if (IPV6_SUPPORT == ENABLED) 00424 //IPV6CP Open event 00425 ipv6cpOpen(context); 00426 #endif 00427 } 00428 } 00429 00430 //Successful processing 00431 return NO_ERROR; 00432 } 00433 00434 00435 /** 00436 * @brief Process Failure packet 00437 * @param[in] context PPP context 00438 * @param[in] failurePacket Packet received from the peer 00439 * @param[in] length Length of the packet, in bytes 00440 * @return Error code 00441 **/ 00442 00443 error_t chapProcessFailure(PppContext *context, 00444 const ChapFailurePacket *failurePacket, size_t length) 00445 { 00446 //Debug message 00447 TRACE_INFO("\r\nCHAP Failure packet received\r\n"); 00448 00449 //Make sure the Failure packet is acceptable 00450 if(context->peerConfig.authProtocol != PPP_PROTOCOL_CHAP) 00451 return ERROR_FAILURE; 00452 00453 //Check the length of the packet 00454 if(length < sizeof(ChapFailurePacket)) 00455 return ERROR_INVALID_LENGTH; 00456 00457 //When a packet is received with an invalid Identifier field, the 00458 //packet is silently discarded without affecting the automaton 00459 if(failurePacket->identifier != context->chapFsm.peerIdentifier) 00460 return ERROR_WRONG_IDENTIFIER; 00461 00462 //Switch to the Failure-Rcvd state 00463 context->chapFsm.peerState = CHAP_STATE_9_FAILURE_RCVD; 00464 //Authentication failed 00465 lcpClose(context); 00466 00467 //Successful processing 00468 return NO_ERROR; 00469 } 00470 00471 00472 /** 00473 * @brief Send Challenge packet 00474 * @param[in] context PPP context 00475 * @return Error code 00476 **/ 00477 00478 error_t chapSendChallenge(PppContext *context) 00479 { 00480 error_t error; 00481 size_t n; 00482 size_t length; 00483 size_t offset; 00484 NetBuffer *buffer; 00485 ChapChallengePacket *challengePacket; 00486 00487 //Retrieve the length of the username 00488 n = strlen(context->username); 00489 //Calculate the length of the Challenge packet 00490 length = sizeof(ChapChallengePacket) + MD5_DIGEST_SIZE + n; 00491 00492 //Allocate a buffer memory to hold the Challenge packet 00493 buffer = pppAllocBuffer(length, &offset); 00494 //Failed to allocate memory? 00495 if(buffer == NULL) 00496 return ERROR_OUT_OF_MEMORY; 00497 00498 //Point to the Challenge packet 00499 challengePacket = netBufferAt(buffer, offset); 00500 00501 //Format packet header 00502 challengePacket->code = CHAP_CODE_CHALLENGE; 00503 challengePacket->identifier = ++context->chapFsm.localIdentifier; 00504 challengePacket->length = htons(length); 00505 challengePacket->valueSize = MD5_DIGEST_SIZE; 00506 00507 //Make sure that the callback function has been registered 00508 if(context->settings.randCallback != NULL) 00509 { 00510 //Generate a random challenge value 00511 error = context->settings.randCallback( 00512 context->chapFsm.challenge, MD5_DIGEST_SIZE); 00513 } 00514 else 00515 { 00516 //Report an error 00517 error = ERROR_FAILURE; 00518 } 00519 00520 //Check status code 00521 if(!error) 00522 { 00523 //Copy the challenge value 00524 memcpy(challengePacket->value, context->chapFsm.challenge, MD5_DIGEST_SIZE); 00525 00526 //The Name field is one or more octets representing the 00527 //identification of the system transmitting the packet 00528 memcpy(challengePacket->value + MD5_DIGEST_SIZE, context->username, n); 00529 00530 //Debug message 00531 TRACE_INFO("Sending CHAP Challenge packet (%" PRIuSIZE " bytes)...\r\n", length); 00532 //Dump packet contents for debugging purpose 00533 pppDumpPacket((PppPacket *) challengePacket, length, PPP_PROTOCOL_CHAP); 00534 00535 //Send PPP frame 00536 error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_CHAP); 00537 00538 //The restart counter is decremented each time a Challenge packet is sent 00539 if(context->chapFsm.restartCounter > 0) 00540 context->chapFsm.restartCounter--; 00541 00542 //Save the time at which the packet was sent 00543 context->chapFsm.timestamp = osGetSystemTime(); 00544 } 00545 00546 //Free previously allocated memory block 00547 netBufferFree(buffer); 00548 //Return status code 00549 return error; 00550 } 00551 00552 00553 /** 00554 * @brief Send Response packet 00555 * @param[in] context PPP context 00556 * @param[in] value Response value 00557 * @return Error code 00558 **/ 00559 00560 error_t chapSendResponse(PppContext *context, const uint8_t *value) 00561 { 00562 error_t error; 00563 size_t n; 00564 size_t length; 00565 size_t offset; 00566 NetBuffer *buffer; 00567 ChapResponsePacket *responsePacket; 00568 00569 //Retrieve the length of the username 00570 n = strlen(context->username); 00571 //Calculate the length of the Response packet 00572 length = sizeof(ChapResponsePacket) + MD5_DIGEST_SIZE + n; 00573 00574 //Allocate a buffer memory to hold the Response packet 00575 buffer = pppAllocBuffer(length, &offset); 00576 //Failed to allocate memory? 00577 if(buffer == NULL) 00578 return ERROR_OUT_OF_MEMORY; 00579 00580 //Point to the Response packet 00581 responsePacket = netBufferAt(buffer, offset); 00582 00583 //Format packet header 00584 responsePacket->code = CHAP_CODE_RESPONSE; 00585 responsePacket->identifier = context->chapFsm.peerIdentifier; 00586 responsePacket->length = htons(length); 00587 responsePacket->valueSize = MD5_DIGEST_SIZE; 00588 00589 //Copy the Response value 00590 memcpy(responsePacket->value, value, MD5_DIGEST_SIZE); 00591 00592 //The Name field is one or more octets representing the 00593 //identification of the system transmitting the packet 00594 memcpy(responsePacket->value + MD5_DIGEST_SIZE, context->username, n); 00595 00596 //Debug message 00597 TRACE_INFO("Sending CHAP Response packet (%" PRIuSIZE " bytes)...\r\n", length); 00598 //Dump packet contents for debugging purpose 00599 pppDumpPacket((PppPacket *) responsePacket, length, PPP_PROTOCOL_CHAP); 00600 00601 //Send PPP frame 00602 error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_CHAP); 00603 00604 //Free previously allocated memory block 00605 netBufferFree(buffer); 00606 //Return status code 00607 return error; 00608 } 00609 00610 00611 /** 00612 * @brief Send Success packet 00613 * @param[in] context PPP context 00614 * @return Error code 00615 **/ 00616 00617 error_t chapSendSuccess(PppContext *context) 00618 { 00619 error_t error; 00620 size_t length; 00621 size_t offset; 00622 NetBuffer *buffer; 00623 PppPacket *successPacket; 00624 00625 //Retrieve the length of the Success packet 00626 length = sizeof(PppPacket); 00627 00628 //Allocate a buffer memory to hold the Success packet 00629 buffer = pppAllocBuffer(length, &offset); 00630 //Failed to allocate memory? 00631 if(buffer == NULL) 00632 return ERROR_OUT_OF_MEMORY; 00633 00634 //Point to the Success packet 00635 successPacket = netBufferAt(buffer, offset); 00636 00637 //Format packet header 00638 successPacket->code = CHAP_CODE_SUCCESS; 00639 successPacket->identifier = context->chapFsm.localIdentifier; 00640 successPacket->length = htons(length); 00641 00642 //Debug message 00643 TRACE_INFO("Sending CHAP Success packet (%" PRIuSIZE " bytes)...\r\n", length); 00644 //Dump packet contents for debugging purpose 00645 pppDumpPacket((PppPacket *) successPacket, length, PPP_PROTOCOL_CHAP); 00646 00647 //Send PPP frame 00648 error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_CHAP); 00649 00650 //Free previously allocated memory block 00651 netBufferFree(buffer); 00652 //Return status code 00653 return error; 00654 } 00655 00656 00657 /** 00658 * @brief Send Failure packet 00659 * @param[in] context PPP context 00660 * @return Error code 00661 **/ 00662 00663 error_t chapSendFailure(PppContext *context) 00664 { 00665 error_t error; 00666 size_t length; 00667 size_t offset; 00668 NetBuffer *buffer; 00669 PppPacket *failurePacket; 00670 00671 //Retrieve the length of the Failure packet 00672 length = sizeof(PppPacket); 00673 00674 //Allocate a buffer memory to hold the Failure packet 00675 buffer = pppAllocBuffer(length, &offset); 00676 //Failed to allocate memory? 00677 if(buffer == NULL) 00678 return ERROR_OUT_OF_MEMORY; 00679 00680 //Point to the Failure packet 00681 failurePacket = netBufferAt(buffer, offset); 00682 00683 //Format packet header 00684 failurePacket->code = CHAP_CODE_FAILURE; 00685 failurePacket->identifier = context->chapFsm.localIdentifier; 00686 failurePacket->length = htons(length); 00687 00688 //Debug message 00689 TRACE_INFO("Sending CHAP Failure packet (%" PRIuSIZE " bytes)...\r\n", length); 00690 //Dump packet contents for debugging purpose 00691 pppDumpPacket((PppPacket *) failurePacket, length, PPP_PROTOCOL_CHAP); 00692 00693 //Send PPP frame 00694 error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_CHAP); 00695 00696 //Free previously allocated memory block 00697 netBufferFree(buffer); 00698 //Return status code 00699 return error; 00700 } 00701 00702 00703 /** 00704 * @brief Password verification 00705 * @param[in] context PPP context 00706 * @param[in] password NULL-terminated string containing the password to be checked 00707 * @return TRUE if the password is valid, else FALSE 00708 **/ 00709 00710 bool_t chapCheckPassword(PppContext *context, const char_t *password) 00711 { 00712 size_t n; 00713 Md5Context md5Context; 00714 00715 //Retrieve the length of the password 00716 n = strlen(password); 00717 00718 //The response value is the one-way hash calculated over a stream 00719 //of octets consisting of the identifier, followed by the secret, 00720 //followed by the challenge value 00721 md5Init(&md5Context); 00722 md5Update(&md5Context, &context->chapFsm.localIdentifier, sizeof(uint8_t)); 00723 md5Update(&md5Context, password, n); 00724 md5Update(&md5Context, context->chapFsm.challenge, MD5_DIGEST_SIZE); 00725 md5Final(&md5Context, NULL); 00726 00727 //Check the resulting digest value 00728 if(!memcmp(md5Context.digest, context->chapFsm.response, MD5_DIGEST_SIZE)) 00729 return TRUE; 00730 else 00731 return FALSE; 00732 } 00733 00734 #endif 00735
Generated on Tue Jul 12 2022 17:10:12 by
1.7.2