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.
pap.c
00001 /** 00002 * @file pap.c 00003 * @brief PAP (Password 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/pap.h" 00039 #include "debug.h" 00040 00041 //Check TCP/IP stack configuration 00042 #if (PPP_SUPPORT == ENABLED && PAP_SUPPORT == ENABLED) 00043 00044 00045 /** 00046 * @brief Start PAP authentication 00047 * @param[in] context PPP context 00048 * @return Error code 00049 **/ 00050 00051 error_t papStartAuth(PppContext *context) 00052 { 00053 //Debug message 00054 TRACE_INFO("\r\nStarting PAP authentication...\r\n"); 00055 00056 //Check whether the other end of the PPP link is being authenticated 00057 if(context->localConfig.authProtocol == PPP_PROTOCOL_PAP) 00058 { 00059 //Switch to the Started state 00060 context->papFsm.localState = PAP_STATE_1_STARTED; 00061 } 00062 00063 //Check whether the other end of the PPP link is the authenticator 00064 if(context->peerConfig.authProtocol == PPP_PROTOCOL_PAP) 00065 { 00066 //Initialize restart counter 00067 context->papFsm.restartCounter = PAP_MAX_REQUESTS; 00068 //Send Authenticate-Request packet 00069 papSendAuthReq(context); 00070 //Switch to the Req-Sent state 00071 context->papFsm.peerState = PAP_STATE_2_REQ_SENT; 00072 } 00073 00074 //Successful processing 00075 return NO_ERROR; 00076 } 00077 00078 00079 /** 00080 * @brief Abort PAP authentication 00081 * @param[in] context PPP context 00082 * @return Error code 00083 **/ 00084 00085 error_t papAbortAuth(PppContext *context) 00086 { 00087 //Debug message 00088 TRACE_INFO("\r\nAborting PAP authentication...\r\n"); 00089 00090 //Abort PAP authentication process 00091 context->papFsm.localState = PAP_STATE_0_INITIAL; 00092 context->papFsm.peerState = PAP_STATE_0_INITIAL; 00093 00094 //Successful processing 00095 return NO_ERROR; 00096 } 00097 00098 00099 /** 00100 * @brief PAP timer handler 00101 * 00102 * This routine must be periodically called by the TCP/IP stack to 00103 * manage retransmissions 00104 * 00105 * @param[in] context PPP context 00106 **/ 00107 00108 void papTick(PppContext *context) 00109 { 00110 //Check whether the restart timer is running 00111 if(context->papFsm.peerState == PAP_STATE_2_REQ_SENT) 00112 { 00113 //Get current time 00114 systime_t time = osGetSystemTime(); 00115 00116 //Check restart timer 00117 if((time - context->papFsm.timestamp) >= PAP_RESTART_TIMER) 00118 { 00119 //Debug message 00120 TRACE_INFO("\r\nPAP Timeout event\r\n"); 00121 00122 //Check whether the restart counter is greater than zero 00123 if(context->papFsm.restartCounter > 0) 00124 { 00125 //Retransmit the Authenticate-Request packet 00126 papSendAuthReq(context); 00127 } 00128 else 00129 { 00130 //Abort PAP authentication 00131 context->papFsm.peerState = PAP_STATE_0_INITIAL; 00132 //Authentication failed 00133 lcpClose(context); 00134 } 00135 } 00136 } 00137 } 00138 00139 00140 /** 00141 * @brief Process an incoming PAP packet 00142 * @param[in] context PPP context 00143 * @param[in] packet PAP packet received from the peer 00144 * @param[in] length Length of the packet, in bytes 00145 **/ 00146 00147 void papProcessPacket(PppContext *context, 00148 const PppPacket *packet, size_t length) 00149 { 00150 //Ensure the length of the incoming PAP 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 PAP packet 00161 length = ntohs(packet->length); 00162 00163 //Debug message 00164 TRACE_INFO("PAP packet received (%" PRIuSIZE " bytes)...\r\n", length); 00165 //Dump PAP packet contents for debugging purpose 00166 pppDumpPacket(packet, length, PPP_PROTOCOL_PAP); 00167 00168 //Because the Authenticate-Ack might be lost, the authenticator must 00169 //allow repeated Authenticate-Request packets after completing the 00170 //Authentication phase 00171 if(context->pppPhase != PPP_PHASE_AUTHENTICATE && 00172 context->pppPhase != PPP_PHASE_NETWORK) 00173 { 00174 //Any packets received during any other phase must be silently discarded 00175 return; 00176 } 00177 00178 //Check PAP code field 00179 switch(packet->code) 00180 { 00181 //Authenticate-Request packet? 00182 case PAP_CODE_AUTH_REQ: 00183 //Process Authenticate-Request packet 00184 papProcessAuthReq(context, (PapAuthReqPacket *) packet, length); 00185 break; 00186 //Authenticate-Ack packet? 00187 case PAP_CODE_AUTH_ACK: 00188 //Process Authenticate-Ack packet 00189 papProcessAuthAck(context, (PapAuthAckPacket *) packet, length); 00190 break; 00191 //Authenticate-Nak packet? 00192 case PAP_CODE_AUTH_NAK: 00193 //Process Authenticate-Nak packet 00194 papProcessAuthNak(context, (PapAuthNakPacket *) packet, length); 00195 break; 00196 //Unknown code field 00197 default: 00198 //Silently drop the incoming packet 00199 break; 00200 } 00201 } 00202 00203 00204 /** 00205 * @brief Process Authenticate-Request packet 00206 * @param[in] context PPP context 00207 * @param[in] authReqPacket Packet received from the peer 00208 * @param[in] length Length of the packet, in bytes 00209 * @return Error code 00210 **/ 00211 00212 error_t papProcessAuthReq(PppContext *context, 00213 const PapAuthReqPacket *authReqPacket, size_t length) 00214 { 00215 bool_t status; 00216 size_t usernameLen; 00217 const uint8_t *p; 00218 00219 //Debug message 00220 TRACE_INFO("\r\nPAP Authenticate-Request packet received\r\n"); 00221 00222 //Make sure the Authenticate-Request packet is acceptable 00223 if(context->localConfig.authProtocol != PPP_PROTOCOL_PAP) 00224 return ERROR_FAILURE; 00225 00226 //Check the length of the packet 00227 if(length < sizeof(PapAuthReqPacket)) 00228 return ERROR_INVALID_LENGTH; 00229 00230 //Retrieve the length of the Peer-ID field 00231 usernameLen = authReqPacket->peerIdLength; 00232 00233 //Malformed Authenticate-Request packet? 00234 if(length < (sizeof(PapAuthReqPacket) + 1 + usernameLen)) 00235 return ERROR_INVALID_LENGTH; 00236 00237 //Limit the length of the string 00238 usernameLen = MIN(usernameLen, PPP_MAX_USERNAME_LEN); 00239 //Copy the name of the peer to be identified 00240 memcpy(context->peerName, authReqPacket->peerId, usernameLen); 00241 //Properly terminate the string with a NULL character 00242 context->peerName[usernameLen] = '\0'; 00243 00244 //Point to the Passwd-Length field 00245 p = authReqPacket->peerId + usernameLen; 00246 00247 //Save the length of Password field 00248 context->papFsm.passwordLen = p[0]; 00249 //Point to the Password field 00250 context->papFsm.password = p + 1; 00251 00252 //Malformed Authenticate-Request packet? 00253 if(length < (sizeof(PapAuthReqPacket) + 1 + usernameLen + context->papFsm.passwordLen)) 00254 return ERROR_INVALID_LENGTH; 00255 00256 //Invoke user-defined callback, if any 00257 if(context->settings.authCallback != NULL) 00258 { 00259 //Perfom username and password verification 00260 status = context->settings.authCallback(context->interface, 00261 context->peerName); 00262 } 00263 else 00264 { 00265 //Unable to perform authentication... 00266 status = FALSE; 00267 } 00268 00269 //Successful authentication? 00270 if(status) 00271 { 00272 //If the Peer-ID/Password pair received in the Authenticate-Request 00273 //is both recognizable and acceptable, then the authenticator must 00274 //transmit an Authenticate-Ack packet 00275 papSendAuthAck(context, authReqPacket->identifier); 00276 00277 //Switch to the Ack-Sent state 00278 context->papFsm.localState = PAP_STATE_4_ACK_SENT; 00279 //The user has been successfully authenticated 00280 context->localAuthDone = TRUE; 00281 00282 //Check whether PPP authentication is complete 00283 if(context->localAuthDone && context->peerAuthDone) 00284 { 00285 //Check current PPP phase 00286 if(context->pppPhase == PPP_PHASE_AUTHENTICATE) 00287 { 00288 //Advance to the Network phase 00289 context->pppPhase = PPP_PHASE_NETWORK; 00290 00291 #if (IPV4_SUPPORT == ENABLED) 00292 //IPCP Open event 00293 ipcpOpen(context); 00294 #endif 00295 #if (IPV6_SUPPORT == ENABLED) 00296 //IPV6CP Open event 00297 ipv6cpOpen(context); 00298 #endif 00299 } 00300 } 00301 } 00302 else 00303 { 00304 //If the Peer-ID/Password pair received in the Authenticate-Request 00305 //is not recognizable or acceptable, then the authenticator must 00306 //transmit an Authenticate-Nak packet 00307 papSendAuthNak(context, authReqPacket->identifier); 00308 00309 //Switch to the Nak-Sent state 00310 context->papFsm.localState = PAP_STATE_6_NAK_SENT; 00311 //The authenticator should take action to terminate the link 00312 lcpClose(context); 00313 } 00314 00315 //Successful processing 00316 return NO_ERROR; 00317 } 00318 00319 00320 /** 00321 * @brief Process Authenticate-Ack packet 00322 * @param[in] context PPP context 00323 * @param[in] authAckPacket Packet received from the peer 00324 * @param[in] length Length of the packet, in bytes 00325 * @return Error code 00326 **/ 00327 00328 error_t papProcessAuthAck(PppContext *context, 00329 const PapAuthAckPacket *authAckPacket, size_t length) 00330 { 00331 //Debug message 00332 TRACE_INFO("\r\nPAP Authenticate-Ack packet received\r\n"); 00333 00334 //Make sure the Authenticate-Ack packet is acceptable 00335 if(context->peerConfig.authProtocol != PPP_PROTOCOL_PAP) 00336 return ERROR_FAILURE; 00337 00338 //Check the length of the packet 00339 if(length < sizeof(PapAuthAckPacket)) 00340 return ERROR_INVALID_LENGTH; 00341 00342 //When a packet is received with an invalid Identifier field, the 00343 //packet is silently discarded without affecting the automaton 00344 if(authAckPacket->identifier != context->papFsm.identifier) 00345 return ERROR_WRONG_IDENTIFIER; 00346 00347 //Switch to the Ack-Rcvd state 00348 context->papFsm.peerState = PAP_STATE_5_ACK_RCVD; 00349 //The user name has been accepted by the authenticator 00350 context->peerAuthDone = TRUE; 00351 00352 //Check whether PPP authentication is complete 00353 if(context->localAuthDone && context->peerAuthDone) 00354 { 00355 //Check current PPP phase 00356 if(context->pppPhase == PPP_PHASE_AUTHENTICATE) 00357 { 00358 //Advance to the Network phase 00359 context->pppPhase = PPP_PHASE_NETWORK; 00360 00361 #if (IPV4_SUPPORT == ENABLED) 00362 //IPCP Open event 00363 ipcpOpen(context); 00364 #endif 00365 #if (IPV6_SUPPORT == ENABLED) 00366 //IPV6CP Open event 00367 ipv6cpOpen(context); 00368 #endif 00369 } 00370 } 00371 00372 //Successful processing 00373 return NO_ERROR; 00374 } 00375 00376 00377 /** 00378 * @brief Process Authenticate-Nak packet 00379 * @param[in] context PPP context 00380 * @param[in] authNakPacket Packet received from the peer 00381 * @param[in] length Length of the packet, in bytes 00382 * @return Error code 00383 **/ 00384 00385 error_t papProcessAuthNak(PppContext *context, 00386 const PapAuthNakPacket *authNakPacket, size_t length) 00387 { 00388 //Debug message 00389 TRACE_INFO("\r\nPAP Authenticate-Nak packet received\r\n"); 00390 00391 //Make sure the Authenticate-Nak packet is acceptable 00392 if(context->peerConfig.authProtocol != PPP_PROTOCOL_PAP) 00393 return ERROR_FAILURE; 00394 00395 //Check the length of the packet 00396 if(length < sizeof(PapAuthNakPacket)) 00397 return ERROR_INVALID_LENGTH; 00398 00399 //When a packet is received with an invalid Identifier field, the 00400 //packet is silently discarded without affecting the automaton 00401 if(authNakPacket->identifier != context->papFsm.identifier) 00402 return ERROR_WRONG_IDENTIFIER; 00403 00404 //Switch to the Nak-Rcvd state 00405 context->papFsm.peerState = PAP_STATE_7_NAK_RCVD; 00406 //Authentication failed 00407 lcpClose(context); 00408 00409 //Successful processing 00410 return NO_ERROR; 00411 } 00412 00413 00414 /** 00415 * @brief Send Authenticate-Request packet 00416 * @param[in] context PPP context 00417 * @return Error code 00418 **/ 00419 00420 error_t papSendAuthReq(PppContext *context) 00421 { 00422 error_t error; 00423 size_t usernameLen; 00424 size_t passwordLen; 00425 size_t length; 00426 size_t offset; 00427 uint8_t *p; 00428 NetBuffer *buffer; 00429 PapAuthReqPacket *authReqPacket; 00430 00431 //Get the length of the user name 00432 usernameLen = strlen(context->username); 00433 //Get the length of the password 00434 passwordLen = strlen(context->password); 00435 00436 //Calculate the length of the Authenticate-Request packet 00437 length = sizeof(PapAuthReqPacket) + 1 + usernameLen + passwordLen; 00438 00439 //Allocate a buffer memory to hold the packet 00440 buffer = pppAllocBuffer(length, &offset); 00441 //Failed to allocate memory? 00442 if(buffer == NULL) 00443 return ERROR_OUT_OF_MEMORY; 00444 00445 //Point to the Authenticate-Request packet 00446 authReqPacket = netBufferAt(buffer, offset); 00447 00448 //Format packet header 00449 authReqPacket->code = PAP_CODE_AUTH_REQ; 00450 authReqPacket->identifier = ++context->papFsm.identifier; 00451 authReqPacket->length = htons(length); 00452 00453 //The Peer-ID-Length field indicates the length of Peer-ID field 00454 authReqPacket->peerIdLength = usernameLen; 00455 //Append Peer-ID 00456 memcpy(authReqPacket->peerId, context->username, usernameLen); 00457 00458 //Point to the Passwd-Length field 00459 p = authReqPacket->peerId + usernameLen; 00460 //The Passwd-Length field indicates the length of Password field 00461 p[0] = passwordLen; 00462 00463 //Append Password 00464 memcpy(p + 1, context->password, passwordLen); 00465 00466 //Adjust the length of the multi-part buffer 00467 netBufferSetLength(buffer, offset + length); 00468 00469 //Debug message 00470 TRACE_INFO("Sending PAP Authenticate-Request packet (%" PRIuSIZE " bytes)...\r\n", length); 00471 //Dump packet contents for debugging purpose 00472 pppDumpPacket((PppPacket *) authReqPacket, length, PPP_PROTOCOL_PAP); 00473 00474 //Send PPP frame 00475 error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_PAP); 00476 00477 //The restart counter is decremented each time a Authenticate-Request is sent 00478 if(context->papFsm.restartCounter > 0) 00479 context->papFsm.restartCounter--; 00480 00481 //Save the time at which the packet was sent 00482 context->papFsm.timestamp = osGetSystemTime(); 00483 00484 //Free previously allocated memory block 00485 netBufferFree(buffer); 00486 //Return status code 00487 return error; 00488 } 00489 00490 00491 /** 00492 * @brief Send Authenticate-Ack packet 00493 * @param[in] context PPP context 00494 * @param[in] identifier Identifier field 00495 * @return Error code 00496 **/ 00497 00498 error_t papSendAuthAck(PppContext *context, uint8_t identifier) 00499 { 00500 error_t error; 00501 size_t length; 00502 size_t offset; 00503 NetBuffer *buffer; 00504 PapAuthAckPacket *authAckPacket; 00505 00506 //Retrieve the length of the Authenticate-Ack packet 00507 length = sizeof(PapAuthAckPacket); 00508 00509 //Allocate a buffer memory to hold the Authenticate-Ack packet 00510 buffer = pppAllocBuffer(length, &offset); 00511 //Failed to allocate memory? 00512 if(buffer == NULL) 00513 return ERROR_OUT_OF_MEMORY; 00514 00515 //Point to the Authenticate-Ack packet 00516 authAckPacket = netBufferAt(buffer, offset); 00517 00518 //Format packet header 00519 authAckPacket->code = PAP_CODE_AUTH_ACK; 00520 authAckPacket->identifier = identifier; 00521 authAckPacket->length = htons(length); 00522 00523 //The Message field is zero or more octets, and its contents are 00524 //implementation dependent 00525 authAckPacket->msgLength = 0; 00526 00527 //Debug message 00528 TRACE_INFO("Sending PAP Authenticate-Ack packet (%" PRIuSIZE " bytes)...\r\n", length); 00529 //Dump packet contents for debugging purpose 00530 pppDumpPacket((PppPacket *) authAckPacket, length, PPP_PROTOCOL_PAP); 00531 00532 //Send PPP frame 00533 error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_PAP); 00534 00535 //Free previously allocated memory block 00536 netBufferFree(buffer); 00537 //Return status code 00538 return error; 00539 } 00540 00541 00542 /** 00543 * @brief Send Authenticate-Nak packet 00544 * @param[in] context PPP context 00545 * @param[in] identifier Identifier field 00546 * @return Error code 00547 **/ 00548 00549 error_t papSendAuthNak(PppContext *context, uint8_t identifier) 00550 { 00551 error_t error; 00552 size_t length; 00553 size_t offset; 00554 NetBuffer *buffer; 00555 PapAuthNakPacket *authNakPacket; 00556 00557 //Retrieve the length of the Authenticate-Nak packet 00558 length = sizeof(PapAuthNakPacket); 00559 00560 //Allocate a buffer memory to hold the Authenticate-Nak packet 00561 buffer = pppAllocBuffer(length, &offset); 00562 //Failed to allocate memory? 00563 if(buffer == NULL) 00564 return ERROR_OUT_OF_MEMORY; 00565 00566 //Point to the Authenticate-Nak packet 00567 authNakPacket = netBufferAt(buffer, offset); 00568 00569 //Format packet header 00570 authNakPacket->code = PAP_CODE_AUTH_NAK; 00571 authNakPacket->identifier = identifier; 00572 authNakPacket->length = htons(length); 00573 00574 //The Message field is zero or more octets, and its contents are 00575 //implementation dependent 00576 authNakPacket->msgLength = 0; 00577 00578 //Debug message 00579 TRACE_INFO("Sending PAP Authenticate-Nak packet (%" PRIuSIZE " bytes)...\r\n", length); 00580 //Dump packet contents for debugging purpose 00581 pppDumpPacket((PppPacket *) authNakPacket, length, PPP_PROTOCOL_PAP); 00582 00583 //Send PPP frame 00584 error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_PAP); 00585 00586 //Free previously allocated memory block 00587 netBufferFree(buffer); 00588 //Return status code 00589 return error; 00590 } 00591 00592 00593 /** 00594 * @brief Password verification 00595 * @param[in] context PPP context 00596 * @param[in] password NULL-terminated string containing the password to be checked 00597 * @return TRUE if the password is valid, else FALSE 00598 **/ 00599 00600 bool_t papCheckPassword(PppContext *context, const char_t *password) 00601 { 00602 size_t n; 00603 bool_t status; 00604 00605 //This flag tells whether the password is valid 00606 status = FALSE; 00607 00608 //Retrieve the length of the password 00609 n = strlen(password); 00610 00611 //Compare the length of the password against the expected value 00612 if(n == context->papFsm.passwordLen) 00613 { 00614 //Check whether the password is valid 00615 if(!memcmp(password, context->papFsm.password, n)) 00616 status = TRUE; 00617 } 00618 00619 //Return TRUE is the password is valid, else FALSE 00620 return status; 00621 } 00622 00623 #endif 00624
Generated on Tue Jul 12 2022 17:10:15 by
1.7.2