Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_chap-new.c Source File

lwip_chap-new.c

00001 /*
00002  * chap-new.c - New CHAP implementation.
00003  *
00004  * Copyright (c) 2003 Paul Mackerras. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *
00013  * 2. The name(s) of the authors of this software must not be used to
00014  *    endorse or promote products derived from this software without
00015  *    prior written permission.
00016  *
00017  * 3. Redistributions of any form whatsoever must retain the following
00018  *    acknowledgment:
00019  *    "This product includes software developed by Paul Mackerras
00020  *     <paulus@samba.org>".
00021  *
00022  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
00023  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00024  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
00025  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00026  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
00027  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
00028  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00029  */
00030 
00031 #include "netif/ppp/ppp_opts.h"
00032 #if PPP_SUPPORT && CHAP_SUPPORT  /* don't build if not configured for use in lwipopts.h */
00033 
00034 #if 0 /* UNUSED */
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #endif /* UNUSED */
00038 
00039 #include "netif/ppp/ppp_impl.h"
00040 
00041 #if 0 /* UNUSED */
00042 #include "session.h"
00043 #endif /* UNUSED */
00044 
00045 #include "netif/ppp/chap-new.h"
00046 #include "netif/ppp/chap-md5.h"
00047 #if MSCHAP_SUPPORT
00048 #include "netif/ppp/chap_ms.h"
00049 #endif
00050 #include "netif/ppp/magic.h"
00051 
00052 #if 0 /* UNUSED */
00053 /* Hook for a plugin to validate CHAP challenge */
00054 int (*chap_verify_hook)(const char *name, const char *ourname, int id,
00055             const struct chap_digest_type *digest,
00056             const unsigned char *challenge, const unsigned char *response,
00057             char *message, int message_space) = NULL;
00058 #endif /* UNUSED */
00059 
00060 #if PPP_OPTIONS
00061 /*
00062  * Command-line options.
00063  */
00064 static option_t chap_option_list[] = {
00065     { "chap-restart", o_int, &chap_timeout_time,
00066       "Set timeout for CHAP", OPT_PRIO },
00067     { "chap-max-challenge", o_int, &pcb->settings.chap_max_transmits,
00068       "Set max #xmits for challenge", OPT_PRIO },
00069     { "chap-interval", o_int, &pcb->settings.chap_rechallenge_time,
00070       "Set interval for rechallenge", OPT_PRIO },
00071     { NULL }
00072 };
00073 #endif /* PPP_OPTIONS */
00074 
00075 
00076 /* Values for flags in chap_client_state and chap_server_state */
00077 #define LOWERUP         1
00078 #define AUTH_STARTED        2
00079 #define AUTH_DONE       4
00080 #define AUTH_FAILED     8
00081 #define TIMEOUT_PENDING     0x10
00082 #define CHALLENGE_VALID     0x20
00083 
00084 /*
00085  * Prototypes.
00086  */
00087 static void chap_init(ppp_pcb *pcb);
00088 static void chap_lowerup(ppp_pcb *pcb);
00089 static void chap_lowerdown(ppp_pcb *pcb);
00090 #if PPP_SERVER
00091 static void chap_timeout(void *arg);
00092 static void chap_generate_challenge(ppp_pcb *pcb);
00093 static void chap_handle_response(ppp_pcb *pcb, int code,
00094         unsigned char *pkt, int len);
00095 static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id,
00096         const struct chap_digest_type *digest,
00097         const unsigned char *challenge, const unsigned char *response,
00098         char *message, int message_space);
00099 #endif /* PPP_SERVER */
00100 static void chap_respond(ppp_pcb *pcb, int id,
00101         unsigned char *pkt, int len);
00102 static void chap_handle_status(ppp_pcb *pcb, int code, int id,
00103         unsigned char *pkt, int len);
00104 static void chap_protrej(ppp_pcb *pcb);
00105 static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen);
00106 #if PRINTPKT_SUPPORT
00107 static int chap_print_pkt(const unsigned char *p, int plen,
00108         void (*printer) (void *, const char *, ...), void *arg);
00109 #endif /* PRINTPKT_SUPPORT */
00110 
00111 /* List of digest types that we know about */
00112 static const struct chap_digest_type* const chap_digests[] = {
00113     &md5_digest,
00114 #if MSCHAP_SUPPORT
00115     &chapms_digest,
00116     &chapms2_digest,
00117 #endif /* MSCHAP_SUPPORT */
00118     NULL
00119 };
00120 
00121 /*
00122  * chap_init - reset to initial state.
00123  */
00124 static void chap_init(ppp_pcb *pcb) {
00125     LWIP_UNUSED_ARG(pcb);
00126 
00127 #if 0 /* Not necessary, everything is cleared in ppp_new() */
00128     memset(&pcb->chap_client, 0, sizeof(chap_client_state));
00129 #if PPP_SERVER
00130     memset(&pcb->chap_server, 0, sizeof(chap_server_state));
00131 #endif /* PPP_SERVER */
00132 #endif /* 0 */
00133 }
00134 
00135 /*
00136  * chap_lowerup - we can start doing stuff now.
00137  */
00138 static void chap_lowerup(ppp_pcb *pcb) {
00139 
00140     pcb->chap_client.flags |= LOWERUP;
00141 #if PPP_SERVER
00142     pcb->chap_server.flags |= LOWERUP;
00143     if (pcb->chap_server.flags & AUTH_STARTED)
00144         chap_timeout(pcb);
00145 #endif /* PPP_SERVER */
00146 }
00147 
00148 static void chap_lowerdown(ppp_pcb *pcb) {
00149 
00150     pcb->chap_client.flags = 0;
00151 #if PPP_SERVER
00152     if (pcb->chap_server.flags & TIMEOUT_PENDING)
00153         UNTIMEOUT(chap_timeout, pcb);
00154     pcb->chap_server.flags = 0;
00155 #endif /* PPP_SERVER */
00156 }
00157 
00158 #if PPP_SERVER
00159 /*
00160  * chap_auth_peer - Start authenticating the peer.
00161  * If the lower layer is already up, we start sending challenges,
00162  * otherwise we wait for the lower layer to come up.
00163  */
00164 void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code) {
00165     const struct chap_digest_type *dp;
00166     int i;
00167 
00168     if (pcb->chap_server.flags & AUTH_STARTED) {
00169         ppp_error("CHAP: peer authentication already started!");
00170         return;
00171     }
00172     for (i = 0; (dp = chap_digests[i]) != NULL; ++i)
00173         if (dp->code == digest_code)
00174             break;
00175     if (dp == NULL)
00176         ppp_fatal("CHAP digest 0x%x requested but not available",
00177               digest_code);
00178 
00179     pcb->chap_server.digest = dp;
00180     pcb->chap_server.name = our_name;
00181     /* Start with a random ID value */
00182     pcb->chap_server.id = magic();
00183     pcb->chap_server.flags |= AUTH_STARTED;
00184     if (pcb->chap_server.flags & LOWERUP)
00185         chap_timeout(pcb);
00186 }
00187 #endif /* PPP_SERVER */
00188 
00189 /*
00190  * chap_auth_with_peer - Prepare to authenticate ourselves to the peer.
00191  * There isn't much to do until we receive a challenge.
00192  */
00193 void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code) {
00194     const struct chap_digest_type *dp;
00195     int i;
00196 
00197     if(NULL == our_name)
00198         return;
00199 
00200     if (pcb->chap_client.flags & AUTH_STARTED) {
00201         ppp_error("CHAP: authentication with peer already started!");
00202         return;
00203     }
00204     for (i = 0; (dp = chap_digests[i]) != NULL; ++i)
00205         if (dp->code == digest_code)
00206             break;
00207 
00208     if (dp == NULL)
00209         ppp_fatal("CHAP digest 0x%x requested but not available",
00210               digest_code);
00211 
00212     pcb->chap_client.digest = dp;
00213     pcb->chap_client.name = our_name;
00214     pcb->chap_client.flags |= AUTH_STARTED;
00215 }
00216 
00217 #if PPP_SERVER
00218 /*
00219  * chap_timeout - It's time to send another challenge to the peer.
00220  * This could be either a retransmission of a previous challenge,
00221  * or a new challenge to start re-authentication.
00222  */
00223 static void chap_timeout(void *arg) {
00224     ppp_pcb *pcb = (ppp_pcb*)arg;
00225     struct pbuf *p;
00226 
00227     pcb->chap_server.flags &= ~TIMEOUT_PENDING;
00228     if ((pcb->chap_server.flags & CHALLENGE_VALID) == 0) {
00229         pcb->chap_server.challenge_xmits = 0;
00230         chap_generate_challenge(pcb);
00231         pcb->chap_server.flags |= CHALLENGE_VALID;
00232     } else if (pcb->chap_server.challenge_xmits >= pcb->settings.chap_max_transmits) {
00233         pcb->chap_server.flags &= ~CHALLENGE_VALID;
00234         pcb->chap_server.flags |= AUTH_DONE | AUTH_FAILED;
00235         auth_peer_fail(pcb, PPP_CHAP);
00236         return;
00237     }
00238 
00239     p = pbuf_alloc(PBUF_RAW, (u16_t)(pcb->chap_server.challenge_pktlen), PPP_CTRL_PBUF_TYPE);
00240     if(NULL == p)
00241         return;
00242     if(p->tot_len != p->len) {
00243         pbuf_free(p);
00244         return;
00245     }
00246     MEMCPY(p->payload, pcb->chap_server.challenge, pcb->chap_server.challenge_pktlen);
00247     ppp_write(pcb, p);
00248     ++pcb->chap_server.challenge_xmits;
00249     pcb->chap_server.flags |= TIMEOUT_PENDING;
00250     TIMEOUT(chap_timeout, arg, pcb->settings.chap_timeout_time);
00251 }
00252 
00253 /*
00254  * chap_generate_challenge - generate a challenge string and format
00255  * the challenge packet in pcb->chap_server.challenge_pkt.
00256  */
00257 static void chap_generate_challenge(ppp_pcb *pcb) {
00258     int clen = 1, nlen, len;
00259     unsigned char *p;
00260 
00261     p = pcb->chap_server.challenge;
00262     MAKEHEADER(p, PPP_CHAP);
00263     p += CHAP_HDRLEN;
00264     pcb->chap_server.digest->generate_challenge(pcb, p);
00265     clen = *p;
00266     nlen = strlen(pcb->chap_server.name);
00267     memcpy(p + 1 + clen, pcb->chap_server.name, nlen);
00268 
00269     len = CHAP_HDRLEN + 1 + clen + nlen;
00270     pcb->chap_server.challenge_pktlen = PPP_HDRLEN + len;
00271 
00272     p = pcb->chap_server.challenge + PPP_HDRLEN;
00273     p[0] = CHAP_CHALLENGE;
00274     p[1] = ++pcb->chap_server.id;
00275     p[2] = len >> 8;
00276     p[3] = len;
00277 }
00278 
00279 /*
00280  * chap_handle_response - check the response to our challenge.
00281  */
00282 static void  chap_handle_response(ppp_pcb *pcb, int id,
00283              unsigned char *pkt, int len) {
00284     int response_len, ok, mlen;
00285     const unsigned char *response;
00286     unsigned char *outp;
00287     struct pbuf *p;
00288     const char *name = NULL;    /* initialized to shut gcc up */
00289 #if 0 /* UNUSED */
00290     int (*verifier)(const char *, const char *, int, const struct chap_digest_type *,
00291         const unsigned char *, const unsigned char *, char *, int);
00292 #endif /* UNUSED */
00293     char rname[MAXNAMELEN+1];
00294     char message[256];
00295 
00296     if ((pcb->chap_server.flags & LOWERUP) == 0)
00297         return;
00298     if (id != pcb->chap_server.challenge[PPP_HDRLEN+1] || len < 2)
00299         return;
00300     if (pcb->chap_server.flags & CHALLENGE_VALID) {
00301         response = pkt;
00302         GETCHAR(response_len, pkt);
00303         len -= response_len + 1;    /* length of name */
00304         name = (char *)pkt + response_len;
00305         if (len < 0)
00306             return;
00307 
00308         if (pcb->chap_server.flags & TIMEOUT_PENDING) {
00309             pcb->chap_server.flags &= ~TIMEOUT_PENDING;
00310             UNTIMEOUT(chap_timeout, pcb);
00311         }
00312 #if PPP_REMOTENAME
00313         if (pcb->settings.explicit_remote) {
00314             name = pcb->remote_name;
00315         } else
00316 #endif /* PPP_REMOTENAME */
00317         {
00318             /* Null terminate and clean remote name. */
00319             ppp_slprintf(rname, sizeof(rname), "%.*v", len, name);
00320             name = rname;
00321         }
00322 
00323 #if 0 /* UNUSED */
00324         if (chap_verify_hook)
00325             verifier = chap_verify_hook;
00326         else
00327             verifier = chap_verify_response;
00328         ok = (*verifier)(name, pcb->chap_server.name, id, pcb->chap_server.digest,
00329                  pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN,
00330                  response, pcb->chap_server.message, sizeof(pcb->chap_server.message));
00331 #endif /* UNUSED */
00332         ok = chap_verify_response(pcb, name, pcb->chap_server.name, id, pcb->chap_server.digest,
00333                     pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN,
00334                     response, message, sizeof(message));
00335 #if 0 /* UNUSED */
00336         if (!ok || !auth_number()) {
00337 #endif /* UNUSED */
00338         if (!ok) {
00339             pcb->chap_server.flags |= AUTH_FAILED;
00340             ppp_warn("Peer %q failed CHAP authentication", name);
00341         }
00342     } else if ((pcb->chap_server.flags & AUTH_DONE) == 0)
00343         return;
00344 
00345     /* send the response */
00346     mlen = strlen(message);
00347     len = CHAP_HDRLEN + mlen;
00348     p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +len), PPP_CTRL_PBUF_TYPE);
00349     if(NULL == p)
00350         return;
00351     if(p->tot_len != p->len) {
00352         pbuf_free(p);
00353         return;
00354     }
00355 
00356     outp = (unsigned char *)p->payload;
00357     MAKEHEADER(outp, PPP_CHAP);
00358 
00359     outp[0] = (pcb->chap_server.flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS;
00360     outp[1] = id;
00361     outp[2] = len >> 8;
00362     outp[3] = len;
00363     if (mlen > 0)
00364         memcpy(outp + CHAP_HDRLEN, message, mlen);
00365     ppp_write(pcb, p);
00366 
00367     if (pcb->chap_server.flags & CHALLENGE_VALID) {
00368         pcb->chap_server.flags &= ~CHALLENGE_VALID;
00369         if (!(pcb->chap_server.flags & AUTH_DONE) && !(pcb->chap_server.flags & AUTH_FAILED)) {
00370 
00371 #if 0 /* UNUSED */
00372             /*
00373              * Auth is OK, so now we need to check session restrictions
00374              * to ensure everything is OK, but only if we used a
00375              * plugin, and only if we're configured to check.  This
00376              * allows us to do PAM checks on PPP servers that
00377              * authenticate against ActiveDirectory, and use AD for
00378              * account info (like when using Winbind integrated with
00379              * PAM).
00380              */
00381             if (session_mgmt &&
00382             session_check(name, NULL, devnam, NULL) == 0) {
00383             pcb->chap_server.flags |= AUTH_FAILED;
00384             ppp_warn("Peer %q failed CHAP Session verification", name);
00385             }
00386 #endif /* UNUSED */
00387 
00388         }
00389         if (pcb->chap_server.flags & AUTH_FAILED) {
00390             auth_peer_fail(pcb, PPP_CHAP);
00391         } else {
00392             if ((pcb->chap_server.flags & AUTH_DONE) == 0)
00393                 auth_peer_success(pcb, PPP_CHAP,
00394                           pcb->chap_server.digest->code,
00395                           name, strlen(name));
00396             if (pcb->settings.chap_rechallenge_time) {
00397                 pcb->chap_server.flags |= TIMEOUT_PENDING;
00398                 TIMEOUT(chap_timeout, pcb,
00399                     pcb->settings.chap_rechallenge_time);
00400             }
00401         }
00402         pcb->chap_server.flags |= AUTH_DONE;
00403     }
00404 }
00405 
00406 /*
00407  * chap_verify_response - check whether the peer's response matches
00408  * what we think it should be.  Returns 1 if it does (authentication
00409  * succeeded), or 0 if it doesn't.
00410  */
00411 static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id,
00412              const struct chap_digest_type *digest,
00413              const unsigned char *challenge, const unsigned char *response,
00414              char *message, int message_space) {
00415     int ok;
00416     unsigned char secret[MAXSECRETLEN];
00417     int secret_len;
00418 
00419     /* Get the secret that the peer is supposed to know */
00420     if (!get_secret(pcb, name, ourname, (char *)secret, &secret_len, 1)) {
00421         ppp_error("No CHAP secret found for authenticating %q", name);
00422         return 0;
00423     }
00424     ok = digest->verify_response(pcb, id, name, secret, secret_len, challenge,
00425                      response, message, message_space);
00426     memset(secret, 0, sizeof(secret));
00427 
00428     return ok;
00429 }
00430 #endif /* PPP_SERVER */
00431 
00432 /*
00433  * chap_respond - Generate and send a response to a challenge.
00434  */
00435 static void chap_respond(ppp_pcb *pcb, int id,
00436          unsigned char *pkt, int len) {
00437     int clen, nlen;
00438     int secret_len;
00439     struct pbuf *p;
00440     u_char *outp;
00441     char rname[MAXNAMELEN+1];
00442     char secret[MAXSECRETLEN+1];
00443 
00444     p = pbuf_alloc(PBUF_RAW, (u16_t)(RESP_MAX_PKTLEN), PPP_CTRL_PBUF_TYPE);
00445     if(NULL == p)
00446         return;
00447     if(p->tot_len != p->len) {
00448         pbuf_free(p);
00449         return;
00450     }
00451 
00452     if ((pcb->chap_client.flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED))
00453         return;     /* not ready */
00454     if (len < 2 || len < pkt[0] + 1)
00455         return;     /* too short */
00456     clen = pkt[0];
00457     nlen = len - (clen + 1);
00458 
00459     /* Null terminate and clean remote name. */
00460     ppp_slprintf(rname, sizeof(rname), "%.*v", nlen, pkt + clen + 1);
00461 
00462 #if PPP_REMOTENAME
00463     /* Microsoft doesn't send their name back in the PPP packet */
00464     if (pcb->settings.explicit_remote || (pcb->settings.remote_name[0] != 0 && rname[0] == 0))
00465         strlcpy(rname, pcb->settings.remote_name, sizeof(rname));
00466 #endif /* PPP_REMOTENAME */
00467 
00468     /* get secret for authenticating ourselves with the specified host */
00469     if (!get_secret(pcb, pcb->chap_client.name, rname, secret, &secret_len, 0)) {
00470         secret_len = 0; /* assume null secret if can't find one */
00471         ppp_warn("No CHAP secret found for authenticating us to %q", rname);
00472     }
00473 
00474     outp = (u_char*)p->payload;
00475     MAKEHEADER(outp, PPP_CHAP);
00476     outp += CHAP_HDRLEN;
00477 
00478     pcb->chap_client.digest->make_response(pcb, outp, id, pcb->chap_client.name, pkt,
00479                   secret, secret_len, pcb->chap_client.priv);
00480     memset(secret, 0, secret_len);
00481 
00482     clen = *outp;
00483     nlen = strlen(pcb->chap_client.name);
00484     memcpy(outp + clen + 1, pcb->chap_client.name, nlen);
00485 
00486     outp = (u_char*)p->payload + PPP_HDRLEN;
00487     len = CHAP_HDRLEN + clen + 1 + nlen;
00488     outp[0] = CHAP_RESPONSE;
00489     outp[1] = id;
00490     outp[2] = len >> 8;
00491     outp[3] = len;
00492 
00493     pbuf_realloc(p, PPP_HDRLEN + len);
00494     ppp_write(pcb, p);
00495 }
00496 
00497 static void chap_handle_status(ppp_pcb *pcb, int code, int id,
00498            unsigned char *pkt, int len) {
00499     const char *msg = NULL;
00500     LWIP_UNUSED_ARG(id);
00501 
00502     if ((pcb->chap_client.flags & (AUTH_DONE|AUTH_STARTED|LOWERUP))
00503         != (AUTH_STARTED|LOWERUP))
00504         return;
00505     pcb->chap_client.flags |= AUTH_DONE;
00506 
00507     if (code == CHAP_SUCCESS) {
00508         /* used for MS-CHAP v2 mutual auth, yuck */
00509         if (pcb->chap_client.digest->check_success != NULL) {
00510             if (!(*pcb->chap_client.digest->check_success)(pcb, pkt, len, pcb->chap_client.priv))
00511                 code = CHAP_FAILURE;
00512         } else
00513             msg = "CHAP authentication succeeded";
00514     } else {
00515         if (pcb->chap_client.digest->handle_failure != NULL)
00516             (*pcb->chap_client.digest->handle_failure)(pcb, pkt, len);
00517         else
00518             msg = "CHAP authentication failed";
00519     }
00520     if (msg) {
00521         if (len > 0)
00522             ppp_info("%s: %.*v", msg, len, pkt);
00523         else
00524             ppp_info("%s", msg);
00525     }
00526     if (code == CHAP_SUCCESS)
00527         auth_withpeer_success(pcb, PPP_CHAP, pcb->chap_client.digest->code);
00528     else {
00529         pcb->chap_client.flags |= AUTH_FAILED;
00530         ppp_error("CHAP authentication failed");
00531         auth_withpeer_fail(pcb, PPP_CHAP);
00532     }
00533 }
00534 
00535 static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen) {
00536     unsigned char code, id;
00537     int len;
00538 
00539     if (pktlen < CHAP_HDRLEN)
00540         return;
00541     GETCHAR(code, pkt);
00542     GETCHAR(id, pkt);
00543     GETSHORT(len, pkt);
00544     if (len < CHAP_HDRLEN || len > pktlen)
00545         return;
00546     len -= CHAP_HDRLEN;
00547 
00548     switch (code) {
00549     case CHAP_CHALLENGE:
00550         chap_respond(pcb, id, pkt, len);
00551         break;
00552 #if PPP_SERVER
00553     case CHAP_RESPONSE:
00554         chap_handle_response(pcb, id, pkt, len);
00555         break;
00556 #endif /* PPP_SERVER */
00557     case CHAP_FAILURE:
00558     case CHAP_SUCCESS:
00559         chap_handle_status(pcb, code, id, pkt, len);
00560         break;
00561     default:
00562         break;
00563     }
00564 }
00565 
00566 static void chap_protrej(ppp_pcb *pcb) {
00567 
00568 #if PPP_SERVER
00569     if (pcb->chap_server.flags & TIMEOUT_PENDING) {
00570         pcb->chap_server.flags &= ~TIMEOUT_PENDING;
00571         UNTIMEOUT(chap_timeout, pcb);
00572     }
00573     if (pcb->chap_server.flags & AUTH_STARTED) {
00574         pcb->chap_server.flags = 0;
00575         auth_peer_fail(pcb, PPP_CHAP);
00576     }
00577 #endif /* PPP_SERVER */
00578     if ((pcb->chap_client.flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) {
00579         pcb->chap_client.flags &= ~AUTH_STARTED;
00580         ppp_error("CHAP authentication failed due to protocol-reject");
00581         auth_withpeer_fail(pcb, PPP_CHAP);
00582     }
00583 }
00584 
00585 #if PRINTPKT_SUPPORT
00586 /*
00587  * chap_print_pkt - print the contents of a CHAP packet.
00588  */
00589 static const char* const chap_code_names[] = {
00590     "Challenge", "Response", "Success", "Failure"
00591 };
00592 
00593 static int chap_print_pkt(const unsigned char *p, int plen,
00594            void (*printer) (void *, const char *, ...), void *arg) {
00595     int code, id, len;
00596     int clen, nlen;
00597     unsigned char x;
00598 
00599     if (plen < CHAP_HDRLEN)
00600         return 0;
00601     GETCHAR(code, p);
00602     GETCHAR(id, p);
00603     GETSHORT(len, p);
00604     if (len < CHAP_HDRLEN || len > plen)
00605         return 0;
00606 
00607     if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(chap_code_names))
00608         printer(arg, " %s", chap_code_names[code-1]);
00609     else
00610         printer(arg, " code=0x%x", code);
00611     printer(arg, " id=0x%x", id);
00612     len -= CHAP_HDRLEN;
00613     switch (code) {
00614     case CHAP_CHALLENGE:
00615     case CHAP_RESPONSE:
00616         if (len < 1)
00617             break;
00618         clen = p[0];
00619         if (len < clen + 1)
00620             break;
00621         ++p;
00622         nlen = len - clen - 1;
00623         printer(arg, " <");
00624         for (; clen > 0; --clen) {
00625             GETCHAR(x, p);
00626             printer(arg, "%.2x", x);
00627         }
00628         printer(arg, ">, name = ");
00629         ppp_print_string(p, nlen, printer, arg);
00630         break;
00631     case CHAP_FAILURE:
00632     case CHAP_SUCCESS:
00633         printer(arg, " ");
00634         ppp_print_string(p, len, printer, arg);
00635         break;
00636     default:
00637         for (clen = len; clen > 0; --clen) {
00638             GETCHAR(x, p);
00639             printer(arg, " %.2x", x);
00640         }
00641         /* no break */
00642     }
00643 
00644     return len + CHAP_HDRLEN;
00645 }
00646 #endif /* PRINTPKT_SUPPORT */
00647 
00648 const struct protent chap_protent = {
00649     PPP_CHAP,
00650     chap_init,
00651     chap_input,
00652     chap_protrej,
00653     chap_lowerup,
00654     chap_lowerdown,
00655     NULL,       /* open */
00656     NULL,       /* close */
00657 #if PRINTPKT_SUPPORT
00658     chap_print_pkt,
00659 #endif /* PRINTPKT_SUPPORT */
00660 #if PPP_DATAINPUT
00661     NULL,       /* datainput */
00662 #endif /* PPP_DATAINPUT */
00663 #if PRINTPKT_SUPPORT
00664     "CHAP",     /* name */
00665     NULL,       /* data_name */
00666 #endif /* PRINTPKT_SUPPORT */
00667 #if PPP_OPTIONS
00668     chap_option_list,
00669     NULL,       /* check_options */
00670 #endif /* PPP_OPTIONS */
00671 #if DEMAND_SUPPORT
00672     NULL,
00673     NULL
00674 #endif /* DEMAND_SUPPORT */
00675 };
00676 
00677 #endif /* PPP_SUPPORT && CHAP_SUPPORT */