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