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