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