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