2 * eap.c - Extensible Authentication Protocol for PPP (RFC 2284)
4 * Copyright (c) 2001 by Sun Microsystems, Inc.
7 * Non-exclusive rights to redistribute, modify, translate, and use
8 * this software in source and binary forms, in whole or in part, is
9 * hereby granted, provided that the above copyright notice is
10 * duplicated in any source form, and that neither the name of the
11 * copyright holder nor the author is used to endorse or promote
12 * products derived from this software.
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 * Original version by James Carlson
20 * This implementation of EAP supports MD5-Challenge and SRP-SHA1
21 * authentication styles. Note that support of MD5-Challenge is a
22 * requirement of RFC 2284, and that it's essentially just a
23 * reimplementation of regular RFC 1994 CHAP using EAP messages.
25 * As an authenticator ("server"), there are multiple phases for each
26 * style. In the first phase of each style, the unauthenticated peer
27 * name is queried using the EAP Identity request type. If the
28 * "remotename" option is used, then this phase is skipped, because
29 * the peer's name is presumed to be known.
31 * For MD5-Challenge, there are two phases, and the second phase
32 * consists of sending the challenge itself and handling the
33 * associated response.
35 * For SRP-SHA1, there are four phases. The second sends 's', 'N',
36 * and 'g'. The reply contains 'A'. The third sends 'B', and the
37 * reply contains 'M1'. The forth sends the 'M2' value.
39 * As an authenticatee ("client"), there's just a single phase --
40 * responding to the queries generated by the peer. EAP is an
41 * authenticator-driven protocol.
43 * Based on draft-ietf-pppext-eap-srp-03.txt.
46 #include "netif/ppp/ppp_opts.h"
47 #if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
49 #include "netif/ppp/ppp_impl.h"
50 #include "netif/ppp/eap.h"
51 #include "netif/ppp/magic.h"
52 #include "netif/ppp/pppcrypt.h"
60 #ifndef SHA_DIGESTSIZE
61 #define SHA_DIGESTSIZE 20
65 static char *pn_secret
= NULL
; /* Pseudonym generating secret */
70 * Command-line options.
72 static option_t eap_option_list
[] = {
73 { "eap-restart", o_int
, &eap_states
[0].es_server
.ea_timeout
,
74 "Set retransmit timeout for EAP Requests (server)" },
75 { "eap-max-sreq", o_int
, &eap_states
[0].es_server
.ea_maxrequests
,
76 "Set max number of EAP Requests sent (server)" },
77 { "eap-timeout", o_int
, &eap_states
[0].es_client
.ea_timeout
,
78 "Set time limit for peer EAP authentication" },
79 { "eap-max-rreq", o_int
, &eap_states
[0].es_client
.ea_maxrequests
,
80 "Set max number of EAP Requests allows (client)" },
81 { "eap-interval", o_int
, &eap_states
[0].es_rechallenge
,
82 "Set interval for EAP rechallenge" },
84 { "srp-interval", o_int
, &eap_states
[0].es_lwrechallenge
,
85 "Set interval for SRP lightweight rechallenge" },
86 { "srp-pn-secret", o_string
, &pn_secret
,
87 "Long term pseudonym generation secret" },
88 { "srp-use-pseudonym", o_bool
, &eap_states
[0].es_usepseudo
,
89 "Use pseudonym if offered one by server", 1 },
93 #endif /* PPP_OPTIONS */
96 * Protocol entry points.
98 static void eap_init(ppp_pcb
*pcb
);
99 static void eap_input(ppp_pcb
*pcb
, u_char
*inp
, int inlen
);
100 static void eap_protrej(ppp_pcb
*pcb
);
101 static void eap_lowerup(ppp_pcb
*pcb
);
102 static void eap_lowerdown(ppp_pcb
*pcb
);
104 static int eap_printpkt(const u_char
*inp
, int inlen
,
105 void (*)(void *arg
, const char *fmt
, ...), void *arg
);
106 #endif /* PRINTPKT_SUPPORT */
108 const struct protent eap_protent
= {
109 PPP_EAP
, /* protocol number */
110 eap_init
, /* initialization procedure */
111 eap_input
, /* process a received packet */
112 eap_protrej
, /* process a received protocol-reject */
113 eap_lowerup
, /* lower layer has gone up */
114 eap_lowerdown
, /* lower layer has gone down */
115 NULL
, /* open the protocol */
116 NULL
, /* close the protocol */
118 eap_printpkt
, /* print a packet in readable form */
119 #endif /* PRINTPKT_SUPPORT */
121 NULL
, /* process a received data packet */
122 #endif /* PPP_DATAINPUT */
124 "EAP", /* text name of protocol */
125 NULL
, /* text name of corresponding data protocol */
126 #endif /* PRINTPKT_SUPPORT */
128 eap_option_list
, /* list of command-line options */
129 NULL
, /* check requested options; assign defaults */
130 #endif /* PPP_OPTIONS */
132 NULL
, /* configure interface for demand-dial */
133 NULL
/* say whether to bring up link for this pkt */
134 #endif /* DEMAND_SUPPORT */
139 * A well-known 2048 bit modulus.
141 static const u_char wkmodulus
[] = {
142 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
143 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
144 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
145 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
146 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
147 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
148 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
149 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
150 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
151 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
152 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
153 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
154 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
155 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
156 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
157 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
158 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
159 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
160 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
161 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
162 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
163 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
164 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
165 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
166 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
167 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
168 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
169 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
170 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
171 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
172 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
173 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
178 /* Local forward declarations. */
179 static void eap_server_timeout(void *arg
);
180 #endif /* PPP_SERVER */
183 * Convert EAP state code to printable string for debug.
185 static const char * eap_state_name(enum eap_state_code esc
)
187 static const char *state_names
[] = { EAP_STATES
};
189 return (state_names
[(int)esc
]);
193 * eap_init - Initialize state for an EAP user. This is currently
194 * called once by main() during start-up.
196 static void eap_init(ppp_pcb
*pcb
) {
198 BZERO(&pcb
->eap
, sizeof(eap_state
));
200 pcb
->eap
.es_server
.ea_id
= magic();
201 #endif /* PPP_SERVER */
205 * eap_client_timeout - Give up waiting for the peer to send any
208 static void eap_client_timeout(void *arg
) {
209 ppp_pcb
*pcb
= (ppp_pcb
*)arg
;
211 if (!eap_client_active(pcb
))
214 ppp_error("EAP: timeout waiting for Request from peer");
215 auth_withpeer_fail(pcb
, PPP_EAP
);
216 pcb
->eap
.es_client
.ea_state
= eapBadAuth
;
220 * eap_authwithpeer - Authenticate to our peer (behave as client).
222 * Start client state and wait for requests. This is called only
225 void eap_authwithpeer(ppp_pcb
*pcb
, const char *localname
) {
227 if(NULL
== localname
)
230 /* Save the peer name we're given */
231 pcb
->eap
.es_client
.ea_name
= localname
;
232 pcb
->eap
.es_client
.ea_namelen
= strlen(localname
);
234 pcb
->eap
.es_client
.ea_state
= eapListen
;
237 * Start a timer so that if the other end just goes
238 * silent, we don't sit here waiting forever.
240 if (pcb
->settings
.eap_req_time
> 0)
241 TIMEOUT(eap_client_timeout
, pcb
,
242 pcb
->settings
.eap_req_time
);
247 * Format a standard EAP Failure message and send it to the peer.
250 static void eap_send_failure(ppp_pcb
*pcb
) {
254 p
= pbuf_alloc(PBUF_RAW
, (u16_t
)(PPP_HDRLEN
+ EAP_HEADERLEN
), PPP_CTRL_PBUF_TYPE
);
257 if(p
->tot_len
!= p
->len
) {
262 outp
= (u_char
*)p
->payload
;
264 MAKEHEADER(outp
, PPP_EAP
);
266 PUTCHAR(EAP_FAILURE
, outp
);
267 pcb
->eap
.es_server
.ea_id
++;
268 PUTCHAR(pcb
->eap
.es_server
.ea_id
, outp
);
269 PUTSHORT(EAP_HEADERLEN
, outp
);
273 pcb
->eap
.es_server
.ea_state
= eapBadAuth
;
274 auth_peer_fail(pcb
, PPP_EAP
);
278 * Format a standard EAP Success message and send it to the peer.
281 static void eap_send_success(ppp_pcb
*pcb
) {
285 p
= pbuf_alloc(PBUF_RAW
, (u16_t
)(PPP_HDRLEN
+ EAP_HEADERLEN
), PPP_CTRL_PBUF_TYPE
);
288 if(p
->tot_len
!= p
->len
) {
293 outp
= (u_char
*)p
->payload
;
295 MAKEHEADER(outp
, PPP_EAP
);
297 PUTCHAR(EAP_SUCCESS
, outp
);
298 pcb
->eap
.es_server
.ea_id
++;
299 PUTCHAR(pcb
->eap
.es_server
.ea_id
, outp
);
300 PUTSHORT(EAP_HEADERLEN
, outp
);
304 auth_peer_success(pcb
, PPP_EAP
, 0,
305 pcb
->eap
.es_server
.ea_peer
, pcb
->eap
.es_server
.ea_peerlen
);
307 #endif /* PPP_SERVER */
311 * Set DES key according to pseudonym-generating secret and current
315 pncrypt_setkey(int timeoffs
)
320 u_char dig
[SHA_DIGESTSIZE
];
323 if (pn_secret
== NULL
)
325 reftime
= time(NULL
) + timeoffs
;
326 tp
= localtime(&reftime
);
328 SHA1Update(&ctxt
, pn_secret
, strlen(pn_secret
));
329 strftime(tbuf
, sizeof (tbuf
), "%Y%m%d", tp
);
330 SHA1Update(&ctxt
, tbuf
, strlen(tbuf
));
331 SHA1Final(dig
, &ctxt
);
332 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */
333 return (DesSetkey(dig
));
336 static char base64
[] =
337 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
345 b64enc(bs
, inp
, inlen
, outp
)
354 bs
->bs_bits
= (bs
->bs_bits
<< 8) | *inp
++;
357 if (bs
->bs_offs
>= 24) {
358 *outp
++ = base64
[(bs
->bs_bits
>> 18) & 0x3F];
359 *outp
++ = base64
[(bs
->bs_bits
>> 12) & 0x3F];
360 *outp
++ = base64
[(bs
->bs_bits
>> 6) & 0x3F];
361 *outp
++ = base64
[bs
->bs_bits
& 0x3F];
377 if (bs
->bs_offs
== 8) {
378 *outp
++ = base64
[(bs
->bs_bits
>> 2) & 0x3F];
379 *outp
++ = base64
[(bs
->bs_bits
<< 4) & 0x3F];
381 } else if (bs
->bs_offs
== 16) {
382 *outp
++ = base64
[(bs
->bs_bits
>> 10) & 0x3F];
383 *outp
++ = base64
[(bs
->bs_bits
>> 4) & 0x3F];
384 *outp
++ = base64
[(bs
->bs_bits
<< 2) & 0x3F];
393 b64dec(bs
, inp
, inlen
, outp
)
403 if ((cp
= strchr(base64
, *inp
++)) == NULL
)
405 bs
->bs_bits
= (bs
->bs_bits
<< 6) | (cp
- base64
);
408 if (bs
->bs_offs
>= 8) {
409 *outp
++ = bs
->bs_bits
>> (bs
->bs_offs
- 8);
420 * Assume that current waiting server state is complete and figure
421 * next state to use based on available authentication data. 'status'
422 * indicates if there was an error in handling the last query. It is
423 * 0 for success and non-zero for failure.
425 static void eap_figure_next_state(ppp_pcb
*pcb
, int status
) {
427 unsigned char secbuf
[MAXSECRETLEN
], clear
[8], *sp
, *dp
;
429 struct t_confent
*tce
, mytce
;
432 int id
, i
, plen
, toffs
;
437 pcb
->settings
.eap_timeout_time
= pcb
->eap
.es_savedtime
;
438 switch (pcb
->eap
.es_server
.ea_state
) {
444 /* Discard any previous session. */
445 ts
= (struct t_server
*)pcb
->eap
.es_server
.ea_session
;
448 pcb
->eap
.es_server
.ea_session
= NULL
;
449 pcb
->eap
.es_server
.ea_skey
= NULL
;
453 pcb
->eap
.es_server
.ea_state
= eapBadAuth
;
457 /* If we've got a pseudonym, try to decode to real name. */
458 if (pcb
->eap
.es_server
.ea_peerlen
> SRP_PSEUDO_LEN
&&
459 strncmp(pcb
->eap
.es_server
.ea_peer
, SRP_PSEUDO_ID
,
460 SRP_PSEUDO_LEN
) == 0 &&
461 (pcb
->eap
.es_server
.ea_peerlen
- SRP_PSEUDO_LEN
) * 3 / 4 <
463 BZERO(&bs
, sizeof (bs
));
465 pcb
->eap
.es_server
.ea_peer
+ SRP_PSEUDO_LEN
,
466 pcb
->eap
.es_server
.ea_peerlen
- SRP_PSEUDO_LEN
,
469 for (i
= 0; i
< 5; i
++) {
470 pncrypt_setkey(toffs
);
472 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */
473 if (!DesDecrypt(secbuf
, clear
)) {
474 ppp_dbglog("no DES here; cannot decode "
478 id
= *(unsigned char *)clear
;
479 if (id
+ 1 <= plen
&& id
+ 9 > plen
)
482 if (plen
% 8 == 0 && i
< 5) {
484 * Note that this is always shorter than the
485 * original stored string, so there's no need
488 if ((i
= plen
= *(unsigned char *)clear
) > 7)
490 pcb
->eap
.es_server
.ea_peerlen
= plen
;
491 dp
= (unsigned char *)pcb
->eap
.es_server
.ea_peer
;
492 MEMCPY(dp
, clear
+ 1, i
);
497 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */
498 (void) DesDecrypt(sp
, dp
);
503 pcb
->eap
.es_server
.ea_peer
[
504 pcb
->eap
.es_server
.ea_peerlen
] = '\0';
505 ppp_dbglog("decoded pseudonym to \"%.*q\"",
506 pcb
->eap
.es_server
.ea_peerlen
,
507 pcb
->eap
.es_server
.ea_peer
);
509 ppp_dbglog("failed to decode real name");
510 /* Stay in eapIdentfy state; requery */
514 /* Look up user in secrets database. */
515 if (get_srp_secret(pcb
->eap
.es_unit
, pcb
->eap
.es_server
.ea_peer
,
516 pcb
->eap
.es_server
.ea_name
, (char *)secbuf
, 1) != 0) {
517 /* Set up default in case SRP entry is bad */
518 pcb
->eap
.es_server
.ea_state
= eapMD5Chall
;
519 /* Get t_confent based on index in srp-secrets */
520 id
= strtol((char *)secbuf
, &cp
, 10);
521 if (*cp
++ != ':' || id
< 0)
525 mytce
.modulus
.data
= (u_char
*)wkmodulus
;
526 mytce
.modulus
.len
= sizeof (wkmodulus
);
527 mytce
.generator
.data
= (u_char
*)"\002";
528 mytce
.generator
.len
= 1;
530 } else if ((tce
= gettcid(id
)) != NULL
) {
532 * Client will have to verify this modulus/
533 * generator combination, and that will take
534 * a while. Lengthen the timeout here.
536 if (pcb
->settings
.eap_timeout_time
> 0 &&
537 pcb
->settings
.eap_timeout_time
< 30)
538 pcb
->settings
.eap_timeout_time
= 30;
542 if ((cp2
= strchr(cp
, ':')) == NULL
)
545 tpw
.pebuf
.name
= pcb
->eap
.es_server
.ea_peer
;
546 tpw
.pebuf
.password
.len
= t_fromb64((char *)tpw
.pwbuf
,
548 tpw
.pebuf
.password
.data
= tpw
.pwbuf
;
549 tpw
.pebuf
.salt
.len
= t_fromb64((char *)tpw
.saltbuf
,
551 tpw
.pebuf
.salt
.data
= tpw
.saltbuf
;
552 if ((ts
= t_serveropenraw(&tpw
.pebuf
, tce
)) == NULL
)
554 pcb
->eap
.es_server
.ea_session
= (void *)ts
;
555 pcb
->eap
.es_server
.ea_state
= eapSRP1
;
556 vals
[0] = pcb
->eap
.es_server
.ea_id
+ 1;
558 t_serveraddexdata(ts
, vals
, 2);
559 /* Generate B; must call before t_servergetkey() */
564 pcb
->eap
.es_server
.ea_state
= eapMD5Chall
;
569 ts
= (struct t_server
*)pcb
->eap
.es_server
.ea_session
;
570 if (ts
!= NULL
&& status
!= 0) {
572 pcb
->eap
.es_server
.ea_session
= NULL
;
573 pcb
->eap
.es_server
.ea_skey
= NULL
;
577 pcb
->eap
.es_server
.ea_state
= eapMD5Chall
;
578 } else if (status
!= 0 || pcb
->eap
.es_server
.ea_session
== NULL
) {
579 pcb
->eap
.es_server
.ea_state
= eapBadAuth
;
581 pcb
->eap
.es_server
.ea_state
= eapSRP2
;
587 ts
= (struct t_server
*)pcb
->eap
.es_server
.ea_session
;
588 if (ts
!= NULL
&& status
!= 0) {
590 pcb
->eap
.es_server
.ea_session
= NULL
;
591 pcb
->eap
.es_server
.ea_skey
= NULL
;
594 if (status
!= 0 || pcb
->eap
.es_server
.ea_session
== NULL
) {
595 pcb
->eap
.es_server
.ea_state
= eapBadAuth
;
597 pcb
->eap
.es_server
.ea_state
= eapSRP3
;
604 ts
= (struct t_server
*)pcb
->eap
.es_server
.ea_session
;
605 if (ts
!= NULL
&& status
!= 0) {
607 pcb
->eap
.es_server
.ea_session
= NULL
;
608 pcb
->eap
.es_server
.ea_skey
= NULL
;
611 if (status
!= 0 || pcb
->eap
.es_server
.ea_session
== NULL
) {
612 pcb
->eap
.es_server
.ea_state
= eapBadAuth
;
614 pcb
->eap
.es_server
.ea_state
= eapOpen
;
620 pcb
->eap
.es_server
.ea_state
= eapBadAuth
;
622 pcb
->eap
.es_server
.ea_state
= eapOpen
;
627 pcb
->eap
.es_server
.ea_state
= eapBadAuth
;
630 if (pcb
->eap
.es_server
.ea_state
== eapBadAuth
)
631 eap_send_failure(pcb
);
635 * Format an EAP Request message and send it to the peer. Message
636 * type depends on current state. (Server operation)
638 static void eap_send_request(ppp_pcb
*pcb
) {
647 u_char clear
[8], cipher
[8], dig
[SHA_DIGESTSIZE
], *optr
, *cp
;
653 /* Handle both initial auth and restart */
654 if (pcb
->eap
.es_server
.ea_state
< eapIdentify
&&
655 pcb
->eap
.es_server
.ea_state
!= eapInitial
) {
656 pcb
->eap
.es_server
.ea_state
= eapIdentify
;
658 if (pcb
->settings
.explicit_remote
&& pcb
->remote_name
) {
660 * If we already know the peer's
661 * unauthenticated name, then there's no
662 * reason to ask. Go to next state instead.
664 int len
= (int)strlen(pcb
->remote_name
);
665 if (len
> MAXNAMELEN
) {
668 MEMCPY(pcb
->eap
.es_server
.ea_peer
, pcb
->remote_name
, len
);
669 pcb
->eap
.es_server
.ea_peer
[len
] = '\0';
670 pcb
->eap
.es_server
.ea_peerlen
= len
;
671 eap_figure_next_state(pcb
, 0);
673 #endif /* PPP_REMOTENAME */
676 if (pcb
->settings
.eap_max_transmits
> 0 &&
677 pcb
->eap
.es_server
.ea_requests
>= pcb
->settings
.eap_max_transmits
) {
678 if (pcb
->eap
.es_server
.ea_responses
> 0)
679 ppp_error("EAP: too many Requests sent");
681 ppp_error("EAP: no response to Requests");
682 eap_send_failure(pcb
);
686 p
= pbuf_alloc(PBUF_RAW
, (u16_t
)(PPP_CTRL_PBUF_MAX_SIZE
), PPP_CTRL_PBUF_TYPE
);
689 if(p
->tot_len
!= p
->len
) {
694 outp
= (u_char
*)p
->payload
;
696 MAKEHEADER(outp
, PPP_EAP
);
698 PUTCHAR(EAP_REQUEST
, outp
);
699 PUTCHAR(pcb
->eap
.es_server
.ea_id
, outp
);
703 switch (pcb
->eap
.es_server
.ea_state
) {
705 PUTCHAR(EAPT_IDENTITY
, outp
);
708 MEMCPY(outp
, str
, len
);
713 PUTCHAR(EAPT_MD5CHAP
, outp
);
715 * pick a random challenge length between
716 * EAP_MIN_CHALLENGE_LENGTH and EAP_MAX_CHALLENGE_LENGTH
718 pcb
->eap
.es_challen
= EAP_MIN_CHALLENGE_LENGTH
+
719 magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH
);
720 PUTCHAR(pcb
->eap
.es_challen
, outp
);
721 magic_random_bytes(pcb
->eap
.es_challenge
, pcb
->eap
.es_challen
);
722 MEMCPY(outp
, pcb
->eap
.es_challenge
, pcb
->eap
.es_challen
);
723 INCPTR(pcb
->eap
.es_challen
, outp
);
724 MEMCPY(outp
, pcb
->eap
.es_server
.ea_name
, pcb
->eap
.es_server
.ea_namelen
);
725 INCPTR(pcb
->eap
.es_server
.ea_namelen
, outp
);
730 PUTCHAR(EAPT_SRP
, outp
);
731 PUTCHAR(EAPSRP_CHALLENGE
, outp
);
733 PUTCHAR(pcb
->eap
.es_server
.ea_namelen
, outp
);
734 MEMCPY(outp
, pcb
->eap
.es_server
.ea_name
, pcb
->eap
.es_server
.ea_namelen
);
735 INCPTR(pcb
->eap
.es_server
.ea_namelen
, outp
);
737 ts
= (struct t_server
*)pcb
->eap
.es_server
.ea_session
;
739 PUTCHAR(ts
->s
.len
, outp
);
740 MEMCPY(outp
, ts
->s
.data
, ts
->s
.len
);
741 INCPTR(ts
->s
.len
, outp
);
743 if (ts
->g
.len
== 1 && ts
->g
.data
[0] == 2) {
746 PUTCHAR(ts
->g
.len
, outp
);
747 MEMCPY(outp
, ts
->g
.data
, ts
->g
.len
);
748 INCPTR(ts
->g
.len
, outp
);
751 if (ts
->n
.len
!= sizeof (wkmodulus
) ||
752 BCMP(ts
->n
.data
, wkmodulus
, sizeof (wkmodulus
)) != 0) {
753 MEMCPY(outp
, ts
->n
.data
, ts
->n
.len
);
754 INCPTR(ts
->n
.len
, outp
);
759 PUTCHAR(EAPT_SRP
, outp
);
760 PUTCHAR(EAPSRP_SKEY
, outp
);
762 ts
= (struct t_server
*)pcb
->eap
.es_server
.ea_session
;
764 MEMCPY(outp
, ts
->B
.data
, ts
->B
.len
);
765 INCPTR(ts
->B
.len
, outp
);
769 PUTCHAR(EAPT_SRP
, outp
);
770 PUTCHAR(EAPSRP_SVALIDATOR
, outp
);
771 PUTLONG(SRPVAL_EBIT
, outp
);
772 ts
= (struct t_server
*)pcb
->eap
.es_server
.ea_session
;
774 MEMCPY(outp
, t_serverresponse(ts
), SHA_DIGESTSIZE
);
775 INCPTR(SHA_DIGESTSIZE
, outp
);
777 if (pncrypt_setkey(0)) {
778 /* Generate pseudonym */
780 cp
= (unsigned char *)pcb
->eap
.es_server
.ea_peer
;
781 if ((j
= i
= pcb
->eap
.es_server
.ea_peerlen
) > 7)
784 MEMCPY(clear
+ 1, cp
, j
);
787 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */
788 if (!DesEncrypt(clear
, cipher
)) {
789 ppp_dbglog("no DES here; not generating pseudonym");
792 BZERO(&b64
, sizeof (b64
));
793 outp
++; /* space for pseudonym length */
794 outp
+= b64enc(&b64
, cipher
, 8, outp
);
796 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */
797 (void) DesEncrypt(cp
, cipher
);
798 outp
+= b64enc(&b64
, cipher
, 8, outp
);
803 MEMCPY(clear
, cp
, i
);
805 magic_random_bytes(cp
, 8-i
);
806 /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */
807 (void) DesEncrypt(clear
, cipher
);
808 outp
+= b64enc(&b64
, cipher
, 8, outp
);
810 outp
+= b64flush(&b64
, outp
);
812 /* Set length and pad out to next 20 octet boundary */
817 magic_random_bytes(outp
, SHA_DIGESTSIZE
-i
);
818 INCPTR(SHA_DIGESTSIZE
-i
, outp
);
821 /* Obscure the pseudonym with SHA1 hash */
823 SHA1Update(&ctxt
, &pcb
->eap
.es_server
.ea_id
, 1);
824 SHA1Update(&ctxt
, pcb
->eap
.es_server
.ea_skey
,
826 SHA1Update(&ctxt
, pcb
->eap
.es_server
.ea_peer
,
827 pcb
->eap
.es_server
.ea_peerlen
);
828 while (optr
< outp
) {
829 SHA1Final(dig
, &ctxt
);
831 while (cp
< dig
+ SHA_DIGESTSIZE
)
834 SHA1Update(&ctxt
, &pcb
->eap
.es_server
.ea_id
, 1);
835 SHA1Update(&ctxt
, pcb
->eap
.es_server
.ea_skey
,
837 SHA1Update(&ctxt
, optr
- SHA_DIGESTSIZE
,
844 PUTCHAR(EAPT_SRP
, outp
);
845 PUTCHAR(EAPSRP_LWRECHALLENGE
, outp
);
846 pcb
->eap
.es_challen
= EAP_MIN_CHALLENGE_LENGTH
+
847 magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH
);
848 magic_random_bytes(pcb
->eap
.es_challenge
, pcb
->eap
.es_challen
);
849 MEMCPY(outp
, pcb
->eap
.es_challenge
, pcb
->eap
.es_challen
);
850 INCPTR(pcb
->eap
.es_challen
, outp
);
858 outlen
= (outp
- (unsigned char*)p
->payload
) - PPP_HDRLEN
;
859 PUTSHORT(outlen
, lenloc
);
861 pbuf_realloc(p
, outlen
+ PPP_HDRLEN
);
864 pcb
->eap
.es_server
.ea_requests
++;
866 if (pcb
->settings
.eap_timeout_time
> 0)
867 TIMEOUT(eap_server_timeout
, pcb
, pcb
->settings
.eap_timeout_time
);
871 * eap_authpeer - Authenticate our peer (behave as server).
873 * Start server state and send first request. This is called only
876 void eap_authpeer(ppp_pcb
*pcb
, const char *localname
) {
878 /* Save the name we're given. */
879 pcb
->eap
.es_server
.ea_name
= localname
;
880 pcb
->eap
.es_server
.ea_namelen
= strlen(localname
);
882 pcb
->eap
.es_savedtime
= pcb
->settings
.eap_timeout_time
;
884 /* Lower layer up yet? */
885 if (pcb
->eap
.es_server
.ea_state
== eapInitial
||
886 pcb
->eap
.es_server
.ea_state
== eapPending
) {
887 pcb
->eap
.es_server
.ea_state
= eapPending
;
891 pcb
->eap
.es_server
.ea_state
= eapPending
;
893 /* ID number not updated here intentionally; hashed into M1 */
894 eap_send_request(pcb
);
898 * eap_server_timeout - Retransmission timer for sending Requests
901 static void eap_server_timeout(void *arg
) {
902 ppp_pcb
*pcb
= (ppp_pcb
*)arg
;
904 if (!eap_server_active(pcb
))
907 /* EAP ID number must not change on timeout. */
908 eap_send_request(pcb
);
912 * When it's time to send rechallenge the peer, this timeout is
913 * called. Once the rechallenge is successful, the response handler
914 * will restart the timer. If it fails, then the link is dropped.
916 static void eap_rechallenge(void *arg
) {
917 ppp_pcb
*pcb
= (ppp_pcb
*)arg
;
919 if (pcb
->eap
.es_server
.ea_state
!= eapOpen
&&
920 pcb
->eap
.es_server
.ea_state
!= eapSRP4
)
923 pcb
->eap
.es_server
.ea_requests
= 0;
924 pcb
->eap
.es_server
.ea_state
= eapIdentify
;
925 eap_figure_next_state(pcb
, 0);
926 pcb
->eap
.es_server
.ea_id
++;
927 eap_send_request(pcb
);
930 static void srp_lwrechallenge(void *arg
) {
931 ppp_pcb
*pcb
= (ppp_pcb
*)arg
;
933 if (pcb
->eap
.es_server
.ea_state
!= eapOpen
||
934 pcb
->eap
.es_server
.ea_type
!= EAPT_SRP
)
937 pcb
->eap
.es_server
.ea_requests
= 0;
938 pcb
->eap
.es_server
.ea_state
= eapSRP4
;
939 pcb
->eap
.es_server
.ea_id
++;
940 eap_send_request(pcb
);
942 #endif /* PPP_SERVER */
945 * eap_lowerup - The lower layer is now up.
947 * This is called before either eap_authpeer or eap_authwithpeer. See
948 * link_established() in auth.c. All that's necessary here is to
949 * return to closed state so that those two routines will do the right
952 static void eap_lowerup(ppp_pcb
*pcb
) {
953 pcb
->eap
.es_client
.ea_state
= eapClosed
;
955 pcb
->eap
.es_server
.ea_state
= eapClosed
;
956 #endif /* PPP_SERVER */
960 * eap_lowerdown - The lower layer is now down.
962 * Cancel all timeouts and return to initial state.
964 static void eap_lowerdown(ppp_pcb
*pcb
) {
966 if (eap_client_active(pcb
) && pcb
->settings
.eap_req_time
> 0) {
967 UNTIMEOUT(eap_client_timeout
, pcb
);
970 if (eap_server_active(pcb
)) {
971 if (pcb
->settings
.eap_timeout_time
> 0) {
972 UNTIMEOUT(eap_server_timeout
, pcb
);
975 if ((pcb
->eap
.es_server
.ea_state
== eapOpen
||
976 pcb
->eap
.es_server
.ea_state
== eapSRP4
) &&
977 pcb
->eap
.es_rechallenge
> 0) {
978 UNTIMEOUT(eap_rechallenge
, (void *)pcb
);
980 if (pcb
->eap
.es_server
.ea_state
== eapOpen
&&
981 pcb
->eap
.es_lwrechallenge
> 0) {
982 UNTIMEOUT(srp_lwrechallenge
, (void *)pcb
);
986 pcb
->eap
.es_client
.ea_state
= pcb
->eap
.es_server
.ea_state
= eapInitial
;
987 pcb
->eap
.es_client
.ea_requests
= pcb
->eap
.es_server
.ea_requests
= 0;
988 #endif /* PPP_SERVER */
992 * eap_protrej - Peer doesn't speak this protocol.
994 * This shouldn't happen. If it does, it represents authentication
997 static void eap_protrej(ppp_pcb
*pcb
) {
999 if (eap_client_active(pcb
)) {
1000 ppp_error("EAP authentication failed due to Protocol-Reject");
1001 auth_withpeer_fail(pcb
, PPP_EAP
);
1004 if (eap_server_active(pcb
)) {
1005 ppp_error("EAP authentication of peer failed on Protocol-Reject");
1006 auth_peer_fail(pcb
, PPP_EAP
);
1008 #endif /* PPP_SERVER */
1013 * Format and send a regular EAP Response message.
1015 static void eap_send_response(ppp_pcb
*pcb
, u_char id
, u_char typenum
, const u_char
*str
, int lenstr
) {
1020 msglen
= EAP_HEADERLEN
+ sizeof (u_char
) + lenstr
;
1021 p
= pbuf_alloc(PBUF_RAW
, (u16_t
)(PPP_HDRLEN
+ msglen
), PPP_CTRL_PBUF_TYPE
);
1024 if(p
->tot_len
!= p
->len
) {
1029 outp
= (u_char
*)p
->payload
;
1031 MAKEHEADER(outp
, PPP_EAP
);
1033 PUTCHAR(EAP_RESPONSE
, outp
);
1035 pcb
->eap
.es_client
.ea_id
= id
;
1036 PUTSHORT(msglen
, outp
);
1037 PUTCHAR(typenum
, outp
);
1039 MEMCPY(outp
, str
, lenstr
);
1046 * Format and send an MD5-Challenge EAP Response message.
1048 static void eap_chap_response(ppp_pcb
*pcb
, u_char id
, u_char
*hash
, const char *name
, int namelen
) {
1053 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
) + MD5_SIGNATURE_SIZE
+
1055 p
= pbuf_alloc(PBUF_RAW
, (u16_t
)(PPP_HDRLEN
+ msglen
), PPP_CTRL_PBUF_TYPE
);
1058 if(p
->tot_len
!= p
->len
) {
1063 outp
= (u_char
*)p
->payload
;
1065 MAKEHEADER(outp
, PPP_EAP
);
1067 PUTCHAR(EAP_RESPONSE
, outp
);
1069 pcb
->eap
.es_client
.ea_id
= id
;
1070 PUTSHORT(msglen
, outp
);
1071 PUTCHAR(EAPT_MD5CHAP
, outp
);
1072 PUTCHAR(MD5_SIGNATURE_SIZE
, outp
);
1073 MEMCPY(outp
, hash
, MD5_SIGNATURE_SIZE
);
1074 INCPTR(MD5_SIGNATURE_SIZE
, outp
);
1076 MEMCPY(outp
, name
, namelen
);
1084 * Format and send a SRP EAP Response message.
1087 eap_srp_response(esp
, id
, subtypenum
, str
, lenstr
)
1094 ppp_pcb
*pcb
= &ppp_pcb_list
[pcb
->eap
.es_unit
];
1099 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
) + lenstr
;
1100 p
= pbuf_alloc(PBUF_RAW
, (u16_t
)(PPP_HDRLEN
+ msglen
), PPP_CTRL_PBUF_TYPE
);
1103 if(p
->tot_len
!= p
->len
) {
1110 MAKEHEADER(outp
, PPP_EAP
);
1112 PUTCHAR(EAP_RESPONSE
, outp
);
1114 pcb
->eap
.es_client
.ea_id
= id
;
1115 PUTSHORT(msglen
, outp
);
1116 PUTCHAR(EAPT_SRP
, outp
);
1117 PUTCHAR(subtypenum
, outp
);
1119 MEMCPY(outp
, str
, lenstr
);
1126 * Format and send a SRP EAP Client Validator Response message.
1129 eap_srpval_response(esp
, id
, flags
, str
)
1135 ppp_pcb
*pcb
= &ppp_pcb_list
[pcb
->eap
.es_unit
];
1140 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
) + sizeof (u32_t
) +
1142 p
= pbuf_alloc(PBUF_RAW
, (u16_t
)(PPP_HDRLEN
+ msglen
), PPP_CTRL_PBUF_TYPE
);
1145 if(p
->tot_len
!= p
->len
) {
1152 MAKEHEADER(outp
, PPP_EAP
);
1154 PUTCHAR(EAP_RESPONSE
, outp
);
1156 pcb
->eap
.es_client
.ea_id
= id
;
1157 PUTSHORT(msglen
, outp
);
1158 PUTCHAR(EAPT_SRP
, outp
);
1159 PUTCHAR(EAPSRP_CVALIDATOR
, outp
);
1160 PUTLONG(flags
, outp
);
1161 MEMCPY(outp
, str
, SHA_DIGESTSIZE
);
1165 #endif /* USE_SRP */
1167 static void eap_send_nak(ppp_pcb
*pcb
, u_char id
, u_char type
) {
1172 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
);
1173 p
= pbuf_alloc(PBUF_RAW
, (u16_t
)(PPP_HDRLEN
+ msglen
), PPP_CTRL_PBUF_TYPE
);
1176 if(p
->tot_len
!= p
->len
) {
1181 outp
= (u_char
*)p
->payload
;
1183 MAKEHEADER(outp
, PPP_EAP
);
1185 PUTCHAR(EAP_RESPONSE
, outp
);
1187 pcb
->eap
.es_client
.ea_id
= id
;
1188 PUTSHORT(msglen
, outp
);
1189 PUTCHAR(EAPT_NAK
, outp
);
1190 PUTCHAR(type
, outp
);
1199 char *user
, *path
, *file
;
1202 static bool pnlogged
= 0;
1204 pw
= getpwuid(getuid());
1205 if (pw
== NULL
|| (user
= pw
->pw_dir
) == NULL
|| user
[0] == 0) {
1209 file
= _PATH_PSEUDONYM
;
1210 pl
= strlen(user
) + strlen(file
) + 2;
1214 (void) slprintf(path
, pl
, "%s/%s", user
, file
);
1216 ppp_dbglog("pseudonym file: %s", path
);
1223 open_pn_file(modebits
)
1229 if ((path
= name_of_pn_file()) == NULL
)
1231 fd
= open(path
, modebits
, S_IRUSR
| S_IWUSR
);
1243 if ((path
= name_of_pn_file()) != NULL
) {
1244 (void) unlink(path
);
1250 write_pseudonym(esp
, inp
, len
, id
)
1256 u_char
*datp
, *digp
;
1258 u_char dig
[SHA_DIGESTSIZE
];
1259 int dsize
, fd
, olen
= len
;
1262 * Do the decoding by working backwards. This eliminates the need
1263 * to save the decoded output in a separate buffer.
1267 if ((dsize
= len
% SHA_DIGESTSIZE
) == 0)
1268 dsize
= SHA_DIGESTSIZE
;
1272 SHA1Update(&ctxt
, &val
, 1);
1273 SHA1Update(&ctxt
, pcb
->eap
.es_client
.ea_skey
, SESSION_KEY_LEN
);
1275 SHA1Update(&ctxt
, datp
, SHA_DIGESTSIZE
);
1277 SHA1Update(&ctxt
, pcb
->eap
.es_client
.ea_name
,
1278 pcb
->eap
.es_client
.ea_namelen
);
1280 SHA1Final(dig
, &ctxt
);
1281 for (digp
= dig
; digp
< dig
+ SHA_DIGESTSIZE
; digp
++)
1285 /* Now check that the result is sane */
1286 if (olen
<= 0 || *inp
+ 1 > olen
) {
1287 ppp_dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen
, inp
);
1292 fd
= open_pn_file(O_WRONLY
| O_CREAT
| O_TRUNC
);
1294 ppp_dbglog("EAP: error saving pseudonym: %m");
1297 len
= write(fd
, inp
+ 1, *inp
);
1298 if (close(fd
) != -1 && len
== *inp
) {
1299 ppp_dbglog("EAP: saved pseudonym");
1300 pcb
->eap
.es_usedpseudo
= 0;
1302 ppp_dbglog("EAP: failed to save pseudonym");
1306 #endif /* USE_SRP */
1309 * eap_request - Receive EAP Request message (client mode).
1311 static void eap_request(ppp_pcb
*pcb
, u_char
*inp
, int id
, int len
) {
1315 char secret
[MAXSECRETLEN
];
1316 char rhostname
[MAXNAMELEN
];
1317 lwip_md5_context mdContext
;
1318 u_char hash
[MD5_SIGNATURE_SIZE
];
1320 struct t_client
*tc
;
1321 struct t_num sval
, gval
, Nval
, *Ap
, Bval
;
1324 u_char dig
[SHA_DIGESTSIZE
];
1326 #endif /* USE_SRP */
1329 * Note: we update es_client.ea_id *only if* a Response
1330 * message is being generated. Otherwise, we leave it the
1331 * same for duplicate detection purposes.
1334 pcb
->eap
.es_client
.ea_requests
++;
1335 if (pcb
->settings
.eap_allow_req
!= 0 &&
1336 pcb
->eap
.es_client
.ea_requests
> pcb
->settings
.eap_allow_req
) {
1337 ppp_info("EAP: received too many Request messages");
1338 if (pcb
->settings
.eap_req_time
> 0) {
1339 UNTIMEOUT(eap_client_timeout
, pcb
);
1341 auth_withpeer_fail(pcb
, PPP_EAP
);
1346 ppp_error("EAP: empty Request message discarded");
1350 GETCHAR(typenum
, inp
);
1356 ppp_info("EAP: Identity prompt \"%.*q\"", len
, inp
);
1358 if (pcb
->eap
.es_usepseudo
&&
1359 (pcb
->eap
.es_usedpseudo
== 0 ||
1360 (pcb
->eap
.es_usedpseudo
== 1 &&
1361 id
== pcb
->eap
.es_client
.ea_id
))) {
1362 pcb
->eap
.es_usedpseudo
= 1;
1363 /* Try to get a pseudonym */
1364 if ((fd
= open_pn_file(O_RDONLY
)) >= 0) {
1365 strcpy(rhostname
, SRP_PSEUDO_ID
);
1366 len
= read(fd
, rhostname
+ SRP_PSEUDO_LEN
,
1367 sizeof (rhostname
) - SRP_PSEUDO_LEN
);
1368 /* XXX NAI unsupported */
1370 eap_send_response(pcb
, id
, typenum
,
1371 rhostname
, len
+ SRP_PSEUDO_LEN
);
1378 /* Stop using pseudonym now. */
1379 if (pcb
->eap
.es_usepseudo
&& pcb
->eap
.es_usedpseudo
!= 2) {
1381 pcb
->eap
.es_usedpseudo
= 2;
1383 #endif /* USE_SRP */
1384 eap_send_response(pcb
, id
, typenum
, (const u_char
*)pcb
->eap
.es_client
.ea_name
,
1385 pcb
->eap
.es_client
.ea_namelen
);
1388 case EAPT_NOTIFICATION
:
1390 ppp_info("EAP: Notification \"%.*q\"", len
, inp
);
1391 eap_send_response(pcb
, id
, typenum
, NULL
, 0);
1396 * Avoid the temptation to send Response Nak in reply
1397 * to Request Nak here. It can only lead to trouble.
1399 ppp_warn("EAP: unexpected Nak in Request; ignored");
1400 /* Return because we're waiting for something real. */
1405 ppp_error("EAP: received MD5-Challenge with no data");
1406 /* Bogus request; wait for something real. */
1409 GETCHAR(vallen
, inp
);
1411 if (vallen
< 8 || vallen
> len
) {
1412 ppp_error("EAP: MD5-Challenge with bad length %d (8..%d)",
1414 /* Try something better. */
1415 eap_send_nak(pcb
, id
, EAPT_SRP
);
1419 /* Not so likely to happen. */
1420 if (vallen
>= len
+ sizeof (rhostname
)) {
1421 ppp_dbglog("EAP: trimming really long peer name down");
1422 MEMCPY(rhostname
, inp
+ vallen
, sizeof (rhostname
) - 1);
1423 rhostname
[sizeof (rhostname
) - 1] = '\0';
1425 MEMCPY(rhostname
, inp
+ vallen
, len
- vallen
);
1426 rhostname
[len
- vallen
] = '\0';
1430 /* In case the remote doesn't give us his name. */
1431 if (pcb
->settings
.explicit_remote
||
1432 (pcb
->settings
.remote_name
[0] != '\0' && vallen
== len
))
1433 strlcpy(rhostname
, pcb
->settings
.remote_name
, sizeof (rhostname
));
1434 #endif /* PPP_REMOTENAME */
1437 * Get the secret for authenticating ourselves with
1438 * the specified host.
1440 if (!get_secret(pcb
, pcb
->eap
.es_client
.ea_name
,
1441 rhostname
, secret
, &secret_len
, 0)) {
1442 ppp_dbglog("EAP: no MD5 secret for auth to %q", rhostname
);
1443 eap_send_nak(pcb
, id
, EAPT_SRP
);
1446 lwip_md5_init(&mdContext
);
1447 lwip_md5_starts(&mdContext
);
1449 lwip_md5_update(&mdContext
, &typenum
, 1);
1450 lwip_md5_update(&mdContext
, (u_char
*)secret
, secret_len
);
1451 BZERO(secret
, sizeof (secret
));
1452 lwip_md5_update(&mdContext
, inp
, vallen
);
1453 lwip_md5_finish(&mdContext
, hash
);
1454 lwip_md5_free(&mdContext
);
1455 eap_chap_response(pcb
, id
, hash
, pcb
->eap
.es_client
.ea_name
,
1456 pcb
->eap
.es_client
.ea_namelen
);
1462 ppp_error("EAP: received empty SRP Request");
1463 /* Bogus request; wait for something real. */
1468 GETCHAR(vallen
, inp
);
1471 case EAPSRP_CHALLENGE
:
1473 if (pcb
->eap
.es_client
.ea_session
!= NULL
) {
1474 tc
= (struct t_client
*)pcb
->eap
.es_client
.
1477 * If this is a new challenge, then start
1478 * over with a new client session context.
1479 * Otherwise, just resend last response.
1481 if (id
!= pcb
->eap
.es_client
.ea_id
) {
1483 pcb
->eap
.es_client
.ea_session
= NULL
;
1487 /* No session key just yet */
1488 pcb
->eap
.es_client
.ea_skey
= NULL
;
1492 GETCHAR(vallen
, inp
);
1494 if (vallen
>= len
) {
1495 ppp_error("EAP: badly-formed SRP Challenge"
1497 /* Ignore badly-formed messages */
1500 MEMCPY(rhostname
, inp
, vallen
);
1501 rhostname
[vallen
] = '\0';
1502 INCPTR(vallen
, inp
);
1506 * In case the remote doesn't give us his name,
1507 * use configured name.
1509 if (explicit_remote
||
1510 (remote_name
[0] != '\0' && vallen
== 0)) {
1511 strlcpy(rhostname
, remote_name
,
1512 sizeof (rhostname
));
1515 rhostnamelen
= (int)strlen(rhostname
);
1516 if (rhostnamelen
> MAXNAMELEN
) {
1517 rhostnamelen
= MAXNAMELEN
;
1519 MEMCPY(pcb
->eap
.es_client
.ea_peer
, rhostname
, rhostnamelen
);
1520 pcb
->eap
.es_client
.ea_peer
[rhostnamelen
] = '\0';
1521 pcb
->eap
.es_client
.ea_peerlen
= rhostnamelen
;
1523 GETCHAR(vallen
, inp
);
1525 if (vallen
>= len
) {
1526 ppp_error("EAP: badly-formed SRP Challenge"
1528 /* Ignore badly-formed messages */
1533 INCPTR(vallen
, inp
);
1536 GETCHAR(vallen
, inp
);
1539 ppp_error("EAP: badly-formed SRP Challenge"
1541 /* Ignore badly-formed messages */
1544 /* If no generator present, then use value 2 */
1546 gval
.data
= (u_char
*)"\002";
1552 INCPTR(vallen
, inp
);
1556 * If no modulus present, then use well-known
1560 Nval
.data
= (u_char
*)wkmodulus
;
1561 Nval
.len
= sizeof (wkmodulus
);
1566 tc
= t_clientopen(pcb
->eap
.es_client
.ea_name
,
1567 &Nval
, &gval
, &sval
);
1569 eap_send_nak(pcb
, id
, EAPT_MD5CHAP
);
1572 pcb
->eap
.es_client
.ea_session
= (void *)tc
;
1574 /* Add Challenge ID & type to verifier */
1577 t_clientaddexdata(tc
, vals
, 2);
1579 Ap
= t_clientgenexp(tc
);
1580 eap_srp_response(esp
, id
, EAPSRP_CKEY
, Ap
->data
,
1585 tc
= (struct t_client
*)pcb
->eap
.es_client
.ea_session
;
1587 ppp_warn("EAP: peer sent Subtype 2 without 1");
1588 eap_send_nak(pcb
, id
, EAPT_MD5CHAP
);
1591 if (pcb
->eap
.es_client
.ea_skey
!= NULL
) {
1593 * ID number should not change here. Warn
1594 * if it does (but otherwise ignore).
1596 if (id
!= pcb
->eap
.es_client
.ea_id
) {
1597 ppp_warn("EAP: ID changed from %d to %d "
1598 "in SRP Subtype 2 rexmit",
1599 pcb
->eap
.es_client
.ea_id
, id
);
1602 if (get_srp_secret(pcb
->eap
.es_unit
,
1603 pcb
->eap
.es_client
.ea_name
,
1604 pcb
->eap
.es_client
.ea_peer
, secret
, 0) == 0) {
1606 * Can't work with this peer because
1607 * the secret is missing. Just give
1610 eap_send_nak(pcb
, id
, EAPT_MD5CHAP
);
1615 t_clientpasswd(tc
, secret
);
1616 BZERO(secret
, sizeof (secret
));
1617 pcb
->eap
.es_client
.ea_skey
=
1618 t_clientgetkey(tc
, &Bval
);
1619 if (pcb
->eap
.es_client
.ea_skey
== NULL
) {
1620 /* Server is rogue; stop now */
1621 ppp_error("EAP: SRP server is rogue");
1622 goto client_failure
;
1625 eap_srpval_response(esp
, id
, SRPVAL_EBIT
,
1626 t_clientresponse(tc
));
1629 case EAPSRP_SVALIDATOR
:
1630 tc
= (struct t_client
*)pcb
->eap
.es_client
.ea_session
;
1631 if (tc
== NULL
|| pcb
->eap
.es_client
.ea_skey
== NULL
) {
1632 ppp_warn("EAP: peer sent Subtype 3 without 1/2");
1633 eap_send_nak(pcb
, id
, EAPT_MD5CHAP
);
1637 * If we're already open, then this ought to be a
1638 * duplicate. Otherwise, check that the server is
1639 * who we think it is.
1641 if (pcb
->eap
.es_client
.ea_state
== eapOpen
) {
1642 if (id
!= pcb
->eap
.es_client
.ea_id
) {
1643 ppp_warn("EAP: ID changed from %d to %d "
1644 "in SRP Subtype 3 rexmit",
1645 pcb
->eap
.es_client
.ea_id
, id
);
1648 len
-= sizeof (u32_t
) + SHA_DIGESTSIZE
;
1649 if (len
< 0 || t_clientverify(tc
, inp
+
1650 sizeof (u32_t
)) != 0) {
1651 ppp_error("EAP: SRP server verification "
1653 goto client_failure
;
1655 GETLONG(pcb
->eap
.es_client
.ea_keyflags
, inp
);
1656 /* Save pseudonym if user wants it. */
1657 if (len
> 0 && pcb
->eap
.es_usepseudo
) {
1658 INCPTR(SHA_DIGESTSIZE
, inp
);
1659 write_pseudonym(esp
, inp
, len
, id
);
1663 * We've verified our peer. We're now mostly done,
1664 * except for waiting on the regular EAP Success
1667 eap_srp_response(esp
, id
, EAPSRP_ACK
, NULL
, 0);
1670 case EAPSRP_LWRECHALLENGE
:
1672 ppp_warn("EAP: malformed Lightweight rechallenge");
1677 SHA1Update(&ctxt
, vals
, 1);
1678 SHA1Update(&ctxt
, pcb
->eap
.es_client
.ea_skey
,
1680 SHA1Update(&ctxt
, inp
, len
);
1681 SHA1Update(&ctxt
, pcb
->eap
.es_client
.ea_name
,
1682 pcb
->eap
.es_client
.ea_namelen
);
1683 SHA1Final(dig
, &ctxt
);
1684 eap_srp_response(esp
, id
, EAPSRP_LWRECHALLENGE
, dig
,
1689 ppp_error("EAP: unknown SRP Subtype %d", vallen
);
1690 eap_send_nak(pcb
, id
, EAPT_MD5CHAP
);
1694 #endif /* USE_SRP */
1697 ppp_info("EAP: unknown authentication type %d; Naking", typenum
);
1698 eap_send_nak(pcb
, id
, EAPT_SRP
);
1702 if (pcb
->settings
.eap_req_time
> 0) {
1703 UNTIMEOUT(eap_client_timeout
, pcb
);
1704 TIMEOUT(eap_client_timeout
, pcb
,
1705 pcb
->settings
.eap_req_time
);
1711 pcb
->eap
.es_client
.ea_state
= eapBadAuth
;
1712 if (pcb
->settings
.eap_req_time
> 0) {
1713 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
1715 pcb
->eap
.es_client
.ea_session
= NULL
;
1717 auth_withpeer_fail(pcb
, PPP_EAP
);
1718 #endif /* USE_SRP */
1723 * eap_response - Receive EAP Response message (server mode).
1725 static void eap_response(ppp_pcb
*pcb
, u_char
*inp
, int id
, int len
) {
1729 char secret
[MAXSECRETLEN
];
1730 char rhostname
[MAXNAMELEN
];
1731 lwip_md5_context mdContext
;
1732 u_char hash
[MD5_SIGNATURE_SIZE
];
1734 struct t_server
*ts
;
1737 u_char dig
[SHA_DIGESTSIZE
];
1738 #endif /* USE_SRP */
1740 if (pcb
->eap
.es_server
.ea_id
!= id
) {
1741 ppp_dbglog("EAP: discarding Response %d; expected ID %d", id
,
1742 pcb
->eap
.es_server
.ea_id
);
1746 pcb
->eap
.es_server
.ea_responses
++;
1749 ppp_error("EAP: empty Response message discarded");
1753 GETCHAR(typenum
, inp
);
1758 if (pcb
->eap
.es_server
.ea_state
!= eapIdentify
) {
1759 ppp_dbglog("EAP discarding unwanted Identify \"%.q\"", len
,
1763 ppp_info("EAP: unauthenticated peer name \"%.*q\"", len
, inp
);
1764 if (len
> MAXNAMELEN
) {
1767 MEMCPY(pcb
->eap
.es_server
.ea_peer
, inp
, len
);
1768 pcb
->eap
.es_server
.ea_peer
[len
] = '\0';
1769 pcb
->eap
.es_server
.ea_peerlen
= len
;
1770 eap_figure_next_state(pcb
, 0);
1773 case EAPT_NOTIFICATION
:
1774 ppp_dbglog("EAP unexpected Notification; response discarded");
1779 ppp_info("EAP: Nak Response with no suggested protocol");
1780 eap_figure_next_state(pcb
, 1);
1784 GETCHAR(vallen
, inp
);
1789 !pcb
->explicit_remote
&&
1790 #endif /* PPP_REMOTENAME */
1791 pcb
->eap
.es_server
.ea_state
== eapIdentify
){
1792 /* Peer cannot Nak Identify Request */
1793 eap_figure_next_state(pcb
, 1);
1799 /* Run through SRP validator selection again. */
1800 pcb
->eap
.es_server
.ea_state
= eapIdentify
;
1801 eap_figure_next_state(pcb
, 0);
1805 pcb
->eap
.es_server
.ea_state
= eapMD5Chall
;
1809 ppp_dbglog("EAP: peer requesting unknown Type %d", vallen
);
1810 switch (pcb
->eap
.es_server
.ea_state
) {
1814 pcb
->eap
.es_server
.ea_state
= eapMD5Chall
;
1818 pcb
->eap
.es_server
.ea_state
= eapIdentify
;
1819 eap_figure_next_state(pcb
, 0);
1829 if (pcb
->eap
.es_server
.ea_state
!= eapMD5Chall
) {
1830 ppp_error("EAP: unexpected MD5-Response");
1831 eap_figure_next_state(pcb
, 1);
1835 ppp_error("EAP: received MD5-Response with no data");
1836 eap_figure_next_state(pcb
, 1);
1839 GETCHAR(vallen
, inp
);
1841 if (vallen
!= 16 || vallen
> len
) {
1842 ppp_error("EAP: MD5-Response with bad length %d", vallen
);
1843 eap_figure_next_state(pcb
, 1);
1847 /* Not so likely to happen. */
1848 if (vallen
>= len
+ sizeof (rhostname
)) {
1849 ppp_dbglog("EAP: trimming really long peer name down");
1850 MEMCPY(rhostname
, inp
+ vallen
, sizeof (rhostname
) - 1);
1851 rhostname
[sizeof (rhostname
) - 1] = '\0';
1853 MEMCPY(rhostname
, inp
+ vallen
, len
- vallen
);
1854 rhostname
[len
- vallen
] = '\0';
1858 /* In case the remote doesn't give us his name. */
1859 if (explicit_remote
||
1860 (remote_name
[0] != '\0' && vallen
== len
))
1861 strlcpy(rhostname
, remote_name
, sizeof (rhostname
));
1862 #endif /* PPP_REMOTENAME */
1865 * Get the secret for authenticating the specified
1868 if (!get_secret(pcb
, rhostname
,
1869 pcb
->eap
.es_server
.ea_name
, secret
, &secret_len
, 1)) {
1870 ppp_dbglog("EAP: no MD5 secret for auth of %q", rhostname
);
1871 eap_send_failure(pcb
);
1874 lwip_md5_init(&mdContext
);
1875 lwip_md5_starts(&mdContext
);
1876 lwip_md5_update(&mdContext
, &pcb
->eap
.es_server
.ea_id
, 1);
1877 lwip_md5_update(&mdContext
, (u_char
*)secret
, secret_len
);
1878 BZERO(secret
, sizeof (secret
));
1879 lwip_md5_update(&mdContext
, pcb
->eap
.es_challenge
, pcb
->eap
.es_challen
);
1880 lwip_md5_finish(&mdContext
, hash
);
1881 lwip_md5_free(&mdContext
);
1882 if (BCMP(hash
, inp
, MD5_SIGNATURE_SIZE
) != 0) {
1883 eap_send_failure(pcb
);
1886 pcb
->eap
.es_server
.ea_type
= EAPT_MD5CHAP
;
1887 eap_send_success(pcb
);
1888 eap_figure_next_state(pcb
, 0);
1889 if (pcb
->eap
.es_rechallenge
!= 0)
1890 TIMEOUT(eap_rechallenge
, pcb
, pcb
->eap
.es_rechallenge
);
1896 ppp_error("EAP: empty SRP Response");
1897 eap_figure_next_state(pcb
, 1);
1900 GETCHAR(typenum
, inp
);
1904 if (pcb
->eap
.es_server
.ea_state
!= eapSRP1
) {
1905 ppp_error("EAP: unexpected SRP Subtype 1 Response");
1906 eap_figure_next_state(pcb
, 1);
1911 ts
= (struct t_server
*)pcb
->eap
.es_server
.ea_session
;
1913 pcb
->eap
.es_server
.ea_skey
= t_servergetkey(ts
, &A
);
1914 if (pcb
->eap
.es_server
.ea_skey
== NULL
) {
1915 /* Client's A value is bogus; terminate now */
1916 ppp_error("EAP: bogus A value from client");
1917 eap_send_failure(pcb
);
1919 eap_figure_next_state(pcb
, 0);
1923 case EAPSRP_CVALIDATOR
:
1924 if (pcb
->eap
.es_server
.ea_state
!= eapSRP2
) {
1925 ppp_error("EAP: unexpected SRP Subtype 2 Response");
1926 eap_figure_next_state(pcb
, 1);
1929 if (len
< sizeof (u32_t
) + SHA_DIGESTSIZE
) {
1930 ppp_error("EAP: M1 length %d < %d", len
,
1931 sizeof (u32_t
) + SHA_DIGESTSIZE
);
1932 eap_figure_next_state(pcb
, 1);
1935 GETLONG(pcb
->eap
.es_server
.ea_keyflags
, inp
);
1936 ts
= (struct t_server
*)pcb
->eap
.es_server
.ea_session
;
1938 if (t_serververify(ts
, inp
)) {
1939 ppp_info("EAP: unable to validate client identity");
1940 eap_send_failure(pcb
);
1943 eap_figure_next_state(pcb
, 0);
1947 if (pcb
->eap
.es_server
.ea_state
!= eapSRP3
) {
1948 ppp_error("EAP: unexpected SRP Subtype 3 Response");
1949 eap_send_failure(esp
);
1952 pcb
->eap
.es_server
.ea_type
= EAPT_SRP
;
1953 eap_send_success(pcb
, esp
);
1954 eap_figure_next_state(pcb
, 0);
1955 if (pcb
->eap
.es_rechallenge
!= 0)
1956 TIMEOUT(eap_rechallenge
, pcb
,
1957 pcb
->eap
.es_rechallenge
);
1958 if (pcb
->eap
.es_lwrechallenge
!= 0)
1959 TIMEOUT(srp_lwrechallenge
, pcb
,
1960 pcb
->eap
.es_lwrechallenge
);
1963 case EAPSRP_LWRECHALLENGE
:
1964 if (pcb
->eap
.es_server
.ea_state
!= eapSRP4
) {
1965 ppp_info("EAP: unexpected SRP Subtype 4 Response");
1968 if (len
!= SHA_DIGESTSIZE
) {
1969 ppp_error("EAP: bad Lightweight rechallenge "
1975 SHA1Update(&ctxt
, &vallen
, 1);
1976 SHA1Update(&ctxt
, pcb
->eap
.es_server
.ea_skey
,
1978 SHA1Update(&ctxt
, pcb
->eap
.es_challenge
, pcb
->eap
.es_challen
);
1979 SHA1Update(&ctxt
, pcb
->eap
.es_server
.ea_peer
,
1980 pcb
->eap
.es_server
.ea_peerlen
);
1981 SHA1Final(dig
, &ctxt
);
1982 if (BCMP(dig
, inp
, SHA_DIGESTSIZE
) != 0) {
1983 ppp_error("EAP: failed Lightweight rechallenge");
1984 eap_send_failure(pcb
);
1987 pcb
->eap
.es_server
.ea_state
= eapOpen
;
1988 if (pcb
->eap
.es_lwrechallenge
!= 0)
1989 TIMEOUT(srp_lwrechallenge
, esp
,
1990 pcb
->eap
.es_lwrechallenge
);
1994 #endif /* USE_SRP */
1997 /* This can't happen. */
1998 ppp_error("EAP: unknown Response type %d; ignored", typenum
);
2002 if (pcb
->settings
.eap_timeout_time
> 0) {
2003 UNTIMEOUT(eap_server_timeout
, pcb
);
2006 if (pcb
->eap
.es_server
.ea_state
!= eapBadAuth
&&
2007 pcb
->eap
.es_server
.ea_state
!= eapOpen
) {
2008 pcb
->eap
.es_server
.ea_id
++;
2009 eap_send_request(pcb
);
2012 #endif /* PPP_SERVER */
2015 * eap_success - Receive EAP Success message (client mode).
2017 static void eap_success(ppp_pcb
*pcb
, u_char
*inp
, int id
, int len
) {
2018 LWIP_UNUSED_ARG(id
);
2020 if (pcb
->eap
.es_client
.ea_state
!= eapOpen
&& !eap_client_active(pcb
)) {
2021 ppp_dbglog("EAP unexpected success message in state %s (%d)",
2022 eap_state_name(pcb
->eap
.es_client
.ea_state
),
2023 pcb
->eap
.es_client
.ea_state
);
2027 if (pcb
->settings
.eap_req_time
> 0) {
2028 UNTIMEOUT(eap_client_timeout
, pcb
);
2032 /* This is odd. The spec doesn't allow for this. */
2036 pcb
->eap
.es_client
.ea_state
= eapOpen
;
2037 auth_withpeer_success(pcb
, PPP_EAP
, 0);
2041 * eap_failure - Receive EAP Failure message (client mode).
2043 static void eap_failure(ppp_pcb
*pcb
, u_char
*inp
, int id
, int len
) {
2044 LWIP_UNUSED_ARG(id
);
2046 if (!eap_client_active(pcb
)) {
2047 ppp_dbglog("EAP unexpected failure message in state %s (%d)",
2048 eap_state_name(pcb
->eap
.es_client
.ea_state
),
2049 pcb
->eap
.es_client
.ea_state
);
2052 if (pcb
->settings
.eap_req_time
> 0) {
2053 UNTIMEOUT(eap_client_timeout
, pcb
);
2057 /* This is odd. The spec doesn't allow for this. */
2061 pcb
->eap
.es_client
.ea_state
= eapBadAuth
;
2063 ppp_error("EAP: peer reports authentication failure");
2064 auth_withpeer_fail(pcb
, PPP_EAP
);
2068 * eap_input - Handle received EAP message.
2070 static void eap_input(ppp_pcb
*pcb
, u_char
*inp
, int inlen
) {
2075 * Parse header (code, id and length). If packet too short,
2078 if (inlen
< EAP_HEADERLEN
) {
2079 ppp_error("EAP: packet too short: %d < %d", inlen
, EAP_HEADERLEN
);
2085 if (len
< EAP_HEADERLEN
|| len
> inlen
) {
2086 ppp_error("EAP: packet has illegal length field %d (%d..%d)", len
,
2087 EAP_HEADERLEN
, inlen
);
2090 len
-= EAP_HEADERLEN
;
2092 /* Dispatch based on message code */
2095 eap_request(pcb
, inp
, id
, len
);
2100 eap_response(pcb
, inp
, id
, len
);
2102 #endif /* PPP_SERVER */
2105 eap_success(pcb
, inp
, id
, len
);
2109 eap_failure(pcb
, inp
, id
, len
);
2112 default: /* XXX Need code reject */
2113 /* Note: it's not legal to send EAP Nak here. */
2114 ppp_warn("EAP: unknown code %d received", code
);
2119 #if PRINTPKT_SUPPORT
2121 * eap_printpkt - print the contents of an EAP packet.
2123 static const char* const eap_codenames
[] = {
2124 "Request", "Response", "Success", "Failure"
2127 static const char* const eap_typenames
[] = {
2128 "Identity", "Notification", "Nak", "MD5-Challenge",
2129 "OTP", "Generic-Token", NULL
, NULL
,
2130 "RSA", "DSS", "KEA", "KEA-Validate",
2131 "TLS", "Defender", "Windows 2000", "Arcot",
2132 "Cisco", "Nokia", "SRP"
2135 static int eap_printpkt(const u_char
*inp
, int inlen
, void (*printer
) (void *, const char *, ...), void *arg
) {
2136 int code
, id
, len
, rtype
, vallen
;
2137 const u_char
*pstart
;
2140 if (inlen
< EAP_HEADERLEN
)
2146 if (len
< EAP_HEADERLEN
|| len
> inlen
)
2149 if (code
>= 1 && code
<= (int)LWIP_ARRAYSIZE(eap_codenames
))
2150 printer(arg
, " %s", eap_codenames
[code
-1]);
2152 printer(arg
, " code=0x%x", code
);
2153 printer(arg
, " id=0x%x", id
);
2154 len
-= EAP_HEADERLEN
;
2158 printer(arg
, " <missing type>");
2161 GETCHAR(rtype
, inp
);
2163 if (rtype
>= 1 && rtype
<= (int)LWIP_ARRAYSIZE(eap_typenames
))
2164 printer(arg
, " %s", eap_typenames
[rtype
-1]);
2166 printer(arg
, " type=0x%x", rtype
);
2169 case EAPT_NOTIFICATION
:
2171 printer(arg
, " <Message ");
2172 ppp_print_string(inp
, len
, printer
, arg
);
2177 printer(arg
, " <No message>");
2184 GETCHAR(vallen
, inp
);
2188 printer(arg
, " <Value%.*B>", vallen
, inp
);
2189 INCPTR(vallen
, inp
);
2192 printer(arg
, " <Name ");
2193 ppp_print_string(inp
, len
, printer
, arg
);
2198 printer(arg
, " <No name>");
2205 GETCHAR(vallen
, inp
);
2207 printer(arg
, "-%d", vallen
);
2209 case EAPSRP_CHALLENGE
:
2210 GETCHAR(vallen
, inp
);
2215 printer(arg
, " <Name ");
2216 ppp_print_string(inp
, vallen
, printer
,
2220 printer(arg
, " <No name>");
2222 INCPTR(vallen
, inp
);
2224 GETCHAR(vallen
, inp
);
2228 printer(arg
, " <s%.*B>", vallen
, inp
);
2229 INCPTR(vallen
, inp
);
2231 GETCHAR(vallen
, inp
);
2236 printer(arg
, " <Default g=2>");
2238 printer(arg
, " <g%.*B>", vallen
, inp
);
2240 INCPTR(vallen
, inp
);
2243 printer(arg
, " <Default N>");
2245 printer(arg
, " <N%.*B>", len
, inp
);
2252 printer(arg
, " <B%.*B>", len
, inp
);
2257 case EAPSRP_SVALIDATOR
:
2258 if (len
< (int)sizeof (u32_t
))
2261 len
-= sizeof (u32_t
);
2262 if (uval
& SRPVAL_EBIT
) {
2264 uval
&= ~SRPVAL_EBIT
;
2267 printer(arg
, " f<%X>", uval
);
2269 if ((vallen
= len
) > SHA_DIGESTSIZE
)
2270 vallen
= SHA_DIGESTSIZE
;
2271 printer(arg
, " <M2%.*B%s>", len
, inp
,
2272 len
< SHA_DIGESTSIZE
? "?" : "");
2273 INCPTR(vallen
, inp
);
2276 printer(arg
, " <PN%.*B>", len
, inp
);
2282 case EAPSRP_LWRECHALLENGE
:
2283 printer(arg
, " <Challenge%.*B>", len
, inp
);
2299 GETCHAR(rtype
, inp
);
2301 if (rtype
>= 1 && rtype
<= (int)LWIP_ARRAYSIZE(eap_typenames
))
2302 printer(arg
, " %s", eap_typenames
[rtype
-1]);
2304 printer(arg
, " type=0x%x", rtype
);
2308 printer(arg
, " <Name ");
2309 ppp_print_string(inp
, len
, printer
, arg
);
2318 printer(arg
, " <missing hint>");
2321 GETCHAR(rtype
, inp
);
2323 printer(arg
, " <Suggested-type %02X", rtype
);
2324 if (rtype
>= 1 && rtype
< (int)LWIP_ARRAYSIZE(eap_typenames
))
2325 printer(arg
, " (%s)", eap_typenames
[rtype
-1]);
2331 printer(arg
, " <missing length>");
2334 GETCHAR(vallen
, inp
);
2338 printer(arg
, " <Value%.*B>", vallen
, inp
);
2339 INCPTR(vallen
, inp
);
2342 printer(arg
, " <Name ");
2343 ppp_print_string(inp
, len
, printer
, arg
);
2348 printer(arg
, " <No name>");
2355 GETCHAR(vallen
, inp
);
2357 printer(arg
, "-%d", vallen
);
2360 printer(arg
, " <A%.*B>", len
, inp
);
2365 case EAPSRP_CVALIDATOR
:
2366 if (len
< (int)sizeof (u32_t
))
2369 len
-= sizeof (u32_t
);
2370 if (uval
& SRPVAL_EBIT
) {
2372 uval
&= ~SRPVAL_EBIT
;
2375 printer(arg
, " f<%X>", uval
);
2377 printer(arg
, " <M1%.*B%s>", len
, inp
,
2378 len
== SHA_DIGESTSIZE
? "" : "?");
2386 case EAPSRP_LWRECHALLENGE
:
2387 printer(arg
, " <Response%.*B%s>", len
, inp
,
2388 len
== SHA_DIGESTSIZE
? "" : "?");
2389 if ((vallen
= len
) > SHA_DIGESTSIZE
)
2390 vallen
= SHA_DIGESTSIZE
;
2391 INCPTR(vallen
, inp
);
2403 case EAP_SUCCESS
: /* No payload expected for these! */
2409 printer(arg
, " <truncated>");
2414 printer(arg
, "%8B...", inp
);
2416 printer(arg
, "%.*B", len
, inp
);
2419 return (inp
- pstart
);
2421 #endif /* PRINTPKT_SUPPORT */
2423 #endif /* PPP_SUPPORT && EAP_SUPPORT */