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 MERCHANTABILITY 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  */
eap_state_name(enum eap_state_code esc)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  */
eap_init(ppp_pcb * pcb)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  */
eap_client_timeout(void * arg)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  */
eap_authwithpeer(ppp_pcb * pcb,const char * localname)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  */
eap_send_failure(ppp_pcb * pcb)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), PBUF_RAM);
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  */
eap_send_success(ppp_pcb * pcb)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), PBUF_RAM);
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
pncrypt_setkey(int timeoffs)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
b64enc(bs,inp,inlen,outp)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
b64flush(bs,outp)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
b64dec(bs,inp,inlen,outp)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  */
eap_figure_next_state(ppp_pcb * pcb,int status)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  */
eap_send_request(ppp_pcb * pcb)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_UNKNOWN_SIZE), PBUF_RAM);
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  */
eap_authpeer(ppp_pcb * pcb,const char * localname)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  */
eap_server_timeout(void * arg)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  */
eap_rechallenge(void * arg)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 
srp_lwrechallenge(void * arg)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  */
eap_lowerup(ppp_pcb * pcb)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  */
eap_lowerdown(ppp_pcb * pcb)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  */
eap_protrej(ppp_pcb * pcb)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  */
eap_send_response(ppp_pcb * pcb,u_char id,u_char typenum,const u_char * str,int lenstr)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), PBUF_RAM);
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  */
eap_chap_response(ppp_pcb * pcb,u_char id,u_char * hash,const char * name,int namelen)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), PBUF_RAM);
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
eap_srp_response(esp,id,subtypenum,str,lenstr)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), PBUF_RAM);
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
eap_srpval_response(esp,id,flags,str)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), PBUF_RAM);
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 
eap_send_nak(ppp_pcb * pcb,u_char id,u_char type)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), PBUF_RAM);
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 *
name_of_pn_file()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
open_pn_file(modebits)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
remove_pn_file()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
write_pseudonym(esp,inp,len,id)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  */
eap_request(ppp_pcb * pcb,u_char * inp,int id,int len)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 	 * Ignore requests if we're not open
1330 	 */
1331 	if (pcb->eap.es_client.ea_state <= eapClosed)
1332 		return;
1333 
1334 	/*
1335 	 * Note: we update es_client.ea_id *only if* a Response
1336 	 * message is being generated.  Otherwise, we leave it the
1337 	 * same for duplicate detection purposes.
1338 	 */
1339 
1340 	pcb->eap.es_client.ea_requests++;
1341 	if (pcb->settings.eap_allow_req != 0 &&
1342 	    pcb->eap.es_client.ea_requests > pcb->settings.eap_allow_req) {
1343 		ppp_info(("EAP: received too many Request messages"));
1344 		if (pcb->settings.eap_req_time > 0) {
1345 			UNTIMEOUT(eap_client_timeout, pcb);
1346 		}
1347 		auth_withpeer_fail(pcb, PPP_EAP);
1348 		return;
1349 	}
1350 
1351 	if (len <= 0) {
1352 		ppp_error(("EAP: empty Request message discarded"));
1353 		return;
1354 	}
1355 
1356 	GETCHAR(typenum, inp);
1357 	len--;
1358 
1359 	switch (typenum) {
1360 	case EAPT_IDENTITY:
1361 		if (len > 0)
1362 			ppp_info(("EAP: Identity prompt \"%.*q\"", len, inp));
1363 #ifdef USE_SRP
1364 		if (pcb->eap.es_usepseudo &&
1365 		    (pcb->eap.es_usedpseudo == 0 ||
1366 			(pcb->eap.es_usedpseudo == 1 &&
1367 			    id == pcb->eap.es_client.ea_id))) {
1368 			pcb->eap.es_usedpseudo = 1;
1369 			/* Try to get a pseudonym */
1370 			if ((fd = open_pn_file(O_RDONLY)) >= 0) {
1371 				strcpy(rhostname, SRP_PSEUDO_ID);
1372 				len = read(fd, rhostname + SRP_PSEUDO_LEN,
1373 				    sizeof (rhostname) - SRP_PSEUDO_LEN);
1374 				/* XXX NAI unsupported */
1375 				if (len > 0) {
1376 					eap_send_response(pcb, id, typenum,
1377 					    rhostname, len + SRP_PSEUDO_LEN);
1378 				}
1379 				(void) close(fd);
1380 				if (len > 0)
1381 					break;
1382 			}
1383 		}
1384 		/* Stop using pseudonym now. */
1385 		if (pcb->eap.es_usepseudo && pcb->eap.es_usedpseudo != 2) {
1386 			remove_pn_file();
1387 			pcb->eap.es_usedpseudo = 2;
1388 		}
1389 #endif /* USE_SRP */
1390 		eap_send_response(pcb, id, typenum, (const u_char*)pcb->eap.es_client.ea_name,
1391 		    pcb->eap.es_client.ea_namelen);
1392 		break;
1393 
1394 	case EAPT_NOTIFICATION:
1395 		if (len > 0)
1396 			ppp_info(("EAP: Notification \"%.*q\"", len, inp));
1397 		eap_send_response(pcb, id, typenum, NULL, 0);
1398 		break;
1399 
1400 	case EAPT_NAK:
1401 		/*
1402 		 * Avoid the temptation to send Response Nak in reply
1403 		 * to Request Nak here.  It can only lead to trouble.
1404 		 */
1405 		ppp_warn(("EAP: unexpected Nak in Request; ignored"));
1406 		/* Return because we're waiting for something real. */
1407 		return;
1408 
1409 	case EAPT_MD5CHAP:
1410 		if (len < 1) {
1411 			ppp_error(("EAP: received MD5-Challenge with no data"));
1412 			/* Bogus request; wait for something real. */
1413 			return;
1414 		}
1415 		GETCHAR(vallen, inp);
1416 		len--;
1417 		if (vallen < 8 || vallen > len) {
1418 			ppp_error(("EAP: MD5-Challenge with bad length %d (8..%d)",
1419 			    vallen, len));
1420 			/* Try something better. */
1421 			eap_send_nak(pcb, id, EAPT_SRP);
1422 			break;
1423 		}
1424 
1425 		/* Not so likely to happen. */
1426 		if (len - vallen >= (int)sizeof (rhostname)) {
1427 			ppp_dbglog(("EAP: trimming really long peer name down"));
1428 			MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1);
1429 			rhostname[sizeof (rhostname) - 1] = '\0';
1430 		} else {
1431 			MEMCPY(rhostname, inp + vallen, len - vallen);
1432 			rhostname[len - vallen] = '\0';
1433 		}
1434 
1435 #if PPP_REMOTENAME
1436 		/* In case the remote doesn't give us his name. */
1437 		if (pcb->settings.explicit_remote ||
1438 		    (pcb->settings.remote_name[0] != '\0' && vallen == len))
1439 			strlcpy(rhostname, pcb->settings.remote_name, sizeof (rhostname));
1440 #endif /* PPP_REMOTENAME */
1441 
1442 		/*
1443 		 * Get the secret for authenticating ourselves with
1444 		 * the specified host.
1445 		 */
1446 		if (!get_secret(pcb, pcb->eap.es_client.ea_name,
1447 		    rhostname, secret, &secret_len, 0)) {
1448 			ppp_dbglog(("EAP: no MD5 secret for auth to %q", rhostname));
1449 			eap_send_nak(pcb, id, EAPT_SRP);
1450 			break;
1451 		}
1452 		lwip_md5_init(&mdContext);
1453 		lwip_md5_starts(&mdContext);
1454 		typenum = id;
1455 		lwip_md5_update(&mdContext, &typenum, 1);
1456 		lwip_md5_update(&mdContext, (u_char *)secret, secret_len);
1457 		BZERO(secret, sizeof (secret));
1458 		lwip_md5_update(&mdContext, inp, vallen);
1459 		lwip_md5_finish(&mdContext, hash);
1460 		lwip_md5_free(&mdContext);
1461 		eap_chap_response(pcb, id, hash, pcb->eap.es_client.ea_name,
1462 		    pcb->eap.es_client.ea_namelen);
1463 		break;
1464 
1465 #ifdef USE_SRP
1466 	case EAPT_SRP:
1467 		if (len < 1) {
1468 			ppp_error(("EAP: received empty SRP Request"));
1469 			/* Bogus request; wait for something real. */
1470 			return;
1471 		}
1472 
1473 		/* Get subtype */
1474 		GETCHAR(vallen, inp);
1475 		len--;
1476 		switch (vallen) {
1477 		case EAPSRP_CHALLENGE:
1478 			tc = NULL;
1479 			if (pcb->eap.es_client.ea_session != NULL) {
1480 				tc = (struct t_client *)pcb->eap.es_client.
1481 				    ea_session;
1482 				/*
1483 				 * If this is a new challenge, then start
1484 				 * over with a new client session context.
1485 				 * Otherwise, just resend last response.
1486 				 */
1487 				if (id != pcb->eap.es_client.ea_id) {
1488 					t_clientclose(tc);
1489 					pcb->eap.es_client.ea_session = NULL;
1490 					tc = NULL;
1491 				}
1492 			}
1493 			/* No session key just yet */
1494 			pcb->eap.es_client.ea_skey = NULL;
1495 			if (tc == NULL) {
1496 				int rhostnamelen;
1497 
1498 				GETCHAR(vallen, inp);
1499 				len--;
1500 				if (vallen >= len) {
1501 					ppp_error(("EAP: badly-formed SRP Challenge"
1502 					    " (name)"));
1503 					/* Ignore badly-formed messages */
1504 					return;
1505 				}
1506 				MEMCPY(rhostname, inp, vallen);
1507 				rhostname[vallen] = '\0';
1508 				INCPTR(vallen, inp);
1509 				len -= vallen;
1510 
1511 				/*
1512 				 * In case the remote doesn't give us his name,
1513 				 * use configured name.
1514 				 */
1515 				if (explicit_remote ||
1516 				    (remote_name[0] != '\0' && vallen == 0)) {
1517 					strlcpy(rhostname, remote_name,
1518 					    sizeof (rhostname));
1519 				}
1520 
1521 				rhostnamelen = (int)strlen(rhostname);
1522 				if (rhostnamelen > MAXNAMELEN) {
1523 					rhostnamelen = MAXNAMELEN;
1524 				}
1525 				MEMCPY(pcb->eap.es_client.ea_peer, rhostname, rhostnamelen);
1526 				pcb->eap.es_client.ea_peer[rhostnamelen] = '\0';
1527 				pcb->eap.es_client.ea_peerlen = rhostnamelen;
1528 
1529 				GETCHAR(vallen, inp);
1530 				len--;
1531 				if (vallen >= len) {
1532 					ppp_error(("EAP: badly-formed SRP Challenge"
1533 					    " (s)"));
1534 					/* Ignore badly-formed messages */
1535 					return;
1536 				}
1537 				sval.data = inp;
1538 				sval.len = vallen;
1539 				INCPTR(vallen, inp);
1540 				len -= vallen;
1541 
1542 				GETCHAR(vallen, inp);
1543 				len--;
1544 				if (vallen > len) {
1545 					ppp_error(("EAP: badly-formed SRP Challenge"
1546 					    " (g)"));
1547 					/* Ignore badly-formed messages */
1548 					return;
1549 				}
1550 				/* If no generator present, then use value 2 */
1551 				if (vallen == 0) {
1552 					gval.data = (u_char *)"\002";
1553 					gval.len = 1;
1554 				} else {
1555 					gval.data = inp;
1556 					gval.len = vallen;
1557 				}
1558 				INCPTR(vallen, inp);
1559 				len -= vallen;
1560 
1561 				/*
1562 				 * If no modulus present, then use well-known
1563 				 * value.
1564 				 */
1565 				if (len == 0) {
1566 					Nval.data = (u_char *)wkmodulus;
1567 					Nval.len = sizeof (wkmodulus);
1568 				} else {
1569 					Nval.data = inp;
1570 					Nval.len = len;
1571 				}
1572 				tc = t_clientopen(pcb->eap.es_client.ea_name,
1573 				    &Nval, &gval, &sval);
1574 				if (tc == NULL) {
1575 					eap_send_nak(pcb, id, EAPT_MD5CHAP);
1576 					break;
1577 				}
1578 				pcb->eap.es_client.ea_session = (void *)tc;
1579 
1580 				/* Add Challenge ID & type to verifier */
1581 				vals[0] = id;
1582 				vals[1] = EAPT_SRP;
1583 				t_clientaddexdata(tc, vals, 2);
1584 			}
1585 			Ap = t_clientgenexp(tc);
1586 			eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
1587 			    Ap->len);
1588 			break;
1589 
1590 		case EAPSRP_SKEY:
1591 			tc = (struct t_client *)pcb->eap.es_client.ea_session;
1592 			if (tc == NULL) {
1593 				ppp_warn(("EAP: peer sent Subtype 2 without 1"));
1594 				eap_send_nak(pcb, id, EAPT_MD5CHAP);
1595 				break;
1596 			}
1597 			if (pcb->eap.es_client.ea_skey != NULL) {
1598 				/*
1599 				 * ID number should not change here.  Warn
1600 				 * if it does (but otherwise ignore).
1601 				 */
1602 				if (id != pcb->eap.es_client.ea_id) {
1603 					ppp_warn(("EAP: ID changed from %d to %d "
1604 					    "in SRP Subtype 2 rexmit",
1605 					    pcb->eap.es_client.ea_id, id));
1606 				}
1607 			} else {
1608 				if (get_srp_secret(pcb->eap.es_unit,
1609 				    pcb->eap.es_client.ea_name,
1610 				    pcb->eap.es_client.ea_peer, secret, 0) == 0) {
1611 					/*
1612 					 * Can't work with this peer because
1613 					 * the secret is missing.  Just give
1614 					 * up.
1615 					 */
1616 					eap_send_nak(pcb, id, EAPT_MD5CHAP);
1617 					break;
1618 				}
1619 				Bval.data = inp;
1620 				Bval.len = len;
1621 				t_clientpasswd(tc, secret);
1622 				BZERO(secret, sizeof (secret));
1623 				pcb->eap.es_client.ea_skey =
1624 				    t_clientgetkey(tc, &Bval);
1625 				if (pcb->eap.es_client.ea_skey == NULL) {
1626 					/* Server is rogue; stop now */
1627 					ppp_error(("EAP: SRP server is rogue"));
1628 					goto client_failure;
1629 				}
1630 			}
1631 			eap_srpval_response(esp, id, SRPVAL_EBIT,
1632 			    t_clientresponse(tc));
1633 			break;
1634 
1635 		case EAPSRP_SVALIDATOR:
1636 			tc = (struct t_client *)pcb->eap.es_client.ea_session;
1637 			if (tc == NULL || pcb->eap.es_client.ea_skey == NULL) {
1638 				ppp_warn(("EAP: peer sent Subtype 3 without 1/2"));
1639 				eap_send_nak(pcb, id, EAPT_MD5CHAP);
1640 				break;
1641 			}
1642 			/*
1643 			 * If we're already open, then this ought to be a
1644 			 * duplicate.  Otherwise, check that the server is
1645 			 * who we think it is.
1646 			 */
1647 			if (pcb->eap.es_client.ea_state == eapOpen) {
1648 				if (id != pcb->eap.es_client.ea_id) {
1649 					ppp_warn(("EAP: ID changed from %d to %d "
1650 					    "in SRP Subtype 3 rexmit",
1651 					    pcb->eap.es_client.ea_id, id));
1652 				}
1653 			} else {
1654 				len -= sizeof (u32_t) + SHA_DIGESTSIZE;
1655 				if (len < 0 || t_clientverify(tc, inp +
1656 					sizeof (u32_t)) != 0) {
1657 					ppp_error(("EAP: SRP server verification "
1658 					    "failed"));
1659 					goto client_failure;
1660 				}
1661 				GETLONG(pcb->eap.es_client.ea_keyflags, inp);
1662 				/* Save pseudonym if user wants it. */
1663 				if (len > 0 && pcb->eap.es_usepseudo) {
1664 					INCPTR(SHA_DIGESTSIZE, inp);
1665 					write_pseudonym(esp, inp, len, id);
1666 				}
1667 			}
1668 			/*
1669 			 * We've verified our peer.  We're now mostly done,
1670 			 * except for waiting on the regular EAP Success
1671 			 * message.
1672 			 */
1673 			eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
1674 			break;
1675 
1676 		case EAPSRP_LWRECHALLENGE:
1677 			if (len < 4) {
1678 				ppp_warn(("EAP: malformed Lightweight rechallenge"));
1679 				return;
1680 			}
1681 			SHA1Init(&ctxt);
1682 			vals[0] = id;
1683 			SHA1Update(&ctxt, vals, 1);
1684 			SHA1Update(&ctxt, pcb->eap.es_client.ea_skey,
1685 			    SESSION_KEY_LEN);
1686 			SHA1Update(&ctxt, inp, len);
1687 			SHA1Update(&ctxt, pcb->eap.es_client.ea_name,
1688 			    pcb->eap.es_client.ea_namelen);
1689 			SHA1Final(dig, &ctxt);
1690 			eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
1691 			    SHA_DIGESTSIZE);
1692 			break;
1693 
1694 		default:
1695 			ppp_error(("EAP: unknown SRP Subtype %d", vallen));
1696 			eap_send_nak(pcb, id, EAPT_MD5CHAP);
1697 			break;
1698 		}
1699 		break;
1700 #endif /* USE_SRP */
1701 
1702 	default:
1703 		ppp_info(("EAP: unknown authentication type %d; Naking", typenum));
1704 		eap_send_nak(pcb, id, EAPT_SRP);
1705 		break;
1706 	}
1707 
1708 	if (pcb->settings.eap_req_time > 0) {
1709 		UNTIMEOUT(eap_client_timeout, pcb);
1710 		TIMEOUT(eap_client_timeout, pcb,
1711 		    pcb->settings.eap_req_time);
1712 	}
1713 	return;
1714 
1715 #ifdef USE_SRP
1716 client_failure:
1717 	pcb->eap.es_client.ea_state = eapBadAuth;
1718 	if (pcb->settings.eap_req_time > 0) {
1719 		UNTIMEOUT(eap_client_timeout, (void *)esp);
1720 	}
1721 	pcb->eap.es_client.ea_session = NULL;
1722 	t_clientclose(tc);
1723 	auth_withpeer_fail(pcb, PPP_EAP);
1724 #endif /* USE_SRP */
1725 }
1726 
1727 #if PPP_SERVER
1728 /*
1729  * eap_response - Receive EAP Response message (server mode).
1730  */
eap_response(ppp_pcb * pcb,u_char * inp,int id,int len)1731 static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) {
1732 	u_char typenum;
1733 	u_char vallen;
1734 	int secret_len;
1735 	char secret[MAXSECRETLEN];
1736 	char rhostname[MAXNAMELEN];
1737 	lwip_md5_context mdContext;
1738 	u_char hash[MD5_SIGNATURE_SIZE];
1739 #ifdef USE_SRP
1740 	struct t_server *ts;
1741 	struct t_num A;
1742 	SHA1_CTX ctxt;
1743 	u_char dig[SHA_DIGESTSIZE];
1744 #endif /* USE_SRP */
1745 
1746 	/*
1747 	 * Ignore responses if we're not open
1748 	 */
1749 	if (pcb->eap.es_server.ea_state <= eapClosed)
1750 		return;
1751 
1752 	if (pcb->eap.es_server.ea_id != id) {
1753 		ppp_dbglog(("EAP: discarding Response %d; expected ID %d", id,
1754 		    pcb->eap.es_server.ea_id));
1755 		return;
1756 	}
1757 
1758 	pcb->eap.es_server.ea_responses++;
1759 
1760 	if (len <= 0) {
1761 		ppp_error(("EAP: empty Response message discarded"));
1762 		return;
1763 	}
1764 
1765 	GETCHAR(typenum, inp);
1766 	len--;
1767 
1768 	switch (typenum) {
1769 	case EAPT_IDENTITY:
1770 		if (pcb->eap.es_server.ea_state != eapIdentify) {
1771 			ppp_dbglog(("EAP discarding unwanted Identify \"%.q\"", len,
1772 			    inp));
1773 			break;
1774 		}
1775 		ppp_info(("EAP: unauthenticated peer name \"%.*q\"", len, inp));
1776 		if (len > MAXNAMELEN) {
1777 		  len = MAXNAMELEN;
1778 		}
1779 		MEMCPY(pcb->eap.es_server.ea_peer, inp, len);
1780 		pcb->eap.es_server.ea_peer[len] = '\0';
1781 		pcb->eap.es_server.ea_peerlen = len;
1782 		eap_figure_next_state(pcb, 0);
1783 		break;
1784 
1785 	case EAPT_NOTIFICATION:
1786 		ppp_dbglog(("EAP unexpected Notification; response discarded"));
1787 		break;
1788 
1789 	case EAPT_NAK:
1790 		if (len < 1) {
1791 			ppp_info(("EAP: Nak Response with no suggested protocol"));
1792 			eap_figure_next_state(pcb, 1);
1793 			break;
1794 		}
1795 
1796 		GETCHAR(vallen, inp);
1797 		len--;
1798 
1799 		if (
1800 #if PPP_REMOTENAME
1801 		!pcb->explicit_remote &&
1802 #endif /* PPP_REMOTENAME */
1803 		pcb->eap.es_server.ea_state == eapIdentify){
1804 			/* Peer cannot Nak Identify Request */
1805 			eap_figure_next_state(pcb, 1);
1806 			break;
1807 		}
1808 
1809 		switch (vallen) {
1810 		case EAPT_SRP:
1811 			/* Run through SRP validator selection again. */
1812 			pcb->eap.es_server.ea_state = eapIdentify;
1813 			eap_figure_next_state(pcb, 0);
1814 			break;
1815 
1816 		case EAPT_MD5CHAP:
1817 			pcb->eap.es_server.ea_state = eapMD5Chall;
1818 			break;
1819 
1820 		default:
1821 			ppp_dbglog(("EAP: peer requesting unknown Type %d", vallen));
1822 			switch (pcb->eap.es_server.ea_state) {
1823 			case eapSRP1:
1824 			case eapSRP2:
1825 			case eapSRP3:
1826 				pcb->eap.es_server.ea_state = eapMD5Chall;
1827 				break;
1828 			case eapMD5Chall:
1829 			case eapSRP4:
1830 				pcb->eap.es_server.ea_state = eapIdentify;
1831 				eap_figure_next_state(pcb, 0);
1832 				break;
1833 			default:
1834 				break;
1835 			}
1836 			break;
1837 		}
1838 		break;
1839 
1840 	case EAPT_MD5CHAP:
1841 		if (pcb->eap.es_server.ea_state != eapMD5Chall) {
1842 			ppp_error(("EAP: unexpected MD5-Response"));
1843 			eap_figure_next_state(pcb, 1);
1844 			break;
1845 		}
1846 		if (len < 1) {
1847 			ppp_error(("EAP: received MD5-Response with no data"));
1848 			eap_figure_next_state(pcb, 1);
1849 			break;
1850 		}
1851 		GETCHAR(vallen, inp);
1852 		len--;
1853 		if (vallen != 16 || vallen > len) {
1854 			ppp_error(("EAP: MD5-Response with bad length %d", vallen));
1855 			eap_figure_next_state(pcb, 1);
1856 			break;
1857 		}
1858 
1859 		/* Not so likely to happen. */
1860 		if (len - vallen >= (int)sizeof (rhostname)) {
1861 			ppp_dbglog(("EAP: trimming really long peer name down"));
1862 			MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1);
1863 			rhostname[sizeof (rhostname) - 1] = '\0';
1864 		} else {
1865 			MEMCPY(rhostname, inp + vallen, len - vallen);
1866 			rhostname[len - vallen] = '\0';
1867 		}
1868 
1869 #if PPP_REMOTENAME
1870 		/* In case the remote doesn't give us his name. */
1871 		if (explicit_remote ||
1872 		    (remote_name[0] != '\0' && vallen == len))
1873 			strlcpy(rhostname, remote_name, sizeof (rhostname));
1874 #endif /* PPP_REMOTENAME */
1875 
1876 		/*
1877 		 * Get the secret for authenticating the specified
1878 		 * host.
1879 		 */
1880 		if (!get_secret(pcb, rhostname,
1881 		    pcb->eap.es_server.ea_name, secret, &secret_len, 1)) {
1882 			ppp_dbglog(("EAP: no MD5 secret for auth of %q", rhostname));
1883 			eap_send_failure(pcb);
1884 			break;
1885 		}
1886 		lwip_md5_init(&mdContext);
1887 		lwip_md5_starts(&mdContext);
1888 		lwip_md5_update(&mdContext, &pcb->eap.es_server.ea_id, 1);
1889 		lwip_md5_update(&mdContext, (u_char *)secret, secret_len);
1890 		BZERO(secret, sizeof (secret));
1891 		lwip_md5_update(&mdContext, pcb->eap.es_challenge, pcb->eap.es_challen);
1892 		lwip_md5_finish(&mdContext, hash);
1893 		lwip_md5_free(&mdContext);
1894 		if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) {
1895 			eap_send_failure(pcb);
1896 			break;
1897 		}
1898 		pcb->eap.es_server.ea_type = EAPT_MD5CHAP;
1899 		eap_send_success(pcb);
1900 		eap_figure_next_state(pcb, 0);
1901 		if (pcb->eap.es_rechallenge != 0)
1902 			TIMEOUT(eap_rechallenge, pcb, pcb->eap.es_rechallenge);
1903 		break;
1904 
1905 #ifdef USE_SRP
1906 	case EAPT_SRP:
1907 		if (len < 1) {
1908 			ppp_error(("EAP: empty SRP Response"));
1909 			eap_figure_next_state(pcb, 1);
1910 			break;
1911 		}
1912 		GETCHAR(typenum, inp);
1913 		len--;
1914 		switch (typenum) {
1915 		case EAPSRP_CKEY:
1916 			if (pcb->eap.es_server.ea_state != eapSRP1) {
1917 				ppp_error(("EAP: unexpected SRP Subtype 1 Response"));
1918 				eap_figure_next_state(pcb, 1);
1919 				break;
1920 			}
1921 			A.data = inp;
1922 			A.len = len;
1923 			ts = (struct t_server *)pcb->eap.es_server.ea_session;
1924 			assert(ts != NULL);
1925 			pcb->eap.es_server.ea_skey = t_servergetkey(ts, &A);
1926 			if (pcb->eap.es_server.ea_skey == NULL) {
1927 				/* Client's A value is bogus; terminate now */
1928 				ppp_error(("EAP: bogus A value from client"));
1929 				eap_send_failure(pcb);
1930 			} else {
1931 				eap_figure_next_state(pcb, 0);
1932 			}
1933 			break;
1934 
1935 		case EAPSRP_CVALIDATOR:
1936 			if (pcb->eap.es_server.ea_state != eapSRP2) {
1937 				ppp_error(("EAP: unexpected SRP Subtype 2 Response"));
1938 				eap_figure_next_state(pcb, 1);
1939 				break;
1940 			}
1941 			if (len < sizeof (u32_t) + SHA_DIGESTSIZE) {
1942 				ppp_error(("EAP: M1 length %d < %d", len,
1943 				    sizeof (u32_t) + SHA_DIGESTSIZE));
1944 				eap_figure_next_state(pcb, 1);
1945 				break;
1946 			}
1947 			GETLONG(pcb->eap.es_server.ea_keyflags, inp);
1948 			ts = (struct t_server *)pcb->eap.es_server.ea_session;
1949 			assert(ts != NULL);
1950 			if (t_serververify(ts, inp)) {
1951 				ppp_info(("EAP: unable to validate client identity"));
1952 				eap_send_failure(pcb);
1953 				break;
1954 			}
1955 			eap_figure_next_state(pcb, 0);
1956 			break;
1957 
1958 		case EAPSRP_ACK:
1959 			if (pcb->eap.es_server.ea_state != eapSRP3) {
1960 				ppp_error(("EAP: unexpected SRP Subtype 3 Response"));
1961 				eap_send_failure(esp);
1962 				break;
1963 			}
1964 			pcb->eap.es_server.ea_type = EAPT_SRP;
1965 			eap_send_success(pcb, esp);
1966 			eap_figure_next_state(pcb, 0);
1967 			if (pcb->eap.es_rechallenge != 0)
1968 				TIMEOUT(eap_rechallenge, pcb,
1969 				    pcb->eap.es_rechallenge);
1970 			if (pcb->eap.es_lwrechallenge != 0)
1971 				TIMEOUT(srp_lwrechallenge, pcb,
1972 				    pcb->eap.es_lwrechallenge);
1973 			break;
1974 
1975 		case EAPSRP_LWRECHALLENGE:
1976 			if (pcb->eap.es_server.ea_state != eapSRP4) {
1977 				ppp_info(("EAP: unexpected SRP Subtype 4 Response"));
1978 				return;
1979 			}
1980 			if (len != SHA_DIGESTSIZE) {
1981 				ppp_error(("EAP: bad Lightweight rechallenge "
1982 				    "response"));
1983 				return;
1984 			}
1985 			SHA1Init(&ctxt);
1986 			vallen = id;
1987 			SHA1Update(&ctxt, &vallen, 1);
1988 			SHA1Update(&ctxt, pcb->eap.es_server.ea_skey,
1989 			    SESSION_KEY_LEN);
1990 			SHA1Update(&ctxt, pcb->eap.es_challenge, pcb->eap.es_challen);
1991 			SHA1Update(&ctxt, pcb->eap.es_server.ea_peer,
1992 			    pcb->eap.es_server.ea_peerlen);
1993 			SHA1Final(dig, &ctxt);
1994 			if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) {
1995 				ppp_error(("EAP: failed Lightweight rechallenge"));
1996 				eap_send_failure(pcb);
1997 				break;
1998 			}
1999 			pcb->eap.es_server.ea_state = eapOpen;
2000 			if (pcb->eap.es_lwrechallenge != 0)
2001 				TIMEOUT(srp_lwrechallenge, esp,
2002 				    pcb->eap.es_lwrechallenge);
2003 			break;
2004 		}
2005 		break;
2006 #endif /* USE_SRP */
2007 
2008 	default:
2009 		/* This can't happen. */
2010 		ppp_error(("EAP: unknown Response type %d; ignored", typenum));
2011 		return;
2012 	}
2013 
2014 	if (pcb->settings.eap_timeout_time > 0) {
2015 		UNTIMEOUT(eap_server_timeout, pcb);
2016 	}
2017 
2018 	if (pcb->eap.es_server.ea_state != eapBadAuth &&
2019 	    pcb->eap.es_server.ea_state != eapOpen) {
2020 		pcb->eap.es_server.ea_id++;
2021 		eap_send_request(pcb);
2022 	}
2023 }
2024 #endif /* PPP_SERVER */
2025 
2026 /*
2027  * eap_success - Receive EAP Success message (client mode).
2028  */
eap_success(ppp_pcb * pcb,u_char * inp,int id,int len)2029 static void eap_success(ppp_pcb *pcb, u_char *inp, int id, int len) {
2030 	LWIP_UNUSED_ARG(id);
2031 
2032 	if (pcb->eap.es_client.ea_state != eapOpen && !eap_client_active(pcb)) {
2033 		ppp_dbglog(("EAP unexpected success message in state %s (%d)",
2034 		    eap_state_name(pcb->eap.es_client.ea_state),
2035 		    pcb->eap.es_client.ea_state));
2036 		return;
2037 	}
2038 
2039 	if (pcb->settings.eap_req_time > 0) {
2040 		UNTIMEOUT(eap_client_timeout, pcb);
2041 	}
2042 
2043 	if (len > 0) {
2044 		/* This is odd.  The spec doesn't allow for this. */
2045 		PRINTMSG(inp, len);
2046 	}
2047 
2048 	pcb->eap.es_client.ea_state = eapOpen;
2049 	auth_withpeer_success(pcb, PPP_EAP, 0);
2050 }
2051 
2052 /*
2053  * eap_failure - Receive EAP Failure message (client mode).
2054  */
eap_failure(ppp_pcb * pcb,u_char * inp,int id,int len)2055 static void eap_failure(ppp_pcb *pcb, u_char *inp, int id, int len) {
2056 	LWIP_UNUSED_ARG(id);
2057 
2058 	/*
2059 	 * Ignore failure messages if we're not open
2060 	 */
2061 	if (pcb->eap.es_client.ea_state <= eapClosed)
2062 		return;
2063 
2064 	if (!eap_client_active(pcb)) {
2065 		ppp_dbglog(("EAP unexpected failure message in state %s (%d)",
2066 		    eap_state_name(pcb->eap.es_client.ea_state),
2067 		    pcb->eap.es_client.ea_state));
2068 	}
2069 
2070 	if (pcb->settings.eap_req_time > 0) {
2071 		UNTIMEOUT(eap_client_timeout, pcb);
2072 	}
2073 
2074 	if (len > 0) {
2075 		/* This is odd.  The spec doesn't allow for this. */
2076 		PRINTMSG(inp, len);
2077 	}
2078 
2079 	pcb->eap.es_client.ea_state = eapBadAuth;
2080 
2081 	ppp_error(("EAP: peer reports authentication failure"));
2082 	auth_withpeer_fail(pcb, PPP_EAP);
2083 }
2084 
2085 /*
2086  * eap_input - Handle received EAP message.
2087  */
eap_input(ppp_pcb * pcb,u_char * inp,int inlen)2088 static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen) {
2089 	u_char code, id;
2090 	int len;
2091 
2092 	/*
2093 	 * Parse header (code, id and length).  If packet too short,
2094 	 * drop it.
2095 	 */
2096 	if (inlen < EAP_HEADERLEN) {
2097 		ppp_error(("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN));
2098 		return;
2099 	}
2100 	GETCHAR(code, inp);
2101 	GETCHAR(id, inp);
2102 	GETSHORT(len, inp);
2103 	if (len < EAP_HEADERLEN || len > inlen) {
2104 		ppp_error(("EAP: packet has illegal length field %d (%d..%d)", len,
2105 		    EAP_HEADERLEN, inlen));
2106 		return;
2107 	}
2108 	len -= EAP_HEADERLEN;
2109 
2110 	/* Dispatch based on message code */
2111 	switch (code) {
2112 	case EAP_REQUEST:
2113 		eap_request(pcb, inp, id, len);
2114 		break;
2115 
2116 #if PPP_SERVER
2117 	case EAP_RESPONSE:
2118 		eap_response(pcb, inp, id, len);
2119 		break;
2120 #endif /* PPP_SERVER */
2121 
2122 	case EAP_SUCCESS:
2123 		eap_success(pcb, inp, id, len);
2124 		break;
2125 
2126 	case EAP_FAILURE:
2127 		eap_failure(pcb, inp, id, len);
2128 		break;
2129 
2130 	default:				/* XXX Need code reject */
2131 		/* Note: it's not legal to send EAP Nak here. */
2132 		ppp_warn(("EAP: unknown code %d received", code));
2133 		break;
2134 	}
2135 }
2136 
2137 #if PRINTPKT_SUPPORT
2138 /*
2139  * eap_printpkt - print the contents of an EAP packet.
2140  */
2141 static const char* const eap_codenames[] = {
2142 	"Request", "Response", "Success", "Failure"
2143 };
2144 
2145 static const char* const eap_typenames[] = {
2146 	"Identity", "Notification", "Nak", "MD5-Challenge",
2147 	"OTP", "Generic-Token", NULL, NULL,
2148 	"RSA", "DSS", "KEA", "KEA-Validate",
2149 	"TLS", "Defender", "Windows 2000", "Arcot",
2150 	"Cisco", "Nokia", "SRP"
2151 };
2152 
eap_printpkt(const u_char * inp,int inlen,void (* printer)(void *,const char *,...),void * arg)2153 static int eap_printpkt(const u_char *inp, int inlen, void (*printer) (void *, const char *, ...), void *arg) {
2154 	int code, id, len, rtype, vallen;
2155 	const u_char *pstart;
2156 	u32_t uval;
2157 
2158 	if (inlen < EAP_HEADERLEN)
2159 		return (0);
2160 	pstart = inp;
2161 	GETCHAR(code, inp);
2162 	GETCHAR(id, inp);
2163 	GETSHORT(len, inp);
2164 	if (len < EAP_HEADERLEN || len > inlen)
2165 		return (0);
2166 
2167 	if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(eap_codenames))
2168 		printer(arg, " %s", eap_codenames[code-1]);
2169 	else
2170 		printer(arg, " code=0x%x", code);
2171 	printer(arg, " id=0x%x", id);
2172 	len -= EAP_HEADERLEN;
2173 	switch (code) {
2174 	case EAP_REQUEST:
2175 		if (len < 1) {
2176 			printer(arg, " <missing type>");
2177 			break;
2178 		}
2179 		GETCHAR(rtype, inp);
2180 		len--;
2181 		if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames))
2182 			printer(arg, " %s", eap_typenames[rtype-1]);
2183 		else
2184 			printer(arg, " type=0x%x", rtype);
2185 		switch (rtype) {
2186 		case EAPT_IDENTITY:
2187 		case EAPT_NOTIFICATION:
2188 			if (len > 0) {
2189 				printer(arg, " <Message ");
2190 				ppp_print_string(inp, len, printer, arg);
2191 				printer(arg, ">");
2192 				INCPTR(len, inp);
2193 				len = 0;
2194 			} else {
2195 				printer(arg, " <No message>");
2196 			}
2197 			break;
2198 
2199 		case EAPT_MD5CHAP:
2200 			if (len <= 0)
2201 				break;
2202 			GETCHAR(vallen, inp);
2203 			len--;
2204 			if (vallen > len)
2205 				goto truncated;
2206 			printer(arg, " <Value%.*B>", vallen, inp);
2207 			INCPTR(vallen, inp);
2208 			len -= vallen;
2209 			if (len > 0) {
2210 				printer(arg, " <Name ");
2211 				ppp_print_string(inp, len, printer, arg);
2212 				printer(arg, ">");
2213 				INCPTR(len, inp);
2214 				len = 0;
2215 			} else {
2216 				printer(arg, " <No name>");
2217 			}
2218 			break;
2219 
2220 		case EAPT_SRP:
2221 			if (len < 3)
2222 				goto truncated;
2223 			GETCHAR(vallen, inp);
2224 			len--;
2225 			printer(arg, "-%d", vallen);
2226 			switch (vallen) {
2227 			case EAPSRP_CHALLENGE:
2228 				GETCHAR(vallen, inp);
2229 				len--;
2230 				if (vallen >= len)
2231 					goto truncated;
2232 				if (vallen > 0) {
2233 					printer(arg, " <Name ");
2234 					ppp_print_string(inp, vallen, printer,
2235 					    arg);
2236 					printer(arg, ">");
2237 				} else {
2238 					printer(arg, " <No name>");
2239 				}
2240 				INCPTR(vallen, inp);
2241 				len -= vallen;
2242 				GETCHAR(vallen, inp);
2243 				len--;
2244 				if (vallen >= len)
2245 					goto truncated;
2246 				printer(arg, " <s%.*B>", vallen, inp);
2247 				INCPTR(vallen, inp);
2248 				len -= vallen;
2249 				GETCHAR(vallen, inp);
2250 				len--;
2251 				if (vallen > len)
2252 					goto truncated;
2253 				if (vallen == 0) {
2254 					printer(arg, " <Default g=2>");
2255 				} else {
2256 					printer(arg, " <g%.*B>", vallen, inp);
2257 				}
2258 				INCPTR(vallen, inp);
2259 				len -= vallen;
2260 				if (len == 0) {
2261 					printer(arg, " <Default N>");
2262 				} else {
2263 					printer(arg, " <N%.*B>", len, inp);
2264 					INCPTR(len, inp);
2265 					len = 0;
2266 				}
2267 				break;
2268 
2269 			case EAPSRP_SKEY:
2270 				printer(arg, " <B%.*B>", len, inp);
2271 				INCPTR(len, inp);
2272 				len = 0;
2273 				break;
2274 
2275 			case EAPSRP_SVALIDATOR:
2276 				if (len < (int)sizeof (u32_t))
2277 					break;
2278 				GETLONG(uval, inp);
2279 				len -= sizeof (u32_t);
2280 				if (uval & SRPVAL_EBIT) {
2281 					printer(arg, " E");
2282 					uval &= ~SRPVAL_EBIT;
2283 				}
2284 				if (uval != 0) {
2285 					printer(arg, " f<%X>", uval);
2286 				}
2287 				if ((vallen = len) > SHA_DIGESTSIZE)
2288 					vallen = SHA_DIGESTSIZE;
2289 				printer(arg, " <M2%.*B%s>", len, inp,
2290 				    len < SHA_DIGESTSIZE ? "?" : "");
2291 				INCPTR(vallen, inp);
2292 				len -= vallen;
2293 				if (len > 0) {
2294 					printer(arg, " <PN%.*B>", len, inp);
2295 					INCPTR(len, inp);
2296 					len = 0;
2297 				}
2298 				break;
2299 
2300 			case EAPSRP_LWRECHALLENGE:
2301 				printer(arg, " <Challenge%.*B>", len, inp);
2302 				INCPTR(len, inp);
2303 				len = 0;
2304 				break;
2305 			default:
2306 				break;
2307 			}
2308 			break;
2309 		default:
2310 			break;
2311 		}
2312 		break;
2313 
2314 	case EAP_RESPONSE:
2315 		if (len < 1)
2316 			break;
2317 		GETCHAR(rtype, inp);
2318 		len--;
2319 		if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames))
2320 			printer(arg, " %s", eap_typenames[rtype-1]);
2321 		else
2322 			printer(arg, " type=0x%x", rtype);
2323 		switch (rtype) {
2324 		case EAPT_IDENTITY:
2325 			if (len > 0) {
2326 				printer(arg, " <Name ");
2327 				ppp_print_string(inp, len, printer, arg);
2328 				printer(arg, ">");
2329 				INCPTR(len, inp);
2330 				len = 0;
2331 			}
2332 			break;
2333 
2334 		case EAPT_NAK:
2335 			if (len <= 0) {
2336 				printer(arg, " <missing hint>");
2337 				break;
2338 			}
2339 			GETCHAR(rtype, inp);
2340 			len--;
2341 			printer(arg, " <Suggested-type %02X", rtype);
2342 			if (rtype >= 1 && rtype < (int)LWIP_ARRAYSIZE(eap_typenames))
2343 				printer(arg, " (%s)", eap_typenames[rtype-1]);
2344 			printer(arg, ">");
2345 			break;
2346 
2347 		case EAPT_MD5CHAP:
2348 			if (len <= 0) {
2349 				printer(arg, " <missing length>");
2350 				break;
2351 			}
2352 			GETCHAR(vallen, inp);
2353 			len--;
2354 			if (vallen > len)
2355 				goto truncated;
2356 			printer(arg, " <Value%.*B>", vallen, inp);
2357 			INCPTR(vallen, inp);
2358 			len -= vallen;
2359 			if (len > 0) {
2360 				printer(arg, " <Name ");
2361 				ppp_print_string(inp, len, printer, arg);
2362 				printer(arg, ">");
2363 				INCPTR(len, inp);
2364 				len = 0;
2365 			} else {
2366 				printer(arg, " <No name>");
2367 			}
2368 			break;
2369 
2370 		case EAPT_SRP:
2371 			if (len < 1)
2372 				goto truncated;
2373 			GETCHAR(vallen, inp);
2374 			len--;
2375 			printer(arg, "-%d", vallen);
2376 			switch (vallen) {
2377 			case EAPSRP_CKEY:
2378 				printer(arg, " <A%.*B>", len, inp);
2379 				INCPTR(len, inp);
2380 				len = 0;
2381 				break;
2382 
2383 			case EAPSRP_CVALIDATOR:
2384 				if (len < (int)sizeof (u32_t))
2385 					break;
2386 				GETLONG(uval, inp);
2387 				len -= sizeof (u32_t);
2388 				if (uval & SRPVAL_EBIT) {
2389 					printer(arg, " E");
2390 					uval &= ~SRPVAL_EBIT;
2391 				}
2392 				if (uval != 0) {
2393 					printer(arg, " f<%X>", uval);
2394 				}
2395 				printer(arg, " <M1%.*B%s>", len, inp,
2396 				    len == SHA_DIGESTSIZE ? "" : "?");
2397 				INCPTR(len, inp);
2398 				len = 0;
2399 				break;
2400 
2401 			case EAPSRP_ACK:
2402 				break;
2403 
2404 			case EAPSRP_LWRECHALLENGE:
2405 				printer(arg, " <Response%.*B%s>", len, inp,
2406 				    len == SHA_DIGESTSIZE ? "" : "?");
2407 				if ((vallen = len) > SHA_DIGESTSIZE)
2408 					vallen = SHA_DIGESTSIZE;
2409 				INCPTR(vallen, inp);
2410 				len -= vallen;
2411 				break;
2412 			default:
2413 				break;
2414 			}
2415 			break;
2416 		default:
2417 			break;
2418 		}
2419 		break;
2420 
2421 	case EAP_SUCCESS:	/* No payload expected for these! */
2422 	case EAP_FAILURE:
2423 	default:
2424 		break;
2425 
2426 	truncated:
2427 		printer(arg, " <truncated>");
2428 		break;
2429 	}
2430 
2431 	if (len > 8)
2432 		printer(arg, "%8B...", inp);
2433 	else if (len > 0)
2434 		printer(arg, "%.*B", len, inp);
2435 	INCPTR(len, inp);
2436 
2437 	return (inp - pstart);
2438 }
2439 #endif /* PRINTPKT_SUPPORT */
2440 
2441 #endif /* PPP_SUPPORT && EAP_SUPPORT */
2442