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
79static const char rcsid[] = RCSID;
80
81eap_state eap_states[NUM_PPP];		/* EAP state; one for each unit */
82#ifdef USE_SRP
83static char *pn_secret = NULL;		/* Pseudonym generating secret */
84#endif
85
86/*
87 * Command-line options.
88 */
89static 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 */
114static void eap_init __P((int unit));
115static void eap_input __P((int unit, u_char *inp, int inlen));
116static void eap_protrej __P((int unit));
117static void eap_lowerup __P((int unit));
118static void eap_lowerdown __P((int unit));
119static int  eap_printpkt __P((u_char *inp, int inlen,
120    void (*)(void *arg, char *fmt, ...), void *arg));
121
122struct 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 */
145static 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. */
181static void eap_server_timeout __P((void *arg));
182
183/*
184 * Convert EAP state code to printable string for debug.
185 */
186static const char *
187eap_state_name(esc)
188enum 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 */
199static void
200eap_init(unit)
201int 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 */
218static void
219eap_client_timeout(arg)
220void *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 */
238void
239eap_authwithpeer(unit, localname)
240int unit;
241char *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 */
264static void
265eap_send_failure(esp)
266eap_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 */
289static void
290eap_send_success(esp)
291eap_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 */
315static bool
316pncrypt_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
336static char base64[] =
337"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
338
339struct b64state {
340	u_int32_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/*
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 */
424static void
425eap_figure_next_state(esp, status)
426eap_state *esp;
427int 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 */
639static void
640eap_send_request(esp)
641eap_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 */
873void
874eap_authpeer(unit, localname)
875int unit;
876char *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 */
903static void
904eap_server_timeout(arg)
905void *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 */
921static void
922eap_rechallenge(arg)
923void *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
938static void
939srp_lwrechallenge(arg)
940void *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 */
962static void
963eap_lowerup(unit)
964int 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 */
986static void
987eap_lowerdown(unit)
988int 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 */
1021static void
1022eap_protrej(unit)
1023int 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 */
1041static void
1042eap_send_response(esp, id, typenum, str, lenstr)
1043eap_state *esp;
1044u_char id;
1045u_char typenum;
1046u_char *str;
1047int 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 */
1072static void
1073eap_chap_response(esp, id, hash, name, namelen)
1074eap_state *esp;
1075u_char id;
1076u_char *hash;
1077char *name;
1078int 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 */
1108static void
1109eap_srp_response(esp, id, subtypenum, str, lenstr)
1110eap_state *esp;
1111u_char id;
1112u_char subtypenum;
1113u_char *str;
1114int 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 */
1140static void
1141eap_srpval_response(esp, id, flags, str)
1142eap_state *esp;
1143u_char id;
1144u_int32_t flags;
1145u_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
1169static void
1170eap_send_nak(esp, id, type)
1171eap_state *esp;
1172u_char id;
1173u_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
1194static char *
1195name_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
1220static int
1221open_pn_file(modebits)
1222mode_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
1236static void
1237remove_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
1247static void
1248write_pseudonym(esp, inp, len, id)
1249eap_state *esp;
1250u_char *inp;
1251int 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 */
1309static void
1310eap_request(esp, inp, id, len)
1311eap_state *esp;
1312u_char *inp;
1313int id;
1314int 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 (vallen >= len + 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
1705client_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 */
1719static void
1720eap_response(esp, inp, id, len)
1721eap_state *esp;
1722u_char *inp;
1723int id;
1724int 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 (vallen >= len + 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 */
2014static void
2015eap_success(esp, inp, id, len)
2016eap_state *esp;
2017u_char *inp;
2018int id;
2019int 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 */
2044static void
2045eap_failure(esp, inp, id, len)
2046eap_state *esp;
2047u_char *inp;
2048int id;
2049int 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 */
2075static void
2076eap_input(unit, inp, inlen)
2077int unit;
2078u_char *inp;
2079int 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 */
2131static char *eap_codenames[] = {
2132	"Request", "Response", "Success", "Failure"
2133};
2134
2135static 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
2143static int
2144eap_printpkt(inp, inlen, printer, arg)
2145u_char *inp;
2146int inlen;
2147void (*printer) __P((void *, char *, ...));
2148void *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