xref: /minix/minix/lib/liblwip/dist/src/netif/ppp/eap.c (revision e4dbab1e)
1 /*
2  * eap.c - Extensible Authentication Protocol for PPP (RFC 2284)
3  *
4  * Copyright (c) 2001 by Sun Microsystems, Inc.
5  * All rights reserved.
6  *
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.
13  *
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.
17  *
18  * Original version by James Carlson
19  *
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.
24  *
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.
30  *
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.
34  *
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.
38  *
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.
42  *
43  * Based on draft-ietf-pppext-eap-srp-03.txt.
44  */
45 
46 #include "netif/ppp/ppp_opts.h"
47 #if PPP_SUPPORT && EAP_SUPPORT  /* don't build if not configured for use in lwipopts.h */
48 
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"
53 
54 #ifdef USE_SRP
55 #include <t_pwd.h>
56 #include <t_server.h>
57 #include <t_client.h>
58 #endif /* USE_SRP */
59 
60 #ifndef SHA_DIGESTSIZE
61 #define	SHA_DIGESTSIZE 20
62 #endif
63 
64 #ifdef USE_SRP
65 static char *pn_secret = NULL;		/* Pseudonym generating secret */
66 #endif
67 
68 #if PPP_OPTIONS
69 /*
70  * Command-line options.
71  */
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" },
83 #ifdef USE_SRP
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 },
90 #endif
91     { NULL }
92 };
93 #endif /* PPP_OPTIONS */
94 
95 /*
96  * Protocol entry points.
97  */
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);
103 #if PRINTPKT_SUPPORT
104 static int  eap_printpkt(const u_char *inp, int inlen,
105     void (*)(void *arg, const char *fmt, ...), void *arg);
106 #endif /* PRINTPKT_SUPPORT */
107 
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 */
117 #if PRINTPKT_SUPPORT
118 	eap_printpkt,		/* print a packet in readable form */
119 #endif /* PRINTPKT_SUPPORT */
120 #if PPP_DATAINPUT
121 	NULL,			/* process a received data packet */
122 #endif /* PPP_DATAINPUT */
123 #if PRINTPKT_SUPPORT
124 	"EAP",			/* text name of protocol */
125 	NULL,			/* text name of corresponding data protocol */
126 #endif /* PRINTPKT_SUPPORT */
127 #if PPP_OPTIONS
128 	eap_option_list,	/* list of command-line options */
129 	NULL,			/* check requested options; assign defaults */
130 #endif /* PPP_OPTIONS */
131 #if DEMAND_SUPPORT
132 	NULL,			/* configure interface for demand-dial */
133 	NULL			/* say whether to bring up link for this pkt */
134 #endif /* DEMAND_SUPPORT */
135 };
136 
137 #ifdef USE_SRP
138 /*
139  * A well-known 2048 bit modulus.
140  */
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
174 };
175 #endif
176 
177 #if PPP_SERVER
178 /* Local forward declarations. */
179 static void eap_server_timeout(void *arg);
180 #endif /* PPP_SERVER */
181 
182 /*
183  * Convert EAP state code to printable string for debug.
184  */
185 static const char * eap_state_name(enum eap_state_code esc)
186 {
187 	static const char *state_names[] = { EAP_STATES };
188 
189 	return (state_names[(int)esc]);
190 }
191 
192 /*
193  * eap_init - Initialize state for an EAP user.  This is currently
194  * called once by main() during start-up.
195  */
196 static void eap_init(ppp_pcb *pcb) {
197 
198 	BZERO(&pcb->eap, sizeof(eap_state));
199 #if PPP_SERVER
200 	pcb->eap.es_server.ea_id = magic();
201 #endif /* PPP_SERVER */
202 }
203 
204 /*
205  * eap_client_timeout - Give up waiting for the peer to send any
206  * Request messages.
207  */
208 static void eap_client_timeout(void *arg) {
209 	ppp_pcb *pcb = (ppp_pcb*)arg;
210 
211 	if (!eap_client_active(pcb))
212 		return;
213 
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;
217 }
218 
219 /*
220  * eap_authwithpeer - Authenticate to our peer (behave as client).
221  *
222  * Start client state and wait for requests.  This is called only
223  * after eap_lowerup.
224  */
225 void eap_authwithpeer(ppp_pcb *pcb, const char *localname) {
226 
227 	if(NULL == localname)
228 		return;
229 
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);
233 
234 	pcb->eap.es_client.ea_state = eapListen;
235 
236 	/*
237 	 * Start a timer so that if the other end just goes
238 	 * silent, we don't sit here waiting forever.
239 	 */
240 	if (pcb->settings.eap_req_time > 0)
241 		TIMEOUT(eap_client_timeout, pcb,
242 		    pcb->settings.eap_req_time);
243 }
244 
245 #if PPP_SERVER
246 /*
247  * Format a standard EAP Failure message and send it to the peer.
248  * (Server operation)
249  */
250 static void eap_send_failure(ppp_pcb *pcb) {
251 	struct pbuf *p;
252 	u_char *outp;
253 
254 	p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE);
255 	if(NULL == p)
256 		return;
257 	if(p->tot_len != p->len) {
258 		pbuf_free(p);
259 		return;
260 	}
261 
262 	outp = (u_char*)p->payload;
263 
264 	MAKEHEADER(outp, PPP_EAP);
265 
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);
270 
271 	ppp_write(pcb, p);
272 
273 	pcb->eap.es_server.ea_state = eapBadAuth;
274 	auth_peer_fail(pcb, PPP_EAP);
275 }
276 
277 /*
278  * Format a standard EAP Success message and send it to the peer.
279  * (Server operation)
280  */
281 static void eap_send_success(ppp_pcb *pcb) {
282 	struct pbuf *p;
283 	u_char *outp;
284 
285 	p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE);
286 	if(NULL == p)
287 		return;
288 	if(p->tot_len != p->len) {
289 		pbuf_free(p);
290 		return;
291 	}
292 
293 	outp = (u_char*)p->payload;
294 
295 	MAKEHEADER(outp, PPP_EAP);
296 
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);
301 
302 	ppp_write(pcb, p);
303 
304 	auth_peer_success(pcb, PPP_EAP, 0,
305 	    pcb->eap.es_server.ea_peer, pcb->eap.es_server.ea_peerlen);
306 }
307 #endif /* PPP_SERVER */
308 
309 #ifdef USE_SRP
310 /*
311  * Set DES key according to pseudonym-generating secret and current
312  * date.
313  */
314 static bool
315 pncrypt_setkey(int timeoffs)
316 {
317 	struct tm *tp;
318 	char tbuf[9];
319 	SHA1_CTX ctxt;
320 	u_char dig[SHA_DIGESTSIZE];
321 	time_t reftime;
322 
323 	if (pn_secret == NULL)
324 		return (0);
325 	reftime = time(NULL) + timeoffs;
326 	tp = localtime(&reftime);
327 	SHA1Init(&ctxt);
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));
334 }
335 
336 static char base64[] =
337 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
338 
339 struct b64state {
340 	u32_t bs_bits;
341 	int bs_offs;
342 };
343 
344 static int
345 b64enc(bs, inp, inlen, outp)
346 struct b64state *bs;
347 u_char *inp;
348 int inlen;
349 u_char *outp;
350 {
351 	int outlen = 0;
352 
353 	while (inlen > 0) {
354 		bs->bs_bits = (bs->bs_bits << 8) | *inp++;
355 		inlen--;
356 		bs->bs_offs += 8;
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];
362 			outlen += 4;
363 			bs->bs_offs = 0;
364 			bs->bs_bits = 0;
365 		}
366 	}
367 	return (outlen);
368 }
369 
370 static int
371 b64flush(bs, outp)
372 struct b64state *bs;
373 u_char *outp;
374 {
375 	int outlen = 0;
376 
377 	if (bs->bs_offs == 8) {
378 		*outp++ = base64[(bs->bs_bits >> 2) & 0x3F];
379 		*outp++ = base64[(bs->bs_bits << 4) & 0x3F];
380 		outlen = 2;
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];
385 		outlen = 3;
386 	}
387 	bs->bs_offs = 0;
388 	bs->bs_bits = 0;
389 	return (outlen);
390 }
391 
392 static int
393 b64dec(bs, inp, inlen, outp)
394 struct b64state *bs;
395 u_char *inp;
396 int inlen;
397 u_char *outp;
398 {
399 	int outlen = 0;
400 	char *cp;
401 
402 	while (inlen > 0) {
403 		if ((cp = strchr(base64, *inp++)) == NULL)
404 			break;
405 		bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);
406 		inlen--;
407 		bs->bs_offs += 6;
408 		if (bs->bs_offs >= 8) {
409 			*outp++ = bs->bs_bits >> (bs->bs_offs - 8);
410 			outlen++;
411 			bs->bs_offs -= 8;
412 		}
413 	}
414 	return (outlen);
415 }
416 #endif /* USE_SRP */
417 
418 #if PPP_SERVER
419 /*
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.
424  */
425 static void eap_figure_next_state(ppp_pcb *pcb, int status) {
426 #ifdef USE_SRP
427 	unsigned char secbuf[MAXSECRETLEN], clear[8], *sp, *dp;
428 	struct t_pw tpw;
429 	struct t_confent *tce, mytce;
430 	char *cp, *cp2;
431 	struct t_server *ts;
432 	int id, i, plen, toffs;
433 	u_char vals[2];
434 	struct b64state bs;
435 #endif /* USE_SRP */
436 
437 	pcb->settings.eap_timeout_time = pcb->eap.es_savedtime;
438 	switch (pcb->eap.es_server.ea_state) {
439 	case eapBadAuth:
440 		return;
441 
442 	case eapIdentify:
443 #ifdef USE_SRP
444 		/* Discard any previous session. */
445 		ts = (struct t_server *)pcb->eap.es_server.ea_session;
446 		if (ts != NULL) {
447 			t_serverclose(ts);
448 			pcb->eap.es_server.ea_session = NULL;
449 			pcb->eap.es_server.ea_skey = NULL;
450 		}
451 #endif /* USE_SRP */
452 		if (status != 0) {
453 			pcb->eap.es_server.ea_state = eapBadAuth;
454 			break;
455 		}
456 #ifdef USE_SRP
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 <
462 		    sizeof (secbuf)) {
463 			BZERO(&bs, sizeof (bs));
464 			plen = b64dec(&bs,
465 			    pcb->eap.es_server.ea_peer + SRP_PSEUDO_LEN,
466 			    pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN,
467 			    secbuf);
468 			toffs = 0;
469 			for (i = 0; i < 5; i++) {
470 				pncrypt_setkey(toffs);
471 				toffs -= 86400;
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 "
475 					    "pseudonym");
476 					return;
477 				}
478 				id = *(unsigned char *)clear;
479 				if (id + 1 <= plen && id + 9 > plen)
480 					break;
481 			}
482 			if (plen % 8 == 0 && i < 5) {
483 				/*
484 				 * Note that this is always shorter than the
485 				 * original stored string, so there's no need
486 				 * to realloc.
487 				 */
488 				if ((i = plen = *(unsigned char *)clear) > 7)
489 					i = 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);
493 				plen -= i;
494 				dp += i;
495 				sp = secbuf + 8;
496 				while (plen > 0) {
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);
499 					sp += 8;
500 					dp += 8;
501 					plen -= 8;
502 				}
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);
508 			} else {
509 				ppp_dbglog("failed to decode real name");
510 				/* Stay in eapIdentfy state; requery */
511 				break;
512 			}
513 		}
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)
522 				break;
523 			if (id == 0) {
524 				mytce.index = 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;
529 				tce = &mytce;
530 			} else if ((tce = gettcid(id)) != NULL) {
531 				/*
532 				 * Client will have to verify this modulus/
533 				 * generator combination, and that will take
534 				 * a while.  Lengthen the timeout here.
535 				 */
536 				if (pcb->settings.eap_timeout_time > 0 &&
537 				    pcb->settings.eap_timeout_time < 30)
538 					pcb->settings.eap_timeout_time = 30;
539 			} else {
540 				break;
541 			}
542 			if ((cp2 = strchr(cp, ':')) == NULL)
543 				break;
544 			*cp2++ = '\0';
545 			tpw.pebuf.name = pcb->eap.es_server.ea_peer;
546 			tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,
547 			    cp);
548 			tpw.pebuf.password.data = tpw.pwbuf;
549 			tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,
550 			    cp2);
551 			tpw.pebuf.salt.data = tpw.saltbuf;
552 			if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)
553 				break;
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;
557 			vals[1] = EAPT_SRP;
558 			t_serveraddexdata(ts, vals, 2);
559 			/* Generate B; must call before t_servergetkey() */
560 			t_servergenexp(ts);
561 			break;
562 		}
563 #endif /* USE_SRP */
564 		pcb->eap.es_server.ea_state = eapMD5Chall;
565 		break;
566 
567 	case eapSRP1:
568 #ifdef USE_SRP
569 		ts = (struct t_server *)pcb->eap.es_server.ea_session;
570 		if (ts != NULL && status != 0) {
571 			t_serverclose(ts);
572 			pcb->eap.es_server.ea_session = NULL;
573 			pcb->eap.es_server.ea_skey = NULL;
574 		}
575 #endif /* USE_SRP */
576 		if (status == 1) {
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;
580 		} else {
581 			pcb->eap.es_server.ea_state = eapSRP2;
582 		}
583 		break;
584 
585 	case eapSRP2:
586 #ifdef USE_SRP
587 		ts = (struct t_server *)pcb->eap.es_server.ea_session;
588 		if (ts != NULL && status != 0) {
589 			t_serverclose(ts);
590 			pcb->eap.es_server.ea_session = NULL;
591 			pcb->eap.es_server.ea_skey = NULL;
592 		}
593 #endif /* USE_SRP */
594 		if (status != 0 || pcb->eap.es_server.ea_session == NULL) {
595 			pcb->eap.es_server.ea_state = eapBadAuth;
596 		} else {
597 			pcb->eap.es_server.ea_state = eapSRP3;
598 		}
599 		break;
600 
601 	case eapSRP3:
602 	case eapSRP4:
603 #ifdef USE_SRP
604 		ts = (struct t_server *)pcb->eap.es_server.ea_session;
605 		if (ts != NULL && status != 0) {
606 			t_serverclose(ts);
607 			pcb->eap.es_server.ea_session = NULL;
608 			pcb->eap.es_server.ea_skey = NULL;
609 		}
610 #endif /* USE_SRP */
611 		if (status != 0 || pcb->eap.es_server.ea_session == NULL) {
612 			pcb->eap.es_server.ea_state = eapBadAuth;
613 		} else {
614 			pcb->eap.es_server.ea_state = eapOpen;
615 		}
616 		break;
617 
618 	case eapMD5Chall:
619 		if (status != 0) {
620 			pcb->eap.es_server.ea_state = eapBadAuth;
621 		} else {
622 			pcb->eap.es_server.ea_state = eapOpen;
623 		}
624 		break;
625 
626 	default:
627 		pcb->eap.es_server.ea_state = eapBadAuth;
628 		break;
629 	}
630 	if (pcb->eap.es_server.ea_state == eapBadAuth)
631 		eap_send_failure(pcb);
632 }
633 
634 /*
635  * Format an EAP Request message and send it to the peer.  Message
636  * type depends on current state.  (Server operation)
637  */
638 static void eap_send_request(ppp_pcb *pcb) {
639 	struct pbuf *p;
640 	u_char *outp;
641 	u_char *lenloc;
642 	int outlen;
643 	int len;
644 	const char *str;
645 #ifdef USE_SRP
646 	struct t_server *ts;
647 	u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp;
648 	int i, j;
649 	struct b64state b64;
650 	SHA1_CTX ctxt;
651 #endif /* USE_SRP */
652 
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;
657 #if PPP_REMOTENAME
658 		if (pcb->settings.explicit_remote && pcb->remote_name) {
659 			/*
660 			 * If we already know the peer's
661 			 * unauthenticated name, then there's no
662 			 * reason to ask.  Go to next state instead.
663 			 */
664 			int len = (int)strlen(pcb->remote_name);
665 			if (len > MAXNAMELEN) {
666 				len = MAXNAMELEN;
667 			}
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);
672 		}
673 #endif /* PPP_REMOTENAME */
674 	}
675 
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");
680 		else
681 			ppp_error("EAP: no response to Requests");
682 		eap_send_failure(pcb);
683 		return;
684 	}
685 
686 	p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE);
687 	if(NULL == p)
688 		return;
689 	if(p->tot_len != p->len) {
690 		pbuf_free(p);
691 		return;
692 	}
693 
694 	outp = (u_char*)p->payload;
695 
696 	MAKEHEADER(outp, PPP_EAP);
697 
698 	PUTCHAR(EAP_REQUEST, outp);
699 	PUTCHAR(pcb->eap.es_server.ea_id, outp);
700 	lenloc = outp;
701 	INCPTR(2, outp);
702 
703 	switch (pcb->eap.es_server.ea_state) {
704 	case eapIdentify:
705 		PUTCHAR(EAPT_IDENTITY, outp);
706 		str = "Name";
707 		len = strlen(str);
708 		MEMCPY(outp, str, len);
709 		INCPTR(len, outp);
710 		break;
711 
712 	case eapMD5Chall:
713 		PUTCHAR(EAPT_MD5CHAP, outp);
714 		/*
715 		 * pick a random challenge length between
716 		 * EAP_MIN_CHALLENGE_LENGTH and EAP_MAX_CHALLENGE_LENGTH
717 		 */
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);
726 		break;
727 
728 #ifdef USE_SRP
729 	case eapSRP1:
730 		PUTCHAR(EAPT_SRP, outp);
731 		PUTCHAR(EAPSRP_CHALLENGE, outp);
732 
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);
736 
737 		ts = (struct t_server *)pcb->eap.es_server.ea_session;
738 		assert(ts != NULL);
739 		PUTCHAR(ts->s.len, outp);
740 		MEMCPY(outp, ts->s.data, ts->s.len);
741 		INCPTR(ts->s.len, outp);
742 
743 		if (ts->g.len == 1 && ts->g.data[0] == 2) {
744 			PUTCHAR(0, outp);
745 		} else {
746 			PUTCHAR(ts->g.len, outp);
747 			MEMCPY(outp, ts->g.data, ts->g.len);
748 			INCPTR(ts->g.len, outp);
749 		}
750 
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);
755 		}
756 		break;
757 
758 	case eapSRP2:
759 		PUTCHAR(EAPT_SRP, outp);
760 		PUTCHAR(EAPSRP_SKEY, outp);
761 
762 		ts = (struct t_server *)pcb->eap.es_server.ea_session;
763 		assert(ts != NULL);
764 		MEMCPY(outp, ts->B.data, ts->B.len);
765 		INCPTR(ts->B.len, outp);
766 		break;
767 
768 	case eapSRP3:
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;
773 		assert(ts != NULL);
774 		MEMCPY(outp, t_serverresponse(ts), SHA_DIGESTSIZE);
775 		INCPTR(SHA_DIGESTSIZE, outp);
776 
777 		if (pncrypt_setkey(0)) {
778 			/* Generate pseudonym */
779 			optr = outp;
780 			cp = (unsigned char *)pcb->eap.es_server.ea_peer;
781 			if ((j = i = pcb->eap.es_server.ea_peerlen) > 7)
782 				j = 7;
783 			clear[0] = i;
784 			MEMCPY(clear + 1, cp, j);
785 			i -= j;
786 			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");
790 				break;
791 			}
792 			BZERO(&b64, sizeof (b64));
793 			outp++;		/* space for pseudonym length */
794 			outp += b64enc(&b64, cipher, 8, outp);
795 			while (i >= 8) {
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);
799 				cp += 8;
800 				i -= 8;
801 			}
802 			if (i > 0) {
803 				MEMCPY(clear, cp, i);
804 				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);
809 			}
810 			outp += b64flush(&b64, outp);
811 
812 			/* Set length and pad out to next 20 octet boundary */
813 			i = outp - optr - 1;
814 			*optr = i;
815 			i %= SHA_DIGESTSIZE;
816 			if (i != 0) {
817 				magic_random_bytes(outp, SHA_DIGESTSIZE-i);
818 				INCPTR(SHA_DIGESTSIZE-i, outp);
819 			}
820 
821 			/* Obscure the pseudonym with SHA1 hash */
822 			SHA1Init(&ctxt);
823 			SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1);
824 			SHA1Update(&ctxt, pcb->eap.es_server.ea_skey,
825 			    SESSION_KEY_LEN);
826 			SHA1Update(&ctxt, pcb->eap.es_server.ea_peer,
827 			    pcb->eap.es_server.ea_peerlen);
828 			while (optr < outp) {
829 				SHA1Final(dig, &ctxt);
830 				cp = dig;
831 				while (cp < dig + SHA_DIGESTSIZE)
832 					*optr++ ^= *cp++;
833 				SHA1Init(&ctxt);
834 				SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1);
835 				SHA1Update(&ctxt, pcb->eap.es_server.ea_skey,
836 				    SESSION_KEY_LEN);
837 				SHA1Update(&ctxt, optr - SHA_DIGESTSIZE,
838 				    SHA_DIGESTSIZE);
839 			}
840 		}
841 		break;
842 
843 	case eapSRP4:
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);
851 		break;
852 #endif /* USE_SRP */
853 
854 	default:
855 		return;
856 	}
857 
858 	outlen = (outp - (unsigned char*)p->payload) - PPP_HDRLEN;
859 	PUTSHORT(outlen, lenloc);
860 
861 	pbuf_realloc(p, outlen + PPP_HDRLEN);
862 	ppp_write(pcb, p);
863 
864 	pcb->eap.es_server.ea_requests++;
865 
866 	if (pcb->settings.eap_timeout_time > 0)
867 		TIMEOUT(eap_server_timeout, pcb, pcb->settings.eap_timeout_time);
868 }
869 
870 /*
871  * eap_authpeer - Authenticate our peer (behave as server).
872  *
873  * Start server state and send first request.  This is called only
874  * after eap_lowerup.
875  */
876 void eap_authpeer(ppp_pcb *pcb, const char *localname) {
877 
878 	/* Save the name we're given. */
879 	pcb->eap.es_server.ea_name = localname;
880 	pcb->eap.es_server.ea_namelen = strlen(localname);
881 
882 	pcb->eap.es_savedtime = pcb->settings.eap_timeout_time;
883 
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;
888 		return;
889 	}
890 
891 	pcb->eap.es_server.ea_state = eapPending;
892 
893 	/* ID number not updated here intentionally; hashed into M1 */
894 	eap_send_request(pcb);
895 }
896 
897 /*
898  * eap_server_timeout - Retransmission timer for sending Requests
899  * expired.
900  */
901 static void eap_server_timeout(void *arg) {
902 	ppp_pcb *pcb = (ppp_pcb*)arg;
903 
904 	if (!eap_server_active(pcb))
905 		return;
906 
907 	/* EAP ID number must not change on timeout. */
908 	eap_send_request(pcb);
909 }
910 
911 /*
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.
915  */
916 static void eap_rechallenge(void *arg) {
917 	ppp_pcb *pcb = (ppp_pcb*)arg;
918 
919 	if (pcb->eap.es_server.ea_state != eapOpen &&
920 	    pcb->eap.es_server.ea_state != eapSRP4)
921 		return;
922 
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);
928 }
929 
930 static void srp_lwrechallenge(void *arg) {
931 	ppp_pcb *pcb = (ppp_pcb*)arg;
932 
933 	if (pcb->eap.es_server.ea_state != eapOpen ||
934 	    pcb->eap.es_server.ea_type != EAPT_SRP)
935 		return;
936 
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);
941 }
942 #endif /* PPP_SERVER */
943 
944 /*
945  * eap_lowerup - The lower layer is now up.
946  *
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
950  * thing.
951  */
952 static void eap_lowerup(ppp_pcb *pcb) {
953 	pcb->eap.es_client.ea_state = eapClosed;
954 #if PPP_SERVER
955 	pcb->eap.es_server.ea_state = eapClosed;
956 #endif /* PPP_SERVER */
957 }
958 
959 /*
960  * eap_lowerdown - The lower layer is now down.
961  *
962  * Cancel all timeouts and return to initial state.
963  */
964 static void eap_lowerdown(ppp_pcb *pcb) {
965 
966 	if (eap_client_active(pcb) && pcb->settings.eap_req_time > 0) {
967 		UNTIMEOUT(eap_client_timeout, pcb);
968 	}
969 #if PPP_SERVER
970 	if (eap_server_active(pcb)) {
971 		if (pcb->settings.eap_timeout_time > 0) {
972 			UNTIMEOUT(eap_server_timeout, pcb);
973 		}
974 	} else {
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);
979 		}
980 		if (pcb->eap.es_server.ea_state == eapOpen &&
981 		    pcb->eap.es_lwrechallenge > 0) {
982 			UNTIMEOUT(srp_lwrechallenge, (void *)pcb);
983 		}
984 	}
985 
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 */
989 }
990 
991 /*
992  * eap_protrej - Peer doesn't speak this protocol.
993  *
994  * This shouldn't happen.  If it does, it represents authentication
995  * failure.
996  */
997 static void eap_protrej(ppp_pcb *pcb) {
998 
999 	if (eap_client_active(pcb)) {
1000 		ppp_error("EAP authentication failed due to Protocol-Reject");
1001 		auth_withpeer_fail(pcb, PPP_EAP);
1002 	}
1003 #if PPP_SERVER
1004 	if (eap_server_active(pcb)) {
1005 		ppp_error("EAP authentication of peer failed on Protocol-Reject");
1006 		auth_peer_fail(pcb, PPP_EAP);
1007 	}
1008 #endif /* PPP_SERVER */
1009 	eap_lowerdown(pcb);
1010 }
1011 
1012 /*
1013  * Format and send a regular EAP Response message.
1014  */
1015 static void eap_send_response(ppp_pcb *pcb, u_char id, u_char typenum, const u_char *str, int lenstr) {
1016 	struct pbuf *p;
1017 	u_char *outp;
1018 	int msglen;
1019 
1020 	msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr;
1021 	p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE);
1022 	if(NULL == p)
1023 		return;
1024 	if(p->tot_len != p->len) {
1025 		pbuf_free(p);
1026 		return;
1027 	}
1028 
1029 	outp = (u_char*)p->payload;
1030 
1031 	MAKEHEADER(outp, PPP_EAP);
1032 
1033 	PUTCHAR(EAP_RESPONSE, outp);
1034 	PUTCHAR(id, outp);
1035 	pcb->eap.es_client.ea_id = id;
1036 	PUTSHORT(msglen, outp);
1037 	PUTCHAR(typenum, outp);
1038 	if (lenstr > 0) {
1039 		MEMCPY(outp, str, lenstr);
1040 	}
1041 
1042 	ppp_write(pcb, p);
1043 }
1044 
1045 /*
1046  * Format and send an MD5-Challenge EAP Response message.
1047  */
1048 static void eap_chap_response(ppp_pcb *pcb, u_char id, u_char *hash, const char *name, int namelen) {
1049 	struct pbuf *p;
1050 	u_char *outp;
1051 	int msglen;
1052 
1053 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE +
1054 	    namelen;
1055 	p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE);
1056 	if(NULL == p)
1057 		return;
1058 	if(p->tot_len != p->len) {
1059 		pbuf_free(p);
1060 		return;
1061 	}
1062 
1063 	outp = (u_char*)p->payload;
1064 
1065 	MAKEHEADER(outp, PPP_EAP);
1066 
1067 	PUTCHAR(EAP_RESPONSE, outp);
1068 	PUTCHAR(id, 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);
1075 	if (namelen > 0) {
1076 		MEMCPY(outp, name, namelen);
1077 	}
1078 
1079 	ppp_write(pcb, p);
1080 }
1081 
1082 #ifdef USE_SRP
1083 /*
1084  * Format and send a SRP EAP Response message.
1085  */
1086 static void
1087 eap_srp_response(esp, id, subtypenum, str, lenstr)
1088 eap_state *esp;
1089 u_char id;
1090 u_char subtypenum;
1091 u_char *str;
1092 int lenstr;
1093 {
1094 	ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit];
1095 	struct pbuf *p;
1096 	u_char *outp;
1097 	int msglen;
1098 
1099 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr;
1100 	p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE);
1101 	if(NULL == p)
1102 		return;
1103 	if(p->tot_len != p->len) {
1104 		pbuf_free(p);
1105 		return;
1106 	}
1107 
1108 	outp = p->payload;
1109 
1110 	MAKEHEADER(outp, PPP_EAP);
1111 
1112 	PUTCHAR(EAP_RESPONSE, outp);
1113 	PUTCHAR(id, outp);
1114 	pcb->eap.es_client.ea_id = id;
1115 	PUTSHORT(msglen, outp);
1116 	PUTCHAR(EAPT_SRP, outp);
1117 	PUTCHAR(subtypenum, outp);
1118 	if (lenstr > 0) {
1119 		MEMCPY(outp, str, lenstr);
1120 	}
1121 
1122 	ppp_write(pcb, p);
1123 }
1124 
1125 /*
1126  * Format and send a SRP EAP Client Validator Response message.
1127  */
1128 static void
1129 eap_srpval_response(esp, id, flags, str)
1130 eap_state *esp;
1131 u_char id;
1132 u32_t flags;
1133 u_char *str;
1134 {
1135 	ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit];
1136 	struct pbuf *p;
1137 	u_char *outp;
1138 	int msglen;
1139 
1140 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u32_t) +
1141 	    SHA_DIGESTSIZE;
1142 	p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE);
1143 	if(NULL == p)
1144 		return;
1145 	if(p->tot_len != p->len) {
1146 		pbuf_free(p);
1147 		return;
1148 	}
1149 
1150 	outp = p->payload;
1151 
1152 	MAKEHEADER(outp, PPP_EAP);
1153 
1154 	PUTCHAR(EAP_RESPONSE, outp);
1155 	PUTCHAR(id, 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);
1162 
1163 	ppp_write(pcb, p);
1164 }
1165 #endif /* USE_SRP */
1166 
1167 static void eap_send_nak(ppp_pcb *pcb, u_char id, u_char type) {
1168 	struct pbuf *p;
1169 	u_char *outp;
1170 	int msglen;
1171 
1172 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char);
1173 	p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE);
1174 	if(NULL == p)
1175 		return;
1176 	if(p->tot_len != p->len) {
1177 		pbuf_free(p);
1178 		return;
1179 	}
1180 
1181 	outp = (u_char*)p->payload;
1182 
1183 	MAKEHEADER(outp, PPP_EAP);
1184 
1185 	PUTCHAR(EAP_RESPONSE, outp);
1186 	PUTCHAR(id, outp);
1187 	pcb->eap.es_client.ea_id = id;
1188 	PUTSHORT(msglen, outp);
1189 	PUTCHAR(EAPT_NAK, outp);
1190 	PUTCHAR(type, outp);
1191 
1192 	ppp_write(pcb, p);
1193 }
1194 
1195 #ifdef USE_SRP
1196 static char *
1197 name_of_pn_file()
1198 {
1199 	char *user, *path, *file;
1200 	struct passwd *pw;
1201 	size_t pl;
1202 	static bool pnlogged = 0;
1203 
1204 	pw = getpwuid(getuid());
1205 	if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
1206 		errno = EINVAL;
1207 		return (NULL);
1208 	}
1209 	file = _PATH_PSEUDONYM;
1210 	pl = strlen(user) + strlen(file) + 2;
1211 	path = malloc(pl);
1212 	if (path == NULL)
1213 		return (NULL);
1214 	(void) slprintf(path, pl, "%s/%s", user, file);
1215 	if (!pnlogged) {
1216 		ppp_dbglog("pseudonym file: %s", path);
1217 		pnlogged = 1;
1218 	}
1219 	return (path);
1220 }
1221 
1222 static int
1223 open_pn_file(modebits)
1224 mode_t modebits;
1225 {
1226 	char *path;
1227 	int fd, err;
1228 
1229 	if ((path = name_of_pn_file()) == NULL)
1230 		return (-1);
1231 	fd = open(path, modebits, S_IRUSR | S_IWUSR);
1232 	err = errno;
1233 	free(path);
1234 	errno = err;
1235 	return (fd);
1236 }
1237 
1238 static void
1239 remove_pn_file()
1240 {
1241 	char *path;
1242 
1243 	if ((path = name_of_pn_file()) != NULL) {
1244 		(void) unlink(path);
1245 		(void) free(path);
1246 	}
1247 }
1248 
1249 static void
1250 write_pseudonym(esp, inp, len, id)
1251 eap_state *esp;
1252 u_char *inp;
1253 int len, id;
1254 {
1255 	u_char val;
1256 	u_char *datp, *digp;
1257 	SHA1_CTX ctxt;
1258 	u_char dig[SHA_DIGESTSIZE];
1259 	int dsize, fd, olen = len;
1260 
1261 	/*
1262 	 * Do the decoding by working backwards.  This eliminates the need
1263 	 * to save the decoded output in a separate buffer.
1264 	 */
1265 	val = id;
1266 	while (len > 0) {
1267 		if ((dsize = len % SHA_DIGESTSIZE) == 0)
1268 			dsize = SHA_DIGESTSIZE;
1269 		len -= dsize;
1270 		datp = inp + len;
1271 		SHA1Init(&ctxt);
1272 		SHA1Update(&ctxt, &val, 1);
1273 		SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, SESSION_KEY_LEN);
1274 		if (len > 0) {
1275 			SHA1Update(&ctxt, datp, SHA_DIGESTSIZE);
1276 		} else {
1277 			SHA1Update(&ctxt, pcb->eap.es_client.ea_name,
1278 			    pcb->eap.es_client.ea_namelen);
1279 		}
1280 		SHA1Final(dig, &ctxt);
1281 		for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++)
1282 			*datp++ ^= *digp;
1283 	}
1284 
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);
1288 		return;
1289 	}
1290 
1291 	/* Save it away */
1292 	fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);
1293 	if (fd < 0) {
1294 		ppp_dbglog("EAP: error saving pseudonym: %m");
1295 		return;
1296 	}
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;
1301 	} else {
1302 		ppp_dbglog("EAP: failed to save pseudonym");
1303 		remove_pn_file();
1304 	}
1305 }
1306 #endif /* USE_SRP */
1307 
1308 /*
1309  * eap_request - Receive EAP Request message (client mode).
1310  */
1311 static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) {
1312 	u_char typenum;
1313 	u_char vallen;
1314 	int secret_len;
1315 	char secret[MAXSECRETLEN];
1316 	char rhostname[MAXNAMELEN];
1317 	lwip_md5_context mdContext;
1318 	u_char hash[MD5_SIGNATURE_SIZE];
1319 #ifdef USE_SRP
1320 	struct t_client *tc;
1321 	struct t_num sval, gval, Nval, *Ap, Bval;
1322 	u_char vals[2];
1323 	SHA1_CTX ctxt;
1324 	u_char dig[SHA_DIGESTSIZE];
1325 	int fd;
1326 #endif /* USE_SRP */
1327 
1328 	/*
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.
1332 	 */
1333 
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);
1340 		}
1341 		auth_withpeer_fail(pcb, PPP_EAP);
1342 		return;
1343 	}
1344 
1345 	if (len <= 0) {
1346 		ppp_error("EAP: empty Request message discarded");
1347 		return;
1348 	}
1349 
1350 	GETCHAR(typenum, inp);
1351 	len--;
1352 
1353 	switch (typenum) {
1354 	case EAPT_IDENTITY:
1355 		if (len > 0)
1356 			ppp_info("EAP: Identity prompt \"%.*q\"", len, inp);
1357 #ifdef USE_SRP
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 */
1369 				if (len > 0) {
1370 					eap_send_response(pcb, id, typenum,
1371 					    rhostname, len + SRP_PSEUDO_LEN);
1372 				}
1373 				(void) close(fd);
1374 				if (len > 0)
1375 					break;
1376 			}
1377 		}
1378 		/* Stop using pseudonym now. */
1379 		if (pcb->eap.es_usepseudo && pcb->eap.es_usedpseudo != 2) {
1380 			remove_pn_file();
1381 			pcb->eap.es_usedpseudo = 2;
1382 		}
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);
1386 		break;
1387 
1388 	case EAPT_NOTIFICATION:
1389 		if (len > 0)
1390 			ppp_info("EAP: Notification \"%.*q\"", len, inp);
1391 		eap_send_response(pcb, id, typenum, NULL, 0);
1392 		break;
1393 
1394 	case EAPT_NAK:
1395 		/*
1396 		 * Avoid the temptation to send Response Nak in reply
1397 		 * to Request Nak here.  It can only lead to trouble.
1398 		 */
1399 		ppp_warn("EAP: unexpected Nak in Request; ignored");
1400 		/* Return because we're waiting for something real. */
1401 		return;
1402 
1403 	case EAPT_MD5CHAP:
1404 		if (len < 1) {
1405 			ppp_error("EAP: received MD5-Challenge with no data");
1406 			/* Bogus request; wait for something real. */
1407 			return;
1408 		}
1409 		GETCHAR(vallen, inp);
1410 		len--;
1411 		if (vallen < 8 || vallen > len) {
1412 			ppp_error("EAP: MD5-Challenge with bad length %d (8..%d)",
1413 			    vallen, len);
1414 			/* Try something better. */
1415 			eap_send_nak(pcb, id, EAPT_SRP);
1416 			break;
1417 		}
1418 
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';
1424 		} else {
1425 			MEMCPY(rhostname, inp + vallen, len - vallen);
1426 			rhostname[len - vallen] = '\0';
1427 		}
1428 
1429 #if PPP_REMOTENAME
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 */
1435 
1436 		/*
1437 		 * Get the secret for authenticating ourselves with
1438 		 * the specified host.
1439 		 */
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);
1444 			break;
1445 		}
1446 		lwip_md5_init(&mdContext);
1447 		lwip_md5_starts(&mdContext);
1448 		typenum = id;
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);
1457 		break;
1458 
1459 #ifdef USE_SRP
1460 	case EAPT_SRP:
1461 		if (len < 1) {
1462 			ppp_error("EAP: received empty SRP Request");
1463 			/* Bogus request; wait for something real. */
1464 			return;
1465 		}
1466 
1467 		/* Get subtype */
1468 		GETCHAR(vallen, inp);
1469 		len--;
1470 		switch (vallen) {
1471 		case EAPSRP_CHALLENGE:
1472 			tc = NULL;
1473 			if (pcb->eap.es_client.ea_session != NULL) {
1474 				tc = (struct t_client *)pcb->eap.es_client.
1475 				    ea_session;
1476 				/*
1477 				 * If this is a new challenge, then start
1478 				 * over with a new client session context.
1479 				 * Otherwise, just resend last response.
1480 				 */
1481 				if (id != pcb->eap.es_client.ea_id) {
1482 					t_clientclose(tc);
1483 					pcb->eap.es_client.ea_session = NULL;
1484 					tc = NULL;
1485 				}
1486 			}
1487 			/* No session key just yet */
1488 			pcb->eap.es_client.ea_skey = NULL;
1489 			if (tc == NULL) {
1490 				int rhostnamelen;
1491 
1492 				GETCHAR(vallen, inp);
1493 				len--;
1494 				if (vallen >= len) {
1495 					ppp_error("EAP: badly-formed SRP Challenge"
1496 					    " (name)");
1497 					/* Ignore badly-formed messages */
1498 					return;
1499 				}
1500 				MEMCPY(rhostname, inp, vallen);
1501 				rhostname[vallen] = '\0';
1502 				INCPTR(vallen, inp);
1503 				len -= vallen;
1504 
1505 				/*
1506 				 * In case the remote doesn't give us his name,
1507 				 * use configured name.
1508 				 */
1509 				if (explicit_remote ||
1510 				    (remote_name[0] != '\0' && vallen == 0)) {
1511 					strlcpy(rhostname, remote_name,
1512 					    sizeof (rhostname));
1513 				}
1514 
1515 				rhostnamelen = (int)strlen(rhostname);
1516 				if (rhostnamelen > MAXNAMELEN) {
1517 					rhostnamelen = MAXNAMELEN;
1518 				}
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;
1522 
1523 				GETCHAR(vallen, inp);
1524 				len--;
1525 				if (vallen >= len) {
1526 					ppp_error("EAP: badly-formed SRP Challenge"
1527 					    " (s)");
1528 					/* Ignore badly-formed messages */
1529 					return;
1530 				}
1531 				sval.data = inp;
1532 				sval.len = vallen;
1533 				INCPTR(vallen, inp);
1534 				len -= vallen;
1535 
1536 				GETCHAR(vallen, inp);
1537 				len--;
1538 				if (vallen > len) {
1539 					ppp_error("EAP: badly-formed SRP Challenge"
1540 					    " (g)");
1541 					/* Ignore badly-formed messages */
1542 					return;
1543 				}
1544 				/* If no generator present, then use value 2 */
1545 				if (vallen == 0) {
1546 					gval.data = (u_char *)"\002";
1547 					gval.len = 1;
1548 				} else {
1549 					gval.data = inp;
1550 					gval.len = vallen;
1551 				}
1552 				INCPTR(vallen, inp);
1553 				len -= vallen;
1554 
1555 				/*
1556 				 * If no modulus present, then use well-known
1557 				 * value.
1558 				 */
1559 				if (len == 0) {
1560 					Nval.data = (u_char *)wkmodulus;
1561 					Nval.len = sizeof (wkmodulus);
1562 				} else {
1563 					Nval.data = inp;
1564 					Nval.len = len;
1565 				}
1566 				tc = t_clientopen(pcb->eap.es_client.ea_name,
1567 				    &Nval, &gval, &sval);
1568 				if (tc == NULL) {
1569 					eap_send_nak(pcb, id, EAPT_MD5CHAP);
1570 					break;
1571 				}
1572 				pcb->eap.es_client.ea_session = (void *)tc;
1573 
1574 				/* Add Challenge ID & type to verifier */
1575 				vals[0] = id;
1576 				vals[1] = EAPT_SRP;
1577 				t_clientaddexdata(tc, vals, 2);
1578 			}
1579 			Ap = t_clientgenexp(tc);
1580 			eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
1581 			    Ap->len);
1582 			break;
1583 
1584 		case EAPSRP_SKEY:
1585 			tc = (struct t_client *)pcb->eap.es_client.ea_session;
1586 			if (tc == NULL) {
1587 				ppp_warn("EAP: peer sent Subtype 2 without 1");
1588 				eap_send_nak(pcb, id, EAPT_MD5CHAP);
1589 				break;
1590 			}
1591 			if (pcb->eap.es_client.ea_skey != NULL) {
1592 				/*
1593 				 * ID number should not change here.  Warn
1594 				 * if it does (but otherwise ignore).
1595 				 */
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);
1600 				}
1601 			} else {
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) {
1605 					/*
1606 					 * Can't work with this peer because
1607 					 * the secret is missing.  Just give
1608 					 * up.
1609 					 */
1610 					eap_send_nak(pcb, id, EAPT_MD5CHAP);
1611 					break;
1612 				}
1613 				Bval.data = inp;
1614 				Bval.len = len;
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;
1623 				}
1624 			}
1625 			eap_srpval_response(esp, id, SRPVAL_EBIT,
1626 			    t_clientresponse(tc));
1627 			break;
1628 
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);
1634 				break;
1635 			}
1636 			/*
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.
1640 			 */
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);
1646 				}
1647 			} else {
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 "
1652 					    "failed");
1653 					goto client_failure;
1654 				}
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);
1660 				}
1661 			}
1662 			/*
1663 			 * We've verified our peer.  We're now mostly done,
1664 			 * except for waiting on the regular EAP Success
1665 			 * message.
1666 			 */
1667 			eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
1668 			break;
1669 
1670 		case EAPSRP_LWRECHALLENGE:
1671 			if (len < 4) {
1672 				ppp_warn("EAP: malformed Lightweight rechallenge");
1673 				return;
1674 			}
1675 			SHA1Init(&ctxt);
1676 			vals[0] = id;
1677 			SHA1Update(&ctxt, vals, 1);
1678 			SHA1Update(&ctxt, pcb->eap.es_client.ea_skey,
1679 			    SESSION_KEY_LEN);
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,
1685 			    SHA_DIGESTSIZE);
1686 			break;
1687 
1688 		default:
1689 			ppp_error("EAP: unknown SRP Subtype %d", vallen);
1690 			eap_send_nak(pcb, id, EAPT_MD5CHAP);
1691 			break;
1692 		}
1693 		break;
1694 #endif /* USE_SRP */
1695 
1696 	default:
1697 		ppp_info("EAP: unknown authentication type %d; Naking", typenum);
1698 		eap_send_nak(pcb, id, EAPT_SRP);
1699 		break;
1700 	}
1701 
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);
1706 	}
1707 	return;
1708 
1709 #ifdef USE_SRP
1710 client_failure:
1711 	pcb->eap.es_client.ea_state = eapBadAuth;
1712 	if (pcb->settings.eap_req_time > 0) {
1713 		UNTIMEOUT(eap_client_timeout, (void *)esp);
1714 	}
1715 	pcb->eap.es_client.ea_session = NULL;
1716 	t_clientclose(tc);
1717 	auth_withpeer_fail(pcb, PPP_EAP);
1718 #endif /* USE_SRP */
1719 }
1720 
1721 #if PPP_SERVER
1722 /*
1723  * eap_response - Receive EAP Response message (server mode).
1724  */
1725 static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) {
1726 	u_char typenum;
1727 	u_char vallen;
1728 	int secret_len;
1729 	char secret[MAXSECRETLEN];
1730 	char rhostname[MAXNAMELEN];
1731 	lwip_md5_context mdContext;
1732 	u_char hash[MD5_SIGNATURE_SIZE];
1733 #ifdef USE_SRP
1734 	struct t_server *ts;
1735 	struct t_num A;
1736 	SHA1_CTX ctxt;
1737 	u_char dig[SHA_DIGESTSIZE];
1738 #endif /* USE_SRP */
1739 
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);
1743 		return;
1744 	}
1745 
1746 	pcb->eap.es_server.ea_responses++;
1747 
1748 	if (len <= 0) {
1749 		ppp_error("EAP: empty Response message discarded");
1750 		return;
1751 	}
1752 
1753 	GETCHAR(typenum, inp);
1754 	len--;
1755 
1756 	switch (typenum) {
1757 	case EAPT_IDENTITY:
1758 		if (pcb->eap.es_server.ea_state != eapIdentify) {
1759 			ppp_dbglog("EAP discarding unwanted Identify \"%.q\"", len,
1760 			    inp);
1761 			break;
1762 		}
1763 		ppp_info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
1764 		if (len > MAXNAMELEN) {
1765 		  len = MAXNAMELEN;
1766 		}
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);
1771 		break;
1772 
1773 	case EAPT_NOTIFICATION:
1774 		ppp_dbglog("EAP unexpected Notification; response discarded");
1775 		break;
1776 
1777 	case EAPT_NAK:
1778 		if (len < 1) {
1779 			ppp_info("EAP: Nak Response with no suggested protocol");
1780 			eap_figure_next_state(pcb, 1);
1781 			break;
1782 		}
1783 
1784 		GETCHAR(vallen, inp);
1785 		len--;
1786 
1787 		if (
1788 #if PPP_REMOTENAME
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);
1794 			break;
1795 		}
1796 
1797 		switch (vallen) {
1798 		case EAPT_SRP:
1799 			/* Run through SRP validator selection again. */
1800 			pcb->eap.es_server.ea_state = eapIdentify;
1801 			eap_figure_next_state(pcb, 0);
1802 			break;
1803 
1804 		case EAPT_MD5CHAP:
1805 			pcb->eap.es_server.ea_state = eapMD5Chall;
1806 			break;
1807 
1808 		default:
1809 			ppp_dbglog("EAP: peer requesting unknown Type %d", vallen);
1810 			switch (pcb->eap.es_server.ea_state) {
1811 			case eapSRP1:
1812 			case eapSRP2:
1813 			case eapSRP3:
1814 				pcb->eap.es_server.ea_state = eapMD5Chall;
1815 				break;
1816 			case eapMD5Chall:
1817 			case eapSRP4:
1818 				pcb->eap.es_server.ea_state = eapIdentify;
1819 				eap_figure_next_state(pcb, 0);
1820 				break;
1821 			default:
1822 				break;
1823 			}
1824 			break;
1825 		}
1826 		break;
1827 
1828 	case EAPT_MD5CHAP:
1829 		if (pcb->eap.es_server.ea_state != eapMD5Chall) {
1830 			ppp_error("EAP: unexpected MD5-Response");
1831 			eap_figure_next_state(pcb, 1);
1832 			break;
1833 		}
1834 		if (len < 1) {
1835 			ppp_error("EAP: received MD5-Response with no data");
1836 			eap_figure_next_state(pcb, 1);
1837 			break;
1838 		}
1839 		GETCHAR(vallen, inp);
1840 		len--;
1841 		if (vallen != 16 || vallen > len) {
1842 			ppp_error("EAP: MD5-Response with bad length %d", vallen);
1843 			eap_figure_next_state(pcb, 1);
1844 			break;
1845 		}
1846 
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';
1852 		} else {
1853 			MEMCPY(rhostname, inp + vallen, len - vallen);
1854 			rhostname[len - vallen] = '\0';
1855 		}
1856 
1857 #if PPP_REMOTENAME
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 */
1863 
1864 		/*
1865 		 * Get the secret for authenticating the specified
1866 		 * host.
1867 		 */
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);
1872 			break;
1873 		}
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);
1884 			break;
1885 		}
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);
1891 		break;
1892 
1893 #ifdef USE_SRP
1894 	case EAPT_SRP:
1895 		if (len < 1) {
1896 			ppp_error("EAP: empty SRP Response");
1897 			eap_figure_next_state(pcb, 1);
1898 			break;
1899 		}
1900 		GETCHAR(typenum, inp);
1901 		len--;
1902 		switch (typenum) {
1903 		case EAPSRP_CKEY:
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);
1907 				break;
1908 			}
1909 			A.data = inp;
1910 			A.len = len;
1911 			ts = (struct t_server *)pcb->eap.es_server.ea_session;
1912 			assert(ts != NULL);
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);
1918 			} else {
1919 				eap_figure_next_state(pcb, 0);
1920 			}
1921 			break;
1922 
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);
1927 				break;
1928 			}
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);
1933 				break;
1934 			}
1935 			GETLONG(pcb->eap.es_server.ea_keyflags, inp);
1936 			ts = (struct t_server *)pcb->eap.es_server.ea_session;
1937 			assert(ts != NULL);
1938 			if (t_serververify(ts, inp)) {
1939 				ppp_info("EAP: unable to validate client identity");
1940 				eap_send_failure(pcb);
1941 				break;
1942 			}
1943 			eap_figure_next_state(pcb, 0);
1944 			break;
1945 
1946 		case EAPSRP_ACK:
1947 			if (pcb->eap.es_server.ea_state != eapSRP3) {
1948 				ppp_error("EAP: unexpected SRP Subtype 3 Response");
1949 				eap_send_failure(esp);
1950 				break;
1951 			}
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);
1961 			break;
1962 
1963 		case EAPSRP_LWRECHALLENGE:
1964 			if (pcb->eap.es_server.ea_state != eapSRP4) {
1965 				ppp_info("EAP: unexpected SRP Subtype 4 Response");
1966 				return;
1967 			}
1968 			if (len != SHA_DIGESTSIZE) {
1969 				ppp_error("EAP: bad Lightweight rechallenge "
1970 				    "response");
1971 				return;
1972 			}
1973 			SHA1Init(&ctxt);
1974 			vallen = id;
1975 			SHA1Update(&ctxt, &vallen, 1);
1976 			SHA1Update(&ctxt, pcb->eap.es_server.ea_skey,
1977 			    SESSION_KEY_LEN);
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);
1985 				break;
1986 			}
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);
1991 			break;
1992 		}
1993 		break;
1994 #endif /* USE_SRP */
1995 
1996 	default:
1997 		/* This can't happen. */
1998 		ppp_error("EAP: unknown Response type %d; ignored", typenum);
1999 		return;
2000 	}
2001 
2002 	if (pcb->settings.eap_timeout_time > 0) {
2003 		UNTIMEOUT(eap_server_timeout, pcb);
2004 	}
2005 
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);
2010 	}
2011 }
2012 #endif /* PPP_SERVER */
2013 
2014 /*
2015  * eap_success - Receive EAP Success message (client mode).
2016  */
2017 static void eap_success(ppp_pcb *pcb, u_char *inp, int id, int len) {
2018 	LWIP_UNUSED_ARG(id);
2019 
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);
2024 		return;
2025 	}
2026 
2027 	if (pcb->settings.eap_req_time > 0) {
2028 		UNTIMEOUT(eap_client_timeout, pcb);
2029 	}
2030 
2031 	if (len > 0) {
2032 		/* This is odd.  The spec doesn't allow for this. */
2033 		PRINTMSG(inp, len);
2034 	}
2035 
2036 	pcb->eap.es_client.ea_state = eapOpen;
2037 	auth_withpeer_success(pcb, PPP_EAP, 0);
2038 }
2039 
2040 /*
2041  * eap_failure - Receive EAP Failure message (client mode).
2042  */
2043 static void eap_failure(ppp_pcb *pcb, u_char *inp, int id, int len) {
2044 	LWIP_UNUSED_ARG(id);
2045 
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);
2050 	}
2051 
2052 	if (pcb->settings.eap_req_time > 0) {
2053 		UNTIMEOUT(eap_client_timeout, pcb);
2054 	}
2055 
2056 	if (len > 0) {
2057 		/* This is odd.  The spec doesn't allow for this. */
2058 		PRINTMSG(inp, len);
2059 	}
2060 
2061 	pcb->eap.es_client.ea_state = eapBadAuth;
2062 
2063 	ppp_error("EAP: peer reports authentication failure");
2064 	auth_withpeer_fail(pcb, PPP_EAP);
2065 }
2066 
2067 /*
2068  * eap_input - Handle received EAP message.
2069  */
2070 static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen) {
2071 	u_char code, id;
2072 	int len;
2073 
2074 	/*
2075 	 * Parse header (code, id and length).  If packet too short,
2076 	 * drop it.
2077 	 */
2078 	if (inlen < EAP_HEADERLEN) {
2079 		ppp_error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2080 		return;
2081 	}
2082 	GETCHAR(code, inp);
2083 	GETCHAR(id, inp);
2084 	GETSHORT(len, inp);
2085 	if (len < EAP_HEADERLEN || len > inlen) {
2086 		ppp_error("EAP: packet has illegal length field %d (%d..%d)", len,
2087 		    EAP_HEADERLEN, inlen);
2088 		return;
2089 	}
2090 	len -= EAP_HEADERLEN;
2091 
2092 	/* Dispatch based on message code */
2093 	switch (code) {
2094 	case EAP_REQUEST:
2095 		eap_request(pcb, inp, id, len);
2096 		break;
2097 
2098 #if PPP_SERVER
2099 	case EAP_RESPONSE:
2100 		eap_response(pcb, inp, id, len);
2101 		break;
2102 #endif /* PPP_SERVER */
2103 
2104 	case EAP_SUCCESS:
2105 		eap_success(pcb, inp, id, len);
2106 		break;
2107 
2108 	case EAP_FAILURE:
2109 		eap_failure(pcb, inp, id, len);
2110 		break;
2111 
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);
2115 		break;
2116 	}
2117 }
2118 
2119 #if PRINTPKT_SUPPORT
2120 /*
2121  * eap_printpkt - print the contents of an EAP packet.
2122  */
2123 static const char* const eap_codenames[] = {
2124 	"Request", "Response", "Success", "Failure"
2125 };
2126 
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"
2133 };
2134 
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;
2138 	u32_t uval;
2139 
2140 	if (inlen < EAP_HEADERLEN)
2141 		return (0);
2142 	pstart = inp;
2143 	GETCHAR(code, inp);
2144 	GETCHAR(id, inp);
2145 	GETSHORT(len, inp);
2146 	if (len < EAP_HEADERLEN || len > inlen)
2147 		return (0);
2148 
2149 	if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(eap_codenames))
2150 		printer(arg, " %s", eap_codenames[code-1]);
2151 	else
2152 		printer(arg, " code=0x%x", code);
2153 	printer(arg, " id=0x%x", id);
2154 	len -= EAP_HEADERLEN;
2155 	switch (code) {
2156 	case EAP_REQUEST:
2157 		if (len < 1) {
2158 			printer(arg, " <missing type>");
2159 			break;
2160 		}
2161 		GETCHAR(rtype, inp);
2162 		len--;
2163 		if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames))
2164 			printer(arg, " %s", eap_typenames[rtype-1]);
2165 		else
2166 			printer(arg, " type=0x%x", rtype);
2167 		switch (rtype) {
2168 		case EAPT_IDENTITY:
2169 		case EAPT_NOTIFICATION:
2170 			if (len > 0) {
2171 				printer(arg, " <Message ");
2172 				ppp_print_string(inp, len, printer, arg);
2173 				printer(arg, ">");
2174 				INCPTR(len, inp);
2175 				len = 0;
2176 			} else {
2177 				printer(arg, " <No message>");
2178 			}
2179 			break;
2180 
2181 		case EAPT_MD5CHAP:
2182 			if (len <= 0)
2183 				break;
2184 			GETCHAR(vallen, inp);
2185 			len--;
2186 			if (vallen > len)
2187 				goto truncated;
2188 			printer(arg, " <Value%.*B>", vallen, inp);
2189 			INCPTR(vallen, inp);
2190 			len -= vallen;
2191 			if (len > 0) {
2192 				printer(arg, " <Name ");
2193 				ppp_print_string(inp, len, printer, arg);
2194 				printer(arg, ">");
2195 				INCPTR(len, inp);
2196 				len = 0;
2197 			} else {
2198 				printer(arg, " <No name>");
2199 			}
2200 			break;
2201 
2202 		case EAPT_SRP:
2203 			if (len < 3)
2204 				goto truncated;
2205 			GETCHAR(vallen, inp);
2206 			len--;
2207 			printer(arg, "-%d", vallen);
2208 			switch (vallen) {
2209 			case EAPSRP_CHALLENGE:
2210 				GETCHAR(vallen, inp);
2211 				len--;
2212 				if (vallen >= len)
2213 					goto truncated;
2214 				if (vallen > 0) {
2215 					printer(arg, " <Name ");
2216 					ppp_print_string(inp, vallen, printer,
2217 					    arg);
2218 					printer(arg, ">");
2219 				} else {
2220 					printer(arg, " <No name>");
2221 				}
2222 				INCPTR(vallen, inp);
2223 				len -= vallen;
2224 				GETCHAR(vallen, inp);
2225 				len--;
2226 				if (vallen >= len)
2227 					goto truncated;
2228 				printer(arg, " <s%.*B>", vallen, inp);
2229 				INCPTR(vallen, inp);
2230 				len -= vallen;
2231 				GETCHAR(vallen, inp);
2232 				len--;
2233 				if (vallen > len)
2234 					goto truncated;
2235 				if (vallen == 0) {
2236 					printer(arg, " <Default g=2>");
2237 				} else {
2238 					printer(arg, " <g%.*B>", vallen, inp);
2239 				}
2240 				INCPTR(vallen, inp);
2241 				len -= vallen;
2242 				if (len == 0) {
2243 					printer(arg, " <Default N>");
2244 				} else {
2245 					printer(arg, " <N%.*B>", len, inp);
2246 					INCPTR(len, inp);
2247 					len = 0;
2248 				}
2249 				break;
2250 
2251 			case EAPSRP_SKEY:
2252 				printer(arg, " <B%.*B>", len, inp);
2253 				INCPTR(len, inp);
2254 				len = 0;
2255 				break;
2256 
2257 			case EAPSRP_SVALIDATOR:
2258 				if (len < (int)sizeof (u32_t))
2259 					break;
2260 				GETLONG(uval, inp);
2261 				len -= sizeof (u32_t);
2262 				if (uval & SRPVAL_EBIT) {
2263 					printer(arg, " E");
2264 					uval &= ~SRPVAL_EBIT;
2265 				}
2266 				if (uval != 0) {
2267 					printer(arg, " f<%X>", uval);
2268 				}
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);
2274 				len -= vallen;
2275 				if (len > 0) {
2276 					printer(arg, " <PN%.*B>", len, inp);
2277 					INCPTR(len, inp);
2278 					len = 0;
2279 				}
2280 				break;
2281 
2282 			case EAPSRP_LWRECHALLENGE:
2283 				printer(arg, " <Challenge%.*B>", len, inp);
2284 				INCPTR(len, inp);
2285 				len = 0;
2286 				break;
2287 			default:
2288 				break;
2289 			}
2290 			break;
2291 		default:
2292 			break;
2293 		}
2294 		break;
2295 
2296 	case EAP_RESPONSE:
2297 		if (len < 1)
2298 			break;
2299 		GETCHAR(rtype, inp);
2300 		len--;
2301 		if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames))
2302 			printer(arg, " %s", eap_typenames[rtype-1]);
2303 		else
2304 			printer(arg, " type=0x%x", rtype);
2305 		switch (rtype) {
2306 		case EAPT_IDENTITY:
2307 			if (len > 0) {
2308 				printer(arg, " <Name ");
2309 				ppp_print_string(inp, len, printer, arg);
2310 				printer(arg, ">");
2311 				INCPTR(len, inp);
2312 				len = 0;
2313 			}
2314 			break;
2315 
2316 		case EAPT_NAK:
2317 			if (len <= 0) {
2318 				printer(arg, " <missing hint>");
2319 				break;
2320 			}
2321 			GETCHAR(rtype, inp);
2322 			len--;
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]);
2326 			printer(arg, ">");
2327 			break;
2328 
2329 		case EAPT_MD5CHAP:
2330 			if (len <= 0) {
2331 				printer(arg, " <missing length>");
2332 				break;
2333 			}
2334 			GETCHAR(vallen, inp);
2335 			len--;
2336 			if (vallen > len)
2337 				goto truncated;
2338 			printer(arg, " <Value%.*B>", vallen, inp);
2339 			INCPTR(vallen, inp);
2340 			len -= vallen;
2341 			if (len > 0) {
2342 				printer(arg, " <Name ");
2343 				ppp_print_string(inp, len, printer, arg);
2344 				printer(arg, ">");
2345 				INCPTR(len, inp);
2346 				len = 0;
2347 			} else {
2348 				printer(arg, " <No name>");
2349 			}
2350 			break;
2351 
2352 		case EAPT_SRP:
2353 			if (len < 1)
2354 				goto truncated;
2355 			GETCHAR(vallen, inp);
2356 			len--;
2357 			printer(arg, "-%d", vallen);
2358 			switch (vallen) {
2359 			case EAPSRP_CKEY:
2360 				printer(arg, " <A%.*B>", len, inp);
2361 				INCPTR(len, inp);
2362 				len = 0;
2363 				break;
2364 
2365 			case EAPSRP_CVALIDATOR:
2366 				if (len < (int)sizeof (u32_t))
2367 					break;
2368 				GETLONG(uval, inp);
2369 				len -= sizeof (u32_t);
2370 				if (uval & SRPVAL_EBIT) {
2371 					printer(arg, " E");
2372 					uval &= ~SRPVAL_EBIT;
2373 				}
2374 				if (uval != 0) {
2375 					printer(arg, " f<%X>", uval);
2376 				}
2377 				printer(arg, " <M1%.*B%s>", len, inp,
2378 				    len == SHA_DIGESTSIZE ? "" : "?");
2379 				INCPTR(len, inp);
2380 				len = 0;
2381 				break;
2382 
2383 			case EAPSRP_ACK:
2384 				break;
2385 
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);
2392 				len -= vallen;
2393 				break;
2394 			default:
2395 				break;
2396 			}
2397 			break;
2398 		default:
2399 			break;
2400 		}
2401 		break;
2402 
2403 	case EAP_SUCCESS:	/* No payload expected for these! */
2404 	case EAP_FAILURE:
2405 	default:
2406 		break;
2407 
2408 	truncated:
2409 		printer(arg, " <truncated>");
2410 		break;
2411 	}
2412 
2413 	if (len > 8)
2414 		printer(arg, "%8B...", inp);
2415 	else if (len > 0)
2416 		printer(arg, "%.*B", len, inp);
2417 	INCPTR(len, inp);
2418 
2419 	return (inp - pstart);
2420 }
2421 #endif /* PRINTPKT_SUPPORT */
2422 
2423 #endif /* PPP_SUPPORT && EAP_SUPPORT */
2424