dnscrypto-proxy: Support files updated.
[tomato.git] / release / src / router / pppd / pppd / eap.c
blob6ea6c1f8bff6423c4038edb9e47763e111ea0724
1 /*
2 * eap.c - Extensible Authentication Protocol for PPP (RFC 2284)
4 * Copyright (c) 2001 by Sun Microsystems, Inc.
5 * All rights reserved.
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.
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.
18 * Original version by James Carlson
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.
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.
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.
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.
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.
43 * Based on draft-ietf-pppext-eap-srp-03.txt.
46 #define RCSID "$Id: eap.c,v 1.4 2004/11/09 22:39:25 paulus Exp $"
49 * TODO:
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>
63 #include "pppd.h"
64 #include "pathnames.h"
65 #include "md5.h"
66 #include "eap.h"
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 */
75 #ifndef SHA_DIGESTSIZE
76 #define SHA_DIGESTSIZE 20
77 #endif
79 static const char rcsid[] = RCSID;
81 eap_state eap_states[NUM_PPP]; /* EAP state; one for each unit */
82 #ifdef USE_SRP
83 static char *pn_secret = NULL; /* Pseudonym generating secret */
84 #endif
87 * Command-line options.
89 static option_t eap_option_list[] = {
90 { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,
91 "Set retransmit timeout for EAP Requests (server)" },
92 { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,
93 "Set max number of EAP Requests sent (server)" },
94 { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,
95 "Set time limit for peer EAP authentication" },
96 { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,
97 "Set max number of EAP Requests allows (client)" },
98 { "eap-interval", o_int, &eap_states[0].es_rechallenge,
99 "Set interval for EAP rechallenge" },
100 #ifdef USE_SRP
101 { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,
102 "Set interval for SRP lightweight rechallenge" },
103 { "srp-pn-secret", o_string, &pn_secret,
104 "Long term pseudonym generation secret" },
105 { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,
106 "Use pseudonym if offered one by server", 1 },
107 #endif
108 { NULL }
112 * Protocol entry points.
114 static void eap_init __P((int unit));
115 static void eap_input __P((int unit, u_char *inp, int inlen));
116 static void eap_protrej __P((int unit));
117 static void eap_lowerup __P((int unit));
118 static void eap_lowerdown __P((int unit));
119 static int eap_printpkt __P((u_char *inp, int inlen,
120 void (*)(void *arg, char *fmt, ...), void *arg));
122 struct protent eap_protent = {
123 PPP_EAP, /* protocol number */
124 eap_init, /* initialization procedure */
125 eap_input, /* process a received packet */
126 eap_protrej, /* process a received protocol-reject */
127 eap_lowerup, /* lower layer has gone up */
128 eap_lowerdown, /* lower layer has gone down */
129 NULL, /* open the protocol */
130 NULL, /* close the protocol */
131 eap_printpkt, /* print a packet in readable form */
132 NULL, /* process a received data packet */
133 1, /* protocol enabled */
134 "EAP", /* text name of protocol */
135 NULL, /* text name of corresponding data protocol */
136 eap_option_list, /* list of command-line options */
137 NULL, /* check requested options; assign defaults */
138 NULL, /* configure interface for demand-dial */
139 NULL /* say whether to bring up link for this pkt */
143 * A well-known 2048 bit modulus.
145 static const u_char wkmodulus[] = {
146 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
147 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
148 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
149 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
150 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
151 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
152 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
153 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
154 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
155 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
156 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
157 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
158 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
159 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
160 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
161 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
162 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
163 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
164 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
165 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
166 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
167 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
168 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
169 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
170 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
171 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
172 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
173 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
174 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
175 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
176 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
177 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
180 /* Local forward declarations. */
181 static void eap_server_timeout __P((void *arg));
184 * Convert EAP state code to printable string for debug.
186 static const char *
187 eap_state_name(esc)
188 enum eap_state_code esc;
190 static const char *state_names[] = { EAP_STATES };
192 return (state_names[(int)esc]);
196 * eap_init - Initialize state for an EAP user. This is currently
197 * called once by main() during start-up.
199 static void
200 eap_init(unit)
201 int unit;
203 eap_state *esp = &eap_states[unit];
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;
215 * eap_client_timeout - Give up waiting for the peer to send any
216 * Request messages.
218 static void
219 eap_client_timeout(arg)
220 void *arg;
222 eap_state *esp = (eap_state *) arg;
224 if (!eap_client_active(esp))
225 return;
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;
233 * eap_authwithpeer - Authenticate to our peer (behave as client).
235 * Start client state and wait for requests. This is called only
236 * after eap_lowerup.
238 void
239 eap_authwithpeer(unit, localname)
240 int unit;
241 char *localname;
243 eap_state *esp = &eap_states[unit];
245 /* Save the peer name we're given */
246 esp->es_client.ea_name = localname;
247 esp->es_client.ea_namelen = strlen(localname);
249 esp->es_client.ea_state = eapListen;
252 * Start a timer so that if the other end just goes
253 * silent, we don't sit here waiting forever.
255 if (esp->es_client.ea_timeout > 0)
256 TIMEOUT(eap_client_timeout, (void *)esp,
257 esp->es_client.ea_timeout);
261 * Format a standard EAP Failure message and send it to the peer.
262 * (Server operation)
264 static void
265 eap_send_failure(esp)
266 eap_state *esp;
268 u_char *outp;
270 outp = outpacket_buf;
272 MAKEHEADER(outp, PPP_EAP);
274 PUTCHAR(EAP_FAILURE, outp);
275 esp->es_server.ea_id++;
276 PUTCHAR(esp->es_server.ea_id, outp);
277 PUTSHORT(EAP_HEADERLEN, outp);
279 output(esp->es_unit, outpacket_buf, EAP_HEADERLEN + PPP_HDRLEN);
281 esp->es_server.ea_state = eapBadAuth;
282 auth_peer_fail(esp->es_unit, PPP_EAP);
286 * Format a standard EAP Success message and send it to the peer.
287 * (Server operation)
289 static void
290 eap_send_success(esp)
291 eap_state *esp;
293 u_char *outp;
295 outp = outpacket_buf;
297 MAKEHEADER(outp, PPP_EAP);
299 PUTCHAR(EAP_SUCCESS, outp);
300 esp->es_server.ea_id++;
301 PUTCHAR(esp->es_server.ea_id, outp);
302 PUTSHORT(EAP_HEADERLEN, outp);
304 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);
306 auth_peer_success(esp->es_unit, PPP_EAP, 0,
307 esp->es_server.ea_peer, esp->es_server.ea_peerlen);
310 #ifdef USE_SRP
312 * Set DES key according to pseudonym-generating secret and current
313 * date.
315 static bool
316 pncrypt_setkey(int timeoffs)
318 struct tm *tp;
319 char tbuf[9];
320 SHA1_CTX ctxt;
321 u_char dig[SHA_DIGESTSIZE];
322 time_t reftime;
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));
336 static char base64[] =
337 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
339 struct b64state {
340 u_int32_t bs_bits;
341 int bs_offs;
344 static int
345 b64enc(bs, inp, inlen, outp)
346 struct b64state *bs;
347 u_char *inp;
348 int inlen;
349 u_char *outp;
351 int outlen = 0;
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;
367 return (outlen);
370 static int
371 b64flush(bs, outp)
372 struct b64state *bs;
373 u_char *outp;
375 int outlen = 0;
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;
387 bs->bs_offs = 0;
388 bs->bs_bits = 0;
389 return (outlen);
392 static int
393 b64dec(bs, inp, inlen, outp)
394 struct b64state *bs;
395 u_char *inp;
396 int inlen;
397 u_char *outp;
399 int outlen = 0;
400 char *cp;
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;
414 return (outlen);
416 #endif /* USE_SRP */
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.
424 static void
425 eap_figure_next_state(esp, status)
426 eap_state *esp;
427 int status;
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 */
440 esp->es_server.ea_timeout = esp->es_savedtime;
441 switch (esp->es_server.ea_state) {
442 case eapBadAuth:
443 return;
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;
454 #endif /* USE_SRP */
455 if (status != 0) {
456 esp->es_server.ea_state = eapBadAuth;
457 break;
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;
480 id = *(unsigned char *)clear;
481 if (id + 1 <= plen && id + 9 > plen)
482 break;
484 if (plen % 8 == 0 && i < 5) {
486 * Note that this is always shorter than the
487 * original stored string, so there's no need
488 * to realloc.
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;
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;
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) {
533 * Client will have to verify this modulus/
534 * generator combination, and that will take
535 * a while. Lengthen the timeout here.
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;
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;
564 #endif /* USE_SRP */
565 esp->es_server.ea_state = eapMD5Chall;
566 break;
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;
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;
584 break;
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;
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;
600 break;
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;
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;
617 break;
619 case eapMD5Chall:
620 if (status != 0) {
621 esp->es_server.ea_state = eapBadAuth;
622 } else {
623 esp->es_server.ea_state = eapOpen;
625 break;
627 default:
628 esp->es_server.ea_state = eapBadAuth;
629 break;
631 if (esp->es_server.ea_state == eapBadAuth)
632 eap_send_failure(esp);
636 * Format an EAP Request message and send it to the peer. Message
637 * type depends on current state. (Server operation)
639 static void
640 eap_send_request(esp)
641 eap_state *esp;
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 */
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) {
663 * If we already know the peer's
664 * unauthenticated name, then there's no
665 * reason to ask. Go to next state instead.
667 esp->es_server.ea_peer = remote_name;
668 esp->es_server.ea_peerlen = strlen(remote_name);
669 eap_figure_next_state(esp, 0);
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;
683 outp = outpacket_buf;
685 MAKEHEADER(outp, PPP_EAP);
687 PUTCHAR(EAP_REQUEST, outp);
688 PUTCHAR(esp->es_server.ea_id, outp);
689 lenloc = outp;
690 INCPTR(2, outp);
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;
701 case eapMD5Chall:
702 PUTCHAR(EAPT_MD5CHAP, outp);
704 * pick a random challenge length between
705 * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
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;
721 #ifdef USE_SRP
722 case eapSRP1:
723 PUTCHAR(EAPT_SRP, outp);
724 PUTCHAR(EAPSRP_CHALLENGE, outp);
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);
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);
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);
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);
749 break;
751 case eapSRP2:
752 PUTCHAR(EAPT_SRP, outp);
753 PUTCHAR(EAPSRP_SKEY, outp);
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;
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);
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;
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;
793 if (i > 0) {
794 BCOPY(cp, clear, i);
795 cp += i;
796 while (i < 8) {
797 *cp++ = drand48() * 0x100;
798 i++;
800 (void) DesEncrypt(clear, cipher);
801 outp += b64enc(&b64, cipher, 8, outp);
803 outp += b64flush(&b64, outp);
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++;
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);
836 break;
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 */
852 default:
853 return;
856 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
857 PUTSHORT(outlen, lenloc);
859 output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
861 esp->es_server.ea_requests++;
863 if (esp->es_server.ea_timeout > 0)
864 TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
868 * eap_authpeer - Authenticate our peer (behave as server).
870 * Start server state and send first request. This is called only
871 * after eap_lowerup.
873 void
874 eap_authpeer(unit, localname)
875 int unit;
876 char *localname;
878 eap_state *esp = &eap_states[unit];
880 /* Save the name we're given. */
881 esp->es_server.ea_name = localname;
882 esp->es_server.ea_namelen = strlen(localname);
884 esp->es_savedtime = esp->es_server.ea_timeout;
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;
893 esp->es_server.ea_state = eapPending;
895 /* ID number not updated here intentionally; hashed into M1 */
896 eap_send_request(esp);
900 * eap_server_timeout - Retransmission timer for sending Requests
901 * expired.
903 static void
904 eap_server_timeout(arg)
905 void *arg;
907 eap_state *esp = (eap_state *) arg;
909 if (!eap_server_active(esp))
910 return;
912 /* EAP ID number must not change on timeout. */
913 eap_send_request(esp);
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.
921 static void
922 eap_rechallenge(arg)
923 void *arg;
925 eap_state *esp = (eap_state *)arg;
927 if (esp->es_server.ea_state != eapOpen &&
928 esp->es_server.ea_state != eapSRP4)
929 return;
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);
938 static void
939 srp_lwrechallenge(arg)
940 void *arg;
942 eap_state *esp = (eap_state *)arg;
944 if (esp->es_server.ea_state != eapOpen ||
945 esp->es_server.ea_type != EAPT_SRP)
946 return;
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);
955 * eap_lowerup - The lower layer is now up.
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.
962 static void
963 eap_lowerup(unit)
964 int unit;
966 eap_state *esp = &eap_states[unit];
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;
977 esp->es_client.ea_state = eapClosed;
978 esp->es_server.ea_state = eapClosed;
982 * eap_lowerdown - The lower layer is now down.
984 * Cancel all timeouts and return to initial state.
986 static void
987 eap_lowerdown(unit)
988 int unit;
990 eap_state *esp = &eap_states[unit];
992 if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) {
993 UNTIMEOUT(eap_client_timeout, (void *)esp);
995 if (eap_server_active(esp)) {
996 if (esp->es_server.ea_timeout > 0) {
997 UNTIMEOUT(eap_server_timeout, (void *)esp);
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);
1005 if (esp->es_server.ea_state == eapOpen &&
1006 esp->es_lwrechallenge > 0) {
1007 UNTIMEOUT(srp_lwrechallenge, (void *)esp);
1011 esp->es_client.ea_state = esp->es_server.ea_state = eapInitial;
1012 esp->es_client.ea_requests = esp->es_server.ea_requests = 0;
1016 * eap_protrej - Peer doesn't speak this protocol.
1018 * This shouldn't happen. If it does, it represents authentication
1019 * failure.
1021 static void
1022 eap_protrej(unit)
1023 int unit;
1025 eap_state *esp = &eap_states[unit];
1027 if (eap_client_active(esp)) {
1028 error("EAP authentication failed due to Protocol-Reject");
1029 auth_withpeer_fail(unit, PPP_EAP);
1031 if (eap_server_active(esp)) {
1032 error("EAP authentication of peer failed on Protocol-Reject");
1033 auth_peer_fail(unit, PPP_EAP);
1035 eap_lowerdown(unit);
1039 * Format and send a regular EAP Response message.
1041 static void
1042 eap_send_response(esp, id, typenum, str, lenstr)
1043 eap_state *esp;
1044 u_char id;
1045 u_char typenum;
1046 u_char *str;
1047 int lenstr;
1049 u_char *outp;
1050 int msglen;
1052 outp = outpacket_buf;
1054 MAKEHEADER(outp, PPP_EAP);
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);
1066 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1070 * Format and send an MD5-Challenge EAP Response message.
1072 static void
1073 eap_chap_response(esp, id, hash, name, namelen)
1074 eap_state *esp;
1075 u_char id;
1076 u_char *hash;
1077 char *name;
1078 int namelen;
1080 u_char *outp;
1081 int msglen;
1083 outp = outpacket_buf;
1085 MAKEHEADER(outp, PPP_EAP);
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);
1101 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1104 #ifdef USE_SRP
1106 * Format and send a SRP EAP Response message.
1108 static void
1109 eap_srp_response(esp, id, subtypenum, str, lenstr)
1110 eap_state *esp;
1111 u_char id;
1112 u_char subtypenum;
1113 u_char *str;
1114 int lenstr;
1116 u_char *outp;
1117 int msglen;
1119 outp = outpacket_buf;
1121 MAKEHEADER(outp, PPP_EAP);
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);
1134 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1138 * Format and send a SRP EAP Client Validator Response message.
1140 static void
1141 eap_srpval_response(esp, id, flags, str)
1142 eap_state *esp;
1143 u_char id;
1144 u_int32_t flags;
1145 u_char *str;
1147 u_char *outp;
1148 int msglen;
1150 outp = outpacket_buf;
1152 MAKEHEADER(outp, PPP_EAP);
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);
1165 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1167 #endif /* USE_SRP */
1169 static void
1170 eap_send_nak(esp, id, type)
1171 eap_state *esp;
1172 u_char id;
1173 u_char type;
1175 u_char *outp;
1176 int msglen;
1178 outp = outpacket_buf;
1180 MAKEHEADER(outp, PPP_EAP);
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);
1190 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1193 #ifdef USE_SRP
1194 static char *
1195 name_of_pn_file()
1197 char *user, *path, *file;
1198 struct passwd *pw;
1199 size_t pl;
1200 static bool pnlogged = 0;
1202 pw = getpwuid(getuid());
1203 if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
1204 errno = EINVAL;
1205 return (NULL);
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;
1217 return (path);
1220 static int
1221 open_pn_file(modebits)
1222 mode_t modebits;
1224 char *path;
1225 int fd, err;
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);
1236 static void
1237 remove_pn_file()
1239 char *path;
1241 if ((path = name_of_pn_file()) != NULL) {
1242 (void) unlink(path);
1243 (void) free(path);
1247 static void
1248 write_pseudonym(esp, inp, len, id)
1249 eap_state *esp;
1250 u_char *inp;
1251 int len, id;
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;
1260 * Do the decoding by working backwards. This eliminates the need
1261 * to save the decoded output in a separate buffer.
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);
1278 SHA1Final(dig, &ctxt);
1279 for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++)
1280 *datp++ ^= *digp;
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;
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;
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();
1304 #endif /* USE_SRP */
1307 * eap_request - Receive EAP Request message (client mode).
1309 static void
1310 eap_request(esp, inp, id, len)
1311 eap_state *esp;
1312 u_char *inp;
1313 int id;
1314 int len;
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 */
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.
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);
1345 auth_withpeer_fail(esp->es_unit, PPP_EAP);
1346 return;
1349 if (len <= 0) {
1350 error("EAP: empty Request message discarded");
1351 return;
1354 GETCHAR(typenum, inp);
1355 len--;
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);
1377 (void) close(fd);
1378 if (len > 0)
1379 break;
1382 /* Stop using pseudonym now. */
1383 if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
1384 remove_pn_file();
1385 esp->es_usedpseudo = 2;
1387 #endif /* USE_SRP */
1388 eap_send_response(esp, id, typenum, esp->es_client.ea_name,
1389 esp->es_client.ea_namelen);
1390 break;
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;
1398 case EAPT_NAK:
1400 * Avoid the temptation to send Response Nak in reply
1401 * to Request Nak here. It can only lead to trouble.
1403 warn("EAP: unexpected Nak in Request; ignored");
1404 /* Return because we're waiting for something real. */
1405 return;
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;
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;
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';
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));
1439 * Get the secret for authenticating ourselves with
1440 * the specified host.
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;
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;
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;
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;
1477 * If this is a new challenge, then start
1478 * over with a new client session context.
1479 * Otherwise, just resend last response.
1481 if (id != esp->es_client.ea_id) {
1482 t_clientclose(tc);
1483 esp->es_client.ea_session = NULL;
1484 tc = NULL;
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;
1498 BCOPY(inp, rhostname, vallen);
1499 rhostname[vallen] = '\0';
1500 INCPTR(vallen, inp);
1501 len -= vallen;
1504 * In case the remote doesn't give us his name,
1505 * use configured name.
1507 if (explicit_remote ||
1508 (remote_name[0] != '\0' && vallen == 0)) {
1509 strlcpy(rhostname, remote_name,
1510 sizeof (rhostname));
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);
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;
1526 sval.data = inp;
1527 sval.len = vallen;
1528 INCPTR(vallen, inp);
1529 len -= vallen;
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;
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;
1547 INCPTR(vallen, inp);
1548 len -= vallen;
1551 * If no modulus present, then use well-known
1552 * value.
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;
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;
1567 esp->es_client.ea_session = (void *)tc;
1569 /* Add Challenge ID & type to verifier */
1570 vals[0] = id;
1571 vals[1] = EAPT_SRP;
1572 t_clientaddexdata(tc, vals, 2);
1574 Ap = t_clientgenexp(tc);
1575 eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
1576 Ap->len);
1577 break;
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;
1586 if (esp->es_client.ea_skey != NULL) {
1588 * ID number should not change here. Warn
1589 * if it does (but otherwise ignore).
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);
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) {
1601 * Can't work with this peer because
1602 * the secret is missing. Just give
1603 * up.
1605 eap_send_nak(esp, id, EAPT_MD5CHAP);
1606 break;
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;
1620 eap_srpval_response(esp, id, SRPVAL_EBIT,
1621 t_clientresponse(tc));
1622 break;
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;
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.
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);
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;
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);
1658 * We've verified our peer. We're now mostly done,
1659 * except for waiting on the regular EAP Success
1660 * message.
1662 eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
1663 break;
1665 case EAPSRP_LWRECHALLENGE:
1666 if (len < 4) {
1667 warn("EAP: malformed Lightweight rechallenge");
1668 return;
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;
1683 default:
1684 error("EAP: unknown SRP Subtype %d", vallen);
1685 eap_send_nak(esp, id, EAPT_MD5CHAP);
1686 break;
1688 break;
1689 #endif /* USE_SRP */
1691 default:
1692 info("EAP: unknown authentication type %d; Naking", typenum);
1693 eap_send_nak(esp, id, EAPT_SRP);
1694 break;
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);
1702 return;
1704 #ifdef USE_SRP
1705 client_failure:
1706 esp->es_client.ea_state = eapBadAuth;
1707 if (esp->es_client.ea_timeout > 0) {
1708 UNTIMEOUT(eap_client_timeout, (void *)esp);
1710 esp->es_client.ea_session = NULL;
1711 t_clientclose(tc);
1712 auth_withpeer_fail(esp->es_unit, PPP_EAP);
1713 #endif /* USE_SRP */
1717 * eap_response - Receive EAP Response message (server mode).
1719 static void
1720 eap_response(esp, inp, id, len)
1721 eap_state *esp;
1722 u_char *inp;
1723 int id;
1724 int len;
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 */
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;
1746 esp->es_server.ea_responses++;
1748 if (len <= 0) {
1749 error("EAP: empty Response message discarded");
1750 return;
1753 GETCHAR(typenum, inp);
1754 len--;
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;
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;
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;
1779 case EAPT_NOTIFICATION:
1780 dbglog("EAP unexpected Notification; response discarded");
1781 break;
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;
1790 GETCHAR(vallen, inp);
1791 len--;
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;
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;
1806 case EAPT_MD5CHAP:
1807 esp->es_server.ea_state = eapMD5Chall;
1808 break;
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;
1826 break;
1828 break;
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;
1836 if (len < 1) {
1837 error("EAP: received MD5-Response with no data");
1838 eap_figure_next_state(esp, 1);
1839 break;
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;
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';
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));
1865 * Get the secret for authenticating the specified
1866 * host.
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;
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;
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;
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;
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;
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);
1919 break;
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;
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;
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;
1941 eap_figure_next_state(esp, 0);
1942 break;
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;
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;
1961 case EAPSRP_LWRECHALLENGE:
1962 if (esp->es_server.ea_state != eapSRP4) {
1963 info("EAP: unexpected SRP Subtype 4 Response");
1964 return;
1966 if (len != SHA_DIGESTSIZE) {
1967 error("EAP: bad Lightweight rechallenge "
1968 "response");
1969 return;
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;
1985 esp->es_server.ea_state = eapOpen;
1986 if (esp->es_lwrechallenge != 0)
1987 TIMEOUT(srp_lwrechallenge, esp,
1988 esp->es_lwrechallenge);
1989 break;
1991 break;
1992 #endif /* USE_SRP */
1994 default:
1995 /* This can't happen. */
1996 error("EAP: unknown Response type %d; ignored", typenum);
1997 return;
2000 if (esp->es_server.ea_timeout > 0) {
2001 UNTIMEOUT(eap_server_timeout, (void *)esp);
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);
2012 * eap_success - Receive EAP Success message (client mode).
2014 static void
2015 eap_success(esp, inp, id, len)
2016 eap_state *esp;
2017 u_char *inp;
2018 int id;
2019 int len;
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;
2028 if (esp->es_client.ea_timeout > 0) {
2029 UNTIMEOUT(eap_client_timeout, (void *)esp);
2032 if (len > 0) {
2033 /* This is odd. The spec doesn't allow for this. */
2034 PRINTMSG(inp, len);
2037 esp->es_client.ea_state = eapOpen;
2038 auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2042 * eap_failure - Receive EAP Failure message (client mode).
2044 static void
2045 eap_failure(esp, inp, id, len)
2046 eap_state *esp;
2047 u_char *inp;
2048 int id;
2049 int len;
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);
2057 if (esp->es_client.ea_timeout > 0) {
2058 UNTIMEOUT(eap_client_timeout, (void *)esp);
2061 if (len > 0) {
2062 /* This is odd. The spec doesn't allow for this. */
2063 PRINTMSG(inp, len);
2066 esp->es_client.ea_state = eapBadAuth;
2068 error("EAP: peer reports authentication failure");
2069 auth_withpeer_fail(esp->es_unit, PPP_EAP);
2073 * eap_input - Handle received EAP message.
2075 static void
2076 eap_input(unit, inp, inlen)
2077 int unit;
2078 u_char *inp;
2079 int inlen;
2081 eap_state *esp = &eap_states[unit];
2082 u_char code, id;
2083 int len;
2086 * Parse header (code, id and length). If packet too short,
2087 * drop it.
2089 if (inlen < EAP_HEADERLEN) {
2090 error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2091 return;
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;
2101 len -= EAP_HEADERLEN;
2103 /* Dispatch based on message code */
2104 switch (code) {
2105 case EAP_REQUEST:
2106 eap_request(esp, inp, id, len);
2107 break;
2109 case EAP_RESPONSE:
2110 eap_response(esp, inp, id, len);
2111 break;
2113 case EAP_SUCCESS:
2114 eap_success(esp, inp, id, len);
2115 break;
2117 case EAP_FAILURE:
2118 eap_failure(esp, inp, id, len);
2119 break;
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;
2129 * eap_printpkt - print the contents of an EAP packet.
2131 static char *eap_codenames[] = {
2132 "Request", "Response", "Success", "Failure"
2135 static char *eap_typenames[] = {
2136 "Identity", "Notification", "Nak", "MD5-Challenge",
2137 "OTP", "Generic-Token", NULL, NULL,
2138 "RSA", "DSS", "KEA", "KEA-Validate",
2139 "TLS", "Defender", "Windows 2000", "Arcot",
2140 "Cisco", "Nokia", "SRP"
2143 static int
2144 eap_printpkt(inp, inlen, printer, arg)
2145 u_char *inp;
2146 int inlen;
2147 void (*printer) __P((void *, char *, ...));
2148 void *arg;
2150 int code, id, len, rtype, vallen;
2151 u_char *pstart;
2152 u_int32_t uval;
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);
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;
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>");
2194 break;
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>");
2215 break;
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>");
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);
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;
2264 break;
2266 case EAPSRP_SKEY:
2267 printer(arg, " <B%.*B>", len, inp);
2268 INCPTR(len, inp);
2269 len = 0;
2270 break;
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;
2281 if (uval != 0) {
2282 printer(arg, " f<%X>", uval);
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;
2295 break;
2297 case EAPSRP_LWRECHALLENGE:
2298 printer(arg, " <Challenge%.*B>", len, inp);
2299 INCPTR(len, inp);
2300 len = 0;
2301 break;
2303 break;
2305 break;
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;
2326 break;
2328 case EAPT_NAK:
2329 if (len <= 0) {
2330 printer(arg, " <missing hint>");
2331 break;
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;
2342 case EAPT_MD5CHAP:
2343 if (len <= 0) {
2344 printer(arg, " <missing length>");
2345 break;
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>");
2363 break;
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;
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;
2387 if (uval != 0) {
2388 printer(arg, " f<%X>", uval);
2390 printer(arg, " <M1%.*B%s>", len, inp,
2391 len == SHA_DIGESTSIZE ? "" : "?");
2392 INCPTR(len, inp);
2393 len = 0;
2394 break;
2396 case EAPSRP_ACK:
2397 break;
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;
2408 break;
2410 break;
2412 case EAP_SUCCESS: /* No payload expected for these! */
2413 case EAP_FAILURE:
2414 break;
2416 truncated:
2417 printer(arg, " <truncated>");
2418 break;
2421 if (len > 8)
2422 printer(arg, "%8B...", inp);
2423 else if (len > 0)
2424 printer(arg, "%.*B", len, inp);
2425 INCPTR(len, inp);
2427 return (inp - pstart);