xref: /netbsd-src/external/bsd/ppp/dist/pppd/eap.c (revision a24efa7dea9f1f56c3bdb15a927d3516792ace1c)
1 /*	$NetBSD: eap.c,v 1.4 2014/10/25 21:11:37 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 #if 0
49 #define RCSID	"Id: eap.c,v 1.4 2004/11/09 22:39:25 paulus Exp "
50 static const char rcsid[] = RCSID;
51 #else
52 __RCSID("$NetBSD: eap.c,v 1.4 2014/10/25 21:11:37 christos Exp $");
53 #endif
54 
55 /*
56  * TODO:
57  */
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.h"
72 #include "pathnames.h"
73 #include "eap.h"
74 
75 #ifdef USE_SRP
76 #include <t_pwd.h>
77 #include <t_server.h>
78 #include <t_client.h>
79 #include "pppcrypt.h"
80 #endif /* USE_SRP */
81 
82 #ifndef SHA_DIGESTSIZE
83 #define	SHA_DIGESTSIZE 20
84 #endif
85 
86 
87 eap_state eap_states[NUM_PPP];		/* EAP state; one for each unit */
88 #ifdef USE_SRP
89 static char *pn_secret = NULL;		/* Pseudonym generating secret */
90 #endif
91 
92 /*
93  * Command-line options.
94  */
95 static option_t eap_option_list[] = {
96     { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,
97       "Set retransmit timeout for EAP Requests (server)" },
98     { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,
99       "Set max number of EAP Requests sent (server)" },
100     { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,
101       "Set time limit for peer EAP authentication" },
102     { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,
103       "Set max number of EAP Requests allows (client)" },
104     { "eap-interval", o_int, &eap_states[0].es_rechallenge,
105       "Set interval for EAP rechallenge" },
106 #ifdef USE_SRP
107     { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,
108       "Set interval for SRP lightweight rechallenge" },
109     { "srp-pn-secret", o_string, &pn_secret,
110       "Long term pseudonym generation secret" },
111     { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,
112       "Use pseudonym if offered one by server", 1 },
113 #endif
114     { NULL }
115 };
116 
117 /*
118  * Protocol entry points.
119  */
120 static void eap_init __P((int unit));
121 static void eap_input __P((int unit, u_char *inp, int inlen));
122 static void eap_protrej __P((int unit));
123 static void eap_lowerup __P((int unit));
124 static void eap_lowerdown __P((int unit));
125 static int  eap_printpkt __P((u_char *inp, int inlen,
126     void (*)(void *arg, char *fmt, ...), void *arg));
127 
128 struct protent eap_protent = {
129 	PPP_EAP,		/* protocol number */
130 	eap_init,		/* initialization procedure */
131 	eap_input,		/* process a received packet */
132 	eap_protrej,		/* process a received protocol-reject */
133 	eap_lowerup,		/* lower layer has gone up */
134 	eap_lowerdown,		/* lower layer has gone down */
135 	NULL,			/* open the protocol */
136 	NULL,			/* close the protocol */
137 	eap_printpkt,		/* print a packet in readable form */
138 	NULL,			/* process a received data packet */
139 	1,			/* protocol enabled */
140 	"EAP",			/* text name of protocol */
141 	NULL,			/* text name of corresponding data protocol */
142 	eap_option_list,	/* list of command-line options */
143 	NULL,			/* check requested options; assign defaults */
144 	NULL,			/* configure interface for demand-dial */
145 	NULL			/* say whether to bring up link for this pkt */
146 };
147 
148 /*
149  * A well-known 2048 bit modulus.
150  */
151 #ifdef USE_SRP
152 static const u_char wkmodulus[] = {
153 	0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
154 	0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
155 	0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
156 	0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
157 	0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
158 	0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
159 	0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
160 	0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
161 	0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
162 	0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
163 	0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
164 	0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
165 	0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
166 	0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
167 	0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
168 	0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
169 	0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
170 	0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
171 	0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
172 	0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
173 	0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
174 	0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
175 	0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
176 	0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
177 	0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
178 	0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
179 	0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
180 	0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
181 	0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
182 	0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
183 	0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
184 	0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
185 };
186 #endif
187 
188 /* Local forward declarations. */
189 static void eap_server_timeout __P((void *arg));
190 static const char *eap_state_name __P((enum eap_state_code));
191 static void eap_client_timeout __P((void *arg));
192 static void eap_send_failure __P((eap_state *));
193 static void eap_send_success __P((eap_state *));
194 static void eap_figure_next_state __P((eap_state *, int));
195 static void eap_send_request __P((eap_state *));
196 static void eap_rechallenge __P((void *));
197 static void srp_lwrechallenge __P((void *));
198 static void eap_send_response __P((eap_state *, u_char, u_char, const u_char *, int));
199 static void eap_chap_response __P((eap_state *, u_char, const u_char *, const char *, int));
200 static void eap_send_nak __P((eap_state *,u_char,u_char));
201 static void eap_request __P((eap_state *, u_char *, int, int));
202 static void eap_response __P((eap_state *, u_char *, int, int));
203 static void eap_success __P((eap_state *, u_char *, int, int));
204 static void eap_failure __P((eap_state *, u_char *, int, int));
205 
206 /*
207  * Convert EAP state code to printable string for debug.
208  */
209 static const char *
210 eap_state_name(esc)
211 enum eap_state_code esc;
212 {
213 	static const char *state_names[] = { EAP_STATES };
214 
215 	return (state_names[(int)esc]);
216 }
217 
218 /*
219  * eap_init - Initialize state for an EAP user.  This is currently
220  * called once by main() during start-up.
221  */
222 static void
223 eap_init(unit)
224 int unit;
225 {
226 	eap_state *esp = &eap_states[unit];
227 
228 	BZERO(esp, sizeof (*esp));
229 	esp->es_unit = unit;
230 	esp->es_server.ea_timeout = EAP_DEFTIMEOUT;
231 	esp->es_server.ea_maxrequests = EAP_DEFTRANSMITS;
232 	esp->es_server.ea_id = (u_char)(drand48() * 0x100);
233 	esp->es_client.ea_timeout = EAP_DEFREQTIME;
234 	esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
235 }
236 
237 /*
238  * eap_client_timeout - Give up waiting for the peer to send any
239  * Request messages.
240  */
241 static void
242 eap_client_timeout(arg)
243 void *arg;
244 {
245 	eap_state *esp = (eap_state *) arg;
246 
247 	if (!eap_client_active(esp))
248 		return;
249 
250 	error("EAP: timeout waiting for Request from peer");
251 	auth_withpeer_fail(esp->es_unit, PPP_EAP);
252 	esp->es_client.ea_state = eapBadAuth;
253 }
254 
255 /*
256  * eap_authwithpeer - Authenticate to our peer (behave as client).
257  *
258  * Start client state and wait for requests.  This is called only
259  * after eap_lowerup.
260  */
261 void
262 eap_authwithpeer(unit, localname)
263 int unit;
264 char *localname;
265 {
266 	eap_state *esp = &eap_states[unit];
267 
268 	/* Save the peer name we're given */
269 	esp->es_client.ea_name = localname;
270 	esp->es_client.ea_namelen = strlen(localname);
271 
272 	esp->es_client.ea_state = eapListen;
273 
274 	/*
275 	 * Start a timer so that if the other end just goes
276 	 * silent, we don't sit here waiting forever.
277 	 */
278 	if (esp->es_client.ea_timeout > 0)
279 		TIMEOUT(eap_client_timeout, (void *)esp,
280 		    esp->es_client.ea_timeout);
281 }
282 
283 /*
284  * Format a standard EAP Failure message and send it to the peer.
285  * (Server operation)
286  */
287 static void
288 eap_send_failure(esp)
289 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(esp)
314 eap_state *esp;
315 {
316 	u_char *outp;
317 
318 	outp = outpacket_buf;
319 
320 	MAKEHEADER(outp, PPP_EAP);
321 
322 	PUTCHAR(EAP_SUCCESS, outp);
323 	esp->es_server.ea_id++;
324 	PUTCHAR(esp->es_server.ea_id, outp);
325 	PUTSHORT(EAP_HEADERLEN, outp);
326 
327 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);
328 
329 	auth_peer_success(esp->es_unit, PPP_EAP, 0,
330 	    esp->es_server.ea_peer, esp->es_server.ea_peerlen);
331 }
332 
333 #ifdef USE_SRP
334 /*
335  * Set DES key according to pseudonym-generating secret and current
336  * date.
337  */
338 static bool
339 pncrypt_setkey(int timeoffs)
340 {
341 	struct tm *tp;
342 	char tbuf[9];
343 	SHA1_CTX ctxt;
344 	u_char dig[SHA_DIGESTSIZE];
345 	time_t reftime;
346 
347 	if (pn_secret == NULL)
348 		return (0);
349 	reftime = time(NULL) + timeoffs;
350 	tp = localtime(&reftime);
351 	SHA1Init(&ctxt);
352 	SHA1Update(&ctxt, pn_secret, strlen(pn_secret));
353 	strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp);
354 	SHA1Update(&ctxt, tbuf, strlen(tbuf));
355 	SHA1Final(dig, &ctxt);
356 	return (DesSetkey(dig));
357 }
358 
359 static char base64[] =
360 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
361 
362 struct b64state {
363 	u_int32_t bs_bits;
364 	int bs_offs;
365 };
366 
367 static int
368 b64enc(bs, inp, inlen, outp)
369 struct b64state *bs;
370 u_char *inp;
371 int inlen;
372 u_char *outp;
373 {
374 	int outlen = 0;
375 
376 	while (inlen > 0) {
377 		bs->bs_bits = (bs->bs_bits << 8) | *inp++;
378 		inlen--;
379 		bs->bs_offs += 8;
380 		if (bs->bs_offs >= 24) {
381 			*outp++ = base64[(bs->bs_bits >> 18) & 0x3F];
382 			*outp++ = base64[(bs->bs_bits >> 12) & 0x3F];
383 			*outp++ = base64[(bs->bs_bits >> 6) & 0x3F];
384 			*outp++ = base64[bs->bs_bits & 0x3F];
385 			outlen += 4;
386 			bs->bs_offs = 0;
387 			bs->bs_bits = 0;
388 		}
389 	}
390 	return (outlen);
391 }
392 
393 static int
394 b64flush(bs, outp)
395 struct b64state *bs;
396 u_char *outp;
397 {
398 	int outlen = 0;
399 
400 	if (bs->bs_offs == 8) {
401 		*outp++ = base64[(bs->bs_bits >> 2) & 0x3F];
402 		*outp++ = base64[(bs->bs_bits << 4) & 0x3F];
403 		outlen = 2;
404 	} else if (bs->bs_offs == 16) {
405 		*outp++ = base64[(bs->bs_bits >> 10) & 0x3F];
406 		*outp++ = base64[(bs->bs_bits >> 4) & 0x3F];
407 		*outp++ = base64[(bs->bs_bits << 2) & 0x3F];
408 		outlen = 3;
409 	}
410 	bs->bs_offs = 0;
411 	bs->bs_bits = 0;
412 	return (outlen);
413 }
414 
415 static int
416 b64dec(bs, inp, inlen, outp)
417 struct b64state *bs;
418 u_char *inp;
419 int inlen;
420 u_char *outp;
421 {
422 	int outlen = 0;
423 	char *cp;
424 
425 	while (inlen > 0) {
426 		if ((cp = strchr(base64, *inp++)) == NULL)
427 			break;
428 		bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);
429 		inlen--;
430 		bs->bs_offs += 6;
431 		if (bs->bs_offs >= 8) {
432 			*outp++ = bs->bs_bits >> (bs->bs_offs - 8);
433 			outlen++;
434 			bs->bs_offs -= 8;
435 		}
436 	}
437 	return (outlen);
438 }
439 #endif /* USE_SRP */
440 
441 /*
442  * Assume that current waiting server state is complete and figure
443  * next state to use based on available authentication data.  'status'
444  * indicates if there was an error in handling the last query.  It is
445  * 0 for success and non-zero for failure.
446  */
447 static void
448 eap_figure_next_state(esp, status)
449 eap_state *esp;
450 int status;
451 {
452 #ifdef USE_SRP
453 	unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp;
454 	struct t_pw tpw;
455 	struct t_confent *tce, mytce;
456 	char *cp, *cp2;
457 	struct t_server *ts;
458 	int id, i, plen, toffs;
459 	u_char vals[2];
460 	struct b64state bs;
461 #endif /* USE_SRP */
462 
463 	esp->es_server.ea_timeout = esp->es_savedtime;
464 	switch (esp->es_server.ea_state) {
465 	case eapBadAuth:
466 		return;
467 
468 	case eapIdentify:
469 #ifdef USE_SRP
470 		/* Discard any previous session. */
471 		ts = (struct t_server *)esp->es_server.ea_session;
472 		if (ts != NULL) {
473 			t_serverclose(ts);
474 			esp->es_server.ea_session = NULL;
475 			esp->es_server.ea_skey = NULL;
476 		}
477 #endif /* USE_SRP */
478 		if (status != 0) {
479 			esp->es_server.ea_state = eapBadAuth;
480 			break;
481 		}
482 #ifdef USE_SRP
483 		/* If we've got a pseudonym, try to decode to real name. */
484 		if (esp->es_server.ea_peerlen > SRP_PSEUDO_LEN &&
485 		    strncmp(esp->es_server.ea_peer, SRP_PSEUDO_ID,
486 			SRP_PSEUDO_LEN) == 0 &&
487 		    (esp->es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 <
488 		    sizeof (secbuf)) {
489 			BZERO(&bs, sizeof (bs));
490 			plen = b64dec(&bs,
491 			    esp->es_server.ea_peer + SRP_PSEUDO_LEN,
492 			    esp->es_server.ea_peerlen - SRP_PSEUDO_LEN,
493 			    secbuf);
494 			toffs = 0;
495 			for (i = 0; i < 5; i++) {
496 				pncrypt_setkey(toffs);
497 				toffs -= 86400;
498 				if (!DesDecrypt(secbuf, clear)) {
499 					dbglog("no DES here; cannot decode "
500 					    "pseudonym");
501 					return;
502 				}
503 				id = *(unsigned char *)clear;
504 				if (id + 1 <= plen && id + 9 > plen)
505 					break;
506 			}
507 			if (plen % 8 == 0 && i < 5) {
508 				/*
509 				 * Note that this is always shorter than the
510 				 * original stored string, so there's no need
511 				 * to realloc.
512 				 */
513 				if ((i = plen = *(unsigned char *)clear) > 7)
514 					i = 7;
515 				esp->es_server.ea_peerlen = plen;
516 				dp = (unsigned char *)esp->es_server.ea_peer;
517 				BCOPY(clear + 1, dp, i);
518 				plen -= i;
519 				dp += i;
520 				sp = secbuf + 8;
521 				while (plen > 0) {
522 					(void) DesDecrypt(sp, dp);
523 					sp += 8;
524 					dp += 8;
525 					plen -= 8;
526 				}
527 				esp->es_server.ea_peer[
528 					esp->es_server.ea_peerlen] = '\0';
529 				dbglog("decoded pseudonym to \"%.*q\"",
530 				    esp->es_server.ea_peerlen,
531 				    esp->es_server.ea_peer);
532 			} else {
533 				dbglog("failed to decode real name");
534 				/* Stay in eapIdentfy state; requery */
535 				break;
536 			}
537 		}
538 		/* Look up user in secrets database. */
539 		if (get_srp_secret(esp->es_unit, esp->es_server.ea_peer,
540 		    esp->es_server.ea_name, (char *)secbuf, 1) != 0) {
541 			/* Set up default in case SRP entry is bad */
542 			esp->es_server.ea_state = eapMD5Chall;
543 			/* Get t_confent based on index in srp-secrets */
544 			id = strtol((char *)secbuf, &cp, 10);
545 			if (*cp++ != ':' || id < 0)
546 				break;
547 			if (id == 0) {
548 				mytce.index = 0;
549 				mytce.modulus.data = (u_char *)wkmodulus;
550 				mytce.modulus.len = sizeof (wkmodulus);
551 				mytce.generator.data = (u_char *)"\002";
552 				mytce.generator.len = 1;
553 				tce = &mytce;
554 			} else if ((tce = gettcid(id)) != NULL) {
555 				/*
556 				 * Client will have to verify this modulus/
557 				 * generator combination, and that will take
558 				 * a while.  Lengthen the timeout here.
559 				 */
560 				if (esp->es_server.ea_timeout > 0 &&
561 				    esp->es_server.ea_timeout < 30)
562 					esp->es_server.ea_timeout = 30;
563 			} else {
564 				break;
565 			}
566 			if ((cp2 = strchr(cp, ':')) == NULL)
567 				break;
568 			*cp2++ = '\0';
569 			tpw.pebuf.name = esp->es_server.ea_peer;
570 			tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,
571 			    cp);
572 			tpw.pebuf.password.data = tpw.pwbuf;
573 			tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,
574 			    cp2);
575 			tpw.pebuf.salt.data = tpw.saltbuf;
576 			if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)
577 				break;
578 			esp->es_server.ea_session = (void *)ts;
579 			esp->es_server.ea_state = eapSRP1;
580 			vals[0] = esp->es_server.ea_id + 1;
581 			vals[1] = EAPT_SRP;
582 			t_serveraddexdata(ts, vals, 2);
583 			/* Generate B; must call before t_servergetkey() */
584 			t_servergenexp(ts);
585 			break;
586 		}
587 #endif /* USE_SRP */
588 		esp->es_server.ea_state = eapMD5Chall;
589 		break;
590 
591 	case eapSRP1:
592 #ifdef USE_SRP
593 		ts = (struct t_server *)esp->es_server.ea_session;
594 		if (ts != NULL && status != 0) {
595 			t_serverclose(ts);
596 			esp->es_server.ea_session = NULL;
597 			esp->es_server.ea_skey = NULL;
598 		}
599 #endif /* USE_SRP */
600 		if (status == 1) {
601 			esp->es_server.ea_state = eapMD5Chall;
602 		} else if (status != 0 || esp->es_server.ea_session == NULL) {
603 			esp->es_server.ea_state = eapBadAuth;
604 		} else {
605 			esp->es_server.ea_state = eapSRP2;
606 		}
607 		break;
608 
609 	case eapSRP2:
610 #ifdef USE_SRP
611 		ts = (struct t_server *)esp->es_server.ea_session;
612 		if (ts != NULL && status != 0) {
613 			t_serverclose(ts);
614 			esp->es_server.ea_session = NULL;
615 			esp->es_server.ea_skey = NULL;
616 		}
617 #endif /* USE_SRP */
618 		if (status != 0 || esp->es_server.ea_session == NULL) {
619 			esp->es_server.ea_state = eapBadAuth;
620 		} else {
621 			esp->es_server.ea_state = eapSRP3;
622 		}
623 		break;
624 
625 	case eapSRP3:
626 	case eapSRP4:
627 #ifdef USE_SRP
628 		ts = (struct t_server *)esp->es_server.ea_session;
629 		if (ts != NULL && status != 0) {
630 			t_serverclose(ts);
631 			esp->es_server.ea_session = NULL;
632 			esp->es_server.ea_skey = NULL;
633 		}
634 #endif /* USE_SRP */
635 		if (status != 0 || esp->es_server.ea_session == NULL) {
636 			esp->es_server.ea_state = eapBadAuth;
637 		} else {
638 			esp->es_server.ea_state = eapOpen;
639 		}
640 		break;
641 
642 	case eapMD5Chall:
643 		if (status != 0) {
644 			esp->es_server.ea_state = eapBadAuth;
645 		} else {
646 			esp->es_server.ea_state = eapOpen;
647 		}
648 		break;
649 
650 	default:
651 		esp->es_server.ea_state = eapBadAuth;
652 		break;
653 	}
654 	if (esp->es_server.ea_state == eapBadAuth)
655 		eap_send_failure(esp);
656 }
657 
658 /*
659  * Format an EAP Request message and send it to the peer.  Message
660  * type depends on current state.  (Server operation)
661  */
662 static void
663 eap_send_request(esp)
664 eap_state *esp;
665 {
666 	u_char *outp;
667 	u_char *lenloc;
668 	u_char *ptr;
669 	int outlen;
670 	int challen;
671 	char *str;
672 #ifdef USE_SRP
673 	struct t_server *ts;
674 	u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp;
675 	int i, j;
676 	struct b64state b64;
677 	SHA1_CTX ctxt;
678 #endif /* USE_SRP */
679 
680 	/* Handle both initial auth and restart */
681 	if (esp->es_server.ea_state < eapIdentify &&
682 	    esp->es_server.ea_state != eapInitial) {
683 		esp->es_server.ea_state = eapIdentify;
684 		if (explicit_remote) {
685 			/*
686 			 * If we already know the peer's
687 			 * unauthenticated name, then there's no
688 			 * reason to ask.  Go to next state instead.
689 			 */
690 			esp->es_server.ea_peer = remote_name;
691 			esp->es_server.ea_peerlen = strlen(remote_name);
692 			eap_figure_next_state(esp, 0);
693 		}
694 	}
695 
696 	if (esp->es_server.ea_maxrequests > 0 &&
697 	    esp->es_server.ea_requests >= esp->es_server.ea_maxrequests) {
698 		if (esp->es_server.ea_responses > 0)
699 			error("EAP: too many Requests sent");
700 		else
701 			error("EAP: no response to Requests");
702 		eap_send_failure(esp);
703 		return;
704 	}
705 
706 	outp = outpacket_buf;
707 
708 	MAKEHEADER(outp, PPP_EAP);
709 
710 	PUTCHAR(EAP_REQUEST, outp);
711 	PUTCHAR(esp->es_server.ea_id, outp);
712 	lenloc = outp;
713 	INCPTR(2, outp);
714 
715 	switch (esp->es_server.ea_state) {
716 	case eapIdentify:
717 		PUTCHAR(EAPT_IDENTITY, outp);
718 		str = "Name";
719 		challen = strlen(str);
720 		BCOPY(str, outp, challen);
721 		INCPTR(challen, outp);
722 		break;
723 
724 	case eapMD5Chall:
725 		PUTCHAR(EAPT_MD5CHAP, outp);
726 		/*
727 		 * pick a random challenge length between
728 		 * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
729 		 */
730 		challen = (drand48() *
731 		    (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
732 			    MIN_CHALLENGE_LENGTH;
733 		PUTCHAR(challen, outp);
734 		esp->es_challen = challen;
735 		ptr = esp->es_challenge;
736 		while (--challen >= 0)
737 			*ptr++ = (u_char) (drand48() * 0x100);
738 		BCOPY(esp->es_challenge, outp, esp->es_challen);
739 		INCPTR(esp->es_challen, outp);
740 		BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
741 		INCPTR(esp->es_server.ea_namelen, outp);
742 		break;
743 
744 #ifdef USE_SRP
745 	case eapSRP1:
746 		PUTCHAR(EAPT_SRP, outp);
747 		PUTCHAR(EAPSRP_CHALLENGE, outp);
748 
749 		PUTCHAR(esp->es_server.ea_namelen, outp);
750 		BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
751 		INCPTR(esp->es_server.ea_namelen, outp);
752 
753 		ts = (struct t_server *)esp->es_server.ea_session;
754 		assert(ts != NULL);
755 		PUTCHAR(ts->s.len, outp);
756 		BCOPY(ts->s.data, outp, ts->s.len);
757 		INCPTR(ts->s.len, outp);
758 
759 		if (ts->g.len == 1 && ts->g.data[0] == 2) {
760 			PUTCHAR(0, outp);
761 		} else {
762 			PUTCHAR(ts->g.len, outp);
763 			BCOPY(ts->g.data, outp, ts->g.len);
764 			INCPTR(ts->g.len, outp);
765 		}
766 
767 		if (ts->n.len != sizeof (wkmodulus) ||
768 		    BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) {
769 			BCOPY(ts->n.data, outp, ts->n.len);
770 			INCPTR(ts->n.len, outp);
771 		}
772 		break;
773 
774 	case eapSRP2:
775 		PUTCHAR(EAPT_SRP, outp);
776 		PUTCHAR(EAPSRP_SKEY, outp);
777 
778 		ts = (struct t_server *)esp->es_server.ea_session;
779 		assert(ts != NULL);
780 		BCOPY(ts->B.data, outp, ts->B.len);
781 		INCPTR(ts->B.len, outp);
782 		break;
783 
784 	case eapSRP3:
785 		PUTCHAR(EAPT_SRP, outp);
786 		PUTCHAR(EAPSRP_SVALIDATOR, outp);
787 		PUTLONG(SRPVAL_EBIT, outp);
788 		ts = (struct t_server *)esp->es_server.ea_session;
789 		assert(ts != NULL);
790 		BCOPY(t_serverresponse(ts), outp, SHA_DIGESTSIZE);
791 		INCPTR(SHA_DIGESTSIZE, outp);
792 
793 		if (pncrypt_setkey(0)) {
794 			/* Generate pseudonym */
795 			optr = outp;
796 			cp = (unsigned char *)esp->es_server.ea_peer;
797 			if ((j = i = esp->es_server.ea_peerlen) > 7)
798 				j = 7;
799 			clear[0] = i;
800 			BCOPY(cp, clear + 1, j);
801 			i -= j;
802 			cp += j;
803 			if (!DesEncrypt(clear, cipher)) {
804 				dbglog("no DES here; not generating pseudonym");
805 				break;
806 			}
807 			BZERO(&b64, sizeof (b64));
808 			outp++;		/* space for pseudonym length */
809 			outp += b64enc(&b64, cipher, 8, outp);
810 			while (i >= 8) {
811 				(void) DesEncrypt(cp, cipher);
812 				outp += b64enc(&b64, cipher, 8, outp);
813 				cp += 8;
814 				i -= 8;
815 			}
816 			if (i > 0) {
817 				BCOPY(cp, clear, i);
818 				cp += i;
819 				while (i < 8) {
820 					*cp++ = drand48() * 0x100;
821 					i++;
822 				}
823 				(void) DesEncrypt(clear, cipher);
824 				outp += b64enc(&b64, cipher, 8, outp);
825 			}
826 			outp += b64flush(&b64, outp);
827 
828 			/* Set length and pad out to next 20 octet boundary */
829 			i = outp - optr - 1;
830 			*optr = i;
831 			i %= SHA_DIGESTSIZE;
832 			if (i != 0) {
833 				while (i < SHA_DIGESTSIZE) {
834 					*outp++ = drand48() * 0x100;
835 					i++;
836 				}
837 			}
838 
839 			/* Obscure the pseudonym with SHA1 hash */
840 			SHA1Init(&ctxt);
841 			SHA1Update(&ctxt, &esp->es_server.ea_id, 1);
842 			SHA1Update(&ctxt, esp->es_server.ea_skey,
843 			    SESSION_KEY_LEN);
844 			SHA1Update(&ctxt, esp->es_server.ea_peer,
845 			    esp->es_server.ea_peerlen);
846 			while (optr < outp) {
847 				SHA1Final(dig, &ctxt);
848 				cp = dig;
849 				while (cp < dig + SHA_DIGESTSIZE)
850 					*optr++ ^= *cp++;
851 				SHA1Init(&ctxt);
852 				SHA1Update(&ctxt, &esp->es_server.ea_id, 1);
853 				SHA1Update(&ctxt, esp->es_server.ea_skey,
854 				    SESSION_KEY_LEN);
855 				SHA1Update(&ctxt, optr - SHA_DIGESTSIZE,
856 				    SHA_DIGESTSIZE);
857 			}
858 		}
859 		break;
860 
861 	case eapSRP4:
862 		PUTCHAR(EAPT_SRP, outp);
863 		PUTCHAR(EAPSRP_LWRECHALLENGE, outp);
864 		challen = MIN_CHALLENGE_LENGTH +
865 		    ((MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH) * drand48());
866 		esp->es_challen = challen;
867 		ptr = esp->es_challenge;
868 		while (--challen >= 0)
869 			*ptr++ = drand48() * 0x100;
870 		BCOPY(esp->es_challenge, outp, esp->es_challen);
871 		INCPTR(esp->es_challen, outp);
872 		break;
873 #endif /* USE_SRP */
874 
875 	default:
876 		return;
877 	}
878 
879 	outlen = (outp - outpacket_buf) - PPP_HDRLEN;
880 	PUTSHORT(outlen, lenloc);
881 
882 	output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
883 
884 	esp->es_server.ea_requests++;
885 
886 	if (esp->es_server.ea_timeout > 0)
887 		TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
888 }
889 
890 /*
891  * eap_authpeer - Authenticate our peer (behave as server).
892  *
893  * Start server state and send first request.  This is called only
894  * after eap_lowerup.
895  */
896 void
897 eap_authpeer(unit, localname)
898 int unit;
899 char *localname;
900 {
901 	eap_state *esp = &eap_states[unit];
902 
903 	/* Save the name we're given. */
904 	esp->es_server.ea_name = localname;
905 	esp->es_server.ea_namelen = strlen(localname);
906 
907 	esp->es_savedtime = esp->es_server.ea_timeout;
908 
909 	/* Lower layer up yet? */
910 	if (esp->es_server.ea_state == eapInitial ||
911 	    esp->es_server.ea_state == eapPending) {
912 		esp->es_server.ea_state = eapPending;
913 		return;
914 	}
915 
916 	esp->es_server.ea_state = eapPending;
917 
918 	/* ID number not updated here intentionally; hashed into M1 */
919 	eap_send_request(esp);
920 }
921 
922 /*
923  * eap_server_timeout - Retransmission timer for sending Requests
924  * expired.
925  */
926 static void
927 eap_server_timeout(arg)
928 void *arg;
929 {
930 	eap_state *esp = (eap_state *) arg;
931 
932 	if (!eap_server_active(esp))
933 		return;
934 
935 	/* EAP ID number must not change on timeout. */
936 	eap_send_request(esp);
937 }
938 
939 /*
940  * When it's time to send rechallenge the peer, this timeout is
941  * called.  Once the rechallenge is successful, the response handler
942  * will restart the timer.  If it fails, then the link is dropped.
943  */
944 static void
945 eap_rechallenge(arg)
946 void *arg;
947 {
948 	eap_state *esp = (eap_state *)arg;
949 
950 	if (esp->es_server.ea_state != eapOpen &&
951 	    esp->es_server.ea_state != eapSRP4)
952 		return;
953 
954 	esp->es_server.ea_requests = 0;
955 	esp->es_server.ea_state = eapIdentify;
956 	eap_figure_next_state(esp, 0);
957 	esp->es_server.ea_id++;
958 	eap_send_request(esp);
959 }
960 
961 static void
962 srp_lwrechallenge(arg)
963 void *arg;
964 {
965 	eap_state *esp = (eap_state *)arg;
966 
967 	if (esp->es_server.ea_state != eapOpen ||
968 	    esp->es_server.ea_type != EAPT_SRP)
969 		return;
970 
971 	esp->es_server.ea_requests = 0;
972 	esp->es_server.ea_state = eapSRP4;
973 	esp->es_server.ea_id++;
974 	eap_send_request(esp);
975 }
976 
977 /*
978  * eap_lowerup - The lower layer is now up.
979  *
980  * This is called before either eap_authpeer or eap_authwithpeer.  See
981  * link_established() in auth.c.  All that's necessary here is to
982  * return to closed state so that those two routines will do the right
983  * thing.
984  */
985 static void
986 eap_lowerup(unit)
987 int unit;
988 {
989 	eap_state *esp = &eap_states[unit];
990 
991 	/* Discard any (possibly authenticated) peer name. */
992 	if (esp->es_server.ea_peer != NULL &&
993 	    esp->es_server.ea_peer != remote_name)
994 		free(esp->es_server.ea_peer);
995 	esp->es_server.ea_peer = NULL;
996 	if (esp->es_client.ea_peer != NULL)
997 		free(esp->es_client.ea_peer);
998 	esp->es_client.ea_peer = NULL;
999 
1000 	esp->es_client.ea_state = eapClosed;
1001 	esp->es_server.ea_state = eapClosed;
1002 }
1003 
1004 /*
1005  * eap_lowerdown - The lower layer is now down.
1006  *
1007  * Cancel all timeouts and return to initial state.
1008  */
1009 static void
1010 eap_lowerdown(unit)
1011 int unit;
1012 {
1013 	eap_state *esp = &eap_states[unit];
1014 
1015 	if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) {
1016 		UNTIMEOUT(eap_client_timeout, (void *)esp);
1017 	}
1018 	if (eap_server_active(esp)) {
1019 		if (esp->es_server.ea_timeout > 0) {
1020 			UNTIMEOUT(eap_server_timeout, (void *)esp);
1021 		}
1022 	} else {
1023 		if ((esp->es_server.ea_state == eapOpen ||
1024 		    esp->es_server.ea_state == eapSRP4) &&
1025 		    esp->es_rechallenge > 0) {
1026 			UNTIMEOUT(eap_rechallenge, (void *)esp);
1027 		}
1028 		if (esp->es_server.ea_state == eapOpen &&
1029 		    esp->es_lwrechallenge > 0) {
1030 			UNTIMEOUT(srp_lwrechallenge, (void *)esp);
1031 		}
1032 	}
1033 
1034 	esp->es_client.ea_state = esp->es_server.ea_state = eapInitial;
1035 	esp->es_client.ea_requests = esp->es_server.ea_requests = 0;
1036 }
1037 
1038 /*
1039  * eap_protrej - Peer doesn't speak this protocol.
1040  *
1041  * This shouldn't happen.  If it does, it represents authentication
1042  * failure.
1043  */
1044 static void
1045 eap_protrej(unit)
1046 int unit;
1047 {
1048 	eap_state *esp = &eap_states[unit];
1049 
1050 	if (eap_client_active(esp)) {
1051 		error("EAP authentication failed due to Protocol-Reject");
1052 		auth_withpeer_fail(unit, PPP_EAP);
1053 	}
1054 	if (eap_server_active(esp)) {
1055 		error("EAP authentication of peer failed on Protocol-Reject");
1056 		auth_peer_fail(unit, PPP_EAP);
1057 	}
1058 	eap_lowerdown(unit);
1059 }
1060 
1061 /*
1062  * Format and send a regular EAP Response message.
1063  */
1064 static void
1065 eap_send_response(eap_state *esp, u_char id, u_char typenum,
1066 		  const u_char *str, int lenstr)
1067 {
1068 	u_char *outp;
1069 	int msglen;
1070 
1071 	outp = outpacket_buf;
1072 
1073 	MAKEHEADER(outp, PPP_EAP);
1074 
1075 	PUTCHAR(EAP_RESPONSE, outp);
1076 	PUTCHAR(id, outp);
1077 	esp->es_client.ea_id = id;
1078 	msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr;
1079 	PUTSHORT(msglen, outp);
1080 	PUTCHAR(typenum, outp);
1081 	if (lenstr > 0) {
1082 		BCOPY(str, outp, lenstr);
1083 	}
1084 
1085 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1086 }
1087 
1088 /*
1089  * Format and send an MD5-Challenge EAP Response message.
1090  */
1091 static void
1092 eap_chap_response(eap_state *esp, u_char id, const u_char *hash,
1093 		  const char *name, int namelen)
1094 {
1095 	u_char *outp;
1096 	int msglen;
1097 
1098 	outp = outpacket_buf;
1099 
1100 	MAKEHEADER(outp, PPP_EAP);
1101 
1102 	PUTCHAR(EAP_RESPONSE, outp);
1103 	PUTCHAR(id, outp);
1104 	esp->es_client.ea_id = id;
1105 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE +
1106 	    namelen;
1107 	PUTSHORT(msglen, outp);
1108 	PUTCHAR(EAPT_MD5CHAP, outp);
1109 	PUTCHAR(MD5_SIGNATURE_SIZE, outp);
1110 	BCOPY(hash, outp, MD5_SIGNATURE_SIZE);
1111 	INCPTR(MD5_SIGNATURE_SIZE, outp);
1112 	if (namelen > 0) {
1113 		BCOPY(name, outp, namelen);
1114 	}
1115 
1116 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1117 }
1118 
1119 #ifdef USE_SRP
1120 /*
1121  * Format and send a SRP EAP Response message.
1122  */
1123 static void
1124 eap_srp_response(esp, id, subtypenum, str, lenstr)
1125 eap_state *esp;
1126 u_char id;
1127 u_char subtypenum;
1128 u_char *str;
1129 int lenstr;
1130 {
1131 	u_char *outp;
1132 	int msglen;
1133 
1134 	outp = outpacket_buf;
1135 
1136 	MAKEHEADER(outp, PPP_EAP);
1137 
1138 	PUTCHAR(EAP_RESPONSE, outp);
1139 	PUTCHAR(id, outp);
1140 	esp->es_client.ea_id = id;
1141 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr;
1142 	PUTSHORT(msglen, outp);
1143 	PUTCHAR(EAPT_SRP, outp);
1144 	PUTCHAR(subtypenum, outp);
1145 	if (lenstr > 0) {
1146 		BCOPY(str, outp, lenstr);
1147 	}
1148 
1149 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1150 }
1151 
1152 /*
1153  * Format and send a SRP EAP Client Validator Response message.
1154  */
1155 static void
1156 eap_srpval_response(esp, id, flags, str)
1157 eap_state *esp;
1158 u_char id;
1159 u_int32_t flags;
1160 u_char *str;
1161 {
1162 	u_char *outp;
1163 	int msglen;
1164 
1165 	outp = outpacket_buf;
1166 
1167 	MAKEHEADER(outp, PPP_EAP);
1168 
1169 	PUTCHAR(EAP_RESPONSE, outp);
1170 	PUTCHAR(id, outp);
1171 	esp->es_client.ea_id = id;
1172 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) +
1173 	    SHA_DIGESTSIZE;
1174 	PUTSHORT(msglen, outp);
1175 	PUTCHAR(EAPT_SRP, outp);
1176 	PUTCHAR(EAPSRP_CVALIDATOR, outp);
1177 	PUTLONG(flags, outp);
1178 	BCOPY(str, outp, SHA_DIGESTSIZE);
1179 
1180 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1181 }
1182 #endif /* USE_SRP */
1183 
1184 static void
1185 eap_send_nak(eap_state *esp, u_char id, u_char type)
1186 {
1187 	u_char *outp;
1188 	int msglen;
1189 
1190 	outp = outpacket_buf;
1191 
1192 	MAKEHEADER(outp, PPP_EAP);
1193 
1194 	PUTCHAR(EAP_RESPONSE, outp);
1195 	PUTCHAR(id, outp);
1196 	esp->es_client.ea_id = id;
1197 	msglen = EAP_HEADERLEN + 2 * sizeof (u_char);
1198 	PUTSHORT(msglen, outp);
1199 	PUTCHAR(EAPT_NAK, outp);
1200 	PUTCHAR(type, outp);
1201 
1202 	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1203 }
1204 
1205 #ifdef USE_SRP
1206 static char *
1207 name_of_pn_file()
1208 {
1209 	char *user, *path, *file;
1210 	struct passwd *pw;
1211 	size_t pl;
1212 	static bool pnlogged = 0;
1213 
1214 	pw = getpwuid(getuid());
1215 	if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
1216 		errno = EINVAL;
1217 		return (NULL);
1218 	}
1219 	file = _PATH_PSEUDONYM;
1220 	pl = strlen(user) + strlen(file) + 2;
1221 	path = malloc(pl);
1222 	if (path == NULL)
1223 		return (NULL);
1224 	(void) slprintf(path, pl, "%s/%s", user, file);
1225 	if (!pnlogged) {
1226 		dbglog("pseudonym file: %s", path);
1227 		pnlogged = 1;
1228 	}
1229 	return (path);
1230 }
1231 
1232 static int
1233 open_pn_file(modebits)
1234 mode_t modebits;
1235 {
1236 	char *path;
1237 	int fd, err;
1238 
1239 	if ((path = name_of_pn_file()) == NULL)
1240 		return (-1);
1241 	fd = open(path, modebits, S_IRUSR | S_IWUSR);
1242 	err = errno;
1243 	free(path);
1244 	errno = err;
1245 	return (fd);
1246 }
1247 
1248 static void
1249 remove_pn_file()
1250 {
1251 	char *path;
1252 
1253 	if ((path = name_of_pn_file()) != NULL) {
1254 		(void) unlink(path);
1255 		(void) free(path);
1256 	}
1257 }
1258 
1259 static void
1260 write_pseudonym(esp, inp, len, id)
1261 eap_state *esp;
1262 u_char *inp;
1263 int len, id;
1264 {
1265 	u_char val;
1266 	u_char *datp, *digp;
1267 	SHA1_CTX ctxt;
1268 	u_char dig[SHA_DIGESTSIZE];
1269 	int dsize, fd, olen = len;
1270 
1271 	/*
1272 	 * Do the decoding by working backwards.  This eliminates the need
1273 	 * to save the decoded output in a separate buffer.
1274 	 */
1275 	val = id;
1276 	while (len > 0) {
1277 		if ((dsize = len % SHA_DIGESTSIZE) == 0)
1278 			dsize = SHA_DIGESTSIZE;
1279 		len -= dsize;
1280 		datp = inp + len;
1281 		SHA1Init(&ctxt);
1282 		SHA1Update(&ctxt, &val, 1);
1283 		SHA1Update(&ctxt, esp->es_client.ea_skey, SESSION_KEY_LEN);
1284 		if (len > 0) {
1285 			SHA1Update(&ctxt, datp, SHA_DIGESTSIZE);
1286 		} else {
1287 			SHA1Update(&ctxt, esp->es_client.ea_name,
1288 			    esp->es_client.ea_namelen);
1289 		}
1290 		SHA1Final(dig, &ctxt);
1291 		for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++)
1292 			*datp++ ^= *digp;
1293 	}
1294 
1295 	/* Now check that the result is sane */
1296 	if (olen <= 0 || *inp + 1 > olen) {
1297 		dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp);
1298 		return;
1299 	}
1300 
1301 	/* Save it away */
1302 	fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);
1303 	if (fd < 0) {
1304 		dbglog("EAP: error saving pseudonym: %m");
1305 		return;
1306 	}
1307 	len = write(fd, inp + 1, *inp);
1308 	if (close(fd) != -1 && len == *inp) {
1309 		dbglog("EAP: saved pseudonym");
1310 		esp->es_usedpseudo = 0;
1311 	} else {
1312 		dbglog("EAP: failed to save pseudonym");
1313 		remove_pn_file();
1314 	}
1315 }
1316 #endif /* USE_SRP */
1317 
1318 /*
1319  * eap_request - Receive EAP Request message (client mode).
1320  */
1321 static void
1322 eap_request(esp, inp, id, len)
1323 eap_state *esp;
1324 u_char *inp;
1325 int id;
1326 int len;
1327 {
1328 	u_char typenum;
1329 	u_char vallen;
1330 	int secret_len;
1331 	char secret[MAXWORDLEN];
1332 	char rhostname[256];
1333 	MD5_CTX mdContext;
1334 	u_char hash[MD5_SIGNATURE_SIZE];
1335 #ifdef USE_SRP
1336 	struct t_client *tc;
1337 	struct t_num sval, gval, Nval, *Ap, Bval;
1338 	u_char vals[2];
1339 	SHA1_CTX ctxt;
1340 	u_char dig[SHA_DIGESTSIZE];
1341 	int fd;
1342 #endif /* USE_SRP */
1343 
1344 	/*
1345 	 * Note: we update es_client.ea_id *only if* a Response
1346 	 * message is being generated.  Otherwise, we leave it the
1347 	 * same for duplicate detection purposes.
1348 	 */
1349 
1350 	esp->es_client.ea_requests++;
1351 	if (esp->es_client.ea_maxrequests != 0 &&
1352 	    esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {
1353 		info("EAP: received too many Request messages");
1354 		if (esp->es_client.ea_timeout > 0) {
1355 			UNTIMEOUT(eap_client_timeout, (void *)esp);
1356 		}
1357 		auth_withpeer_fail(esp->es_unit, PPP_EAP);
1358 		return;
1359 	}
1360 
1361 	if (len <= 0) {
1362 		error("EAP: empty Request message discarded");
1363 		return;
1364 	}
1365 
1366 	GETCHAR(typenum, inp);
1367 	len--;
1368 
1369 	switch (typenum) {
1370 	case EAPT_IDENTITY:
1371 		if (len > 0)
1372 			info("EAP: Identity prompt \"%.*q\"", len, inp);
1373 #ifdef USE_SRP
1374 		if (esp->es_usepseudo &&
1375 		    (esp->es_usedpseudo == 0 ||
1376 			(esp->es_usedpseudo == 1 &&
1377 			    id == esp->es_client.ea_id))) {
1378 			esp->es_usedpseudo = 1;
1379 			/* Try to get a pseudonym */
1380 			if ((fd = open_pn_file(O_RDONLY)) >= 0) {
1381 				strcpy(rhostname, SRP_PSEUDO_ID);
1382 				len = read(fd, rhostname + SRP_PSEUDO_LEN,
1383 				    sizeof (rhostname) - SRP_PSEUDO_LEN);
1384 				/* XXX NAI unsupported */
1385 				if (len > 0) {
1386 					eap_send_response(esp, id, typenum,
1387 					    rhostname, len + SRP_PSEUDO_LEN);
1388 				}
1389 				(void) close(fd);
1390 				if (len > 0)
1391 					break;
1392 			}
1393 		}
1394 		/* Stop using pseudonym now. */
1395 		if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
1396 			remove_pn_file();
1397 			esp->es_usedpseudo = 2;
1398 		}
1399 #endif /* USE_SRP */
1400 		eap_send_response(esp, id, typenum, esp->es_client.ea_name,
1401 		    esp->es_client.ea_namelen);
1402 		break;
1403 
1404 	case EAPT_NOTIFICATION:
1405 		if (len > 0)
1406 			info("EAP: Notification \"%.*q\"", len, inp);
1407 		eap_send_response(esp, id, typenum, NULL, 0);
1408 		break;
1409 
1410 	case EAPT_NAK:
1411 		/*
1412 		 * Avoid the temptation to send Response Nak in reply
1413 		 * to Request Nak here.  It can only lead to trouble.
1414 		 */
1415 		warn("EAP: unexpected Nak in Request; ignored");
1416 		/* Return because we're waiting for something real. */
1417 		return;
1418 
1419 	case EAPT_MD5CHAP:
1420 		if (len < 1) {
1421 			error("EAP: received MD5-Challenge with no data");
1422 			/* Bogus request; wait for something real. */
1423 			return;
1424 		}
1425 		GETCHAR(vallen, inp);
1426 		len--;
1427 		if (vallen < 8 || vallen > len) {
1428 			error("EAP: MD5-Challenge with bad length %d (8..%d)",
1429 			    vallen, len);
1430 			/* Try something better. */
1431 			eap_send_nak(esp, id, EAPT_SRP);
1432 			break;
1433 		}
1434 
1435 		/* Not so likely to happen. */
1436 		if (vallen >= len + sizeof (rhostname)) {
1437 			dbglog("EAP: trimming really long peer name down");
1438 			BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1439 			rhostname[sizeof (rhostname) - 1] = '\0';
1440 		} else {
1441 			BCOPY(inp + vallen, rhostname, len - vallen);
1442 			rhostname[len - vallen] = '\0';
1443 		}
1444 
1445 		/* In case the remote doesn't give us his name. */
1446 		if (explicit_remote ||
1447 		    (remote_name[0] != '\0' && vallen == len))
1448 			strlcpy(rhostname, remote_name, sizeof (rhostname));
1449 
1450 		/*
1451 		 * Get the secret for authenticating ourselves with
1452 		 * the specified host.
1453 		 */
1454 		if (!get_secret(esp->es_unit, esp->es_client.ea_name,
1455 		    rhostname, secret, &secret_len, 0)) {
1456 			dbglog("EAP: no MD5 secret for auth to %q", rhostname);
1457 			eap_send_nak(esp, id, EAPT_SRP);
1458 			break;
1459 		}
1460 		MD5Init(&mdContext);
1461 		typenum = id;
1462 		MD5Update(&mdContext, &typenum, 1);
1463 		MD5Update(&mdContext, secret, secret_len);
1464 		BZERO(secret, sizeof (secret));
1465 		MD5Update(&mdContext, inp, vallen);
1466 		MD5Final(hash, &mdContext);
1467 		eap_chap_response(esp, id, hash, esp->es_client.ea_name,
1468 		    esp->es_client.ea_namelen);
1469 		break;
1470 
1471 #ifdef USE_SRP
1472 	case EAPT_SRP:
1473 		if (len < 1) {
1474 			error("EAP: received empty SRP Request");
1475 			/* Bogus request; wait for something real. */
1476 			return;
1477 		}
1478 
1479 		/* Get subtype */
1480 		GETCHAR(vallen, inp);
1481 		len--;
1482 		switch (vallen) {
1483 		case EAPSRP_CHALLENGE:
1484 			tc = NULL;
1485 			if (esp->es_client.ea_session != NULL) {
1486 				tc = (struct t_client *)esp->es_client.
1487 				    ea_session;
1488 				/*
1489 				 * If this is a new challenge, then start
1490 				 * over with a new client session context.
1491 				 * Otherwise, just resend last response.
1492 				 */
1493 				if (id != esp->es_client.ea_id) {
1494 					t_clientclose(tc);
1495 					esp->es_client.ea_session = NULL;
1496 					tc = NULL;
1497 				}
1498 			}
1499 			/* No session key just yet */
1500 			esp->es_client.ea_skey = NULL;
1501 			if (tc == NULL) {
1502 				GETCHAR(vallen, inp);
1503 				len--;
1504 				if (vallen >= len) {
1505 					error("EAP: badly-formed SRP Challenge"
1506 					    " (name)");
1507 					/* Ignore badly-formed messages */
1508 					return;
1509 				}
1510 				BCOPY(inp, rhostname, vallen);
1511 				rhostname[vallen] = '\0';
1512 				INCPTR(vallen, inp);
1513 				len -= vallen;
1514 
1515 				/*
1516 				 * In case the remote doesn't give us his name,
1517 				 * use configured name.
1518 				 */
1519 				if (explicit_remote ||
1520 				    (remote_name[0] != '\0' && vallen == 0)) {
1521 					strlcpy(rhostname, remote_name,
1522 					    sizeof (rhostname));
1523 				}
1524 
1525 				if (esp->es_client.ea_peer != NULL)
1526 					free(esp->es_client.ea_peer);
1527 				esp->es_client.ea_peer = strdup(rhostname);
1528 				esp->es_client.ea_peerlen = strlen(rhostname);
1529 
1530 				GETCHAR(vallen, inp);
1531 				len--;
1532 				if (vallen >= len) {
1533 					error("EAP: badly-formed SRP Challenge"
1534 					    " (s)");
1535 					/* Ignore badly-formed messages */
1536 					return;
1537 				}
1538 				sval.data = inp;
1539 				sval.len = vallen;
1540 				INCPTR(vallen, inp);
1541 				len -= vallen;
1542 
1543 				GETCHAR(vallen, inp);
1544 				len--;
1545 				if (vallen > len) {
1546 					error("EAP: badly-formed SRP Challenge"
1547 					    " (g)");
1548 					/* Ignore badly-formed messages */
1549 					return;
1550 				}
1551 				/* If no generator present, then use value 2 */
1552 				if (vallen == 0) {
1553 					gval.data = (u_char *)"\002";
1554 					gval.len = 1;
1555 				} else {
1556 					gval.data = inp;
1557 					gval.len = vallen;
1558 				}
1559 				INCPTR(vallen, inp);
1560 				len -= vallen;
1561 
1562 				/*
1563 				 * If no modulus present, then use well-known
1564 				 * value.
1565 				 */
1566 				if (len == 0) {
1567 					Nval.data = (u_char *)wkmodulus;
1568 					Nval.len = sizeof (wkmodulus);
1569 				} else {
1570 					Nval.data = inp;
1571 					Nval.len = len;
1572 				}
1573 				tc = t_clientopen(esp->es_client.ea_name,
1574 				    &Nval, &gval, &sval);
1575 				if (tc == NULL) {
1576 					eap_send_nak(esp, id, EAPT_MD5CHAP);
1577 					break;
1578 				}
1579 				esp->es_client.ea_session = (void *)tc;
1580 
1581 				/* Add Challenge ID & type to verifier */
1582 				vals[0] = id;
1583 				vals[1] = EAPT_SRP;
1584 				t_clientaddexdata(tc, vals, 2);
1585 			}
1586 			Ap = t_clientgenexp(tc);
1587 			eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
1588 			    Ap->len);
1589 			break;
1590 
1591 		case EAPSRP_SKEY:
1592 			tc = (struct t_client *)esp->es_client.ea_session;
1593 			if (tc == NULL) {
1594 				warn("EAP: peer sent Subtype 2 without 1");
1595 				eap_send_nak(esp, id, EAPT_MD5CHAP);
1596 				break;
1597 			}
1598 			if (esp->es_client.ea_skey != NULL) {
1599 				/*
1600 				 * ID number should not change here.  Warn
1601 				 * if it does (but otherwise ignore).
1602 				 */
1603 				if (id != esp->es_client.ea_id) {
1604 					warn("EAP: ID changed from %d to %d "
1605 					    "in SRP Subtype 2 rexmit",
1606 					    esp->es_client.ea_id, id);
1607 				}
1608 			} else {
1609 				if (get_srp_secret(esp->es_unit,
1610 				    esp->es_client.ea_name,
1611 				    esp->es_client.ea_peer, secret, 0) == 0) {
1612 					/*
1613 					 * Can't work with this peer because
1614 					 * the secret is missing.  Just give
1615 					 * up.
1616 					 */
1617 					eap_send_nak(esp, id, EAPT_MD5CHAP);
1618 					break;
1619 				}
1620 				Bval.data = inp;
1621 				Bval.len = len;
1622 				t_clientpasswd(tc, secret);
1623 				BZERO(secret, sizeof (secret));
1624 				esp->es_client.ea_skey =
1625 				    t_clientgetkey(tc, &Bval);
1626 				if (esp->es_client.ea_skey == NULL) {
1627 					/* Server is rogue; stop now */
1628 					error("EAP: SRP server is rogue");
1629 					goto client_failure;
1630 				}
1631 			}
1632 			eap_srpval_response(esp, id, SRPVAL_EBIT,
1633 			    t_clientresponse(tc));
1634 			break;
1635 
1636 		case EAPSRP_SVALIDATOR:
1637 			tc = (struct t_client *)esp->es_client.ea_session;
1638 			if (tc == NULL || esp->es_client.ea_skey == NULL) {
1639 				warn("EAP: peer sent Subtype 3 without 1/2");
1640 				eap_send_nak(esp, id, EAPT_MD5CHAP);
1641 				break;
1642 			}
1643 			/*
1644 			 * If we're already open, then this ought to be a
1645 			 * duplicate.  Otherwise, check that the server is
1646 			 * who we think it is.
1647 			 */
1648 			if (esp->es_client.ea_state == eapOpen) {
1649 				if (id != esp->es_client.ea_id) {
1650 					warn("EAP: ID changed from %d to %d "
1651 					    "in SRP Subtype 3 rexmit",
1652 					    esp->es_client.ea_id, id);
1653 				}
1654 			} else {
1655 				len -= sizeof (u_int32_t) + SHA_DIGESTSIZE;
1656 				if (len < 0 || t_clientverify(tc, inp +
1657 					sizeof (u_int32_t)) != 0) {
1658 					error("EAP: SRP server verification "
1659 					    "failed");
1660 					goto client_failure;
1661 				}
1662 				GETLONG(esp->es_client.ea_keyflags, inp);
1663 				/* Save pseudonym if user wants it. */
1664 				if (len > 0 && esp->es_usepseudo) {
1665 					INCPTR(SHA_DIGESTSIZE, inp);
1666 					write_pseudonym(esp, inp, len, id);
1667 				}
1668 			}
1669 			/*
1670 			 * We've verified our peer.  We're now mostly done,
1671 			 * except for waiting on the regular EAP Success
1672 			 * message.
1673 			 */
1674 			eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
1675 			break;
1676 
1677 		case EAPSRP_LWRECHALLENGE:
1678 			if (len < 4) {
1679 				warn("EAP: malformed Lightweight rechallenge");
1680 				return;
1681 			}
1682 			SHA1Init(&ctxt);
1683 			vals[0] = id;
1684 			SHA1Update(&ctxt, vals, 1);
1685 			SHA1Update(&ctxt, esp->es_client.ea_skey,
1686 			    SESSION_KEY_LEN);
1687 			SHA1Update(&ctxt, inp, len);
1688 			SHA1Update(&ctxt, esp->es_client.ea_name,
1689 			    esp->es_client.ea_namelen);
1690 			SHA1Final(dig, &ctxt);
1691 			eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
1692 			    SHA_DIGESTSIZE);
1693 			break;
1694 
1695 		default:
1696 			error("EAP: unknown SRP Subtype %d", vallen);
1697 			eap_send_nak(esp, id, EAPT_MD5CHAP);
1698 			break;
1699 		}
1700 		break;
1701 #endif /* USE_SRP */
1702 
1703 	default:
1704 		info("EAP: unknown authentication type %d; Naking", typenum);
1705 		eap_send_nak(esp, id, EAPT_SRP);
1706 		break;
1707 	}
1708 
1709 	if (esp->es_client.ea_timeout > 0) {
1710 		UNTIMEOUT(eap_client_timeout, (void *)esp);
1711 		TIMEOUT(eap_client_timeout, (void *)esp,
1712 		    esp->es_client.ea_timeout);
1713 	}
1714 	return;
1715 
1716 #ifdef USE_SRP
1717 client_failure:
1718 	esp->es_client.ea_state = eapBadAuth;
1719 	if (esp->es_client.ea_timeout > 0) {
1720 		UNTIMEOUT(eap_client_timeout, (void *)esp);
1721 	}
1722 	esp->es_client.ea_session = NULL;
1723 	t_clientclose(tc);
1724 	auth_withpeer_fail(esp->es_unit, PPP_EAP);
1725 #endif /* USE_SRP */
1726 }
1727 
1728 /*
1729  * eap_response - Receive EAP Response message (server mode).
1730  */
1731 static void
1732 eap_response(esp, inp, id, len)
1733 eap_state *esp;
1734 u_char *inp;
1735 int id;
1736 int len;
1737 {
1738 	u_char typenum;
1739 	u_char vallen;
1740 	int secret_len;
1741 	char secret[MAXSECRETLEN];
1742 	char rhostname[256];
1743 	MD5_CTX mdContext;
1744 	u_char hash[MD5_SIGNATURE_SIZE];
1745 #ifdef USE_SRP
1746 	struct t_server *ts;
1747 	struct t_num A;
1748 	SHA1_CTX ctxt;
1749 	u_char dig[SHA_DIGESTSIZE];
1750 #endif /* USE_SRP */
1751 
1752 	if (esp->es_server.ea_id != id) {
1753 		dbglog("EAP: discarding Response %d; expected ID %d", id,
1754 		    esp->es_server.ea_id);
1755 		return;
1756 	}
1757 
1758 	esp->es_server.ea_responses++;
1759 
1760 	if (len <= 0) {
1761 		error("EAP: empty Response message discarded");
1762 		return;
1763 	}
1764 
1765 	GETCHAR(typenum, inp);
1766 	len--;
1767 
1768 	switch (typenum) {
1769 	case EAPT_IDENTITY:
1770 		if (esp->es_server.ea_state != eapIdentify) {
1771 			dbglog("EAP discarding unwanted Identify \"%.q\"", len,
1772 			    inp);
1773 			break;
1774 		}
1775 		info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
1776 		if (esp->es_server.ea_peer != NULL &&
1777 		    esp->es_server.ea_peer != remote_name)
1778 			free(esp->es_server.ea_peer);
1779 		esp->es_server.ea_peer = malloc(len + 1);
1780 		if (esp->es_server.ea_peer == NULL) {
1781 			esp->es_server.ea_peerlen = 0;
1782 			eap_figure_next_state(esp, 1);
1783 			break;
1784 		}
1785 		BCOPY(inp, esp->es_server.ea_peer, len);
1786 		esp->es_server.ea_peer[len] = '\0';
1787 		esp->es_server.ea_peerlen = len;
1788 		eap_figure_next_state(esp, 0);
1789 		break;
1790 
1791 	case EAPT_NOTIFICATION:
1792 		dbglog("EAP unexpected Notification; response discarded");
1793 		break;
1794 
1795 	case EAPT_NAK:
1796 		if (len < 1) {
1797 			info("EAP: Nak Response with no suggested protocol");
1798 			eap_figure_next_state(esp, 1);
1799 			break;
1800 		}
1801 
1802 		GETCHAR(vallen, inp);
1803 		len--;
1804 
1805 		if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
1806 			/* Peer cannot Nak Identify Request */
1807 			eap_figure_next_state(esp, 1);
1808 			break;
1809 		}
1810 
1811 		switch (vallen) {
1812 		case EAPT_SRP:
1813 			/* Run through SRP validator selection again. */
1814 			esp->es_server.ea_state = eapIdentify;
1815 			eap_figure_next_state(esp, 0);
1816 			break;
1817 
1818 		case EAPT_MD5CHAP:
1819 			esp->es_server.ea_state = eapMD5Chall;
1820 			break;
1821 
1822 		default:
1823 			dbglog("EAP: peer requesting unknown Type %d", vallen);
1824 			switch (esp->es_server.ea_state) {
1825 			case eapSRP1:
1826 			case eapSRP2:
1827 			case eapSRP3:
1828 				esp->es_server.ea_state = eapMD5Chall;
1829 				break;
1830 			case eapMD5Chall:
1831 			case eapSRP4:
1832 				esp->es_server.ea_state = eapIdentify;
1833 				eap_figure_next_state(esp, 0);
1834 				break;
1835 			default:
1836 				break;
1837 			}
1838 			break;
1839 		}
1840 		break;
1841 
1842 	case EAPT_MD5CHAP:
1843 		if (esp->es_server.ea_state != eapMD5Chall) {
1844 			error("EAP: unexpected MD5-Response");
1845 			eap_figure_next_state(esp, 1);
1846 			break;
1847 		}
1848 		if (len < 1) {
1849 			error("EAP: received MD5-Response with no data");
1850 			eap_figure_next_state(esp, 1);
1851 			break;
1852 		}
1853 		GETCHAR(vallen, inp);
1854 		len--;
1855 		if (vallen != 16 || vallen > len) {
1856 			error("EAP: MD5-Response with bad length %d", vallen);
1857 			eap_figure_next_state(esp, 1);
1858 			break;
1859 		}
1860 
1861 		/* Not so likely to happen. */
1862 		if (vallen >= len + sizeof (rhostname)) {
1863 			dbglog("EAP: trimming really long peer name down");
1864 			BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1865 			rhostname[sizeof (rhostname) - 1] = '\0';
1866 		} else {
1867 			BCOPY(inp + vallen, rhostname, len - vallen);
1868 			rhostname[len - vallen] = '\0';
1869 		}
1870 
1871 		/* In case the remote doesn't give us his name. */
1872 		if (explicit_remote ||
1873 		    (remote_name[0] != '\0' && vallen == len))
1874 			strlcpy(rhostname, remote_name, sizeof (rhostname));
1875 
1876 		/*
1877 		 * Get the secret for authenticating the specified
1878 		 * host.
1879 		 */
1880 		if (!get_secret(esp->es_unit, rhostname,
1881 		    esp->es_server.ea_name, secret, &secret_len, 1)) {
1882 			dbglog("EAP: no MD5 secret for auth of %q", rhostname);
1883 			eap_send_failure(esp);
1884 			break;
1885 		}
1886 		MD5Init(&mdContext);
1887 		MD5Update(&mdContext, &esp->es_server.ea_id, 1);
1888 		MD5Update(&mdContext, secret, secret_len);
1889 		BZERO(secret, sizeof (secret));
1890 		MD5Update(&mdContext, esp->es_challenge, esp->es_challen);
1891 		MD5Final(hash, &mdContext);
1892 		if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) {
1893 			eap_send_failure(esp);
1894 			break;
1895 		}
1896 		esp->es_server.ea_type = EAPT_MD5CHAP;
1897 		eap_send_success(esp);
1898 		eap_figure_next_state(esp, 0);
1899 		if (esp->es_rechallenge != 0)
1900 			TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
1901 		break;
1902 
1903 #ifdef USE_SRP
1904 	case EAPT_SRP:
1905 		if (len < 1) {
1906 			error("EAP: empty SRP Response");
1907 			eap_figure_next_state(esp, 1);
1908 			break;
1909 		}
1910 		GETCHAR(typenum, inp);
1911 		len--;
1912 		switch (typenum) {
1913 		case EAPSRP_CKEY:
1914 			if (esp->es_server.ea_state != eapSRP1) {
1915 				error("EAP: unexpected SRP Subtype 1 Response");
1916 				eap_figure_next_state(esp, 1);
1917 				break;
1918 			}
1919 			A.data = inp;
1920 			A.len = len;
1921 			ts = (struct t_server *)esp->es_server.ea_session;
1922 			assert(ts != NULL);
1923 			esp->es_server.ea_skey = t_servergetkey(ts, &A);
1924 			if (esp->es_server.ea_skey == NULL) {
1925 				/* Client's A value is bogus; terminate now */
1926 				error("EAP: bogus A value from client");
1927 				eap_send_failure(esp);
1928 			} else {
1929 				eap_figure_next_state(esp, 0);
1930 			}
1931 			break;
1932 
1933 		case EAPSRP_CVALIDATOR:
1934 			if (esp->es_server.ea_state != eapSRP2) {
1935 				error("EAP: unexpected SRP Subtype 2 Response");
1936 				eap_figure_next_state(esp, 1);
1937 				break;
1938 			}
1939 			if (len < sizeof (u_int32_t) + SHA_DIGESTSIZE) {
1940 				error("EAP: M1 length %d < %d", len,
1941 				    sizeof (u_int32_t) + SHA_DIGESTSIZE);
1942 				eap_figure_next_state(esp, 1);
1943 				break;
1944 			}
1945 			GETLONG(esp->es_server.ea_keyflags, inp);
1946 			ts = (struct t_server *)esp->es_server.ea_session;
1947 			assert(ts != NULL);
1948 			if (t_serververify(ts, inp)) {
1949 				info("EAP: unable to validate client identity");
1950 				eap_send_failure(esp);
1951 				break;
1952 			}
1953 			eap_figure_next_state(esp, 0);
1954 			break;
1955 
1956 		case EAPSRP_ACK:
1957 			if (esp->es_server.ea_state != eapSRP3) {
1958 				error("EAP: unexpected SRP Subtype 3 Response");
1959 				eap_send_failure(esp);
1960 				break;
1961 			}
1962 			esp->es_server.ea_type = EAPT_SRP;
1963 			eap_send_success(esp);
1964 			eap_figure_next_state(esp, 0);
1965 			if (esp->es_rechallenge != 0)
1966 				TIMEOUT(eap_rechallenge, esp,
1967 				    esp->es_rechallenge);
1968 			if (esp->es_lwrechallenge != 0)
1969 				TIMEOUT(srp_lwrechallenge, esp,
1970 				    esp->es_lwrechallenge);
1971 			break;
1972 
1973 		case EAPSRP_LWRECHALLENGE:
1974 			if (esp->es_server.ea_state != eapSRP4) {
1975 				info("EAP: unexpected SRP Subtype 4 Response");
1976 				return;
1977 			}
1978 			if (len != SHA_DIGESTSIZE) {
1979 				error("EAP: bad Lightweight rechallenge "
1980 				    "response");
1981 				return;
1982 			}
1983 			SHA1Init(&ctxt);
1984 			vallen = id;
1985 			SHA1Update(&ctxt, &vallen, 1);
1986 			SHA1Update(&ctxt, esp->es_server.ea_skey,
1987 			    SESSION_KEY_LEN);
1988 			SHA1Update(&ctxt, esp->es_challenge, esp->es_challen);
1989 			SHA1Update(&ctxt, esp->es_server.ea_peer,
1990 			    esp->es_server.ea_peerlen);
1991 			SHA1Final(dig, &ctxt);
1992 			if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) {
1993 				error("EAP: failed Lightweight rechallenge");
1994 				eap_send_failure(esp);
1995 				break;
1996 			}
1997 			esp->es_server.ea_state = eapOpen;
1998 			if (esp->es_lwrechallenge != 0)
1999 				TIMEOUT(srp_lwrechallenge, esp,
2000 				    esp->es_lwrechallenge);
2001 			break;
2002 		}
2003 		break;
2004 #endif /* USE_SRP */
2005 
2006 	default:
2007 		/* This can't happen. */
2008 		error("EAP: unknown Response type %d; ignored", typenum);
2009 		return;
2010 	}
2011 
2012 	if (esp->es_server.ea_timeout > 0) {
2013 		UNTIMEOUT(eap_server_timeout, (void *)esp);
2014 	}
2015 
2016 	if (esp->es_server.ea_state != eapBadAuth &&
2017 	    esp->es_server.ea_state != eapOpen) {
2018 		esp->es_server.ea_id++;
2019 		eap_send_request(esp);
2020 	}
2021 }
2022 
2023 /*
2024  * eap_success - Receive EAP Success message (client mode).
2025  */
2026 static void
2027 eap_success(esp, inp, id, len)
2028 eap_state *esp;
2029 u_char *inp;
2030 int id;
2031 int len;
2032 {
2033 	if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) {
2034 		dbglog("EAP unexpected success message in state %s (%d)",
2035 		    eap_state_name(esp->es_client.ea_state),
2036 		    esp->es_client.ea_state);
2037 		return;
2038 	}
2039 
2040 	if (esp->es_client.ea_timeout > 0) {
2041 		UNTIMEOUT(eap_client_timeout, (void *)esp);
2042 	}
2043 
2044 	if (len > 0) {
2045 		/* This is odd.  The spec doesn't allow for this. */
2046 		PRINTMSG(inp, len);
2047 	}
2048 
2049 	esp->es_client.ea_state = eapOpen;
2050 	auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2051 }
2052 
2053 /*
2054  * eap_failure - Receive EAP Failure message (client mode).
2055  */
2056 static void
2057 eap_failure(esp, inp, id, len)
2058 eap_state *esp;
2059 u_char *inp;
2060 int id;
2061 int len;
2062 {
2063 	if (!eap_client_active(esp)) {
2064 		dbglog("EAP unexpected failure message in state %s (%d)",
2065 		    eap_state_name(esp->es_client.ea_state),
2066 		    esp->es_client.ea_state);
2067 	}
2068 
2069 	if (esp->es_client.ea_timeout > 0) {
2070 		UNTIMEOUT(eap_client_timeout, (void *)esp);
2071 	}
2072 
2073 	if (len > 0) {
2074 		/* This is odd.  The spec doesn't allow for this. */
2075 		PRINTMSG(inp, len);
2076 	}
2077 
2078 	esp->es_client.ea_state = eapBadAuth;
2079 
2080 	error("EAP: peer reports authentication failure");
2081 	auth_withpeer_fail(esp->es_unit, PPP_EAP);
2082 }
2083 
2084 /*
2085  * eap_input - Handle received EAP message.
2086  */
2087 static void
2088 eap_input(unit, inp, inlen)
2089 int unit;
2090 u_char *inp;
2091 int inlen;
2092 {
2093 	eap_state *esp = &eap_states[unit];
2094 	u_char code, id;
2095 	int len;
2096 
2097 	/*
2098 	 * Parse header (code, id and length).  If packet too short,
2099 	 * drop it.
2100 	 */
2101 	if (inlen < EAP_HEADERLEN) {
2102 		error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2103 		return;
2104 	}
2105 	GETCHAR(code, inp);
2106 	GETCHAR(id, inp);
2107 	GETSHORT(len, inp);
2108 	if (len < EAP_HEADERLEN || len > inlen) {
2109 		error("EAP: packet has illegal length field %d (%d..%d)", len,
2110 		    EAP_HEADERLEN, inlen);
2111 		return;
2112 	}
2113 	len -= EAP_HEADERLEN;
2114 
2115 	/* Dispatch based on message code */
2116 	switch (code) {
2117 	case EAP_REQUEST:
2118 		eap_request(esp, inp, id, len);
2119 		break;
2120 
2121 	case EAP_RESPONSE:
2122 		eap_response(esp, inp, id, len);
2123 		break;
2124 
2125 	case EAP_SUCCESS:
2126 		eap_success(esp, inp, id, len);
2127 		break;
2128 
2129 	case EAP_FAILURE:
2130 		eap_failure(esp, inp, id, len);
2131 		break;
2132 
2133 	default:				/* XXX Need code reject */
2134 		/* Note: it's not legal to send EAP Nak here. */
2135 		warn("EAP: unknown code %d received", code);
2136 		break;
2137 	}
2138 }
2139 
2140 /*
2141  * eap_printpkt - print the contents of an EAP packet.
2142  */
2143 static char *eap_codenames[] = {
2144 	"Request", "Response", "Success", "Failure"
2145 };
2146 
2147 static char *eap_typenames[] = {
2148 	"Identity", "Notification", "Nak", "MD5-Challenge",
2149 	"OTP", "Generic-Token", NULL, NULL,
2150 	"RSA", "DSS", "KEA", "KEA-Validate",
2151 	"TLS", "Defender", "Windows 2000", "Arcot",
2152 	"Cisco", "Nokia", "SRP"
2153 };
2154 
2155 static int
2156 eap_printpkt(inp, inlen, printer, arg)
2157 u_char *inp;
2158 int inlen;
2159 void (*printer) __P((void *, char *, ...));
2160 void *arg;
2161 {
2162 	int code, id, len, rtype, vallen;
2163 	u_char *pstart;
2164 	u_int32_t uval;
2165 
2166 	if (inlen < EAP_HEADERLEN)
2167 		return (0);
2168 	pstart = inp;
2169 	GETCHAR(code, inp);
2170 	GETCHAR(id, inp);
2171 	GETSHORT(len, inp);
2172 	if (len < EAP_HEADERLEN || len > inlen)
2173 		return (0);
2174 
2175 	if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
2176 		printer(arg, " %s", eap_codenames[code-1]);
2177 	else
2178 		printer(arg, " code=0x%x", code);
2179 	printer(arg, " id=0x%x", id);
2180 	len -= EAP_HEADERLEN;
2181 	switch (code) {
2182 	case EAP_REQUEST:
2183 		if (len < 1) {
2184 			printer(arg, " <missing type>");
2185 			break;
2186 		}
2187 		GETCHAR(rtype, inp);
2188 		len--;
2189 		if (rtype >= 1 &&
2190 		    rtype <= sizeof (eap_typenames) / sizeof (char *))
2191 			printer(arg, " %s", eap_typenames[rtype-1]);
2192 		else
2193 			printer(arg, " type=0x%x", rtype);
2194 		switch (rtype) {
2195 		case EAPT_IDENTITY:
2196 		case EAPT_NOTIFICATION:
2197 			if (len > 0) {
2198 				printer(arg, " <Message ");
2199 				print_string((char *)inp, len, printer, arg);
2200 				printer(arg, ">");
2201 				INCPTR(len, inp);
2202 				len = 0;
2203 			} else {
2204 				printer(arg, " <No message>");
2205 			}
2206 			break;
2207 
2208 		case EAPT_MD5CHAP:
2209 			if (len <= 0)
2210 				break;
2211 			GETCHAR(vallen, inp);
2212 			len--;
2213 			if (vallen > len)
2214 				goto truncated;
2215 			printer(arg, " <Value%.*B>", vallen, inp);
2216 			INCPTR(vallen, inp);
2217 			len -= vallen;
2218 			if (len > 0) {
2219 				printer(arg, " <Name ");
2220 				print_string((char *)inp, len, printer, arg);
2221 				printer(arg, ">");
2222 				INCPTR(len, inp);
2223 				len = 0;
2224 			} else {
2225 				printer(arg, " <No name>");
2226 			}
2227 			break;
2228 
2229 		case EAPT_SRP:
2230 			if (len < 3)
2231 				goto truncated;
2232 			GETCHAR(vallen, inp);
2233 			len--;
2234 			printer(arg, "-%d", vallen);
2235 			switch (vallen) {
2236 			case EAPSRP_CHALLENGE:
2237 				GETCHAR(vallen, inp);
2238 				len--;
2239 				if (vallen >= len)
2240 					goto truncated;
2241 				if (vallen > 0) {
2242 					printer(arg, " <Name ");
2243 					print_string((char *)inp, vallen, printer,
2244 					    arg);
2245 					printer(arg, ">");
2246 				} else {
2247 					printer(arg, " <No name>");
2248 				}
2249 				INCPTR(vallen, inp);
2250 				len -= vallen;
2251 				GETCHAR(vallen, inp);
2252 				len--;
2253 				if (vallen >= len)
2254 					goto truncated;
2255 				printer(arg, " <s%.*B>", vallen, inp);
2256 				INCPTR(vallen, inp);
2257 				len -= vallen;
2258 				GETCHAR(vallen, inp);
2259 				len--;
2260 				if (vallen > len)
2261 					goto truncated;
2262 				if (vallen == 0) {
2263 					printer(arg, " <Default g=2>");
2264 				} else {
2265 					printer(arg, " <g%.*B>", vallen, inp);
2266 				}
2267 				INCPTR(vallen, inp);
2268 				len -= vallen;
2269 				if (len == 0) {
2270 					printer(arg, " <Default N>");
2271 				} else {
2272 					printer(arg, " <N%.*B>", len, inp);
2273 					INCPTR(len, inp);
2274 					len = 0;
2275 				}
2276 				break;
2277 
2278 			case EAPSRP_SKEY:
2279 				printer(arg, " <B%.*B>", len, inp);
2280 				INCPTR(len, inp);
2281 				len = 0;
2282 				break;
2283 
2284 			case EAPSRP_SVALIDATOR:
2285 				if (len < sizeof (u_int32_t))
2286 					break;
2287 				GETLONG(uval, inp);
2288 				len -= sizeof (u_int32_t);
2289 				if (uval & SRPVAL_EBIT) {
2290 					printer(arg, " E");
2291 					uval &= ~SRPVAL_EBIT;
2292 				}
2293 				if (uval != 0) {
2294 					printer(arg, " f<%X>", uval);
2295 				}
2296 				if ((vallen = len) > SHA_DIGESTSIZE)
2297 					vallen = SHA_DIGESTSIZE;
2298 				printer(arg, " <M2%.*B%s>", len, inp,
2299 				    len < SHA_DIGESTSIZE ? "?" : "");
2300 				INCPTR(vallen, inp);
2301 				len -= vallen;
2302 				if (len > 0) {
2303 					printer(arg, " <PN%.*B>", len, inp);
2304 					INCPTR(len, inp);
2305 					len = 0;
2306 				}
2307 				break;
2308 
2309 			case EAPSRP_LWRECHALLENGE:
2310 				printer(arg, " <Challenge%.*B>", len, inp);
2311 				INCPTR(len, inp);
2312 				len = 0;
2313 				break;
2314 			}
2315 			break;
2316 		}
2317 		break;
2318 
2319 	case EAP_RESPONSE:
2320 		if (len < 1)
2321 			break;
2322 		GETCHAR(rtype, inp);
2323 		len--;
2324 		if (rtype >= 1 &&
2325 		    rtype <= sizeof (eap_typenames) / sizeof (char *))
2326 			printer(arg, " %s", eap_typenames[rtype-1]);
2327 		else
2328 			printer(arg, " type=0x%x", rtype);
2329 		switch (rtype) {
2330 		case EAPT_IDENTITY:
2331 			if (len > 0) {
2332 				printer(arg, " <Name ");
2333 				print_string((char *)inp, len, printer, arg);
2334 				printer(arg, ">");
2335 				INCPTR(len, inp);
2336 				len = 0;
2337 			}
2338 			break;
2339 
2340 		case EAPT_NAK:
2341 			if (len <= 0) {
2342 				printer(arg, " <missing hint>");
2343 				break;
2344 			}
2345 			GETCHAR(rtype, inp);
2346 			len--;
2347 			printer(arg, " <Suggested-type %02X", rtype);
2348 			if (rtype >= 1 &&
2349 			    rtype < sizeof (eap_typenames) / sizeof (char *))
2350 				printer(arg, " (%s)", eap_typenames[rtype-1]);
2351 			printer(arg, ">");
2352 			break;
2353 
2354 		case EAPT_MD5CHAP:
2355 			if (len <= 0) {
2356 				printer(arg, " <missing length>");
2357 				break;
2358 			}
2359 			GETCHAR(vallen, inp);
2360 			len--;
2361 			if (vallen > len)
2362 				goto truncated;
2363 			printer(arg, " <Value%.*B>", vallen, inp);
2364 			INCPTR(vallen, inp);
2365 			len -= vallen;
2366 			if (len > 0) {
2367 				printer(arg, " <Name ");
2368 				print_string((char *)inp, len, printer, arg);
2369 				printer(arg, ">");
2370 				INCPTR(len, inp);
2371 				len = 0;
2372 			} else {
2373 				printer(arg, " <No name>");
2374 			}
2375 			break;
2376 
2377 		case EAPT_SRP:
2378 			if (len < 1)
2379 				goto truncated;
2380 			GETCHAR(vallen, inp);
2381 			len--;
2382 			printer(arg, "-%d", vallen);
2383 			switch (vallen) {
2384 			case EAPSRP_CKEY:
2385 				printer(arg, " <A%.*B>", len, inp);
2386 				INCPTR(len, inp);
2387 				len = 0;
2388 				break;
2389 
2390 			case EAPSRP_CVALIDATOR:
2391 				if (len < sizeof (u_int32_t))
2392 					break;
2393 				GETLONG(uval, inp);
2394 				len -= sizeof (u_int32_t);
2395 				if (uval & SRPVAL_EBIT) {
2396 					printer(arg, " E");
2397 					uval &= ~SRPVAL_EBIT;
2398 				}
2399 				if (uval != 0) {
2400 					printer(arg, " f<%X>", uval);
2401 				}
2402 				printer(arg, " <M1%.*B%s>", len, inp,
2403 				    len == SHA_DIGESTSIZE ? "" : "?");
2404 				INCPTR(len, inp);
2405 				len = 0;
2406 				break;
2407 
2408 			case EAPSRP_ACK:
2409 				break;
2410 
2411 			case EAPSRP_LWRECHALLENGE:
2412 				printer(arg, " <Response%.*B%s>", len, inp,
2413 				    len == SHA_DIGESTSIZE ? "" : "?");
2414 				if ((vallen = len) > SHA_DIGESTSIZE)
2415 					vallen = SHA_DIGESTSIZE;
2416 				INCPTR(vallen, inp);
2417 				len -= vallen;
2418 				break;
2419 			}
2420 			break;
2421 		}
2422 		break;
2423 
2424 	case EAP_SUCCESS:	/* No payload expected for these! */
2425 	case EAP_FAILURE:
2426 		break;
2427 
2428 	truncated:
2429 		printer(arg, " <truncated>");
2430 		break;
2431 	}
2432 
2433 	if (len > 8)
2434 		printer(arg, "%8B...", inp);
2435 	else if (len > 0)
2436 		printer(arg, "%.*B", len, inp);
2437 	INCPTR(len, inp);
2438 
2439 	return (inp - pstart);
2440 }
2441