31 #include "netif/ppp/ppp_opts.h" 32 #if PPP_SUPPORT && CHAP_SUPPORT 39 #include "netif/ppp/ppp_impl.h" 45 #include "netif/ppp/chap-new.h" 46 #include "netif/ppp/chap-md5.h" 48 #include "netif/ppp/chap_ms.h" 50 #include "netif/ppp/magic.h" 54 int (*chap_verify_hook)(
const char *name,
const char *ourname,
int id,
55 const struct chap_digest_type *digest,
56 const unsigned char *challenge,
const unsigned char *response,
57 char *message,
int message_space) = NULL;
64 static option_t chap_option_list[] = {
65 {
"chap-restart", o_int, &chap_timeout_time,
66 "Set timeout for CHAP", OPT_PRIO },
67 {
"chap-max-challenge", o_int, &pcb->settings.chap_max_transmits,
68 "Set max #xmits for challenge", OPT_PRIO },
69 {
"chap-interval", o_int, &pcb->settings.chap_rechallenge_time,
70 "Set interval for rechallenge", OPT_PRIO },
78 #define AUTH_STARTED 2 81 #define TIMEOUT_PENDING 0x10 82 #define CHALLENGE_VALID 0x20 87 static void chap_init(ppp_pcb *pcb);
88 static void chap_lowerup(ppp_pcb *pcb);
89 static void chap_lowerdown(ppp_pcb *pcb);
91 static void chap_timeout(
void *arg);
92 static void chap_generate_challenge(ppp_pcb *pcb);
93 static void chap_handle_response(ppp_pcb *pcb,
int code,
94 unsigned char *pkt,
int len);
95 static int chap_verify_response(ppp_pcb *pcb,
const char *name,
const char *ourname,
int id,
96 const struct chap_digest_type *digest,
97 const unsigned char *challenge,
const unsigned char *response,
98 char *message,
int message_space);
100 static void chap_respond(ppp_pcb *pcb,
int id,
101 unsigned char *pkt,
int len);
102 static void chap_handle_status(ppp_pcb *pcb,
int code,
int id,
103 unsigned char *pkt,
int len);
104 static void chap_protrej(ppp_pcb *pcb);
105 static void chap_input(ppp_pcb *pcb,
unsigned char *pkt,
int pktlen);
107 static int chap_print_pkt(
const unsigned char *p,
int plen,
108 void (*printer) (
void *,
const char *, ...),
void *arg);
112 static const struct chap_digest_type*
const chap_digests[] = {
124 static void chap_init(ppp_pcb *pcb) {
128 memset(&pcb->chap_client, 0,
sizeof(chap_client_state));
130 memset(&pcb->chap_server, 0,
sizeof(chap_server_state));
138 static void chap_lowerup(ppp_pcb *pcb) {
140 pcb->chap_client.flags |= LOWERUP;
142 pcb->chap_server.flags |= LOWERUP;
143 if (pcb->chap_server.flags & AUTH_STARTED)
148 static void chap_lowerdown(ppp_pcb *pcb) {
150 pcb->chap_client.flags = 0;
152 if (pcb->chap_server.flags & TIMEOUT_PENDING)
153 UNTIMEOUT(chap_timeout, pcb);
154 pcb->chap_server.flags = 0;
164 void chap_auth_peer(ppp_pcb *pcb,
const char *our_name,
int digest_code) {
165 const struct chap_digest_type *dp;
168 if (pcb->chap_server.flags & AUTH_STARTED) {
169 ppp_error(
"CHAP: peer authentication already started!");
172 for (i = 0; (dp = chap_digests[i]) != NULL; ++i)
173 if (dp->code == digest_code)
176 ppp_fatal(
"CHAP digest 0x%x requested but not available",
179 pcb->chap_server.digest = dp;
180 pcb->chap_server.name = our_name;
182 pcb->chap_server.id = magic();
183 pcb->chap_server.flags |= AUTH_STARTED;
184 if (pcb->chap_server.flags & LOWERUP)
193 void chap_auth_with_peer(ppp_pcb *pcb,
const char *our_name,
int digest_code) {
194 const struct chap_digest_type *dp;
200 if (pcb->chap_client.flags & AUTH_STARTED) {
201 ppp_error(
"CHAP: authentication with peer already started!");
204 for (i = 0; (dp = chap_digests[i]) != NULL; ++i)
205 if (dp->code == digest_code)
209 ppp_fatal(
"CHAP digest 0x%x requested but not available",
212 pcb->chap_client.digest = dp;
213 pcb->chap_client.name = our_name;
214 pcb->chap_client.flags |= AUTH_STARTED;
223 static void chap_timeout(
void *arg) {
224 ppp_pcb *pcb = (ppp_pcb*)arg;
227 pcb->chap_server.
flags &= ~TIMEOUT_PENDING;
228 if ((pcb->chap_server.flags & CHALLENGE_VALID) == 0) {
229 pcb->chap_server.challenge_xmits = 0;
230 chap_generate_challenge(pcb);
231 pcb->chap_server.flags |= CHALLENGE_VALID;
232 }
else if (pcb->chap_server.challenge_xmits >= pcb->settings.chap_max_transmits) {
233 pcb->chap_server.flags &= ~CHALLENGE_VALID;
234 pcb->chap_server.flags |= AUTH_DONE | AUTH_FAILED;
235 auth_peer_fail(pcb, PPP_CHAP);
239 p =
pbuf_alloc(
PBUF_RAW, (u16_t)(pcb->chap_server.challenge_pktlen), PPP_CTRL_PBUF_TYPE);
246 MEMCPY(p->
payload, pcb->chap_server.challenge, pcb->chap_server.challenge_pktlen);
248 ++pcb->chap_server.challenge_xmits;
249 pcb->chap_server.flags |= TIMEOUT_PENDING;
250 TIMEOUT(chap_timeout, arg, pcb->settings.chap_timeout_time);
257 static void chap_generate_challenge(ppp_pcb *pcb) {
258 int clen = 1, nlen,
len;
261 p = pcb->chap_server.challenge;
262 MAKEHEADER(p, PPP_CHAP);
264 pcb->chap_server.digest->generate_challenge(pcb, p);
266 nlen = strlen(pcb->chap_server.name);
267 memcpy(p + 1 + clen, pcb->chap_server.name, nlen);
269 len = CHAP_HDRLEN + 1 + clen + nlen;
270 pcb->chap_server.challenge_pktlen = PPP_HDRLEN +
len;
272 p = pcb->chap_server.challenge + PPP_HDRLEN;
273 p[0] = CHAP_CHALLENGE;
274 p[1] = ++pcb->chap_server.id;
282 static void chap_handle_response(ppp_pcb *pcb,
int id,
283 unsigned char *pkt,
int len) {
284 int response_len, ok, mlen;
285 const unsigned char *response;
288 const char *name = NULL;
290 int (*verifier)(
const char *,
const char *, int,
const struct chap_digest_type *,
291 const unsigned char *,
const unsigned char *,
char *, int);
293 char rname[MAXNAMELEN+1];
296 if ((pcb->chap_server.flags & LOWERUP) == 0)
298 if (
id != pcb->chap_server.challenge[PPP_HDRLEN+1] || len < 2)
300 if (pcb->chap_server.flags & CHALLENGE_VALID) {
302 GETCHAR(response_len, pkt);
303 len -= response_len + 1;
304 name = (
char *)pkt + response_len;
308 if (pcb->chap_server.flags & TIMEOUT_PENDING) {
309 pcb->chap_server.flags &= ~TIMEOUT_PENDING;
310 UNTIMEOUT(chap_timeout, pcb);
313 if (pcb->settings.explicit_remote) {
314 name = pcb->remote_name;
319 ppp_slprintf(rname,
sizeof(rname),
"%.*v", len, name);
324 if (chap_verify_hook)
325 verifier = chap_verify_hook;
327 verifier = chap_verify_response;
328 ok = (*verifier)(name, pcb->chap_server.name, id, pcb->chap_server.digest,
329 pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN,
330 response, pcb->chap_server.message,
sizeof(pcb->chap_server.message));
332 ok = chap_verify_response(pcb, name, pcb->chap_server.name,
id, pcb->chap_server.digest,
333 pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN,
334 response, message,
sizeof(message));
336 if (!ok || !auth_number()) {
339 pcb->chap_server.flags |= AUTH_FAILED;
340 ppp_warn(
"Peer %q failed CHAP authentication", name);
342 }
else if ((pcb->chap_server.flags & AUTH_DONE) == 0)
346 mlen = strlen(message);
347 len = CHAP_HDRLEN + mlen;
356 outp = (
unsigned char *)p->
payload;
357 MAKEHEADER(outp, PPP_CHAP);
359 outp[0] = (pcb->chap_server.flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS;
364 memcpy(outp + CHAP_HDRLEN, message, mlen);
367 if (pcb->chap_server.flags & CHALLENGE_VALID) {
368 pcb->chap_server.flags &= ~CHALLENGE_VALID;
369 if (!(pcb->chap_server.flags & AUTH_DONE) && !(pcb->chap_server.flags & AUTH_FAILED)) {
382 session_check(name, NULL, devnam, NULL) == 0) {
383 pcb->chap_server.flags |= AUTH_FAILED;
384 ppp_warn(
"Peer %q failed CHAP Session verification", name);
389 if (pcb->chap_server.flags & AUTH_FAILED) {
390 auth_peer_fail(pcb, PPP_CHAP);
392 if ((pcb->chap_server.flags & AUTH_DONE) == 0)
393 auth_peer_success(pcb, PPP_CHAP,
394 pcb->chap_server.digest->code,
396 if (pcb->settings.chap_rechallenge_time) {
397 pcb->chap_server.flags |= TIMEOUT_PENDING;
398 TIMEOUT(chap_timeout, pcb,
399 pcb->settings.chap_rechallenge_time);
402 pcb->chap_server.flags |= AUTH_DONE;
411 static int chap_verify_response(ppp_pcb *pcb,
const char *name,
const char *ourname,
int id,
412 const struct chap_digest_type *digest,
413 const unsigned char *challenge,
const unsigned char *response,
414 char *message,
int message_space) {
416 unsigned char secret[MAXSECRETLEN];
420 if (!get_secret(pcb, name, ourname, (
char *)secret, &secret_len, 1)) {
421 ppp_error(
"No CHAP secret found for authenticating %q", name);
424 ok = digest->verify_response(pcb,
id, name, secret, secret_len, challenge,
425 response, message, message_space);
426 memset(secret, 0,
sizeof(secret));
435 static void chap_respond(ppp_pcb *pcb,
int id,
436 unsigned char *pkt,
int len) {
441 char rname[MAXNAMELEN+1];
442 char secret[MAXSECRETLEN+1];
452 if ((pcb->chap_client.flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED))
454 if (len < 2 || len < pkt[0] + 1)
457 nlen = len - (clen + 1);
460 ppp_slprintf(rname,
sizeof(rname),
"%.*v", nlen, pkt + clen + 1);
464 if (pcb->settings.explicit_remote || (pcb->settings.remote_name[0] != 0 && rname[0] == 0))
465 strlcpy(rname, pcb->settings.remote_name,
sizeof(rname));
469 if (!get_secret(pcb, pcb->chap_client.name, rname, secret, &secret_len, 0)) {
471 ppp_warn(
"No CHAP secret found for authenticating us to %q", rname);
475 MAKEHEADER(outp, PPP_CHAP);
478 pcb->chap_client.digest->make_response(pcb, outp,
id, pcb->chap_client.name, pkt,
479 secret, secret_len, pcb->chap_client.priv);
480 memset(secret, 0, secret_len);
483 nlen = strlen(pcb->chap_client.name);
484 memcpy(outp + clen + 1, pcb->chap_client.name, nlen);
486 outp = (u_char*)p->
payload + PPP_HDRLEN;
487 len = CHAP_HDRLEN + clen + 1 + nlen;
488 outp[0] = CHAP_RESPONSE;
497 static void chap_handle_status(ppp_pcb *pcb,
int code,
int id,
498 unsigned char *pkt,
int len) {
499 const char *msg = NULL;
502 if ((pcb->chap_client.flags & (AUTH_DONE|AUTH_STARTED|LOWERUP))
503 != (AUTH_STARTED|LOWERUP))
505 pcb->chap_client.flags |= AUTH_DONE;
507 if (code == CHAP_SUCCESS) {
509 if (pcb->chap_client.digest->check_success != NULL) {
510 if (!(*pcb->chap_client.digest->check_success)(pcb, pkt, len, pcb->chap_client.priv))
513 msg =
"CHAP authentication succeeded";
515 if (pcb->chap_client.digest->handle_failure != NULL)
516 (*pcb->chap_client.digest->handle_failure)(pcb, pkt, len);
518 msg =
"CHAP authentication failed";
522 ppp_info(
"%s: %.*v", msg, len, pkt);
526 if (code == CHAP_SUCCESS)
527 auth_withpeer_success(pcb, PPP_CHAP, pcb->chap_client.digest->code);
529 pcb->chap_client.flags |= AUTH_FAILED;
530 ppp_error(
"CHAP authentication failed");
531 auth_withpeer_fail(pcb, PPP_CHAP);
535 static void chap_input(ppp_pcb *pcb,
unsigned char *pkt,
int pktlen) {
536 unsigned char code, id;
539 if (pktlen < CHAP_HDRLEN)
544 if (len < CHAP_HDRLEN || len > pktlen)
550 chap_respond(pcb,
id, pkt, len);
554 chap_handle_response(pcb,
id, pkt, len);
559 chap_handle_status(pcb, code,
id, pkt, len);
566 static void chap_protrej(ppp_pcb *pcb) {
569 if (pcb->chap_server.flags & TIMEOUT_PENDING) {
570 pcb->chap_server.flags &= ~TIMEOUT_PENDING;
571 UNTIMEOUT(chap_timeout, pcb);
573 if (pcb->chap_server.flags & AUTH_STARTED) {
574 pcb->chap_server.flags = 0;
575 auth_peer_fail(pcb, PPP_CHAP);
578 if ((pcb->chap_client.flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) {
579 pcb->chap_client.flags &= ~AUTH_STARTED;
580 ppp_error(
"CHAP authentication failed due to protocol-reject");
581 auth_withpeer_fail(pcb, PPP_CHAP);
589 static const char*
const chap_code_names[] = {
590 "Challenge",
"Response",
"Success",
"Failure" 593 static int chap_print_pkt(
const unsigned char *p,
int plen,
594 void (*printer) (
void *,
const char *, ...),
void *arg) {
599 if (plen < CHAP_HDRLEN)
604 if (len < CHAP_HDRLEN || len > plen)
607 if (code >= 1 && code <= (
int)LWIP_ARRAYSIZE(chap_code_names))
608 printer(arg,
" %s", chap_code_names[code-1]);
610 printer(arg,
" code=0x%x", code);
611 printer(arg,
" id=0x%x",
id);
622 nlen = len - clen - 1;
624 for (; clen > 0; --clen) {
626 printer(arg,
"%.2x", x);
628 printer(arg,
">, name = ");
629 ppp_print_string(p, nlen, printer, arg);
634 ppp_print_string(p, len, printer, arg);
637 for (clen = len; clen > 0; --clen) {
639 printer(arg,
" %.2x", x);
644 return len + CHAP_HDRLEN;
648 const struct protent chap_protent = {
void pbuf_realloc(struct pbuf *p, u16_t new_len)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
#define LWIP_UNUSED_ARG(x)
u8_t pbuf_free(struct pbuf *p)