xref: /netbsd-src/external/bsd/ppp/dist/pppd/eap.c (revision f12839c5f795a8def46f685de6698463dbd213a9)
1 /*	$NetBSD: eap.c,v 1.7 2025/01/08 19:59:39 christos Exp $	*/
2 /*
3  * eap.c - Extensible Authentication Protocol for PPP (RFC 2284)
4  *
5  * Copyright (c) 2001 by Sun Microsystems, Inc.
6  * All rights reserved.
7  *
8  * Non-exclusive rights to redistribute, modify, translate, and use
9  * this software in source and binary forms, in whole or in part, is
10  * hereby granted, provided that the above copyright notice is
11  * duplicated in any source form, and that neither the name of the
12  * copyright holder nor the author is used to endorse or promote
13  * products derived from this software.
14  *
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * Original version by James Carlson
20  *
21  * This implementation of EAP supports MD5-Challenge and SRP-SHA1
22  * authentication styles.  Note that support of MD5-Challenge is a
23  * requirement of RFC 2284, and that it's essentially just a
24  * reimplementation of regular RFC 1994 CHAP using EAP messages.
25  *
26  * As an authenticator ("server"), there are multiple phases for each
27  * style.  In the first phase of each style, the unauthenticated peer
28  * name is queried using the EAP Identity request type.  If the
29  * "remotename" option is used, then this phase is skipped, because
30  * the peer's name is presumed to be known.
31  *
32  * For MD5-Challenge, there are two phases, and the second phase
33  * consists of sending the challenge itself and handling the
34  * associated response.
35  *
36  * For SRP-SHA1, there are four phases.  The second sends 's', 'N',
37  * and 'g'.  The reply contains 'A'.  The third sends 'B', and the
38  * reply contains 'M1'.  The forth sends the 'M2' value.
39  *
40  * As an authenticatee ("client"), there's just a single phase --
41  * responding to the queries generated by the peer.  EAP is an
42  * authenticator-driven protocol.
43  *
44  * Based on draft-ietf-pppext-eap-srp-03.txt.
45  */
46 
47 #include <sys/cdefs.h>
48 __RCSID("$NetBSD: eap.c,v 1.7 2025/01/08 19:59:39 christos Exp $");
49 
50 /*
51  * Modification by Beniamino Galvani, Mar 2005
52  * Implemented EAP-TLS authentication
53  */
54 
55 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58 
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <unistd.h>
63 #include <pwd.h>
64 #include <sys/types.h>
65 #include <sys/stat.h>
66 #include <fcntl.h>
67 #include <assert.h>
68 #include <errno.h>
69 #include <md5.h>
70 
71 #include "pppd-private.h"
72 #include "options.h"
73 #include "pathnames.h"
74 #include "crypto.h"
75 #include "crypto_ms.h"
76 #include "eap.h"
77 #ifdef PPP_WITH_PEAP
78 #include "peap.h"
79 #endif /* PPP_WITH_PEAP */
80 
81 #ifdef PPP_WITH_SRP
82 #ifdef HAVE_TIME_H
83 #include <time.h>
84 #endif
85 #include <t_pwd.h>
86 #include <t_server.h>
87 #include <t_client.h>
88 #endif /* PPP_WITH_SRP */
89 
90 #ifdef PPP_WITH_EAPTLS
91 #include "eap-tls.h"
92 #endif /* PPP_WITH_EAPTLS */
93 
94 #ifdef PPP_WITH_CHAPMS
95 #include "chap.h"
96 #include "chap_ms.h"
97 
98 extern int chapms_strip_domain;
99 #endif /* PPP_WITH_CHAPMS */
100 
101 eap_state eap_states[NUM_PPP];		/* EAP state; one for each unit */
102 #ifdef PPP_WITH_SRP
103 static char *pn_secret = NULL;		/* Pseudonym generating secret */
104 #endif
105 
106 /*
107  * Command-line options.
108  */
109 static struct option eap_option_list[] = {
110     { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,
111       "Set retransmit timeout for EAP Requests (server)" },
112     { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,
113       "Set max number of EAP Requests sent (server)" },
114     { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,
115       "Set time limit for peer EAP authentication" },
116     { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,
117       "Set max number of EAP Requests allows (client)" },
118     { "eap-interval", o_int, &eap_states[0].es_rechallenge,
119       "Set interval for EAP rechallenge" },
120 #ifdef PPP_WITH_SRP
121     { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,
122       "Set interval for SRP lightweight rechallenge" },
123     { "srp-pn-secret", o_string, &pn_secret,
124       "Long term pseudonym generation secret" },
125     { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,
126       "Use pseudonym if offered one by server", 1 },
127 #endif
128     { NULL }
129 };
130 
131 /*
132  * Protocol entry points.
133  */
134 static void eap_init (int unit);
135 static void eap_input (int unit, u_char *inp, int inlen);
136 static void eap_protrej (int unit);
137 static void eap_lowerup (int unit);
138 static void eap_lowerdown (int unit);
139 static int  eap_printpkt (u_char *inp, int inlen,
140     void (*)(void *arg, char *fmt, ...), void *arg);
141 
142 struct protent eap_protent = {
143 	PPP_EAP,		/* protocol number */
144 	eap_init,		/* initialization procedure */
145 	eap_input,		/* process a received packet */
146 	eap_protrej,		/* process a received protocol-reject */
147 	eap_lowerup,		/* lower layer has gone up */
148 	eap_lowerdown,		/* lower layer has gone down */
149 	NULL,			/* open the protocol */
150 	NULL,			/* close the protocol */
151 	eap_printpkt,		/* print a packet in readable form */
152 	NULL,			/* process a received data packet */
153 	1,			/* protocol enabled */
154 	"EAP",			/* text name of protocol */
155 	NULL,			/* text name of corresponding data protocol */
156 	eap_option_list,	/* list of command-line options */
157 	NULL,			/* check requested options; assign defaults */
158 	NULL,			/* configure interface for demand-dial */
159 	NULL			/* say whether to bring up link for this pkt */
160 };
161 
162 #ifdef PPP_WITH_SRP
163 /*
164  * A well-known 2048 bit modulus.
165  */
166 static const u_char wkmodulus[] = {
167 	0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
168 	0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
169 	0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
170 	0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
171 	0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
172 	0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
173 	0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
174 	0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
175 	0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
176 	0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
177 	0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
178 	0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
179 	0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
180 	0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
181 	0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
182 	0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
183 	0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
184 	0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
185 	0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
186 	0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
187 	0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
188 	0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
189 	0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
190 	0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
191 	0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
192 	0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
193 	0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
194 	0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
195 	0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
196 	0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
197 	0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
198 	0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
199 };
200 #endif /* PPP_WITH_SRP */
201 
202 /* Local forward declarations. */
203 static void eap_server_timeout (void *arg);
204 
205 /*
206  * Convert EAP state code to printable string for debug.
207  */
208 static const char *
209 eap_state_name(enum eap_state_code esc)
210 {
211 	static const char *state_names[] = { EAP_STATES };
212 
213 	return (state_names[(int)esc]);
214 }
215 
216 /*
217  * eap_init - Initialize state for an EAP user.  This is currently
218  * called once by main() during start-up.
219  */
220 static void
221 eap_init(int unit)
222 {
223 	eap_state *esp = &eap_states[unit];
224 
225 	BZERO(esp, sizeof (*esp));
226 	esp->es_unit = unit;
227 	esp->es_server.ea_timeout = EAP_DEFTIMEOUT;
228 	esp->es_server.ea_maxrequests = EAP_DEFTRANSMITS;
229 	esp->es_server.ea_id = (u_char)(drand48() * 0x100);
230 	esp->es_client.ea_timeout = EAP_DEFREQTIME;
231 	esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
232 #ifdef PPP_WITH_EAPTLS
233 	esp->es_client.ea_using_eaptls = 0;
234 #endif /* PPP_WITH_EAPTLS */
235 #ifdef PPP_WITH_CHAPMS
236 	esp->es_client.digest = chap_find_digest(CHAP_MICROSOFT_V2);
237 	esp->es_server.digest = chap_find_digest(CHAP_MICROSOFT_V2);
238 #endif
239 }
240 
241 /*
242  * eap_client_timeout - Give up waiting for the peer to send any
243  * Request messages.
244  */
245 static void
246 eap_client_timeout(void *arg)
247 {
248 	eap_state *esp = (eap_state *) arg;
249 
250 	if (!eap_client_active(esp))
251 		return;
252 
253 	error("EAP: timeout waiting for Request from peer");
254 	auth_withpeer_fail(esp->es_unit, PPP_EAP);
255 	esp->es_client.ea_state = eapBadAuth;
256 }
257 
258 /*
259  * eap_authwithpeer - Authenticate to our peer (behave as client).
260  *
261  * Start client state and wait for requests.  This is called only
262  * after eap_lowerup.
263  */
264 void
265 eap_authwithpeer(int unit, char *localname)
266 {
267 	eap_state *esp = &eap_states[unit];
268 
269 	/* Save the peer name we're given */
270 	esp->es_client.ea_name = localname;
271 	esp->es_client.ea_namelen = strlen(localname);
272 
273 	esp->es_client.ea_state = eapListen;
274 
275 	/*
276 	 * Start a timer so that if the other end just goes
277 	 * silent, we don't sit here waiting forever.
278 	 */
279 	if (esp->es_client.ea_timeout > 0)
280 		TIMEOUT(eap_client_timeout, (void *)esp,
281 		    esp->es_client.ea_timeout);
282 }
283 
284 /*
285  * Format a standard EAP Failure message and send it to the peer.
286  * (Server operation)
287  */
288 static void
289 eap_send_failure(eap_state *esp)
290 {
291 	u_char *outp;
292 
293 	outp = outpacket_buf;
294 
295 	MAKEHEADER(outp, PPP_EAP);
296 
297 	PUTCHAR(EAP_FAILURE, outp);
298 	esp->es_server.ea_id++;
299 	PUTCHAR(esp->es_server.ea_id, outp);
300 	PUTSHORT(EAP_HEADERLEN, outp);
301 
302 	output(esp->es_unit, outpacket_buf, EAP_HEADERLEN + PPP_HDRLEN);
303 
304 	esp->es_server.ea_state = eapBadAuth;
305 	auth_peer_fail(esp->es_unit, PPP_EAP);
306 }
307 
308 /*
309  * Format a standard EAP Success message and send it to the peer.
310  * (Server operation)
311  */
312 static void
313 eap_send_success(eap_state *esp)
314 {
315 	u_char *outp;
316 
317 	outp = outpacket_buf;
318 
319 	MAKEHEADER(outp, PPP_EAP);
320 
321 	PUTCHAR(EAP_SUCCESS, outp);
322 	esp->es_server.ea_id++;
323 	PUTCHAR(esp->es_server.ea_id, outp);
324 	PUTSHORT(EAP_HEADERLEN, outp);
325 
326 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);
327 
328 	auth_peer_success(esp->es_unit, PPP_EAP, 0,
329 	    esp->es_server.ea_peer, esp->es_server.ea_peerlen);
330 }
331 
332 #ifdef PPP_WITH_SRP
333 /*
334  * Set DES key according to pseudonym-generating secret and current
335  * date.
336  */
337 static bool
338 pncrypt_getkey(int timeoffs, unsigned char *key, int keylen)
339 {
340 	struct tm *tp;
341 	char tbuf[9];
342 	PPP_MD_CTX *ctxt;
343 	time_t reftime;
344 
345 	if (pn_secret == NULL)
346 		return (0);
347 	reftime = time(NULL) + timeoffs;
348 	tp = localtime(&reftime);
349 
350 	ctxt = PPP_MD_CTX_new();
351 	if (ctxt) {
352 
353 	    strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp);
354 
355 	    PPP_DigestInit(ctxt, PPP_sha1());
356 	    PPP_DigestUpdate(ctxt, pn_secret, strlen(pn_secret));
357 	    PPP_DigestUpdate(ctxt, tbuf, strlen(tbuf));
358 	    PPP_DigestFinal(ctxt, key, &keylen);
359 
360 	    PPP_MD_CTX_free(ctxt);
361 	    return 1;
362 	}
363 
364 	return (0);
365 }
366 
367 static char base64[] =
368 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
369 
370 struct b64state {
371 	u_int32_t bs_bits;
372 	int bs_offs;
373 };
374 
375 static int
376 b64enc(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
377 {
378 	int outlen = 0;
379 
380 	while (inlen > 0) {
381 		bs->bs_bits = (bs->bs_bits << 8) | *inp++;
382 		inlen--;
383 		bs->bs_offs += 8;
384 		if (bs->bs_offs >= 24) {
385 			*outp++ = base64[(bs->bs_bits >> 18) & 0x3F];
386 			*outp++ = base64[(bs->bs_bits >> 12) & 0x3F];
387 			*outp++ = base64[(bs->bs_bits >> 6) & 0x3F];
388 			*outp++ = base64[bs->bs_bits & 0x3F];
389 			outlen += 4;
390 			bs->bs_offs = 0;
391 			bs->bs_bits = 0;
392 		}
393 	}
394 	return (outlen);
395 }
396 
397 static int
398 b64flush(struct b64state *bs, u_char *outp)
399 {
400 	int outlen = 0;
401 
402 	if (bs->bs_offs == 8) {
403 		*outp++ = base64[(bs->bs_bits >> 2) & 0x3F];
404 		*outp++ = base64[(bs->bs_bits << 4) & 0x3F];
405 		outlen = 2;
406 	} else if (bs->bs_offs == 16) {
407 		*outp++ = base64[(bs->bs_bits >> 10) & 0x3F];
408 		*outp++ = base64[(bs->bs_bits >> 4) & 0x3F];
409 		*outp++ = base64[(bs->bs_bits << 2) & 0x3F];
410 		outlen = 3;
411 	}
412 	bs->bs_offs = 0;
413 	bs->bs_bits = 0;
414 	return (outlen);
415 }
416 
417 static int
418 b64dec(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
419 {
420 	int outlen = 0;
421 	char *cp;
422 
423 	while (inlen > 0) {
424 		if ((cp = strchr(base64, *inp++)) == NULL)
425 			break;
426 		bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);
427 		inlen--;
428 		bs->bs_offs += 6;
429 		if (bs->bs_offs >= 8) {
430 			*outp++ = bs->bs_bits >> (bs->bs_offs - 8);
431 			outlen++;
432 			bs->bs_offs -= 8;
433 		}
434 	}
435 	return (outlen);
436 }
437 #endif /* PPP_WITH_SRP */
438 
439 /*
440  * Assume that current waiting server state is complete and figure
441  * next state to use based on available authentication data.  'status'
442  * indicates if there was an error in handling the last query.  It is
443  * 0 for success and non-zero for failure.
444  */
445 static void
446 eap_figure_next_state(eap_state *esp, int status)
447 {
448 #ifdef PPP_WITH_SRP
449 	unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp, key[SHA_DIGEST_LENGTH];
450 	struct t_pw tpw;
451 	struct t_confent *tce, mytce;
452 	char *cp, *cp2;
453 	struct t_server *ts;
454 	int id, i, plen, clen, toffs, keylen;
455 	u_char vals[2];
456 	struct b64state bs;
457 #endif /* PPP_WITH_SRP */
458 #ifdef PPP_WITH_EAPTLS
459 	struct eaptls_session *ets;
460 	int secret_len;
461 	char secret[MAXWORDLEN];
462 #endif /* PPP_WITH_EAPTLS */
463 
464 	esp->es_server.ea_timeout = esp->es_savedtime;
465 #ifdef PPP_WITH_EAPTLS
466 	esp->es_server.ea_prev_state = esp->es_server.ea_state;
467 #endif /* PPP_WITH_EAPTLS */
468 	switch (esp->es_server.ea_state) {
469 	case eapBadAuth:
470 		return;
471 
472 	case eapIdentify:
473 #ifdef PPP_WITH_SRP
474 		/* Discard any previous session. */
475 		ts = (struct t_server *)esp->es_server.ea_session;
476 		if (ts != NULL) {
477 			t_serverclose(ts);
478 			esp->es_server.ea_session = NULL;
479 			esp->es_server.ea_skey = NULL;
480 		}
481 #endif /* PPP_WITH_SRP */
482 		if (status != 0) {
483 			esp->es_server.ea_state = eapBadAuth;
484 			break;
485 		}
486 #ifdef PPP_WITH_SRP
487 		/* If we've got a pseudonym, try to decode to real name. */
488 		if (esp->es_server.ea_peerlen > SRP_PSEUDO_LEN &&
489 		    strncmp(esp->es_server.ea_peer, SRP_PSEUDO_ID,
490 			SRP_PSEUDO_LEN) == 0 &&
491 		    (esp->es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 <
492 		    sizeof (secbuf)) {
493 			BZERO(&bs, sizeof (bs));
494 			plen = b64dec(&bs,
495 			    esp->es_server.ea_peer + SRP_PSEUDO_LEN,
496 			    esp->es_server.ea_peerlen - SRP_PSEUDO_LEN,
497 			    secbuf);
498 			toffs = 0;
499 			for (i = 0; i < 5; i++) {
500 				pncrypt_getkey(toffs, key, keylen);
501 				toffs -= 86400;
502 
503 				if (!DesDecrypt(secbuf, key, clear)) {
504 					dbglog("no DES here; cannot decode "
505 						"pseudonym");
506 					return;
507 				}
508 				id = *(unsigned char *)clear;
509 				if (id + 1 <= plen && id + 9 > plen)
510 					break;
511 			}
512 			if (plen % 8 == 0 && i < 5) {
513 				/*
514 				 * Note that this is always shorter than the
515 				 * original stored string, so there's no need
516 				 * to realloc.
517 				 */
518 				if ((i = plen = *(unsigned char *)clear) > 7)
519 					i = 7;
520 				esp->es_server.ea_peerlen = plen;
521 				dp = (unsigned char *)esp->es_server.ea_peer;
522 				BCOPY(clear + 1, dp, i);
523 				plen -= i;
524 				dp += i;
525 				sp = secbuf + 8;
526 				while (plen > 0) {
527 					DesDecrypt(sp, key, dp);
528 					sp += 8;
529 					dp += 8;
530 					plen -= 8;
531 				}
532 				esp->es_server.ea_peer[
533 					esp->es_server.ea_peerlen] = '\0';
534 				dbglog("decoded pseudonym to \"%.*q\"",
535 				    esp->es_server.ea_peerlen,
536 				    esp->es_server.ea_peer);
537 			} else {
538 				dbglog("failed to decode real name");
539 				/* Stay in eapIdentfy state; requery */
540 				break;
541 			}
542 		}
543 		/* Look up user in secrets database. */
544 		if (get_srp_secret(esp->es_unit, esp->es_server.ea_peer,
545 		    esp->es_server.ea_name, (char *)secbuf, 1) != 0) {
546 			/* Set up default in case SRP entry is bad */
547 			esp->es_server.ea_state = eapMD5Chall;
548 			/* Get t_confent based on index in srp-secrets */
549 			id = strtol((char *)secbuf, &cp, 10);
550 			if (*cp++ != ':' || id < 0)
551 				break;
552 			if (id == 0) {
553 				mytce.index = 0;
554 				mytce.modulus.data = (u_char *)wkmodulus;
555 				mytce.modulus.len = sizeof (wkmodulus);
556 				mytce.generator.data = (u_char *)"\002";
557 				mytce.generator.len = 1;
558 				tce = &mytce;
559 			} else if ((tce = gettcid(id)) != NULL) {
560 				/*
561 				 * Client will have to verify this modulus/
562 				 * generator combination, and that will take
563 				 * a while.  Lengthen the timeout here.
564 				 */
565 				if (esp->es_server.ea_timeout > 0 &&
566 				    esp->es_server.ea_timeout < 30)
567 					esp->es_server.ea_timeout = 30;
568 			} else {
569 				break;
570 			}
571 			if ((cp2 = strchr(cp, ':')) == NULL)
572 				break;
573 			*cp2++ = '\0';
574 			tpw.pebuf.name = esp->es_server.ea_peer;
575 			tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,
576 			    cp);
577 			tpw.pebuf.password.data = (char*) tpw.pwbuf;
578 			tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,
579 			    cp2);
580 			tpw.pebuf.salt.data = tpw.saltbuf;
581 			if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)
582 				break;
583 			esp->es_server.ea_session = (void *)ts;
584 			esp->es_server.ea_state = eapSRP1;
585 			vals[0] = esp->es_server.ea_id + 1;
586 			vals[1] = EAPT_SRP;
587 			t_serveraddexdata(ts, vals, 2);
588 			/* Generate B; must call before t_servergetkey() */
589 			t_servergenexp(ts);
590 			break;
591 		}
592 #endif /* PPP_WITH_SRP */
593 #ifdef PPP_WITH_EAPTLS
594                 if (!get_secret(esp->es_unit, esp->es_server.ea_peer,
595                     esp->es_server.ea_name, secret, &secret_len, 1)) {
596 
597 			esp->es_server.ea_state = eapTlsStart;
598 			break;
599 		}
600 #endif /* PPP_WITH_EAPTLS */
601 
602 		esp->es_server.ea_state = eapMD5Chall;
603 		break;
604 
605 #ifdef PPP_WITH_EAPTLS
606 	case eapTlsStart:
607 		/* Initialize ssl session */
608 		if(!eaptls_init_ssl_server(esp)) {
609 			esp->es_server.ea_state = eapBadAuth;
610 			break;
611 		}
612 
613 		esp->es_server.ea_state = eapTlsRecv;
614 		break;
615 
616 	case eapTlsRecv:
617 		ets = (struct eaptls_session *) esp->es_server.ea_session;
618 
619 		if(ets->alert_sent) {
620 			esp->es_server.ea_state = eapTlsSendAlert;
621 			break;
622 		}
623 
624 		if (status) {
625 			esp->es_server.ea_state = eapBadAuth;
626 			break;
627 		}
628 		ets = (struct eaptls_session *) esp->es_server.ea_session;
629 
630 		if(ets->frag)
631 			esp->es_server.ea_state = eapTlsSendAck;
632 		else
633 			esp->es_server.ea_state = eapTlsSend;
634 		break;
635 
636 	case eapTlsSend:
637 		ets = (struct eaptls_session *) esp->es_server.ea_session;
638 
639 		if(ets->frag)
640 			esp->es_server.ea_state = eapTlsRecvAck;
641 		else
642 			if(SSL_is_init_finished(ets->ssl))
643 				esp->es_server.ea_state = eapTlsRecvClient;
644 			else
645 				/* JJK Add "TLS empty record" message here ??? */
646 				esp->es_server.ea_state = eapTlsRecv;
647 		break;
648 
649 	case eapTlsSendAck:
650 		esp->es_server.ea_state = eapTlsRecv;
651 		break;
652 
653 	case eapTlsRecvAck:
654 		if (status)
655 		{
656 			esp->es_server.ea_state = eapBadAuth;
657 			break;
658 		}
659 
660 		esp->es_server.ea_state = eapTlsSend;
661 		break;
662 
663 	case eapTlsSendAlert:
664 		esp->es_server.ea_state = eapTlsRecvAlertAck;
665 		break;
666 #endif /* PPP_WITH_EAPTLS */
667 
668 	case eapSRP1:
669 #ifdef PPP_WITH_SRP
670 		ts = (struct t_server *)esp->es_server.ea_session;
671 		if (ts != NULL && status != 0) {
672 			t_serverclose(ts);
673 			esp->es_server.ea_session = NULL;
674 			esp->es_server.ea_skey = NULL;
675 		}
676 #endif /* PPP_WITH_SRP */
677 		if (status == 1) {
678 			esp->es_server.ea_state = eapMD5Chall;
679 		} else if (status != 0 || esp->es_server.ea_session == NULL) {
680 			esp->es_server.ea_state = eapBadAuth;
681 		} else {
682 			esp->es_server.ea_state = eapSRP2;
683 		}
684 		break;
685 
686 	case eapSRP2:
687 #ifdef PPP_WITH_SRP
688 		ts = (struct t_server *)esp->es_server.ea_session;
689 		if (ts != NULL && status != 0) {
690 			t_serverclose(ts);
691 			esp->es_server.ea_session = NULL;
692 			esp->es_server.ea_skey = NULL;
693 		}
694 #endif /* PPP_WITH_SRP */
695 		if (status != 0 || esp->es_server.ea_session == NULL) {
696 			esp->es_server.ea_state = eapBadAuth;
697 		} else {
698 			esp->es_server.ea_state = eapSRP3;
699 		}
700 		break;
701 
702 	case eapSRP3:
703 	case eapSRP4:
704 #ifdef PPP_WITH_SRP
705 		ts = (struct t_server *)esp->es_server.ea_session;
706 		if (ts != NULL && status != 0) {
707 			t_serverclose(ts);
708 			esp->es_server.ea_session = NULL;
709 			esp->es_server.ea_skey = NULL;
710 		}
711 #endif /* PPP_WITH_SRP */
712 		if (status != 0 || esp->es_server.ea_session == NULL) {
713 			esp->es_server.ea_state = eapBadAuth;
714 		} else {
715 			esp->es_server.ea_state = eapOpen;
716 		}
717 		break;
718 
719 #ifdef PPP_WITH_CHAPMS
720 	case eapMSCHAPv2Chall:
721 #endif
722 	case eapMD5Chall:
723 		if (status != 0) {
724 			esp->es_server.ea_state = eapBadAuth;
725 		} else {
726 			esp->es_server.ea_state = eapOpen;
727 		}
728 		break;
729 
730 	default:
731 		esp->es_server.ea_state = eapBadAuth;
732 		break;
733 	}
734 	if (esp->es_server.ea_state == eapBadAuth)
735 		eap_send_failure(esp);
736 
737 #ifdef PPP_WITH_EAPTLS
738 	dbglog("EAP id=0x%2x '%s' -> '%s'", esp->es_server.ea_id, eap_state_name(esp->es_server.ea_prev_state), eap_state_name(esp->es_server.ea_state));
739 #endif /* PPP_WITH_EAPTLS */
740 }
741 
742 #if PPP_WITH_CHAPMS
743 /*
744  * eap_chap_verify_response - check whether the peer's response matches
745  * what we think it should be.  Returns 1 if it does (authentication
746  * succeeded), or 0 if it doesn't.
747  */
748 static int
749 eap_chap_verify_response(char *name, char *ourname, int id,
750 			 struct chap_digest_type *digest,
751 			 unsigned char *challenge, unsigned char *response,
752 			 char *message, int message_space)
753 {
754 	int ok;
755 	unsigned char secret[MAXSECRETLEN];
756 	int secret_len;
757 
758 	/* Get the secret that the peer is supposed to know */
759 	if (!get_secret(0, name, ourname, (char *)secret, &secret_len, 1)) {
760 		error("No CHAP secret found for authenticating %q", name);
761 		return 0;
762 	}
763 
764 	ok = digest->verify_response(id, name, secret, secret_len, challenge,
765 				     response, message, message_space);
766 	memset(secret, 0, sizeof(secret));
767 
768 	return ok;
769 }
770 
771 /*
772  * Format and send an CHAPV2-Success/Failure EAP Request message.
773  */
774 static void
775 eap_chapms2_send_request(eap_state *esp, u_char id,
776 			 u_char opcode, u_char chapid,
777 			 char *message, int message_len)
778 {
779 	u_char *outp;
780 	int msglen;
781 
782 	outp = outpacket_buf;
783 
784 	MAKEHEADER(outp, PPP_EAP);
785 
786 	msglen = EAP_HEADERLEN + 5 * sizeof (u_char);
787 	msglen += message_len;
788 
789 	PUTCHAR(EAP_REQUEST, outp);
790 	PUTCHAR(id, outp);
791 	PUTSHORT(msglen, outp);
792 	PUTCHAR(EAPT_MSCHAPV2, outp);
793 	PUTCHAR(opcode, outp);
794 	PUTCHAR(chapid, outp);
795 	/* MS len */
796 	PUTSHORT(msglen - 5, outp);
797 	BCOPY(message, outp, message_len);
798 
799 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
800 
801 	if (opcode == CHAP_SUCCESS) {
802 		auth_peer_success(esp->es_unit, PPP_EAP, 0,
803 				esp->es_server.ea_peer, esp->es_server.ea_peerlen);
804 	}
805 	else {
806 		esp->es_server.ea_state = eapBadAuth;
807 		auth_peer_fail(esp->es_unit, PPP_EAP);
808 	}
809 }
810 #endif /* PPP_WITH_CHAPMS */
811 
812 /*
813  * Format an EAP Request message and send it to the peer.  Message
814  * type depends on current state.  (Server operation)
815  */
816 static void
817 eap_send_request(eap_state *esp)
818 {
819 	u_char *outp;
820 	u_char *lenloc;
821 	u_char *ptr;
822 	int outlen;
823 	int challen;
824 	char *str;
825 #ifdef PPP_WITH_SRP
826 	struct t_server *ts;
827 	u_char clear[8], cipher[8], dig[SHA_DIGEST_LENGTH], *optr, *cp, key[SHA_DIGEST_LENGTH];
828 	int i, j, diglen, clen, keylen = sizeof(key);
829 	struct b64state b64;
830 	PPP_MD_CTX *ctxt;
831 #endif /* PPP_WITH_SRP */
832 
833 	/* Handle both initial auth and restart */
834 	if (esp->es_server.ea_state < eapIdentify &&
835 	    esp->es_server.ea_state != eapInitial) {
836 		esp->es_server.ea_state = eapIdentify;
837 		if (explicit_remote) {
838 			/*
839 			 * If we already know the peer's
840 			 * unauthenticated name, then there's no
841 			 * reason to ask.  Go to next state instead.
842 			 */
843 			esp->es_server.ea_peer = remote_name;
844 			esp->es_server.ea_peerlen = strlen(remote_name);
845 			eap_figure_next_state(esp, 0);
846 		}
847 	}
848 
849 	if (esp->es_server.ea_maxrequests > 0 &&
850 	    esp->es_server.ea_requests >= esp->es_server.ea_maxrequests) {
851 		if (esp->es_server.ea_responses > 0)
852 			error("EAP: too many Requests sent");
853 		else
854 			error("EAP: no response to Requests");
855 		eap_send_failure(esp);
856 		return;
857 	}
858 
859 	outp = outpacket_buf;
860 
861 	MAKEHEADER(outp, PPP_EAP);
862 
863 	PUTCHAR(EAP_REQUEST, outp);
864 	PUTCHAR(esp->es_server.ea_id, outp);
865 	lenloc = outp;
866 	INCPTR(2, outp);
867 
868 	switch (esp->es_server.ea_state) {
869 	case eapIdentify:
870 		PUTCHAR(EAPT_IDENTITY, outp);
871 		str = "Name";
872 		challen = strlen(str);
873 		BCOPY(str, outp, challen);
874 		INCPTR(challen, outp);
875 		break;
876 
877 	case eapMD5Chall:
878 		PUTCHAR(EAPT_MD5CHAP, outp);
879 		/*
880 		 * pick a random challenge length between
881 		 * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
882 		 */
883 		challen = (drand48() *
884 		    (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
885 			    MIN_CHALLENGE_LENGTH;
886 		PUTCHAR(challen, outp);
887 		esp->es_challen = challen;
888 		ptr = esp->es_challenge;
889 		while (--challen >= 0)
890 			*ptr++ = (u_char) (drand48() * 0x100);
891 		BCOPY(esp->es_challenge, outp, esp->es_challen);
892 		INCPTR(esp->es_challen, outp);
893 		BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
894 		INCPTR(esp->es_server.ea_namelen, outp);
895 		break;
896 
897 #ifdef PPP_WITH_CHAPMS
898 	case eapMSCHAPv2Chall:
899 		esp->es_server.digest->generate_challenge(esp->es_challenge);
900 		challen = esp->es_challenge[0];
901 		esp->es_challen = challen;
902 
903 		PUTCHAR(EAPT_MSCHAPV2, outp);
904 		PUTCHAR(CHAP_CHALLENGE, outp);
905 		PUTCHAR(esp->es_server.ea_id, outp);
906 		/* MS len */
907 		PUTSHORT(5 + challen +
908 				esp->es_server.ea_namelen,
909 				outp);
910 		/* challen + challenge */
911 		BCOPY(esp->es_challenge, outp, challen+1);
912 		INCPTR(challen+1, outp);
913 		BCOPY(esp->es_server.ea_name,
914 				outp,
915 				esp->es_server.ea_namelen);
916 		INCPTR(esp->es_server.ea_namelen, outp);
917 		break;
918 #endif /* PPP_WITH_CHAPMS */
919 
920 #ifdef PPP_WITH_EAPTLS
921 	case eapTlsStart:
922 		PUTCHAR(EAPT_TLS, outp);
923 		PUTCHAR(EAP_TLS_FLAGS_START, outp);
924 		eap_figure_next_state(esp, 0);
925 		break;
926 
927 	case eapTlsSend:
928 		eaptls_send(esp->es_server.ea_session, &outp);
929 		eap_figure_next_state(esp, 0);
930 		break;
931 
932 	case eapTlsSendAck:
933 		PUTCHAR(EAPT_TLS, outp);
934 		PUTCHAR(0, outp);
935 		eap_figure_next_state(esp, 0);
936 		break;
937 
938 	case eapTlsSendAlert:
939 		eaptls_send(esp->es_server.ea_session, &outp);
940 		eap_figure_next_state(esp, 0);
941 		break;
942 #endif /* PPP_WITH_EAPTLS */
943 
944 #ifdef PPP_WITH_SRP
945 	case eapSRP1:
946 		PUTCHAR(EAPT_SRP, outp);
947 		PUTCHAR(EAPSRP_CHALLENGE, outp);
948 
949 		PUTCHAR(esp->es_server.ea_namelen, outp);
950 		BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
951 		INCPTR(esp->es_server.ea_namelen, outp);
952 
953 		ts = (struct t_server *)esp->es_server.ea_session;
954 		assert(ts != NULL);
955 		PUTCHAR(ts->s.len, outp);
956 		BCOPY(ts->s.data, outp, ts->s.len);
957 		INCPTR(ts->s.len, outp);
958 
959 		if (ts->g.len == 1 && ts->g.data[0] == 2) {
960 			PUTCHAR(0, outp);
961 		} else {
962 			PUTCHAR(ts->g.len, outp);
963 			BCOPY(ts->g.data, outp, ts->g.len);
964 			INCPTR(ts->g.len, outp);
965 		}
966 
967 		if (ts->n.len != sizeof (wkmodulus) ||
968 		    BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) {
969 			BCOPY(ts->n.data, outp, ts->n.len);
970 			INCPTR(ts->n.len, outp);
971 		}
972 		break;
973 
974 	case eapSRP2:
975 		PUTCHAR(EAPT_SRP, outp);
976 		PUTCHAR(EAPSRP_SKEY, outp);
977 
978 		ts = (struct t_server *)esp->es_server.ea_session;
979 		assert(ts != NULL);
980 		BCOPY(ts->B.data, outp, ts->B.len);
981 		INCPTR(ts->B.len, outp);
982 		break;
983 
984 	case eapSRP3:
985 		PUTCHAR(EAPT_SRP, outp);
986 		PUTCHAR(EAPSRP_SVALIDATOR, outp);
987 		PUTLONG(SRPVAL_EBIT, outp);
988 		ts = (struct t_server *)esp->es_server.ea_session;
989 		assert(ts != NULL);
990 		BCOPY(t_serverresponse(ts), outp, SHA_DIGEST_LENGTH);
991 		INCPTR(SHA_DIGEST_LENGTH, outp);
992 
993 		if (pncrypt_getkey(0, key, keylen)) {
994 			/* Generate pseudonym */
995 			optr = outp;
996 			cp = (unsigned char *)esp->es_server.ea_peer;
997 			if ((j = i = esp->es_server.ea_peerlen) > 7)
998 				j = 7;
999 			clear[0] = i;
1000 			BCOPY(cp, clear + 1, j);
1001 			i -= j;
1002 			cp += j;
1003 
1004 			if (!DesEncrypt(clear, key, cipher)) {
1005 				dbglog("no DES here; not generating pseudonym");
1006 				break;
1007             }
1008 
1009 			BZERO(&b64, sizeof (b64));
1010 			outp++;		/* space for pseudonym length */
1011 			outp += b64enc(&b64, cipher, 8, outp);
1012 			while (i >= 8) {
1013 				DesEncrypt(cp, key, cipher);
1014 				outp += b64enc(&b64, cipher, 8, outp);
1015 				cp += 8;
1016 				i -= 8;
1017 			}
1018 			if (i > 0) {
1019 				BCOPY(cp, clear, i);
1020 				cp += i;
1021 				while (i < 8) {
1022 					*cp++ = drand48() * 0x100;
1023 					i++;
1024 				}
1025 
1026 				DesEncrypt(clear, key, cipher);
1027 				outp += b64enc(&b64, cipher, 8, outp);
1028 			}
1029 			outp += b64flush(&b64, outp);
1030 
1031 			/* Set length and pad out to next 20 octet boundary */
1032 			i = outp - optr - 1;
1033 			*optr = i;
1034 			i %= SHA_DIGEST_LENGTH;
1035 			if (i != 0) {
1036 				while (i < SHA_DIGEST_LENGTH) {
1037 					*outp++ = drand48() * 0x100;
1038 					i++;
1039 				}
1040 			}
1041 
1042 			/* Obscure the pseudonym with SHA1 hash */
1043 			ctxt = PPP_MD_CTX_new();
1044 			if (ctxt) {
1045 
1046 				PPP_DigestInit(ctxt, PPP_sha1());
1047 				PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1);
1048 				PPP_DigestUpdate(ctxt, &esp->es_server.ea_skey,
1049 					SESSION_KEY_LEN);
1050 				PPP_DigestUpdate(ctxt,  esp->es_server.ea_peer,
1051 					esp->es_server.ea_peerlen);
1052 				while (optr < outp) {
1053 					diglen = SHA_DIGEST_LENGTH;
1054 					PPP_DigestFinal(ctxt, dig, &diglen);
1055 					cp = dig;
1056 					while (cp < dig + SHA_DIGEST_LENGTH)
1057 						*optr++ ^= *cp++;
1058 
1059 					PPP_DigestInit(ctxt, PPP_sha1());
1060 					PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1);
1061 					PPP_DigestUpdate(ctxt, esp->es_server.ea_skey,
1062 						SESSION_KEY_LEN);
1063 					PPP_DigestUpdate(ctxt, optr - SHA_DIGEST_LENGTH,
1064 						SHA_DIGEST_LENGTH);
1065 				}
1066 
1067 				PPP_MD_CTX_free(ctxt);
1068 			}
1069 		}
1070 		break;
1071 
1072 	case eapSRP4:
1073 		PUTCHAR(EAPT_SRP, outp);
1074 		PUTCHAR(EAPSRP_LWRECHALLENGE, outp);
1075 		challen = MIN_CHALLENGE_LENGTH +
1076 		    ((MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH) * drand48());
1077 		esp->es_challen = challen;
1078 		ptr = esp->es_challenge;
1079 		while (--challen >= 0)
1080 			*ptr++ = drand48() * 0x100;
1081 		BCOPY(esp->es_challenge, outp, esp->es_challen);
1082 		INCPTR(esp->es_challen, outp);
1083 		break;
1084 #endif /* PPP_WITH_SRP */
1085 
1086 	default:
1087 		return;
1088 	}
1089 
1090 	outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1091 	PUTSHORT(outlen, lenloc);
1092 
1093 	output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
1094 
1095 	esp->es_server.ea_requests++;
1096 
1097 	if (esp->es_server.ea_timeout > 0)
1098 		TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
1099 }
1100 
1101 /*
1102  * eap_authpeer - Authenticate our peer (behave as server).
1103  *
1104  * Start server state and send first request.  This is called only
1105  * after eap_lowerup.
1106  */
1107 void
1108 eap_authpeer(int unit, char *localname)
1109 {
1110 	eap_state *esp = &eap_states[unit];
1111 
1112 	/* Save the name we're given. */
1113 	esp->es_server.ea_name = localname;
1114 	esp->es_server.ea_namelen = strlen(localname);
1115 
1116 	esp->es_savedtime = esp->es_server.ea_timeout;
1117 
1118 	/* Lower layer up yet? */
1119 	if (esp->es_server.ea_state == eapInitial ||
1120 	    esp->es_server.ea_state == eapPending) {
1121 		esp->es_server.ea_state = eapPending;
1122 		return;
1123 	}
1124 
1125 	esp->es_server.ea_state = eapPending;
1126 
1127 	/* ID number not updated here intentionally; hashed into M1 */
1128 	eap_send_request(esp);
1129 }
1130 
1131 /*
1132  * eap_server_timeout - Retransmission timer for sending Requests
1133  * expired.
1134  */
1135 static void
1136 eap_server_timeout(void *arg)
1137 {
1138 #ifdef PPP_WITH_EAPTLS
1139 	u_char *outp;
1140 	u_char *lenloc;
1141 	int outlen;
1142 #endif /* PPP_WITH_EAPTLS */
1143 
1144 	eap_state *esp = (eap_state *) arg;
1145 
1146 	if (!eap_server_active(esp))
1147 		return;
1148 
1149 #ifdef PPP_WITH_EAPTLS
1150 	switch(esp->es_server.ea_prev_state) {
1151 
1152 	/*
1153 	 *  In eap-tls the state changes after a request, so we return to
1154 	 *  previous state ...
1155 	 */
1156 	case(eapTlsStart):
1157 	case(eapTlsSendAck):
1158 		esp->es_server.ea_state = esp->es_server.ea_prev_state;
1159 		break;
1160 
1161 	/*
1162 	 *  ... or resend the stored data
1163 	 */
1164 	case(eapTlsSend):
1165 	case(eapTlsSendAlert):
1166 		outp = outpacket_buf;
1167 		MAKEHEADER(outp, PPP_EAP);
1168 		PUTCHAR(EAP_REQUEST, outp);
1169 		PUTCHAR(esp->es_server.ea_id, outp);
1170 		lenloc = outp;
1171 		INCPTR(2, outp);
1172 
1173 		eaptls_retransmit(esp->es_server.ea_session, &outp);
1174 
1175 		outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1176 		PUTSHORT(outlen, lenloc);
1177 		output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
1178 		esp->es_server.ea_requests++;
1179 
1180 		if (esp->es_server.ea_timeout > 0)
1181 			TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
1182 
1183 		return;
1184 	default:
1185 		break;
1186 	}
1187 #endif /* PPP_WITH_EAPTLS */
1188 
1189 	/* EAP ID number must not change on timeout. */
1190 	eap_send_request(esp);
1191 }
1192 
1193 /*
1194  * When it's time to send rechallenge the peer, this timeout is
1195  * called.  Once the rechallenge is successful, the response handler
1196  * will restart the timer.  If it fails, then the link is dropped.
1197  */
1198 static void
1199 eap_rechallenge(void *arg)
1200 {
1201 	eap_state *esp = (eap_state *)arg;
1202 
1203 	if (esp->es_server.ea_state != eapOpen &&
1204 	    esp->es_server.ea_state != eapSRP4)
1205 		return;
1206 
1207 	esp->es_server.ea_requests = 0;
1208 	esp->es_server.ea_state = eapIdentify;
1209 	eap_figure_next_state(esp, 0);
1210 	esp->es_server.ea_id++;
1211 	eap_send_request(esp);
1212 }
1213 
1214 static void
1215 srp_lwrechallenge(void *arg)
1216 {
1217 	eap_state *esp = (eap_state *)arg;
1218 
1219 	if (esp->es_server.ea_state != eapOpen ||
1220 	    esp->es_server.ea_type != EAPT_SRP)
1221 		return;
1222 
1223 	esp->es_server.ea_requests = 0;
1224 	esp->es_server.ea_state = eapSRP4;
1225 	esp->es_server.ea_id++;
1226 	eap_send_request(esp);
1227 }
1228 
1229 /*
1230  * eap_lowerup - The lower layer is now up.
1231  *
1232  * This is called before either eap_authpeer or eap_authwithpeer.  See
1233  * link_established() in auth.c.  All that's necessary here is to
1234  * return to closed state so that those two routines will do the right
1235  * thing.
1236  */
1237 static void
1238 eap_lowerup(int unit)
1239 {
1240 	eap_state *esp = &eap_states[unit];
1241 
1242 	/* Discard any (possibly authenticated) peer name. */
1243 	if (esp->es_server.ea_peer != NULL &&
1244 	    esp->es_server.ea_peer != remote_name)
1245 		free(esp->es_server.ea_peer);
1246 	esp->es_server.ea_peer = NULL;
1247 	if (esp->es_client.ea_peer != NULL)
1248 		free(esp->es_client.ea_peer);
1249 	esp->es_client.ea_peer = NULL;
1250 
1251 	esp->es_client.ea_state = eapClosed;
1252 	esp->es_server.ea_state = eapClosed;
1253 }
1254 
1255 /*
1256  * eap_lowerdown - The lower layer is now down.
1257  *
1258  * Cancel all timeouts and return to initial state.
1259  */
1260 static void
1261 eap_lowerdown(int unit)
1262 {
1263 	eap_state *esp = &eap_states[unit];
1264 
1265 	if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) {
1266 		UNTIMEOUT(eap_client_timeout, (void *)esp);
1267 	}
1268 	if (eap_server_active(esp)) {
1269 		if (esp->es_server.ea_timeout > 0) {
1270 			UNTIMEOUT(eap_server_timeout, (void *)esp);
1271 		}
1272 	} else {
1273 		if ((esp->es_server.ea_state == eapOpen ||
1274 		    esp->es_server.ea_state == eapSRP4) &&
1275 		    esp->es_rechallenge > 0) {
1276 			UNTIMEOUT(eap_rechallenge, (void *)esp);
1277 		}
1278 		if (esp->es_server.ea_state == eapOpen &&
1279 		    esp->es_lwrechallenge > 0) {
1280 			UNTIMEOUT(srp_lwrechallenge, (void *)esp);
1281 		}
1282 	}
1283 
1284 	esp->es_client.ea_state = esp->es_server.ea_state = eapInitial;
1285 	esp->es_client.ea_requests = esp->es_server.ea_requests = 0;
1286 }
1287 
1288 /*
1289  * eap_protrej - Peer doesn't speak this protocol.
1290  *
1291  * This shouldn't happen.  If it does, it represents authentication
1292  * failure.
1293  */
1294 static void
1295 eap_protrej(int unit)
1296 {
1297 	eap_state *esp = &eap_states[unit];
1298 
1299 	if (eap_client_active(esp)) {
1300 		error("EAP authentication failed due to Protocol-Reject");
1301 		auth_withpeer_fail(unit, PPP_EAP);
1302 	}
1303 	if (eap_server_active(esp)) {
1304 		error("EAP authentication of peer failed on Protocol-Reject");
1305 		auth_peer_fail(unit, PPP_EAP);
1306 	}
1307 	eap_lowerdown(unit);
1308 }
1309 
1310 /*
1311  * Format and send a regular EAP Response message.
1312  */
1313 static void
1314 eap_send_response(eap_state *esp, u_char id, u_char typenum,
1315 		  u_char *str, int lenstr)
1316 {
1317 	u_char *outp;
1318 	int msglen;
1319 
1320 	outp = outpacket_buf;
1321 
1322 	MAKEHEADER(outp, PPP_EAP);
1323 
1324 	PUTCHAR(EAP_RESPONSE, outp);
1325 	PUTCHAR(id, outp);
1326 	esp->es_client.ea_id = id;
1327 	msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr;
1328 	PUTSHORT(msglen, outp);
1329 	PUTCHAR(typenum, outp);
1330 	if (lenstr > 0) {
1331 		BCOPY(str, outp, lenstr);
1332 	}
1333 
1334 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1335 }
1336 
1337 /*
1338  * Format and send an MD5-Challenge EAP Response message.
1339  */
1340 static void
1341 eap_chap_response(eap_state *esp, u_char id, u_char *hash,
1342 		  char *name, int namelen)
1343 {
1344 	u_char *outp;
1345 	int msglen;
1346 
1347 	outp = outpacket_buf;
1348 
1349 	MAKEHEADER(outp, PPP_EAP);
1350 
1351 	PUTCHAR(EAP_RESPONSE, outp);
1352 	PUTCHAR(id, outp);
1353 	esp->es_client.ea_id = id;
1354 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_DIGEST_LENGTH +
1355 	    namelen;
1356 	PUTSHORT(msglen, outp);
1357 	PUTCHAR(EAPT_MD5CHAP, outp);
1358 	PUTCHAR(MD5_DIGEST_LENGTH, outp);
1359 	BCOPY(hash, outp, MD5_DIGEST_LENGTH);
1360 	INCPTR(MD5_DIGEST_LENGTH, outp);
1361 	if (namelen > 0) {
1362 		BCOPY(name, outp, namelen);
1363 	}
1364 
1365 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1366 }
1367 
1368 #ifdef PPP_WITH_SRP
1369 /*
1370  * Format and send a SRP EAP Response message.
1371  */
1372 static void
1373 eap_srp_response(eap_state *esp, u_char id, u_char subtypenum,
1374 		 u_char *str, int lenstr)
1375 {
1376 	u_char *outp;
1377 	int msglen;
1378 
1379 	outp = outpacket_buf;
1380 
1381 	MAKEHEADER(outp, PPP_EAP);
1382 
1383 	PUTCHAR(EAP_RESPONSE, outp);
1384 	PUTCHAR(id, outp);
1385 	esp->es_client.ea_id = id;
1386 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr;
1387 	PUTSHORT(msglen, outp);
1388 	PUTCHAR(EAPT_SRP, outp);
1389 	PUTCHAR(subtypenum, outp);
1390 	if (lenstr > 0) {
1391 		BCOPY(str, outp, lenstr);
1392 	}
1393 
1394 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1395 }
1396 
1397 /*
1398  * Format and send a SRP EAP Client Validator Response message.
1399  */
1400 static void
1401 eap_srpval_response(eap_state *esp, u_char id, u_int32_t flags, u_char *str)
1402 {
1403 	u_char *outp;
1404 	int msglen;
1405 
1406 	outp = outpacket_buf;
1407 
1408 	MAKEHEADER(outp, PPP_EAP);
1409 
1410 	PUTCHAR(EAP_RESPONSE, outp);
1411 	PUTCHAR(id, outp);
1412 	esp->es_client.ea_id = id;
1413 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) +
1414 	    SHA_DIGEST_LENGTH;
1415 	PUTSHORT(msglen, outp);
1416 	PUTCHAR(EAPT_SRP, outp);
1417 	PUTCHAR(EAPSRP_CVALIDATOR, outp);
1418 	PUTLONG(flags, outp);
1419 	BCOPY(str, outp, SHA_DIGEST_LENGTH);
1420 
1421 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1422 }
1423 #endif /* PPP_WITH_SRP */
1424 
1425 #ifdef PPP_WITH_EAPTLS
1426 /*
1427  * Send an EAP-TLS response message with tls data
1428  */
1429 static void
1430 eap_tls_response(eap_state *esp, u_char id)
1431 {
1432 	u_char *outp;
1433 	int outlen;
1434 	u_char *lenloc;
1435 
1436 	outp = outpacket_buf;
1437 
1438 	MAKEHEADER(outp, PPP_EAP);
1439 
1440 	PUTCHAR(EAP_RESPONSE, outp);
1441 	PUTCHAR(id, outp);
1442 
1443 	lenloc = outp;
1444 	INCPTR(2, outp);
1445 
1446 	/*
1447 	   If the id in the request is unchanged, we must retransmit
1448 	   the old data
1449 	*/
1450 	if(id == esp->es_client.ea_id)
1451 		eaptls_retransmit(esp->es_client.ea_session, &outp);
1452 	else
1453 		eaptls_send(esp->es_client.ea_session, &outp);
1454 
1455 	outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1456 	PUTSHORT(outlen, lenloc);
1457 
1458 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1459 
1460 	esp->es_client.ea_id = id;
1461 }
1462 
1463 /*
1464  * Send an EAP-TLS ack
1465  */
1466 static void
1467 eap_tls_sendack(eap_state *esp, u_char id)
1468 {
1469 	u_char *outp;
1470 	int outlen;
1471 	u_char *lenloc;
1472 
1473 	outp = outpacket_buf;
1474 
1475 	MAKEHEADER(outp, PPP_EAP);
1476 
1477 	PUTCHAR(EAP_RESPONSE, outp);
1478 	PUTCHAR(id, outp);
1479 	esp->es_client.ea_id = id;
1480 
1481 	lenloc = outp;
1482 	INCPTR(2, outp);
1483 
1484 	PUTCHAR(EAPT_TLS, outp);
1485 	PUTCHAR(0, outp);
1486 
1487 	outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1488 	PUTSHORT(outlen, lenloc);
1489 
1490 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1491 }
1492 #endif /* PPP_WITH_EAPTLS */
1493 
1494 static void
1495 eap_send_nak(eap_state *esp, u_char id, u_char type)
1496 {
1497 	u_char *outp;
1498 	int msglen;
1499 
1500 	outp = outpacket_buf;
1501 
1502 	MAKEHEADER(outp, PPP_EAP);
1503 
1504 	PUTCHAR(EAP_RESPONSE, outp);
1505 	PUTCHAR(id, outp);
1506 	esp->es_client.ea_id = id;
1507 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char);
1508 	PUTSHORT(msglen, outp);
1509 	PUTCHAR(EAPT_NAK, outp);
1510 	PUTCHAR(type, outp);
1511 
1512 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1513 }
1514 
1515 #ifdef PPP_WITH_SRP
1516 static char *
1517 name_of_pn_file(void)
1518 {
1519 	char *user, *path, *file;
1520 	struct passwd *pw;
1521 	size_t pl;
1522 	static bool pnlogged = 0;
1523 
1524 	pw = getpwuid(getuid());
1525 	if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
1526 		errno = EINVAL;
1527 		return (NULL);
1528 	}
1529 	file = PPP_PATH_PSEUDONYM;
1530 	pl = strlen(user) + strlen(file) + 2;
1531 	path = malloc(pl);
1532 	if (path == NULL)
1533 		return (NULL);
1534 	(void) slprintf(path, pl, "%s/%s", user, file);
1535 	if (!pnlogged) {
1536 		dbglog("pseudonym file: %s", path);
1537 		pnlogged = 1;
1538 	}
1539 	return (path);
1540 }
1541 
1542 static int
1543 open_pn_file(mode_t modebits)
1544 {
1545 	char *path;
1546 	int fd, err;
1547 
1548 	if ((path = name_of_pn_file()) == NULL)
1549 		return (-1);
1550 	fd = open(path, modebits, S_IRUSR | S_IWUSR);
1551 	err = errno;
1552 	free(path);
1553 	errno = err;
1554 	return (fd);
1555 }
1556 
1557 static void
1558 remove_pn_file(void)
1559 {
1560 	char *path;
1561 
1562 	if ((path = name_of_pn_file()) != NULL) {
1563 		(void) unlink(path);
1564 		(void) free(path);
1565 	}
1566 }
1567 
1568 static void
1569 write_pseudonym(eap_state *esp, u_char *inp, int len, int id)
1570 {
1571 	u_char val;
1572 	u_char *datp, *digp;
1573 	PPP_MD_CTX *ctxt;
1574 	u_char dig[SHA_DIGEST_LENGTH];
1575 	int dsize, fd, olen = len, diglen = sizeof(dig);
1576 
1577 	/*
1578 	 * Do the decoding by working backwards.  This eliminates the need
1579 	 * to save the decoded output in a separate buffer.
1580 	 */
1581 	val = id;
1582 	while (len > 0) {
1583 		if ((dsize = len % SHA_DIGEST_LENGTH) == 0)
1584 			dsize = SHA_DIGEST_LENGTH;
1585 		len -= dsize;
1586 		datp = inp + len;
1587 		ctxt = PPP_MD_CTX_new();
1588 		if (ctxt) {
1589 
1590 			PPP_DigestInit(ctxt, PPP_sha1());
1591 			PPP_DigestUpdate(ctxt, &val, 1);
1592 			PPP_DigestUpdate(ctxt, esp->es_client.ea_skey,
1593 					SESSION_KEY_LEN);
1594 			if (len > 0) {
1595 				PPP_DigestUpdate(ctxt, datp, SHA_DIGEST_LENGTH);
1596 			} else {
1597 				PPP_DigestUpdate(ctxt, esp->es_client.ea_name,
1598 					esp->es_client.ea_namelen);
1599 			}
1600 			PPP_DigestFinal(ctxt, dig, &diglen);
1601 
1602 			for (digp = dig; digp < dig + SHA_DIGEST_LENGTH; digp++)
1603 				*datp++ ^= *digp;
1604 
1605 			PPP_MD_CTX_free(ctxt);
1606 		}
1607 	}
1608 
1609 	/* Now check that the result is sane */
1610 	if (olen <= 0 || *inp + 1 > olen) {
1611 		dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp);
1612 		return;
1613 	}
1614 
1615 	/* Save it away */
1616 	fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);
1617 	if (fd < 0) {
1618 		dbglog("EAP: error saving pseudonym: %m");
1619 		return;
1620 	}
1621 	len = write(fd, inp + 1, *inp);
1622 	if (close(fd) != -1 && len == *inp) {
1623 		dbglog("EAP: saved pseudonym");
1624 		esp->es_usedpseudo = 0;
1625 	} else {
1626 		dbglog("EAP: failed to save pseudonym");
1627 		remove_pn_file();
1628 	}
1629 }
1630 #endif /* PPP_WITH_SRP */
1631 
1632 #if PPP_WITH_CHAPMS
1633 /*
1634  * Format and send an CHAPV2-Challenge EAP Response message.
1635  */
1636 static void
1637 eap_chapv2_response(eap_state *esp, u_char id, u_char chapid, u_char *response, char *user, int user_len)
1638 {
1639     u_char *outp;
1640     int msglen;
1641 
1642     outp = outpacket_buf;
1643 
1644     MAKEHEADER(outp, PPP_EAP);
1645 
1646     PUTCHAR(EAP_RESPONSE, outp);
1647     PUTCHAR(id, outp);
1648     esp->es_client.ea_id = id;
1649     msglen = EAP_HEADERLEN + 6 * sizeof (u_char) + MS_CHAP2_RESPONSE_LEN + user_len;
1650     PUTSHORT(msglen, outp);
1651     PUTCHAR(EAPT_MSCHAPV2, outp);
1652     PUTCHAR(CHAP_RESPONSE, outp);
1653     PUTCHAR(chapid, outp);
1654     PUTCHAR(0, outp);
1655     /* len */
1656     PUTCHAR(5 + user_len + MS_CHAP2_RESPONSE_LEN, outp);
1657     BCOPY(response, outp, MS_CHAP2_RESPONSE_LEN+1); // VLEN + VALUE
1658     INCPTR(MS_CHAP2_RESPONSE_LEN+1, outp);
1659     BCOPY(user, outp, user_len);
1660 
1661     output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1662 }
1663 #endif
1664 
1665 /*
1666  * eap_request - Receive EAP Request message (client mode).
1667  */
1668 static void
1669 eap_request(eap_state *esp, u_char *inp, int id, int len)
1670 {
1671 	u_char typenum;
1672 	u_char vallen;
1673 	int secret_len;
1674 	char secret[MAXWORDLEN];
1675 	char rhostname[256];
1676 	PPP_MD_CTX *mdctx;
1677 	u_char hash[MD5_DIGEST_LENGTH];
1678 	int hashlen = MD5_DIGEST_LENGTH;
1679 #ifdef PPP_WITH_EAPTLS
1680 	u_char flags;
1681 	struct eaptls_session *ets = esp->es_client.ea_session;
1682 #endif /* PPP_WITH_EAPTLS */
1683 
1684 #ifdef PPP_WITH_SRP
1685 	struct t_client *tc;
1686 	struct t_num sval, gval, Nval, *Ap, Bval;
1687 	u_char vals[2];
1688 	PPP_MD_CTX *ctxt;
1689 	u_char dig[SHA_DIGEST_LENGTH];
1690 	int diglen = sizeof(dig);
1691 	int fd;
1692 #endif /* PPP_WITH_SRP */
1693 
1694 	/*
1695 	 * Ignore requests if we're not open
1696 	 */
1697 	if (esp->es_client.ea_state <= eapClosed)
1698 		return;
1699 
1700 	/*
1701 	 * Note: we update es_client.ea_id *only if* a Response
1702 	 * message is being generated.  Otherwise, we leave it the
1703 	 * same for duplicate detection purposes.
1704 	 */
1705 
1706 	esp->es_client.ea_requests++;
1707 	if (esp->es_client.ea_maxrequests != 0 &&
1708 	    esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {
1709 		info("EAP: received too many Request messages");
1710 		if (esp->es_client.ea_timeout > 0) {
1711 			UNTIMEOUT(eap_client_timeout, (void *)esp);
1712 		}
1713 		auth_withpeer_fail(esp->es_unit, PPP_EAP);
1714 		return;
1715 	}
1716 
1717 	if (len <= 0) {
1718 		error("EAP: empty Request message discarded");
1719 		return;
1720 	}
1721 
1722 	GETCHAR(typenum, inp);
1723 	len--;
1724 
1725 	switch (typenum) {
1726 	case EAPT_IDENTITY:
1727 		if (len > 0)
1728 			info("EAP: Identity prompt \"%.*q\"", len, inp);
1729 #ifdef PPP_WITH_SRP
1730 		if (esp->es_usepseudo &&
1731 		    (esp->es_usedpseudo == 0 ||
1732 			(esp->es_usedpseudo == 1 &&
1733 			    id == esp->es_client.ea_id))) {
1734 			esp->es_usedpseudo = 1;
1735 			/* Try to get a pseudonym */
1736 			if ((fd = open_pn_file(O_RDONLY)) >= 0) {
1737 				strcpy(rhostname, SRP_PSEUDO_ID);
1738 				len = read(fd, rhostname + SRP_PSEUDO_LEN,
1739 				    sizeof (rhostname) - SRP_PSEUDO_LEN);
1740 				/* XXX NAI unsupported */
1741 				if (len > 0) {
1742 					eap_send_response(esp, id, typenum,
1743 					    rhostname, len + SRP_PSEUDO_LEN);
1744 				}
1745 				(void) close(fd);
1746 				if (len > 0)
1747 					break;
1748 			}
1749 		}
1750 		/* Stop using pseudonym now. */
1751 		if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
1752 			remove_pn_file();
1753 			esp->es_usedpseudo = 2;
1754 		}
1755 #endif /* PPP_WITH_SRP */
1756 		eap_send_response(esp, id, typenum, (u_char *)esp->es_client.ea_name,
1757 		    esp->es_client.ea_namelen);
1758 		break;
1759 
1760 	case EAPT_NOTIFICATION:
1761 		if (len > 0)
1762 			info("EAP: Notification \"%.*q\"", len, inp);
1763 		eap_send_response(esp, id, typenum, NULL, 0);
1764 		break;
1765 
1766 	case EAPT_NAK:
1767 		/*
1768 		 * Avoid the temptation to send Response Nak in reply
1769 		 * to Request Nak here.  It can only lead to trouble.
1770 		 */
1771 		warn("EAP: unexpected Nak in Request; ignored");
1772 		/* Return because we're waiting for something real. */
1773 		return;
1774 
1775 	case EAPT_MD5CHAP:
1776 		if (len < 1) {
1777 			error("EAP: received MD5-Challenge with no data");
1778 			/* Bogus request; wait for something real. */
1779 			return;
1780 		}
1781 		GETCHAR(vallen, inp);
1782 		len--;
1783 		if (vallen < 8 || vallen > len) {
1784 			error("EAP: MD5-Challenge with bad length %d (8..%d)",
1785 			    vallen, len);
1786 			/* Try something better. */
1787 			eap_send_nak(esp, id, EAPT_SRP);
1788 			break;
1789 		}
1790 
1791 		/* Not so likely to happen. */
1792 		if (len - vallen >= sizeof (rhostname)) {
1793 			dbglog("EAP: trimming really long peer name down");
1794 			BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1795 			rhostname[sizeof (rhostname) - 1] = '\0';
1796 		} else {
1797 			BCOPY(inp + vallen, rhostname, len - vallen);
1798 			rhostname[len - vallen] = '\0';
1799 		}
1800 
1801 		/* In case the remote doesn't give us his name. */
1802 		if (explicit_remote ||
1803 		    (remote_name[0] != '\0' && vallen == len))
1804 			strlcpy(rhostname, remote_name, sizeof (rhostname));
1805 
1806 		/*
1807 		 * Get the secret for authenticating ourselves with
1808 		 * the specified host.
1809 		 */
1810 		if (!get_secret(esp->es_unit, esp->es_client.ea_name,
1811 		    rhostname, secret, &secret_len, 0)) {
1812 			dbglog("EAP: no MD5 secret for auth to %q", rhostname);
1813 			eap_send_nak(esp, id, EAPT_SRP);
1814 			break;
1815 		}
1816 
1817 		mdctx = PPP_MD_CTX_new();
1818 		if (mdctx != NULL) {
1819 			if (PPP_DigestInit(mdctx, PPP_md5())) {
1820 				typenum = id;
1821 				if (PPP_DigestUpdate(mdctx, &typenum, 1)) {
1822 					if (PPP_DigestUpdate(mdctx, secret, secret_len)) {
1823 						BZERO(secret, sizeof(secret));
1824 						if (PPP_DigestUpdate(mdctx, inp, vallen)) {
1825 							if (PPP_DigestFinal(mdctx, hash, &hashlen)) {
1826 								eap_chap_response(esp, id, hash, esp->es_client.ea_name,
1827 										esp->es_client.ea_namelen);
1828 								PPP_MD_CTX_free(mdctx);
1829 								break;
1830 							}
1831 						}
1832 					}
1833 				}
1834 			}
1835 			PPP_MD_CTX_free(mdctx);
1836 		}
1837 		dbglog("EAP: Invalid MD5 checksum");
1838         eap_send_nak(esp, id, EAPT_SRP);
1839 		break;
1840 
1841 #ifdef PPP_WITH_EAPTLS
1842 	case EAPT_TLS:
1843 
1844 		switch(esp->es_client.ea_state) {
1845 
1846 		case eapListen:
1847 
1848 			if (len < 1) {
1849 				error("EAP: received EAP-TLS Listen packet with no data");
1850 				/* Bogus request; wait for something real. */
1851 				return;
1852 			}
1853 			GETCHAR(flags, inp);
1854 			if(flags & EAP_TLS_FLAGS_START){
1855 
1856 				esp->es_client.ea_using_eaptls = 1;
1857 
1858 				if (explicit_remote){
1859 					esp->es_client.ea_peer = strdup(remote_name);
1860 					esp->es_client.ea_peerlen = strlen(remote_name);
1861 				} else
1862 					esp->es_client.ea_peer = NULL;
1863 
1864 				/* Init ssl session */
1865 				if(!eaptls_init_ssl_client(esp)) {
1866 					dbglog("cannot init ssl");
1867 					eap_send_nak(esp, id, EAPT_MSCHAPV2);
1868 					esp->es_client.ea_using_eaptls = 0;
1869 					break;
1870 				}
1871 
1872 				ets = esp->es_client.ea_session;
1873 				eap_tls_response(esp, id);
1874 				esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1875 				break;
1876 			}
1877 
1878 			/* The server has sent a bad start packet. */
1879 			eap_send_nak(esp, id, EAPT_MSCHAPV2);
1880 			break;
1881 
1882 		case eapTlsRecvAck:
1883 			eap_tls_response(esp, id);
1884 			esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1885 			break;
1886 
1887 		case eapTlsRecv:
1888 			if (len < 1) {
1889 				error("EAP: discarding EAP-TLS Receive packet with no data");
1890 				/* Bogus request; wait for something real. */
1891 				return;
1892 			}
1893 			eaptls_receive(ets, inp, len);
1894 
1895 			if(ets->frag) {
1896 				eap_tls_sendack(esp, id);
1897 				esp->es_client.ea_state = eapTlsRecv;
1898 				break;
1899 			}
1900 
1901 			if(ets->alert_recv) {
1902 				eap_tls_sendack(esp, id);
1903 				esp->es_client.ea_state = eapTlsRecvFailure;
1904 				break;
1905 			}
1906 
1907 			/* Check if TLS handshake is finished */
1908 			if(eaptls_is_init_finished(ets)) {
1909 #ifdef PPP_WITH_MPPE
1910 				eaptls_gen_mppe_keys(ets, 1);
1911 #endif
1912 				eaptls_free_session(ets);
1913 				eap_tls_sendack(esp, id);
1914 				esp->es_client.ea_state = eapTlsRecvSuccess;
1915 				break;
1916 			}
1917 
1918 			eap_tls_response(esp,id);
1919 			esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1920 			break;
1921 
1922 		default:
1923 			eap_send_nak(esp, id, EAPT_MSCHAPV2);
1924 			esp->es_client.ea_using_eaptls = 0;
1925 			break;
1926 		}
1927 
1928 		break;
1929 #endif /* PPP_WITH_EAPTLS */
1930 
1931 #ifdef PPP_WITH_SRP
1932 	case EAPT_SRP:
1933 		if (len < 1) {
1934 			error("EAP: received empty SRP Request");
1935 			/* Bogus request; wait for something real. */
1936 			return;
1937 		}
1938 
1939 		/* Get subtype */
1940 		GETCHAR(vallen, inp);
1941 		len--;
1942 		switch (vallen) {
1943 		case EAPSRP_CHALLENGE:
1944 			tc = NULL;
1945 			if (esp->es_client.ea_session != NULL) {
1946 				tc = (struct t_client *)esp->es_client.
1947 				    ea_session;
1948 				/*
1949 				 * If this is a new challenge, then start
1950 				 * over with a new client session context.
1951 				 * Otherwise, just resend last response.
1952 				 */
1953 				if (id != esp->es_client.ea_id) {
1954 					t_clientclose(tc);
1955 					esp->es_client.ea_session = NULL;
1956 					tc = NULL;
1957 				}
1958 			}
1959 			/* No session key just yet */
1960 			esp->es_client.ea_skey = NULL;
1961 			if (tc == NULL) {
1962 				GETCHAR(vallen, inp);
1963 				len--;
1964 				if (vallen >= len) {
1965 					error("EAP: badly-formed SRP Challenge"
1966 					    " (name)");
1967 					/* Ignore badly-formed messages */
1968 					return;
1969 				}
1970 				BCOPY(inp, rhostname, vallen);
1971 				rhostname[vallen] = '\0';
1972 				INCPTR(vallen, inp);
1973 				len -= vallen;
1974 
1975 				/*
1976 				 * In case the remote doesn't give us his name,
1977 				 * use configured name.
1978 				 */
1979 				if (explicit_remote ||
1980 				    (remote_name[0] != '\0' && vallen == 0)) {
1981 					strlcpy(rhostname, remote_name,
1982 					    sizeof (rhostname));
1983 				}
1984 
1985 				if (esp->es_client.ea_peer != NULL)
1986 					free(esp->es_client.ea_peer);
1987 				esp->es_client.ea_peer = strdup(rhostname);
1988 				esp->es_client.ea_peerlen = strlen(rhostname);
1989 
1990 				GETCHAR(vallen, inp);
1991 				len--;
1992 				if (vallen >= len) {
1993 					error("EAP: badly-formed SRP Challenge"
1994 					    " (s)");
1995 					/* Ignore badly-formed messages */
1996 					return;
1997 				}
1998 				sval.data = inp;
1999 				sval.len = vallen;
2000 				INCPTR(vallen, inp);
2001 				len -= vallen;
2002 
2003 				GETCHAR(vallen, inp);
2004 				len--;
2005 				if (vallen > len) {
2006 					error("EAP: badly-formed SRP Challenge"
2007 					    " (g)");
2008 					/* Ignore badly-formed messages */
2009 					return;
2010 				}
2011 				/* If no generator present, then use value 2 */
2012 				if (vallen == 0) {
2013 					gval.data = (u_char *)"\002";
2014 					gval.len = 1;
2015 				} else {
2016 					gval.data = inp;
2017 					gval.len = vallen;
2018 				}
2019 				INCPTR(vallen, inp);
2020 				len -= vallen;
2021 
2022 				/*
2023 				 * If no modulus present, then use well-known
2024 				 * value.
2025 				 */
2026 				if (len == 0) {
2027 					Nval.data = (u_char *)wkmodulus;
2028 					Nval.len = sizeof (wkmodulus);
2029 				} else {
2030 					Nval.data = inp;
2031 					Nval.len = len;
2032 				}
2033 				tc = t_clientopen(esp->es_client.ea_name,
2034 				    &Nval, &gval, &sval);
2035 				if (tc == NULL) {
2036 					eap_send_nak(esp, id, EAPT_MD5CHAP);
2037 					break;
2038 				}
2039 				esp->es_client.ea_session = (void *)tc;
2040 
2041 				/* Add Challenge ID & type to verifier */
2042 				vals[0] = id;
2043 				vals[1] = EAPT_SRP;
2044 				t_clientaddexdata(tc, vals, 2);
2045 			}
2046 			Ap = t_clientgenexp(tc);
2047 			eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
2048 			    Ap->len);
2049 			break;
2050 
2051 		case EAPSRP_SKEY:
2052 			tc = (struct t_client *)esp->es_client.ea_session;
2053 			if (tc == NULL) {
2054 				warn("EAP: peer sent Subtype 2 without 1");
2055 				eap_send_nak(esp, id, EAPT_MD5CHAP);
2056 				break;
2057 			}
2058 			if (esp->es_client.ea_skey != NULL) {
2059 				/*
2060 				 * ID number should not change here.  Warn
2061 				 * if it does (but otherwise ignore).
2062 				 */
2063 				if (id != esp->es_client.ea_id) {
2064 					warn("EAP: ID changed from %d to %d "
2065 					    "in SRP Subtype 2 rexmit",
2066 					    esp->es_client.ea_id, id);
2067 				}
2068 			} else {
2069 				if (get_srp_secret(esp->es_unit,
2070 				    esp->es_client.ea_name,
2071 				    esp->es_client.ea_peer, secret, 0) == 0) {
2072 					/*
2073 					 * Can't work with this peer because
2074 					 * the secret is missing.  Just give
2075 					 * up.
2076 					 */
2077 					eap_send_nak(esp, id, EAPT_MD5CHAP);
2078 					break;
2079 				}
2080 				Bval.data = inp;
2081 				Bval.len = len;
2082 				t_clientpasswd(tc, secret);
2083 				BZERO(secret, sizeof (secret));
2084 				esp->es_client.ea_skey =
2085 				    t_clientgetkey(tc, &Bval);
2086 				if (esp->es_client.ea_skey == NULL) {
2087 					/* Server is rogue; stop now */
2088 					error("EAP: SRP server is rogue");
2089 					goto client_failure;
2090 				}
2091 			}
2092 			eap_srpval_response(esp, id, SRPVAL_EBIT,
2093 			    t_clientresponse(tc));
2094 			break;
2095 
2096 		case EAPSRP_SVALIDATOR:
2097 			tc = (struct t_client *)esp->es_client.ea_session;
2098 			if (tc == NULL || esp->es_client.ea_skey == NULL) {
2099 				warn("EAP: peer sent Subtype 3 without 1/2");
2100 				eap_send_nak(esp, id, EAPT_MD5CHAP);
2101 				break;
2102 			}
2103 			/*
2104 			 * If we're already open, then this ought to be a
2105 			 * duplicate.  Otherwise, check that the server is
2106 			 * who we think it is.
2107 			 */
2108 			if (esp->es_client.ea_state == eapOpen) {
2109 				if (id != esp->es_client.ea_id) {
2110 					warn("EAP: ID changed from %d to %d "
2111 					    "in SRP Subtype 3 rexmit",
2112 					    esp->es_client.ea_id, id);
2113 				}
2114 			} else {
2115 				len -= sizeof (u_int32_t) + SHA_DIGEST_LENGTH;
2116 				if (len < 0 || t_clientverify(tc, inp +
2117 					sizeof (u_int32_t)) != 0) {
2118 					error("EAP: SRP server verification "
2119 					    "failed");
2120 					goto client_failure;
2121 				}
2122 				GETLONG(esp->es_client.ea_keyflags, inp);
2123 				/* Save pseudonym if user wants it. */
2124 				if (len > 0 && esp->es_usepseudo) {
2125 					INCPTR(SHA_DIGEST_LENGTH, inp);
2126 					write_pseudonym(esp, inp, len, id);
2127 				}
2128 			}
2129 			/*
2130 			 * We've verified our peer.  We're now mostly done,
2131 			 * except for waiting on the regular EAP Success
2132 			 * message.
2133 			 */
2134 			eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
2135 			break;
2136 
2137 		case EAPSRP_LWRECHALLENGE:
2138 			if (len < 4) {
2139 				warn("EAP: malformed Lightweight rechallenge");
2140 				return;
2141 			}
2142 			ctxt = PPP_MD_CTX_new();
2143 			if (ctxt) {
2144 
2145 				vals[0] = id;
2146 				PPP_DigestInit(ctxt, PPP_sha1());
2147 				PPP_DigestUpdate(ctxt, vals, 1);
2148 				PPP_DigestUpdate(ctxt, esp->es_client.ea_skey,
2149 					SESSION_KEY_LEN);
2150 				PPP_DigestUpdate(ctxt, inp, len);
2151 				PPP_DigestUpdate(ctxt, esp->es_client.ea_name,
2152 					esp->es_client.ea_namelen);
2153 				PPP_DigestFinal(ctxt, dig, &diglen);
2154 
2155 				PPP_MD_CTX_free(ctxt);
2156 
2157 				eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
2158 					SHA_DIGEST_LENGTH);
2159 			}
2160 			break;
2161 
2162 		default:
2163 			error("EAP: unknown SRP Subtype %d", vallen);
2164 			eap_send_nak(esp, id, EAPT_MD5CHAP);
2165 			break;
2166 		}
2167 		break;
2168 #endif /* PPP_WITH_SRP */
2169 
2170 #ifdef PPP_WITH_CHAPMS
2171         case EAPT_MSCHAPV2:
2172 	    if (len < 4) {
2173 		error("EAP: received invalid MSCHAPv2 packet, too short");
2174 		return;
2175 	    }
2176 	    unsigned char opcode;
2177 	    GETCHAR(opcode, inp);
2178 	    unsigned char chapid; /* Chapv2-ID */
2179 	    GETCHAR(chapid, inp);
2180 	    short mssize;
2181 	    GETSHORT(mssize, inp);
2182 
2183 	    /* Validate the mssize field */
2184 	    if (len != mssize) {
2185 		error("EAP: received invalid MSCHAPv2 packet, invalid length");
2186 		return;
2187 	    }
2188 	    len -= 4;
2189 
2190 	    /* If MSCHAPv2 digest was not found, NAK the packet */
2191 	    if (!esp->es_client.digest) {
2192 		error("EAP MSCHAPv2 not supported");
2193 		eap_send_nak(esp, id, EAPT_SRP);
2194 		return;
2195 	    }
2196 
2197 	    switch (opcode) {
2198 	    case CHAP_CHALLENGE: {
2199 
2200 		/* make_response() expects: VLEN + VALUE */
2201 		u_char *challenge = inp;
2202 
2203 		unsigned char vsize;
2204 		GETCHAR(vsize, inp);
2205                 len -= 1;
2206 
2207 		/* Validate the VALUE field */
2208                 if (vsize != MS_CHAP2_PEER_CHAL_LEN || len < MS_CHAP2_PEER_CHAL_LEN) {
2209                     error("EAP: received invalid MSCHAPv2 packet, invalid value-length: %d", vsize);
2210                     return;
2211                 }
2212 
2213 		/* Increment past the VALUE field */
2214 		INCPTR(MS_CHAP2_PEER_CHAL_LEN, inp);
2215 		len -= MS_CHAP2_PEER_CHAL_LEN;
2216 
2217 		/* Extract the hostname */
2218 		rhostname[0] = '\0';
2219 		if (len > 0) {
2220 		    if (len >= sizeof (rhostname)) {
2221 			dbglog("EAP: trimming really long peer name down");
2222 			len = sizeof(rhostname) - 1;
2223 		    }
2224 		    BCOPY(inp, rhostname, len);
2225 		    rhostname[len] = '\0';
2226 		}
2227 
2228 		/* In case the remote doesn't give us his name. */
2229 		if (explicit_remote || (remote_name[0] != '\0' && len == 0))
2230 		    strlcpy(rhostname, remote_name, sizeof(rhostname));
2231 
2232 		/* Get the secret for authenticating ourselves with the specified host. */
2233 		if (!get_secret(esp->es_unit, esp->es_client.ea_name,
2234 		    rhostname, secret, &secret_len, 0)) {
2235 		    dbglog("EAP: no CHAP secret for auth to %q", rhostname);
2236 		    eap_send_nak(esp, id, EAPT_SRP);
2237 		    break;
2238 		}
2239 		esp->es_client.ea_namelen = strlen(esp->es_client.ea_name);
2240 
2241 		/* Create the MSCHAPv2 response (and add to cache) */
2242 		unsigned char response[MS_CHAP2_RESPONSE_LEN+1]; // VLEN + VALUE
2243 		esp->es_client.digest->make_response(response, chapid, esp->es_client.ea_name,
2244 			challenge, secret, secret_len, NULL);
2245 
2246 		eap_chapv2_response(esp, id, chapid, response, esp->es_client.ea_name, esp->es_client.ea_namelen);
2247 		break;
2248 	    }
2249 	    case CHAP_SUCCESS: {
2250 
2251 		/* Check response for mutual authentication */
2252 		u_char status = CHAP_FAILURE;
2253 		if (esp->es_client.digest->check_success(chapid, inp, len) == 1) {
2254 		     info("Chap authentication succeeded! %.*v", len, inp);
2255 		     status = CHAP_SUCCESS;
2256 		}
2257 		eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
2258 		break;
2259 	    }
2260 	    case CHAP_FAILURE: {
2261 
2262 		/* Process the failure string, and log appropriate information */
2263 		esp->es_client.digest->handle_failure(inp, len);
2264 
2265 		u_char status = CHAP_FAILURE;
2266 		eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
2267 		goto client_failure; /* force termination */
2268 	    }
2269 	    default:
2270 
2271                 error("EAP: received invalid MSCHAPv2 packet, invalid or unsupported opcode: %d", opcode);
2272 		eap_send_nak(esp, id, EAPT_SRP);
2273 	    }
2274 
2275 	    break;
2276 #endif /* PPP_WITH_CHAPMS */
2277 #ifdef PPP_WITH_PEAP
2278 	case EAPT_PEAP:
2279 
2280 		/* Initialize the PEAP context (if not already initialized) */
2281 		if (!esp->ea_peap) {
2282 			rhostname[0] = '\0';
2283 			if (explicit_remote || (remote_name[0] != '\0')) {
2284 				strlcpy(rhostname, remote_name, sizeof (rhostname));
2285 			}
2286 			if (peap_init(&esp->ea_peap, rhostname)) {
2287 				eap_send_nak(esp, id, EAPT_TLS);
2288 				break;
2289 			}
2290 		}
2291 
2292 		/* Process the PEAP packet */
2293 		if (peap_process(esp, id, inp, len)) {
2294 			eap_send_nak(esp, id, EAPT_TLS);
2295 		}
2296 
2297 		break;
2298 #endif // PPP_WITH_PEAP
2299 
2300 	default:
2301 		info("EAP: unknown authentication type %d; Naking", typenum);
2302 		eap_send_nak(esp, id, EAPT_SRP);
2303 		break;
2304 	}
2305 
2306 	if (esp->es_client.ea_timeout > 0) {
2307 		UNTIMEOUT(eap_client_timeout, (void *)esp);
2308 		TIMEOUT(eap_client_timeout, (void *)esp,
2309 		    esp->es_client.ea_timeout);
2310 	}
2311 	return;
2312 
2313 client_failure:
2314 	esp->es_client.ea_state = eapBadAuth;
2315 	if (esp->es_client.ea_timeout > 0) {
2316 		UNTIMEOUT(eap_client_timeout, (void *)esp);
2317 	}
2318 	esp->es_client.ea_session = NULL;
2319 #ifdef PPP_WITH_SRP
2320 	t_clientclose(tc);
2321 	auth_withpeer_fail(esp->es_unit, PPP_EAP);
2322 #endif /* PPP_WITH_SRP */
2323 }
2324 
2325 /*
2326  * eap_response - Receive EAP Response message (server mode).
2327  */
2328 static void
2329 eap_response(eap_state *esp, u_char *inp, int id, int len)
2330 {
2331 	u_char typenum;
2332 	u_char vallen;
2333 	int secret_len;
2334 	char secret[MAXSECRETLEN];
2335 	char rhostname[256];
2336 	PPP_MD_CTX *mdctx;
2337 	u_char hash[MD5_DIGEST_LENGTH];
2338 	int hashlen = MD5_DIGEST_LENGTH;
2339 #ifdef PPP_WITH_SRP
2340 	struct t_server *ts;
2341 	struct t_num A;
2342 	PPP_MD_CTX *ctxt;
2343 	u_char dig[SHA_DIGEST_LENGTH];
2344 	int diglen = sizeof(dig);
2345 #endif /* PPP_WITH_SRP */
2346 
2347 #ifdef PPP_WITH_EAPTLS
2348 	struct eaptls_session *ets;
2349 	u_char flags;
2350 #endif /* PPP_WITH_EAPTLS */
2351 #ifdef PPP_WITH_CHAPMS
2352 	u_char opcode;
2353         chap_verify_hook_fn *chap_verifier;
2354 	char response_message[256];
2355 #endif /* PPP_WITH_CHAPMS */
2356 
2357 	/*
2358 	 * Ignore responses if we're not open
2359 	 */
2360 	if (esp->es_server.ea_state <= eapClosed)
2361 		return;
2362 
2363 	if (esp->es_server.ea_id != id) {
2364 		dbglog("EAP: discarding Response %d; expected ID %d", id,
2365 		    esp->es_server.ea_id);
2366 		return;
2367 	}
2368 
2369 	esp->es_server.ea_responses++;
2370 
2371 	if (len <= 0) {
2372 		error("EAP: empty Response message discarded");
2373 		return;
2374 	}
2375 
2376 	GETCHAR(typenum, inp);
2377 	len--;
2378 
2379 	switch (typenum) {
2380 	case EAPT_IDENTITY:
2381 		if (esp->es_server.ea_state != eapIdentify) {
2382 			dbglog("EAP discarding unwanted Identify \"%.q\"", len,
2383 			    inp);
2384 			break;
2385 		}
2386 		info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
2387 		if (esp->es_server.ea_peer != NULL &&
2388 		    esp->es_server.ea_peer != remote_name)
2389 			free(esp->es_server.ea_peer);
2390 		esp->es_server.ea_peer = malloc(len + 1);
2391 		if (esp->es_server.ea_peer == NULL) {
2392 			esp->es_server.ea_peerlen = 0;
2393 			eap_figure_next_state(esp, 1);
2394 			break;
2395 		}
2396 		BCOPY(inp, esp->es_server.ea_peer, len);
2397 		esp->es_server.ea_peer[len] = '\0';
2398 		esp->es_server.ea_peerlen = len;
2399 		eap_figure_next_state(esp, 0);
2400 		break;
2401 
2402 #ifdef PPP_WITH_EAPTLS
2403 	case EAPT_TLS:
2404 		switch(esp->es_server.ea_state) {
2405 
2406 		case eapTlsRecv:
2407 
2408 			ets = (struct eaptls_session *) esp->es_server.ea_session;
2409 
2410 			eap_figure_next_state(esp,
2411 				eaptls_receive(esp->es_server.ea_session, inp, len));
2412 
2413 			if(ets->alert_recv) {
2414 				eap_send_failure(esp);
2415 				break;
2416 			}
2417 			break;
2418 
2419 		case eapTlsRecvAck:
2420 			if(len > 1) {
2421 				dbglog("EAP-TLS ACK with extra data");
2422 			}
2423 			eap_figure_next_state(esp, 0);
2424 			break;
2425 
2426 		case eapTlsRecvClient:
2427 			/* Receive authentication response from client */
2428 			if (len > 0) {
2429 				GETCHAR(flags, inp);
2430 
2431 				if(len == 1 && !flags) {	/* Ack = ok */
2432 #ifdef PPP_WITH_MPPE
2433 					eaptls_gen_mppe_keys( esp->es_server.ea_session, 0 );
2434 #endif
2435 					eap_send_success(esp);
2436 				}
2437 				else {			/* failure */
2438 					warn("Server authentication failed");
2439 					eap_send_failure(esp);
2440 				}
2441 			}
2442 			else
2443 				warn("Bogus EAP-TLS packet received from client");
2444 
2445 			eaptls_free_session(esp->es_server.ea_session);
2446 
2447 			break;
2448 
2449 		case eapTlsRecvAlertAck:
2450 			eap_send_failure(esp);
2451 			break;
2452 
2453 		default:
2454 			eap_figure_next_state(esp, 1);
2455 			break;
2456 		}
2457 		break;
2458 #endif /* PPP_WITH_EAPTLS */
2459 
2460 	case EAPT_NOTIFICATION:
2461 		dbglog("EAP unexpected Notification; response discarded");
2462 		break;
2463 
2464 	case EAPT_NAK:
2465 		if (len < 1) {
2466 			info("EAP: Nak Response with no suggested protocol");
2467 			eap_figure_next_state(esp, 1);
2468 			break;
2469 		}
2470 
2471 		GETCHAR(vallen, inp);
2472 		len--;
2473 
2474 		if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
2475 			/* Peer cannot Nak Identify Request */
2476 			eap_figure_next_state(esp, 1);
2477 			break;
2478 		}
2479 
2480 		switch (vallen) {
2481 		case EAPT_SRP:
2482 			/* Run through SRP validator selection again. */
2483 			esp->es_server.ea_state = eapIdentify;
2484 			eap_figure_next_state(esp, 0);
2485 			break;
2486 
2487 		case EAPT_MD5CHAP:
2488 			esp->es_server.ea_state = eapMD5Chall;
2489 			break;
2490 
2491 #ifdef PPP_WITH_EAPTLS
2492 			/* Send EAP-TLS start packet */
2493 		case EAPT_TLS:
2494 			esp->es_server.ea_state = eapTlsStart;
2495 			break;
2496 #endif /* PPP_WITH_EAPTLS */
2497 
2498 #ifdef PPP_WITH_CHAPMS
2499 		case EAPT_MSCHAPV2:
2500 			info("EAP: peer proposes MSCHAPv2");
2501 			/* If MSCHAPv2 digest was not found, NAK the packet */
2502 			if (!esp->es_server.digest) {
2503 				error("EAP MSCHAPv2 not supported");
2504 				eap_send_nak(esp, id, EAPT_SRP);
2505 				break;
2506 			}
2507 			esp->es_server.ea_state = eapMSCHAPv2Chall;
2508 			break;
2509 #endif /* PPP_WITH_CHAPMS */
2510 
2511 		default:
2512 			dbglog("EAP: peer requesting unknown Type %d", vallen);
2513 			switch (esp->es_server.ea_state) {
2514 			case eapSRP1:
2515 			case eapSRP2:
2516 			case eapSRP3:
2517 				esp->es_server.ea_state = eapMD5Chall;
2518 				break;
2519 			case eapMD5Chall:
2520 			case eapSRP4:
2521 				esp->es_server.ea_state = eapIdentify;
2522 				eap_figure_next_state(esp, 0);
2523 				break;
2524 			default:
2525 				break;
2526 			}
2527 			break;
2528 		}
2529 		break;
2530 
2531 	case EAPT_MD5CHAP:
2532 		if (esp->es_server.ea_state != eapMD5Chall) {
2533 			error("EAP: unexpected MD5-Response");
2534 			eap_figure_next_state(esp, 1);
2535 			break;
2536 		}
2537 		if (len < 1) {
2538 			error("EAP: received MD5-Response with no data");
2539 			eap_figure_next_state(esp, 1);
2540 			break;
2541 		}
2542 		GETCHAR(vallen, inp);
2543 		len--;
2544 		if (vallen != 16 || vallen > len) {
2545 			error("EAP: MD5-Response with bad length %d", vallen);
2546 			eap_figure_next_state(esp, 1);
2547 			break;
2548 		}
2549 
2550 		/* Not so likely to happen. */
2551 		if (len - vallen >= sizeof (rhostname)) {
2552 			dbglog("EAP: trimming really long peer name down");
2553 			BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2554 			rhostname[sizeof (rhostname) - 1] = '\0';
2555 		} else {
2556 			BCOPY(inp + vallen, rhostname, len - vallen);
2557 			rhostname[len - vallen] = '\0';
2558 		}
2559 
2560 		/* In case the remote doesn't give us his name. */
2561 		if (explicit_remote ||
2562 		    (remote_name[0] != '\0' && vallen == len))
2563 			strlcpy(rhostname, remote_name, sizeof (rhostname));
2564 
2565 		/*
2566 		 * Get the secret for authenticating the specified
2567 		 * host.
2568 		 */
2569 		if (!get_secret(esp->es_unit, rhostname,
2570 		    esp->es_server.ea_name, secret, &secret_len, 1)) {
2571 			dbglog("EAP: no MD5 secret for auth of %q", rhostname);
2572 			eap_send_failure(esp);
2573 			break;
2574 		}
2575 
2576 		mdctx = PPP_MD_CTX_new();
2577 		if (mdctx != NULL) {
2578 
2579 			if (PPP_DigestInit(mdctx, PPP_md5())) {
2580 
2581 				if (PPP_DigestUpdate(mdctx, &esp->es_server.ea_id, 1)) {
2582 
2583 					if (PPP_DigestUpdate(mdctx, &secret, secret_len)) {
2584 
2585 						BZERO(secret, sizeof(secret));
2586 						if (PPP_DigestUpdate(mdctx, esp->es_challenge, esp->es_challen)) {
2587 
2588 							if (PPP_DigestFinal(mdctx, hash, &hashlen)) {
2589 
2590 								if (BCMP(hash, inp, MD5_DIGEST_LENGTH) == 0) {
2591 									esp->es_server.ea_type = EAPT_MD5CHAP;
2592 									eap_send_success(esp);
2593 									eap_figure_next_state(esp, 0);
2594 
2595 									if (esp->es_rechallenge != 0) {
2596 										TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2597 									}
2598 									PPP_MD_CTX_free(mdctx);
2599 									break;
2600 								}
2601 							}
2602 						}
2603 					}
2604 				}
2605 			}
2606 
2607 			PPP_MD_CTX_free(mdctx);
2608 		}
2609 
2610 		eap_send_failure(esp);
2611 		break;
2612 
2613 #ifdef PPP_WITH_CHAPMS
2614 	case EAPT_MSCHAPV2:
2615 		if (len < 1) {
2616 			error("EAP: received MSCHAPv2 with no data");
2617 			eap_figure_next_state(esp, 1);
2618 			break;
2619 		}
2620 		GETCHAR(opcode, inp);
2621 		len--;
2622 
2623 		switch (opcode) {
2624 		case CHAP_RESPONSE:
2625 			if (esp->es_server.ea_state != eapMSCHAPv2Chall) {
2626 				error("EAP: unexpected MSCHAPv2-Response");
2627 				eap_figure_next_state(esp, 1);
2628 				break;
2629 			}
2630 			/* skip MS ID + len */
2631 			INCPTR(3, inp);
2632 			GETCHAR(vallen, inp);
2633 			len -= 4;
2634 
2635 			if (vallen != MS_CHAP2_RESPONSE_LEN || vallen > len) {
2636 				error("EAP: Invalid MSCHAPv2-Response "
2637 						"length %d", vallen);
2638 				eap_figure_next_state(esp, 1);
2639 				break;
2640 			}
2641 
2642 			/* Not so likely to happen. */
2643 			if (len - vallen >= sizeof (rhostname)) {
2644 				dbglog("EAP: trimming really long peer name down");
2645 				BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2646 				rhostname[sizeof (rhostname) - 1] = '\0';
2647 			} else {
2648 				BCOPY(inp + vallen, rhostname, len - vallen);
2649 				rhostname[len - vallen] = '\0';
2650 			}
2651 
2652 			/* In case the remote doesn't give us his name. */
2653 			if (explicit_remote ||
2654 					(remote_name[0] != '\0' && vallen == len))
2655 				strlcpy(rhostname, remote_name, sizeof (rhostname));
2656 
2657 			/* strip the MS domain name */
2658 			if (chapms_strip_domain && strrchr(rhostname, '\\')) {
2659 				char tmp[MAXNAMELEN+1];
2660 
2661 				strcpy(tmp, strrchr(rhostname, '\\') + 1);
2662 				strlcpy(rhostname, tmp, sizeof(rhostname));
2663 			}
2664 
2665 			if (chap_verify_hook)
2666 				chap_verifier = chap_verify_hook;
2667 			else
2668 				chap_verifier = eap_chap_verify_response;
2669 
2670 			esp->es_server.ea_id += 1;
2671 			if ((*chap_verifier)(rhostname,
2672 						esp->es_server.ea_name,
2673 						id,
2674 						esp->es_server.digest,
2675 						esp->es_challenge,
2676 						inp - 1,
2677 						response_message,
2678 						sizeof(response_message)))
2679 			{
2680 				info("EAP: MSCHAPv2 success for peer %q",
2681 						rhostname);
2682 				esp->es_server.ea_type = EAPT_MSCHAPV2;
2683 				eap_chapms2_send_request(esp,
2684 						esp->es_server.ea_id,
2685 						CHAP_SUCCESS,
2686 						esp->es_server.ea_id,
2687 						response_message,
2688 						strlen(response_message));
2689 				eap_figure_next_state(esp, 0);
2690 				if (esp->es_rechallenge != 0)
2691 					TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2692 			}
2693 			else {
2694 				warn("EAP: MSCHAPv2 failure for peer %q",
2695 						rhostname);
2696 				eap_chapms2_send_request(esp,
2697 						esp->es_server.ea_id,
2698 						CHAP_FAILURE,
2699 						esp->es_server.ea_id,
2700 						response_message,
2701 						strlen(response_message));
2702 			}
2703 			break;
2704 		case CHAP_SUCCESS:
2705 			info("EAP: MSCHAPv2 success confirmed");
2706 			break;
2707 		case CHAP_FAILURE:
2708 			info("EAP: MSCHAPv2 failure confirmed");
2709 			break;
2710 		default:
2711 			error("EAP: Unhandled MSCHAPv2 opcode %d", opcode);
2712 			eap_send_nak(esp, id, EAPT_SRP);
2713 		}
2714 
2715 		break;
2716 #endif /* PPP_WITH_CHAPMS */
2717 
2718 #ifdef PPP_WITH_SRP
2719 	case EAPT_SRP:
2720 		if (len < 1) {
2721 			error("EAP: empty SRP Response");
2722 			eap_figure_next_state(esp, 1);
2723 			break;
2724 		}
2725 		GETCHAR(typenum, inp);
2726 		len--;
2727 		switch (typenum) {
2728 		case EAPSRP_CKEY:
2729 			if (esp->es_server.ea_state != eapSRP1) {
2730 				error("EAP: unexpected SRP Subtype 1 Response");
2731 				eap_figure_next_state(esp, 1);
2732 				break;
2733 			}
2734 			A.data = inp;
2735 			A.len = len;
2736 			ts = (struct t_server *)esp->es_server.ea_session;
2737 			assert(ts != NULL);
2738 			esp->es_server.ea_skey = t_servergetkey(ts, &A);
2739 			if (esp->es_server.ea_skey == NULL) {
2740 				/* Client's A value is bogus; terminate now */
2741 				error("EAP: bogus A value from client");
2742 				eap_send_failure(esp);
2743 			} else {
2744 				eap_figure_next_state(esp, 0);
2745 			}
2746 			break;
2747 
2748 		case EAPSRP_CVALIDATOR:
2749 			if (esp->es_server.ea_state != eapSRP2) {
2750 				error("EAP: unexpected SRP Subtype 2 Response");
2751 				eap_figure_next_state(esp, 1);
2752 				break;
2753 			}
2754 			if (len < sizeof (u_int32_t) + SHA_DIGEST_LENGTH) {
2755 				error("EAP: M1 length %d < %d", len,
2756 				    sizeof (u_int32_t) + SHA_DIGEST_LENGTH);
2757 				eap_figure_next_state(esp, 1);
2758 				break;
2759 			}
2760 			GETLONG(esp->es_server.ea_keyflags, inp);
2761 			ts = (struct t_server *)esp->es_server.ea_session;
2762 			assert(ts != NULL);
2763 			if (t_serververify(ts, inp)) {
2764 				info("EAP: unable to validate client identity");
2765 				eap_send_failure(esp);
2766 				break;
2767 			}
2768 			eap_figure_next_state(esp, 0);
2769 			break;
2770 
2771 		case EAPSRP_ACK:
2772 			if (esp->es_server.ea_state != eapSRP3) {
2773 				error("EAP: unexpected SRP Subtype 3 Response");
2774 				eap_send_failure(esp);
2775 				break;
2776 			}
2777 			esp->es_server.ea_type = EAPT_SRP;
2778 			eap_send_success(esp);
2779 			eap_figure_next_state(esp, 0);
2780 			if (esp->es_rechallenge != 0)
2781 				TIMEOUT(eap_rechallenge, esp,
2782 				    esp->es_rechallenge);
2783 			if (esp->es_lwrechallenge != 0)
2784 				TIMEOUT(srp_lwrechallenge, esp,
2785 				    esp->es_lwrechallenge);
2786 			break;
2787 
2788 		case EAPSRP_LWRECHALLENGE:
2789 			if (esp->es_server.ea_state != eapSRP4) {
2790 				info("EAP: unexpected SRP Subtype 4 Response");
2791 				return;
2792 			}
2793 			if (len != SHA_DIGEST_LENGTH) {
2794 				error("EAP: bad Lightweight rechallenge "
2795 				    "response");
2796 				return;
2797 			}
2798 			ctxt = PPP_MD_CTX_new();
2799 			if (ctxt) {
2800 				vallen = id;
2801 
2802 				PPP_DigestInit(ctxt, PPP_sha1());
2803 				PPP_DigestUpdate(ctxt, &vallen, 1);
2804 				PPP_DigestUpdate(ctxt, esp->es_server.ea_skey,
2805 					SESSION_KEY_LEN);
2806 				PPP_DigestUpdate(ctxt, esp->es_challenge, esp->es_challen);
2807 				PPP_DigestUpdate(ctxt, esp->es_server.ea_peer,
2808 					esp->es_server.ea_peerlen);
2809 				PPP_DigestFinal(ctxt, dig, &diglen);
2810 
2811 				PPP_MD_CTX_free(ctxt);
2812 
2813 				if (BCMP(dig, inp, SHA_DIGEST_LENGTH) != 0) {
2814 					error("EAP: failed Lightweight rechallenge");
2815 					eap_send_failure(esp);
2816 					break;
2817 				}
2818 
2819 				esp->es_server.ea_state = eapOpen;
2820 				if (esp->es_lwrechallenge != 0)
2821 					TIMEOUT(srp_lwrechallenge, esp,
2822 						esp->es_lwrechallenge);
2823 			}
2824 			break;
2825 		}
2826 		break;
2827 #endif /* PPP_WITH_SRP */
2828 
2829 	default:
2830 		/* This can't happen. */
2831 		error("EAP: unknown Response type %d; ignored", typenum);
2832 		return;
2833 	}
2834 
2835 	if (esp->es_server.ea_timeout > 0) {
2836 		UNTIMEOUT(eap_server_timeout, (void *)esp);
2837 	}
2838 
2839 	if (esp->es_server.ea_state != eapBadAuth &&
2840 	    esp->es_server.ea_state != eapOpen) {
2841 		esp->es_server.ea_id++;
2842 		eap_send_request(esp);
2843 	}
2844 }
2845 
2846 /*
2847  * eap_success - Receive EAP Success message (client mode).
2848  */
2849 static void
2850 eap_success(eap_state *esp, u_char *inp, int id, int len)
2851 {
2852 	if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
2853 #ifdef PPP_WITH_EAPTLS
2854 		&& esp->es_client.ea_state != eapTlsRecvSuccess
2855 #endif /* PPP_WITH_EAPTLS */
2856 		) {
2857 		dbglog("EAP unexpected success message in state %s (%d)",
2858 		    eap_state_name(esp->es_client.ea_state),
2859 		    esp->es_client.ea_state);
2860 		return;
2861 	}
2862 
2863 #ifdef PPP_WITH_EAPTLS
2864 	if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state !=
2865 		eapTlsRecvSuccess) {
2866 		dbglog("EAP-TLS unexpected success message in state %s (%d)",
2867                     eap_state_name(esp->es_client.ea_state),
2868                     esp->es_client.ea_state);
2869 		return;
2870 	}
2871 #endif /* PPP_WITH_EAPTLS */
2872 
2873 	if (esp->es_client.ea_timeout > 0) {
2874 		UNTIMEOUT(eap_client_timeout, (void *)esp);
2875 	}
2876 
2877 	if (len > 0) {
2878 		/* This is odd.  The spec doesn't allow for this. */
2879 		PRINTMSG(inp, len);
2880 	}
2881 
2882 #ifdef PPP_WITH_PEAP
2883 	peap_finish(&esp->ea_peap);
2884 #endif
2885 
2886 	esp->es_client.ea_state = eapOpen;
2887 	auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2888 }
2889 
2890 /*
2891  * eap_failure - Receive EAP Failure message (client mode).
2892  */
2893 static void
2894 eap_failure(eap_state *esp, u_char *inp, int id, int len)
2895 {
2896 	/*
2897 	 * Ignore failure messages if we're not open
2898 	 */
2899 	if (esp->es_client.ea_state <= eapClosed)
2900 		return;
2901 
2902 	if (!eap_client_active(esp)) {
2903 		dbglog("EAP unexpected failure message in state %s (%d)",
2904 		    eap_state_name(esp->es_client.ea_state),
2905 		    esp->es_client.ea_state);
2906 	}
2907 
2908 	if (esp->es_client.ea_timeout > 0) {
2909 		UNTIMEOUT(eap_client_timeout, (void *)esp);
2910 	}
2911 
2912 	if (len > 0) {
2913 		/* This is odd.  The spec doesn't allow for this. */
2914 		PRINTMSG(inp, len);
2915 	}
2916 
2917 	esp->es_client.ea_state = eapBadAuth;
2918 
2919 	error("EAP: peer reports authentication failure");
2920 
2921 #ifdef PPP_WITH_PEAP
2922 	peap_finish(&esp->ea_peap);
2923 #endif
2924 
2925 	auth_withpeer_fail(esp->es_unit, PPP_EAP);
2926 }
2927 
2928 /*
2929  * eap_input - Handle received EAP message.
2930  */
2931 static void
2932 eap_input(int unit, u_char *inp, int inlen)
2933 {
2934 	eap_state *esp = &eap_states[unit];
2935 	u_char code, id;
2936 	int len;
2937 
2938 	/*
2939 	 * Parse header (code, id and length).  If packet too short,
2940 	 * drop it.
2941 	 */
2942 	if (inlen < EAP_HEADERLEN) {
2943 		error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2944 		return;
2945 	}
2946 	GETCHAR(code, inp);
2947 	GETCHAR(id, inp);
2948 	GETSHORT(len, inp);
2949 	if (len < EAP_HEADERLEN || len > inlen) {
2950 		error("EAP: packet has illegal length field %d (%d..%d)", len,
2951 		    EAP_HEADERLEN, inlen);
2952 		return;
2953 	}
2954 	len -= EAP_HEADERLEN;
2955 
2956 	/* Dispatch based on message code */
2957 	switch (code) {
2958 	case EAP_REQUEST:
2959 		eap_request(esp, inp, id, len);
2960 		break;
2961 
2962 	case EAP_RESPONSE:
2963 		eap_response(esp, inp, id, len);
2964 		break;
2965 
2966 	case EAP_SUCCESS:
2967 		eap_success(esp, inp, id, len);
2968 		break;
2969 
2970 	case EAP_FAILURE:
2971 		eap_failure(esp, inp, id, len);
2972 		break;
2973 
2974 	default:				/* XXX Need code reject */
2975 		/* Note: it's not legal to send EAP Nak here. */
2976 		warn("EAP: unknown code %d received", code);
2977 		break;
2978 	}
2979 }
2980 
2981 /*
2982  * eap_printpkt - print the contents of an EAP packet.
2983  */
2984 static char *eap_codenames[] = {
2985 	"Request", "Response", "Success", "Failure"
2986 };
2987 
2988 static char *eap_typenames[] = {
2989 	"Identity", "Notification", "Nak", "MD5-Challenge",
2990 	"OTP", "Generic-Token", NULL, NULL,
2991 	"RSA", "DSS", "KEA", "KEA-Validate",
2992 	"TLS", "Defender", "Windows 2000", "Arcot",
2993 	"Cisco", "Nokia", "SRP", NULL,
2994 	"TTLS", "RAS", "AKA", "3COM", "PEAP",
2995 	"MSCHAPv2"
2996 };
2997 
2998 static int
2999 eap_printpkt(u_char *inp, int inlen,
3000 	     void (*printer) (void *, char *, ...), void *arg)
3001 {
3002 	int code, id, len, rtype, vallen;
3003 	u_char *pstart;
3004 #ifdef PPP_WITH_SRP
3005 	u_int32_t uval;
3006 #endif /* PPP_WITH_SRP */
3007 #ifdef PPP_WITH_EAPTLS
3008 	u_char flags;
3009 #endif /* PPP_WITH_EAPTLS */
3010 #ifdef PPP_WITH_CHAPMS
3011 	u_char opcode;
3012 #endif /* PPP_WITH_CHAPMS */
3013 
3014 	if (inlen < EAP_HEADERLEN)
3015 		return (0);
3016 	pstart = inp;
3017 	GETCHAR(code, inp);
3018 	GETCHAR(id, inp);
3019 	GETSHORT(len, inp);
3020 	if (len < EAP_HEADERLEN || len > inlen)
3021 		return (0);
3022 
3023 	if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
3024 		printer(arg, " %s", eap_codenames[code-1]);
3025 	else
3026 		printer(arg, " code=0x%x", code);
3027 	printer(arg, " id=0x%x", id);
3028 	len -= EAP_HEADERLEN;
3029 	switch (code) {
3030 	case EAP_REQUEST:
3031 		if (len < 1) {
3032 			printer(arg, " <missing type>");
3033 			break;
3034 		}
3035 		GETCHAR(rtype, inp);
3036 		len--;
3037 		if (rtype >= 1 &&
3038 		    rtype <= sizeof (eap_typenames) / sizeof (char *))
3039 			printer(arg, " %s", eap_typenames[rtype-1]);
3040 		else
3041 			printer(arg, " type=0x%x", rtype);
3042 		switch (rtype) {
3043 		case EAPT_IDENTITY:
3044 		case EAPT_NOTIFICATION:
3045 			if (len > 0) {
3046 				printer(arg, " <Message ");
3047 				print_string((char *)inp, len, printer, arg);
3048 				printer(arg, ">");
3049 				INCPTR(len, inp);
3050 				len = 0;
3051 			} else {
3052 				printer(arg, " <No message>");
3053 			}
3054 			break;
3055 
3056 		case EAPT_MD5CHAP:
3057 			if (len <= 0)
3058 				break;
3059 			GETCHAR(vallen, inp);
3060 			len--;
3061 			if (vallen > len)
3062 				goto truncated;
3063 			printer(arg, " <Value%.*B>", vallen, inp);
3064 			INCPTR(vallen, inp);
3065 			len -= vallen;
3066 			if (len > 0) {
3067 				printer(arg, " <Name ");
3068 				print_string((char *)inp, len, printer, arg);
3069 				printer(arg, ">");
3070 				INCPTR(len, inp);
3071 				len = 0;
3072 			} else {
3073 				printer(arg, " <No name>");
3074 			}
3075 			break;
3076 
3077 #ifdef PPP_WITH_CHAPMS
3078 		case EAPT_MSCHAPV2:
3079 			if (len <= 0)
3080 				break;
3081 			GETCHAR(opcode, inp);
3082 			len--;
3083 			switch (opcode) {
3084 			case CHAP_CHALLENGE:
3085 				INCPTR(3, inp);
3086 				len -= 3;
3087 				GETCHAR(vallen, inp);
3088 				len--;
3089 				if (vallen > len)
3090 					goto truncated;
3091 				len -= vallen;
3092 				printer(arg, " Challenge <");
3093 				for (; vallen > 0; --vallen) {
3094 					u_char val;
3095 					GETCHAR(val, inp);
3096 					printer(arg, "%.2x", val);
3097 				}
3098 				printer(arg, ">");
3099 				if (len > 0) {
3100 					printer(arg, ", <Name ");
3101 					print_string((char *)inp, len, printer, arg);
3102 					printer(arg, ">");
3103 					INCPTR(len, inp);
3104 					len = 0;
3105 				} else {
3106 					printer(arg, ", <No name>");
3107 				}
3108 				break;
3109 			case CHAP_SUCCESS:
3110 				INCPTR(3, inp);
3111 				len -= 3;
3112 				printer(arg, " Success <Message ");
3113 				print_string((char *)inp, len, printer, arg);
3114 				printer(arg, ">");
3115 				break;
3116 			case CHAP_FAILURE:
3117 				INCPTR(3, inp);
3118 				len -= 3;
3119 				printer(arg, " Failure <Message ");
3120 				print_string((char *)inp, len, printer, arg);
3121 				printer(arg, ">");
3122 				break;
3123 			default:
3124 				INCPTR(3, inp);
3125 				len -= 3;
3126 				printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
3127 				break;
3128 			}
3129 			break;
3130 #endif /* PPP_WITH_CHAPMS */
3131 
3132 #ifdef PPP_WITH_EAPTLS
3133 		case EAPT_TLS:
3134 			if (len < 1)
3135 				break;
3136 			GETCHAR(flags, inp);
3137 			len--;
3138 
3139                         if(flags == 0 && len == 0){
3140                                 printer(arg, " Ack");
3141                                 break;
3142                         }
3143 
3144 			printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
3145 			printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
3146 			printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
3147 			break;
3148 #endif /* PPP_WITH_EAPTLS */
3149 
3150 #ifdef PPP_WITH_SRP
3151 		case EAPT_SRP:
3152 			if (len < 3)
3153 				goto truncated;
3154 			GETCHAR(vallen, inp);
3155 			len--;
3156 			printer(arg, "-%d", vallen);
3157 			switch (vallen) {
3158 			case EAPSRP_CHALLENGE:
3159 				GETCHAR(vallen, inp);
3160 				len--;
3161 				if (vallen >= len)
3162 					goto truncated;
3163 				if (vallen > 0) {
3164 					printer(arg, " <Name ");
3165 					print_string((char *)inp, vallen, printer,
3166 					    arg);
3167 					printer(arg, ">");
3168 				} else {
3169 					printer(arg, " <No name>");
3170 				}
3171 				INCPTR(vallen, inp);
3172 				len -= vallen;
3173 				GETCHAR(vallen, inp);
3174 				len--;
3175 				if (vallen >= len)
3176 					goto truncated;
3177 				printer(arg, " <s%.*B>", vallen, inp);
3178 				INCPTR(vallen, inp);
3179 				len -= vallen;
3180 				GETCHAR(vallen, inp);
3181 				len--;
3182 				if (vallen > len)
3183 					goto truncated;
3184 				if (vallen == 0) {
3185 					printer(arg, " <Default g=2>");
3186 				} else {
3187 					printer(arg, " <g%.*B>", vallen, inp);
3188 				}
3189 				INCPTR(vallen, inp);
3190 				len -= vallen;
3191 				if (len == 0) {
3192 					printer(arg, " <Default N>");
3193 				} else {
3194 					printer(arg, " <N%.*B>", len, inp);
3195 					INCPTR(len, inp);
3196 					len = 0;
3197 				}
3198 				break;
3199 
3200 			case EAPSRP_SKEY:
3201 				printer(arg, " <B%.*B>", len, inp);
3202 				INCPTR(len, inp);
3203 				len = 0;
3204 				break;
3205 
3206 			case EAPSRP_SVALIDATOR:
3207 				if (len < sizeof (u_int32_t))
3208 					break;
3209 				GETLONG(uval, inp);
3210 				len -= sizeof (u_int32_t);
3211 				if (uval & SRPVAL_EBIT) {
3212 					printer(arg, " E");
3213 					uval &= ~SRPVAL_EBIT;
3214 				}
3215 				if (uval != 0) {
3216 					printer(arg, " f<%X>", uval);
3217 				}
3218 				if ((vallen = len) > SHA_DIGEST_LENGTH)
3219 					vallen = SHA_DIGEST_LENGTH;
3220 				printer(arg, " <M2%.*B%s>", len, inp,
3221 				    len < SHA_DIGEST_LENGTH ? "?" : "");
3222 				INCPTR(vallen, inp);
3223 				len -= vallen;
3224 				if (len > 0) {
3225 					printer(arg, " <PN%.*B>", len, inp);
3226 					INCPTR(len, inp);
3227 					len = 0;
3228 				}
3229 				break;
3230 
3231 			case EAPSRP_LWRECHALLENGE:
3232 				printer(arg, " <Challenge%.*B>", len, inp);
3233 				INCPTR(len, inp);
3234 				len = 0;
3235 				break;
3236 			}
3237 			break;
3238 #endif  /* PPP_WITH_SRP */
3239 		}
3240 		break;
3241 
3242 	case EAP_RESPONSE:
3243 		if (len < 1)
3244 			break;
3245 		GETCHAR(rtype, inp);
3246 		len--;
3247 		if (rtype >= 1 &&
3248 		    rtype <= sizeof (eap_typenames) / sizeof (char *))
3249 			printer(arg, " %s", eap_typenames[rtype-1]);
3250 		else
3251 			printer(arg, " type=0x%x", rtype);
3252 		switch (rtype) {
3253 		case EAPT_IDENTITY:
3254 			if (len > 0) {
3255 				printer(arg, " <Name ");
3256 				print_string((char *)inp, len, printer, arg);
3257 				printer(arg, ">");
3258 				INCPTR(len, inp);
3259 				len = 0;
3260 			}
3261 			break;
3262 
3263 #ifdef PPP_WITH_EAPTLS
3264 		case EAPT_TLS:
3265 			if (len < 1)
3266 				break;
3267 			GETCHAR(flags, inp);
3268 			len--;
3269 
3270                         if(flags == 0 && len == 0){
3271                                 printer(arg, " Ack");
3272                                 break;
3273                         }
3274 
3275 			printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
3276 			printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
3277 			printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
3278 
3279 			break;
3280 #endif /* PPP_WITH_EAPTLS */
3281 
3282 		case EAPT_NAK:
3283 			if (len <= 0) {
3284 				printer(arg, " <missing hint>");
3285 				break;
3286 			}
3287 			GETCHAR(rtype, inp);
3288 			len--;
3289 			printer(arg, " <Suggested-type %02X", rtype);
3290 			if (rtype >= 1 &&
3291 			    rtype <= sizeof (eap_typenames) / sizeof (char *))
3292 				printer(arg, " (%s)", eap_typenames[rtype-1]);
3293 			printer(arg, ">");
3294 			break;
3295 
3296 		case EAPT_MD5CHAP:
3297 			if (len <= 0) {
3298 				printer(arg, " <missing length>");
3299 				break;
3300 			}
3301 			GETCHAR(vallen, inp);
3302 			len--;
3303 			if (vallen > len)
3304 				goto truncated;
3305 			printer(arg, " <Value%.*B>", vallen, inp);
3306 			INCPTR(vallen, inp);
3307 			len -= vallen;
3308 			if (len > 0) {
3309 				printer(arg, " <Name ");
3310 				print_string((char *)inp, len, printer, arg);
3311 				printer(arg, ">");
3312 				INCPTR(len, inp);
3313 				len = 0;
3314 			} else {
3315 				printer(arg, " <No name>");
3316 			}
3317 			break;
3318 
3319 #ifdef PPP_WITH_CHAPMS
3320 		case EAPT_MSCHAPV2:
3321 			if (len <= 0)
3322 				break;
3323 			GETCHAR(opcode, inp);
3324 			len--;
3325 			switch (opcode) {
3326 			case CHAP_RESPONSE:
3327 				INCPTR(3, inp);
3328 				len -= 3;
3329 				GETCHAR(vallen, inp);
3330 				len--;
3331 				if (vallen > len)
3332 					goto truncated;
3333 				len -= vallen;
3334 				printer(arg, " Response <");
3335 				for (; vallen > 0; --vallen) {
3336 					u_char val;
3337 					GETCHAR(val, inp);
3338 					printer(arg, "%.2x", val);
3339 				}
3340 				printer(arg, ">");
3341 				if (len > 0) {
3342 					printer(arg, ", <Name ");
3343 					print_string((char *)inp, len, printer, arg);
3344 					printer(arg, ">");
3345 					INCPTR(len, inp);
3346 					len = 0;
3347 				} else {
3348 					printer(arg, ", <No name>");
3349 				}
3350 				break;
3351 			case CHAP_SUCCESS:
3352 				printer(arg, " Success");
3353 				break;
3354 			case CHAP_FAILURE:
3355 				printer(arg, " Failure");
3356 				break;
3357 			default:
3358 				printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
3359 				break;
3360 			}
3361 			break;
3362 #endif /* PPP_WITH_CHAPMS */
3363 
3364 #ifdef PPP_WITH_SRP
3365 		case EAPT_SRP:
3366 			if (len < 1)
3367 				goto truncated;
3368 			GETCHAR(vallen, inp);
3369 			len--;
3370 			printer(arg, "-%d", vallen);
3371 			switch (vallen) {
3372 			case EAPSRP_CKEY:
3373 				printer(arg, " <A%.*B>", len, inp);
3374 				INCPTR(len, inp);
3375 				len = 0;
3376 				break;
3377 
3378 			case EAPSRP_CVALIDATOR:
3379 				if (len < sizeof (u_int32_t))
3380 					break;
3381 				GETLONG(uval, inp);
3382 				len -= sizeof (u_int32_t);
3383 				if (uval & SRPVAL_EBIT) {
3384 					printer(arg, " E");
3385 					uval &= ~SRPVAL_EBIT;
3386 				}
3387 				if (uval != 0) {
3388 					printer(arg, " f<%X>", uval);
3389 				}
3390 				printer(arg, " <M1%.*B%s>", len, inp,
3391 				    len == SHA_DIGEST_LENGTH ? "" : "?");
3392 				INCPTR(len, inp);
3393 				len = 0;
3394 				break;
3395 
3396 			case EAPSRP_ACK:
3397 				break;
3398 
3399 			case EAPSRP_LWRECHALLENGE:
3400 				printer(arg, " <Response%.*B%s>", len, inp,
3401 				    len == SHA_DIGEST_LENGTH ? "" : "?");
3402 				if ((vallen = len) > SHA_DIGEST_LENGTH)
3403 					vallen = SHA_DIGEST_LENGTH;
3404 				INCPTR(vallen, inp);
3405 				len -= vallen;
3406 				break;
3407 			}
3408 			break;
3409 #endif  /* PPP_WITH_SRP */
3410 		}
3411 		break;
3412 
3413 	case EAP_SUCCESS:	/* No payload expected for these! */
3414 	case EAP_FAILURE:
3415 		break;
3416 
3417 	truncated:
3418 		printer(arg, " <truncated>");
3419 		break;
3420 	}
3421 
3422 	if (len > 8)
3423 		printer(arg, "%8B...", inp);
3424 	else if (len > 0)
3425 		printer(arg, "%.*B", len, inp);
3426 	INCPTR(len, inp);
3427 
3428 	return (inp - pstart);
3429 }
3430