eap.c revision 1.6.8.1 1 /* $NetBSD: eap.c,v 1.6.8.1 2025/08/02 05:23:15 perseant Exp $ */
2 /*
3 * eap.c - Extensible Authentication Protocol for PPP (RFC 2284)
4 *
5 * Copyright (c) 2001 by Sun Microsystems, Inc.
6 * All rights reserved.
7 *
8 * Non-exclusive rights to redistribute, modify, translate, and use
9 * this software in source and binary forms, in whole or in part, is
10 * hereby granted, provided that the above copyright notice is
11 * duplicated in any source form, and that neither the name of the
12 * copyright holder nor the author is used to endorse or promote
13 * products derived from this software.
14 *
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * Original version by James Carlson
20 *
21 * This implementation of EAP supports MD5-Challenge and SRP-SHA1
22 * authentication styles. Note that support of MD5-Challenge is a
23 * requirement of RFC 2284, and that it's essentially just a
24 * reimplementation of regular RFC 1994 CHAP using EAP messages.
25 *
26 * As an authenticator ("server"), there are multiple phases for each
27 * style. In the first phase of each style, the unauthenticated peer
28 * name is queried using the EAP Identity request type. If the
29 * "remotename" option is used, then this phase is skipped, because
30 * the peer's name is presumed to be known.
31 *
32 * For MD5-Challenge, there are two phases, and the second phase
33 * consists of sending the challenge itself and handling the
34 * associated response.
35 *
36 * For SRP-SHA1, there are four phases. The second sends 's', 'N',
37 * and 'g'. The reply contains 'A'. The third sends 'B', and the
38 * reply contains 'M1'. The forth sends the 'M2' value.
39 *
40 * As an authenticatee ("client"), there's just a single phase --
41 * responding to the queries generated by the peer. EAP is an
42 * authenticator-driven protocol.
43 *
44 * Based on draft-ietf-pppext-eap-srp-03.txt.
45 */
46
47 #include <sys/cdefs.h>
48 __RCSID("$NetBSD: eap.c,v 1.6.8.1 2025/08/02 05:23:15 perseant Exp $");
49
50 /*
51 * Modification by Beniamino Galvani, Mar 2005
52 * Implemented EAP-TLS authentication
53 */
54
55 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <unistd.h>
63 #include <pwd.h>
64 #include <sys/types.h>
65 #include <sys/stat.h>
66 #include <fcntl.h>
67 #include <assert.h>
68 #include <errno.h>
69 #include <md5.h>
70
71 #include "pppd-private.h"
72 #include "options.h"
73 #include "pathnames.h"
74 #include "crypto.h"
75 #include "crypto_ms.h"
76 #include "eap.h"
77 #ifdef PPP_WITH_PEAP
78 #include "peap.h"
79 #endif /* PPP_WITH_PEAP */
80
81 #ifdef PPP_WITH_SRP
82 #ifdef HAVE_TIME_H
83 #include <time.h>
84 #endif
85 #include <t_pwd.h>
86 #include <t_server.h>
87 #include <t_client.h>
88 #endif /* PPP_WITH_SRP */
89
90 #ifdef PPP_WITH_EAPTLS
91 #include "eap-tls.h"
92 #endif /* PPP_WITH_EAPTLS */
93
94 #ifdef PPP_WITH_CHAPMS
95 #include "chap.h"
96 #include "chap_ms.h"
97
98 extern int chapms_strip_domain;
99 #endif /* PPP_WITH_CHAPMS */
100
101 eap_state eap_states[NUM_PPP]; /* EAP state; one for each unit */
102 #ifdef PPP_WITH_SRP
103 static char *pn_secret = NULL; /* Pseudonym generating secret */
104 #endif
105
106 /*
107 * Command-line options.
108 */
109 static struct option eap_option_list[] = {
110 { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,
111 "Set retransmit timeout for EAP Requests (server)" },
112 { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,
113 "Set max number of EAP Requests sent (server)" },
114 { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,
115 "Set time limit for peer EAP authentication" },
116 { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,
117 "Set max number of EAP Requests allows (client)" },
118 { "eap-interval", o_int, &eap_states[0].es_rechallenge,
119 "Set interval for EAP rechallenge" },
120 #ifdef PPP_WITH_SRP
121 { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,
122 "Set interval for SRP lightweight rechallenge" },
123 { "srp-pn-secret", o_string, &pn_secret,
124 "Long term pseudonym generation secret" },
125 { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,
126 "Use pseudonym if offered one by server", 1 },
127 #endif
128 { NULL }
129 };
130
131 /*
132 * Protocol entry points.
133 */
134 static void eap_init (int unit);
135 static void eap_input (int unit, u_char *inp, int inlen);
136 static void eap_protrej (int unit);
137 static void eap_lowerup (int unit);
138 static void eap_lowerdown (int unit);
139 static int eap_printpkt (u_char *inp, int inlen,
140 void (*)(void *arg, char *fmt, ...), void *arg);
141
142 struct protent eap_protent = {
143 PPP_EAP, /* protocol number */
144 eap_init, /* initialization procedure */
145 eap_input, /* process a received packet */
146 eap_protrej, /* process a received protocol-reject */
147 eap_lowerup, /* lower layer has gone up */
148 eap_lowerdown, /* lower layer has gone down */
149 NULL, /* open the protocol */
150 NULL, /* close the protocol */
151 eap_printpkt, /* print a packet in readable form */
152 NULL, /* process a received data packet */
153 1, /* protocol enabled */
154 "EAP", /* text name of protocol */
155 NULL, /* text name of corresponding data protocol */
156 eap_option_list, /* list of command-line options */
157 NULL, /* check requested options; assign defaults */
158 NULL, /* configure interface for demand-dial */
159 NULL /* say whether to bring up link for this pkt */
160 };
161
162 #ifdef PPP_WITH_SRP
163 /*
164 * A well-known 2048 bit modulus.
165 */
166 static const u_char wkmodulus[] = {
167 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
168 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
169 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
170 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
171 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
172 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
173 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
174 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
175 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
176 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
177 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
178 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
179 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
180 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
181 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
182 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
183 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
184 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
185 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
186 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
187 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
188 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
189 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
190 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
191 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
192 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
193 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
194 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
195 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
196 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
197 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
198 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
199 };
200 #endif /* PPP_WITH_SRP */
201
202 /* Local forward declarations. */
203 static void eap_server_timeout (void *arg);
204
205 /*
206 * Convert EAP state code to printable string for debug.
207 */
208 static const char *
209 eap_state_name(enum eap_state_code esc)
210 {
211 static const char *state_names[] = { EAP_STATES };
212
213 return (state_names[(int)esc]);
214 }
215
216 /*
217 * eap_init - Initialize state for an EAP user. This is currently
218 * called once by main() during start-up.
219 */
220 static void
221 eap_init(int unit)
222 {
223 eap_state *esp = &eap_states[unit];
224
225 BZERO(esp, sizeof (*esp));
226 esp->es_unit = unit;
227 esp->es_server.ea_timeout = EAP_DEFTIMEOUT;
228 esp->es_server.ea_maxrequests = EAP_DEFTRANSMITS;
229 esp->es_server.ea_id = (u_char)(drand48() * 0x100);
230 esp->es_client.ea_timeout = EAP_DEFREQTIME;
231 esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
232 #ifdef PPP_WITH_EAPTLS
233 esp->es_client.ea_using_eaptls = 0;
234 #endif /* PPP_WITH_EAPTLS */
235 #ifdef PPP_WITH_CHAPMS
236 esp->es_client.digest = chap_find_digest(CHAP_MICROSOFT_V2);
237 esp->es_server.digest = chap_find_digest(CHAP_MICROSOFT_V2);
238 #endif
239 }
240
241 /*
242 * eap_client_timeout - Give up waiting for the peer to send any
243 * Request messages.
244 */
245 static void
246 eap_client_timeout(void *arg)
247 {
248 eap_state *esp = (eap_state *) arg;
249
250 if (!eap_client_active(esp))
251 return;
252
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;
256 }
257
258 /*
259 * eap_authwithpeer - Authenticate to our peer (behave as client).
260 *
261 * Start client state and wait for requests. This is called only
262 * after eap_lowerup.
263 */
264 void
265 eap_authwithpeer(int unit, char *localname)
266 {
267 eap_state *esp = &eap_states[unit];
268
269 /* Save the peer name we're given */
270 esp->es_client.ea_name = localname;
271 esp->es_client.ea_namelen = strlen(localname);
272
273 esp->es_client.ea_state = eapListen;
274
275 /*
276 * Start a timer so that if the other end just goes
277 * silent, we don't sit here waiting forever.
278 */
279 if (esp->es_client.ea_timeout > 0)
280 TIMEOUT(eap_client_timeout, (void *)esp,
281 esp->es_client.ea_timeout);
282 }
283
284 /*
285 * Format a standard EAP Failure message and send it to the peer.
286 * (Server operation)
287 */
288 static void
289 eap_send_failure(eap_state *esp)
290 {
291 u_char *outp;
292
293 outp = outpacket_buf;
294
295 MAKEHEADER(outp, PPP_EAP);
296
297 PUTCHAR(EAP_FAILURE, outp);
298 esp->es_server.ea_id++;
299 PUTCHAR(esp->es_server.ea_id, outp);
300 PUTSHORT(EAP_HEADERLEN, outp);
301
302 output(esp->es_unit, outpacket_buf, EAP_HEADERLEN + PPP_HDRLEN);
303
304 esp->es_server.ea_state = eapBadAuth;
305 auth_peer_fail(esp->es_unit, PPP_EAP);
306 }
307
308 /*
309 * Format a standard EAP Success message and send it to the peer.
310 * (Server operation)
311 */
312 static void
313 eap_send_success(eap_state *esp)
314 {
315 u_char *outp;
316
317 outp = outpacket_buf;
318
319 MAKEHEADER(outp, PPP_EAP);
320
321 PUTCHAR(EAP_SUCCESS, outp);
322 esp->es_server.ea_id++;
323 PUTCHAR(esp->es_server.ea_id, outp);
324 PUTSHORT(EAP_HEADERLEN, outp);
325
326 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);
327
328 auth_peer_success(esp->es_unit, PPP_EAP, 0,
329 esp->es_server.ea_peer, esp->es_server.ea_peerlen);
330 }
331
332 #ifdef PPP_WITH_SRP
333 /*
334 * Set DES key according to pseudonym-generating secret and current
335 * date.
336 */
337 static bool
338 pncrypt_getkey(int timeoffs, unsigned char *key, int keylen)
339 {
340 struct tm *tp;
341 char tbuf[9];
342 PPP_MD_CTX *ctxt;
343 time_t reftime;
344
345 if (pn_secret == NULL)
346 return (0);
347 reftime = time(NULL) + timeoffs;
348 tp = localtime(&reftime);
349
350 ctxt = PPP_MD_CTX_new();
351 if (ctxt) {
352
353 strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp);
354
355 PPP_DigestInit(ctxt, PPP_sha1());
356 PPP_DigestUpdate(ctxt, pn_secret, strlen(pn_secret));
357 PPP_DigestUpdate(ctxt, tbuf, strlen(tbuf));
358 PPP_DigestFinal(ctxt, key, &keylen);
359
360 PPP_MD_CTX_free(ctxt);
361 return 1;
362 }
363
364 return (0);
365 }
366
367 static char base64[] =
368 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
369
370 struct b64state {
371 u_int32_t bs_bits;
372 int bs_offs;
373 };
374
375 static int
376 b64enc(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
377 {
378 int outlen = 0;
379
380 while (inlen > 0) {
381 bs->bs_bits = (bs->bs_bits << 8) | *inp++;
382 inlen--;
383 bs->bs_offs += 8;
384 if (bs->bs_offs >= 24) {
385 *outp++ = base64[(bs->bs_bits >> 18) & 0x3F];
386 *outp++ = base64[(bs->bs_bits >> 12) & 0x3F];
387 *outp++ = base64[(bs->bs_bits >> 6) & 0x3F];
388 *outp++ = base64[bs->bs_bits & 0x3F];
389 outlen += 4;
390 bs->bs_offs = 0;
391 bs->bs_bits = 0;
392 }
393 }
394 return (outlen);
395 }
396
397 static int
398 b64flush(struct b64state *bs, u_char *outp)
399 {
400 int outlen = 0;
401
402 if (bs->bs_offs == 8) {
403 *outp++ = base64[(bs->bs_bits >> 2) & 0x3F];
404 *outp++ = base64[(bs->bs_bits << 4) & 0x3F];
405 outlen = 2;
406 } else if (bs->bs_offs == 16) {
407 *outp++ = base64[(bs->bs_bits >> 10) & 0x3F];
408 *outp++ = base64[(bs->bs_bits >> 4) & 0x3F];
409 *outp++ = base64[(bs->bs_bits << 2) & 0x3F];
410 outlen = 3;
411 }
412 bs->bs_offs = 0;
413 bs->bs_bits = 0;
414 return (outlen);
415 }
416
417 static int
418 b64dec(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
419 {
420 int outlen = 0;
421 char *cp;
422
423 while (inlen > 0) {
424 if ((cp = strchr(base64, *inp++)) == NULL)
425 break;
426 bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);
427 inlen--;
428 bs->bs_offs += 6;
429 if (bs->bs_offs >= 8) {
430 *outp++ = bs->bs_bits >> (bs->bs_offs - 8);
431 outlen++;
432 bs->bs_offs -= 8;
433 }
434 }
435 return (outlen);
436 }
437 #endif /* PPP_WITH_SRP */
438
439 /*
440 * Assume that current waiting server state is complete and figure
441 * next state to use based on available authentication data. 'status'
442 * indicates if there was an error in handling the last query. It is
443 * 0 for success and non-zero for failure.
444 */
445 static void
446 eap_figure_next_state(eap_state *esp, int status)
447 {
448 #ifdef PPP_WITH_SRP
449 unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp, key[SHA_DIGEST_LENGTH];
450 struct t_pw tpw;
451 struct t_confent *tce, mytce;
452 char *cp, *cp2;
453 struct t_server *ts;
454 int id, i, plen, clen, toffs, keylen;
455 u_char vals[2];
456 struct b64state bs;
457 #endif /* PPP_WITH_SRP */
458 #ifdef PPP_WITH_EAPTLS
459 struct eaptls_session *ets;
460 int secret_len;
461 char secret[MAXWORDLEN];
462 #endif /* PPP_WITH_EAPTLS */
463
464 esp->es_server.ea_timeout = esp->es_savedtime;
465 #ifdef PPP_WITH_EAPTLS
466 esp->es_server.ea_prev_state = esp->es_server.ea_state;
467 #endif /* PPP_WITH_EAPTLS */
468 switch (esp->es_server.ea_state) {
469 case eapBadAuth:
470 return;
471
472 case eapIdentify:
473 #ifdef PPP_WITH_SRP
474 /* Discard any previous session. */
475 ts = (struct t_server *)esp->es_server.ea_session;
476 if (ts != NULL) {
477 t_serverclose(ts);
478 esp->es_server.ea_session = NULL;
479 esp->es_server.ea_skey = NULL;
480 }
481 #endif /* PPP_WITH_SRP */
482 if (status != 0) {
483 esp->es_server.ea_state = eapBadAuth;
484 break;
485 }
486 #ifdef PPP_WITH_SRP
487 /* If we've got a pseudonym, try to decode to real name. */
488 if (esp->es_server.ea_peerlen > SRP_PSEUDO_LEN &&
489 strncmp(esp->es_server.ea_peer, SRP_PSEUDO_ID,
490 SRP_PSEUDO_LEN) == 0 &&
491 (esp->es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 <
492 sizeof (secbuf)) {
493 BZERO(&bs, sizeof (bs));
494 plen = b64dec(&bs,
495 esp->es_server.ea_peer + SRP_PSEUDO_LEN,
496 esp->es_server.ea_peerlen - SRP_PSEUDO_LEN,
497 secbuf);
498 toffs = 0;
499 for (i = 0; i < 5; i++) {
500 pncrypt_getkey(toffs, key, keylen);
501 toffs -= 86400;
502
503 if (!DesDecrypt(secbuf, key, clear)) {
504 dbglog("no DES here; cannot decode "
505 "pseudonym");
506 return;
507 }
508 id = *(unsigned char *)clear;
509 if (id + 1 <= plen && id + 9 > plen)
510 break;
511 }
512 if (plen % 8 == 0 && i < 5) {
513 /*
514 * Note that this is always shorter than the
515 * original stored string, so there's no need
516 * to realloc.
517 */
518 if ((i = plen = *(unsigned char *)clear) > 7)
519 i = 7;
520 esp->es_server.ea_peerlen = plen;
521 dp = (unsigned char *)esp->es_server.ea_peer;
522 BCOPY(clear + 1, dp, i);
523 plen -= i;
524 dp += i;
525 sp = secbuf + 8;
526 while (plen > 0) {
527 DesDecrypt(sp, key, dp);
528 sp += 8;
529 dp += 8;
530 plen -= 8;
531 }
532 esp->es_server.ea_peer[
533 esp->es_server.ea_peerlen] = '\0';
534 dbglog("decoded pseudonym to \"%.*q\"",
535 esp->es_server.ea_peerlen,
536 esp->es_server.ea_peer);
537 } else {
538 dbglog("failed to decode real name");
539 /* Stay in eapIdentfy state; requery */
540 break;
541 }
542 }
543 /* Look up user in secrets database. */
544 if (get_srp_secret(esp->es_unit, esp->es_server.ea_peer,
545 esp->es_server.ea_name, (char *)secbuf, 1) != 0) {
546 /* Set up default in case SRP entry is bad */
547 esp->es_server.ea_state = eapMD5Chall;
548 /* Get t_confent based on index in srp-secrets */
549 id = strtol((char *)secbuf, &cp, 10);
550 if (*cp++ != ':' || id < 0)
551 break;
552 if (id == 0) {
553 mytce.index = 0;
554 mytce.modulus.data = (u_char *)wkmodulus;
555 mytce.modulus.len = sizeof (wkmodulus);
556 mytce.generator.data = (u_char *)"\002";
557 mytce.generator.len = 1;
558 tce = &mytce;
559 } else if ((tce = gettcid(id)) != NULL) {
560 /*
561 * Client will have to verify this modulus/
562 * generator combination, and that will take
563 * a while. Lengthen the timeout here.
564 */
565 if (esp->es_server.ea_timeout > 0 &&
566 esp->es_server.ea_timeout < 30)
567 esp->es_server.ea_timeout = 30;
568 } else {
569 break;
570 }
571 if ((cp2 = strchr(cp, ':')) == NULL)
572 break;
573 *cp2++ = '\0';
574 tpw.pebuf.name = esp->es_server.ea_peer;
575 tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,
576 cp);
577 tpw.pebuf.password.data = (char*) tpw.pwbuf;
578 tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,
579 cp2);
580 tpw.pebuf.salt.data = tpw.saltbuf;
581 if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)
582 break;
583 esp->es_server.ea_session = (void *)ts;
584 esp->es_server.ea_state = eapSRP1;
585 vals[0] = esp->es_server.ea_id + 1;
586 vals[1] = EAPT_SRP;
587 t_serveraddexdata(ts, vals, 2);
588 /* Generate B; must call before t_servergetkey() */
589 t_servergenexp(ts);
590 break;
591 }
592 #endif /* PPP_WITH_SRP */
593 #ifdef PPP_WITH_EAPTLS
594 if (!get_secret(esp->es_unit, esp->es_server.ea_peer,
595 esp->es_server.ea_name, secret, &secret_len, 1)) {
596
597 esp->es_server.ea_state = eapTlsStart;
598 break;
599 }
600 #endif /* PPP_WITH_EAPTLS */
601
602 esp->es_server.ea_state = eapMD5Chall;
603 break;
604
605 #ifdef PPP_WITH_EAPTLS
606 case eapTlsStart:
607 /* Initialize ssl session */
608 if(!eaptls_init_ssl_server(esp)) {
609 esp->es_server.ea_state = eapBadAuth;
610 break;
611 }
612
613 esp->es_server.ea_state = eapTlsRecv;
614 break;
615
616 case eapTlsRecv:
617 ets = (struct eaptls_session *) esp->es_server.ea_session;
618
619 if(ets->alert_sent) {
620 esp->es_server.ea_state = eapTlsSendAlert;
621 break;
622 }
623
624 if (status) {
625 esp->es_server.ea_state = eapBadAuth;
626 break;
627 }
628 ets = (struct eaptls_session *) esp->es_server.ea_session;
629
630 if(ets->frag)
631 esp->es_server.ea_state = eapTlsSendAck;
632 else
633 esp->es_server.ea_state = eapTlsSend;
634 break;
635
636 case eapTlsSend:
637 ets = (struct eaptls_session *) esp->es_server.ea_session;
638
639 if(ets->frag)
640 esp->es_server.ea_state = eapTlsRecvAck;
641 else
642 if(SSL_is_init_finished(ets->ssl))
643 esp->es_server.ea_state = eapTlsRecvClient;
644 else
645 /* JJK Add "TLS empty record" message here ??? */
646 esp->es_server.ea_state = eapTlsRecv;
647 break;
648
649 case eapTlsSendAck:
650 esp->es_server.ea_state = eapTlsRecv;
651 break;
652
653 case eapTlsRecvAck:
654 if (status)
655 {
656 esp->es_server.ea_state = eapBadAuth;
657 break;
658 }
659
660 esp->es_server.ea_state = eapTlsSend;
661 break;
662
663 case eapTlsSendAlert:
664 esp->es_server.ea_state = eapTlsRecvAlertAck;
665 break;
666 #endif /* PPP_WITH_EAPTLS */
667
668 case eapSRP1:
669 #ifdef PPP_WITH_SRP
670 ts = (struct t_server *)esp->es_server.ea_session;
671 if (ts != NULL && status != 0) {
672 t_serverclose(ts);
673 esp->es_server.ea_session = NULL;
674 esp->es_server.ea_skey = NULL;
675 }
676 #endif /* PPP_WITH_SRP */
677 if (status == 1) {
678 esp->es_server.ea_state = eapMD5Chall;
679 } else if (status != 0 || esp->es_server.ea_session == NULL) {
680 esp->es_server.ea_state = eapBadAuth;
681 } else {
682 esp->es_server.ea_state = eapSRP2;
683 }
684 break;
685
686 case eapSRP2:
687 #ifdef PPP_WITH_SRP
688 ts = (struct t_server *)esp->es_server.ea_session;
689 if (ts != NULL && status != 0) {
690 t_serverclose(ts);
691 esp->es_server.ea_session = NULL;
692 esp->es_server.ea_skey = NULL;
693 }
694 #endif /* PPP_WITH_SRP */
695 if (status != 0 || esp->es_server.ea_session == NULL) {
696 esp->es_server.ea_state = eapBadAuth;
697 } else {
698 esp->es_server.ea_state = eapSRP3;
699 }
700 break;
701
702 case eapSRP3:
703 case eapSRP4:
704 #ifdef PPP_WITH_SRP
705 ts = (struct t_server *)esp->es_server.ea_session;
706 if (ts != NULL && status != 0) {
707 t_serverclose(ts);
708 esp->es_server.ea_session = NULL;
709 esp->es_server.ea_skey = NULL;
710 }
711 #endif /* PPP_WITH_SRP */
712 if (status != 0 || esp->es_server.ea_session == NULL) {
713 esp->es_server.ea_state = eapBadAuth;
714 } else {
715 esp->es_server.ea_state = eapOpen;
716 }
717 break;
718
719 #ifdef PPP_WITH_CHAPMS
720 case eapMSCHAPv2Chall:
721 #endif
722 case eapMD5Chall:
723 if (status != 0) {
724 esp->es_server.ea_state = eapBadAuth;
725 } else {
726 esp->es_server.ea_state = eapOpen;
727 }
728 break;
729
730 default:
731 esp->es_server.ea_state = eapBadAuth;
732 break;
733 }
734 if (esp->es_server.ea_state == eapBadAuth)
735 eap_send_failure(esp);
736
737 #ifdef PPP_WITH_EAPTLS
738 dbglog("EAP id=0x%2x '%s' -> '%s'", esp->es_server.ea_id, eap_state_name(esp->es_server.ea_prev_state), eap_state_name(esp->es_server.ea_state));
739 #endif /* PPP_WITH_EAPTLS */
740 }
741
742 #if PPP_WITH_CHAPMS
743 /*
744 * eap_chap_verify_response - check whether the peer's response matches
745 * what we think it should be. Returns 1 if it does (authentication
746 * succeeded), or 0 if it doesn't.
747 */
748 static int
749 eap_chap_verify_response(char *name, char *ourname, int id,
750 struct chap_digest_type *digest,
751 unsigned char *challenge, unsigned char *response,
752 char *message, int message_space)
753 {
754 int ok;
755 unsigned char secret[MAXSECRETLEN];
756 int secret_len;
757
758 /* Get the secret that the peer is supposed to know */
759 if (!get_secret(0, name, ourname, (char *)secret, &secret_len, 1)) {
760 error("No CHAP secret found for authenticating %q", name);
761 return 0;
762 }
763
764 ok = digest->verify_response(id, name, secret, secret_len, challenge,
765 response, message, message_space);
766 memset(secret, 0, sizeof(secret));
767
768 return ok;
769 }
770
771 /*
772 * Format and send an CHAPV2-Success/Failure EAP Request message.
773 */
774 static void
775 eap_chapms2_send_request(eap_state *esp, u_char id,
776 u_char opcode, u_char chapid,
777 char *message, int message_len)
778 {
779 u_char *outp;
780 int msglen;
781
782 outp = outpacket_buf;
783
784 MAKEHEADER(outp, PPP_EAP);
785
786 msglen = EAP_HEADERLEN + 5 * sizeof (u_char);
787 msglen += message_len;
788
789 PUTCHAR(EAP_REQUEST, outp);
790 PUTCHAR(id, outp);
791 PUTSHORT(msglen, outp);
792 PUTCHAR(EAPT_MSCHAPV2, outp);
793 PUTCHAR(opcode, outp);
794 PUTCHAR(chapid, outp);
795 /* MS len */
796 PUTSHORT(msglen - 5, outp);
797 BCOPY(message, outp, message_len);
798
799 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
800
801 if (opcode == CHAP_SUCCESS) {
802 auth_peer_success(esp->es_unit, PPP_EAP, 0,
803 esp->es_server.ea_peer, esp->es_server.ea_peerlen);
804 }
805 else {
806 esp->es_server.ea_state = eapBadAuth;
807 auth_peer_fail(esp->es_unit, PPP_EAP);
808 }
809 }
810 #endif /* PPP_WITH_CHAPMS */
811
812 /*
813 * Format an EAP Request message and send it to the peer. Message
814 * type depends on current state. (Server operation)
815 */
816 static void
817 eap_send_request(eap_state *esp)
818 {
819 u_char *outp;
820 u_char *lenloc;
821 u_char *ptr;
822 int outlen;
823 int challen;
824 char *str;
825 #ifdef PPP_WITH_SRP
826 struct t_server *ts;
827 u_char clear[8], cipher[8], dig[SHA_DIGEST_LENGTH], *optr, *cp, key[SHA_DIGEST_LENGTH];
828 int i, j, diglen, clen, keylen = sizeof(key);
829 struct b64state b64;
830 PPP_MD_CTX *ctxt;
831 #endif /* PPP_WITH_SRP */
832
833 /* Handle both initial auth and restart */
834 if (esp->es_server.ea_state < eapIdentify &&
835 esp->es_server.ea_state != eapInitial) {
836 esp->es_server.ea_state = eapIdentify;
837 if (explicit_remote) {
838 /*
839 * If we already know the peer's
840 * unauthenticated name, then there's no
841 * reason to ask. Go to next state instead.
842 */
843 esp->es_server.ea_peer = remote_name;
844 esp->es_server.ea_peerlen = strlen(remote_name);
845 eap_figure_next_state(esp, 0);
846 }
847 }
848
849 if (esp->es_server.ea_maxrequests > 0 &&
850 esp->es_server.ea_requests >= esp->es_server.ea_maxrequests) {
851 if (esp->es_server.ea_responses > 0)
852 error("EAP: too many Requests sent");
853 else
854 error("EAP: no response to Requests");
855 eap_send_failure(esp);
856 return;
857 }
858
859 outp = outpacket_buf;
860
861 MAKEHEADER(outp, PPP_EAP);
862
863 PUTCHAR(EAP_REQUEST, outp);
864 PUTCHAR(esp->es_server.ea_id, outp);
865 lenloc = outp;
866 INCPTR(2, outp);
867
868 switch (esp->es_server.ea_state) {
869 case eapIdentify:
870 PUTCHAR(EAPT_IDENTITY, outp);
871 str = "Name";
872 challen = strlen(str);
873 BCOPY(str, outp, challen);
874 INCPTR(challen, outp);
875 break;
876
877 case eapMD5Chall:
878 PUTCHAR(EAPT_MD5CHAP, outp);
879 /*
880 * pick a random challenge length between
881 * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
882 */
883 challen = (drand48() *
884 (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
885 MIN_CHALLENGE_LENGTH;
886 PUTCHAR(challen, outp);
887 esp->es_challen = challen;
888 ptr = esp->es_challenge;
889 while (--challen >= 0)
890 *ptr++ = (u_char) (drand48() * 0x100);
891 BCOPY(esp->es_challenge, outp, esp->es_challen);
892 INCPTR(esp->es_challen, outp);
893 BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
894 INCPTR(esp->es_server.ea_namelen, outp);
895 break;
896
897 #ifdef PPP_WITH_CHAPMS
898 case eapMSCHAPv2Chall:
899 esp->es_server.digest->generate_challenge(esp->es_challenge);
900 challen = esp->es_challenge[0];
901 esp->es_challen = challen;
902
903 PUTCHAR(EAPT_MSCHAPV2, outp);
904 PUTCHAR(CHAP_CHALLENGE, outp);
905 PUTCHAR(esp->es_server.ea_id, outp);
906 /* MS len */
907 PUTSHORT(5 + challen +
908 esp->es_server.ea_namelen,
909 outp);
910 /* challen + challenge */
911 BCOPY(esp->es_challenge, outp, challen+1);
912 INCPTR(challen+1, outp);
913 BCOPY(esp->es_server.ea_name,
914 outp,
915 esp->es_server.ea_namelen);
916 INCPTR(esp->es_server.ea_namelen, outp);
917 break;
918 #endif /* PPP_WITH_CHAPMS */
919
920 #ifdef PPP_WITH_EAPTLS
921 case eapTlsStart:
922 PUTCHAR(EAPT_TLS, outp);
923 PUTCHAR(EAP_TLS_FLAGS_START, outp);
924 eap_figure_next_state(esp, 0);
925 break;
926
927 case eapTlsSend:
928 eaptls_send(esp->es_server.ea_session, &outp);
929 eap_figure_next_state(esp, 0);
930 break;
931
932 case eapTlsSendAck:
933 PUTCHAR(EAPT_TLS, outp);
934 PUTCHAR(0, outp);
935 eap_figure_next_state(esp, 0);
936 break;
937
938 case eapTlsSendAlert:
939 eaptls_send(esp->es_server.ea_session, &outp);
940 eap_figure_next_state(esp, 0);
941 break;
942 #endif /* PPP_WITH_EAPTLS */
943
944 #ifdef PPP_WITH_SRP
945 case eapSRP1:
946 PUTCHAR(EAPT_SRP, outp);
947 PUTCHAR(EAPSRP_CHALLENGE, outp);
948
949 PUTCHAR(esp->es_server.ea_namelen, outp);
950 BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
951 INCPTR(esp->es_server.ea_namelen, outp);
952
953 ts = (struct t_server *)esp->es_server.ea_session;
954 assert(ts != NULL);
955 PUTCHAR(ts->s.len, outp);
956 BCOPY(ts->s.data, outp, ts->s.len);
957 INCPTR(ts->s.len, outp);
958
959 if (ts->g.len == 1 && ts->g.data[0] == 2) {
960 PUTCHAR(0, outp);
961 } else {
962 PUTCHAR(ts->g.len, outp);
963 BCOPY(ts->g.data, outp, ts->g.len);
964 INCPTR(ts->g.len, outp);
965 }
966
967 if (ts->n.len != sizeof (wkmodulus) ||
968 BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) {
969 BCOPY(ts->n.data, outp, ts->n.len);
970 INCPTR(ts->n.len, outp);
971 }
972 break;
973
974 case eapSRP2:
975 PUTCHAR(EAPT_SRP, outp);
976 PUTCHAR(EAPSRP_SKEY, outp);
977
978 ts = (struct t_server *)esp->es_server.ea_session;
979 assert(ts != NULL);
980 BCOPY(ts->B.data, outp, ts->B.len);
981 INCPTR(ts->B.len, outp);
982 break;
983
984 case eapSRP3:
985 PUTCHAR(EAPT_SRP, outp);
986 PUTCHAR(EAPSRP_SVALIDATOR, outp);
987 PUTLONG(SRPVAL_EBIT, outp);
988 ts = (struct t_server *)esp->es_server.ea_session;
989 assert(ts != NULL);
990 BCOPY(t_serverresponse(ts), outp, SHA_DIGEST_LENGTH);
991 INCPTR(SHA_DIGEST_LENGTH, outp);
992
993 if (pncrypt_getkey(0, key, keylen)) {
994 /* Generate pseudonym */
995 optr = outp;
996 cp = (unsigned char *)esp->es_server.ea_peer;
997 if ((j = i = esp->es_server.ea_peerlen) > 7)
998 j = 7;
999 clear[0] = i;
1000 BCOPY(cp, clear + 1, j);
1001 i -= j;
1002 cp += j;
1003
1004 if (!DesEncrypt(clear, key, cipher)) {
1005 dbglog("no DES here; not generating pseudonym");
1006 break;
1007 }
1008
1009 BZERO(&b64, sizeof (b64));
1010 outp++; /* space for pseudonym length */
1011 outp += b64enc(&b64, cipher, 8, outp);
1012 while (i >= 8) {
1013 DesEncrypt(cp, key, cipher);
1014 outp += b64enc(&b64, cipher, 8, outp);
1015 cp += 8;
1016 i -= 8;
1017 }
1018 if (i > 0) {
1019 BCOPY(cp, clear, i);
1020 cp += i;
1021 while (i < 8) {
1022 *cp++ = drand48() * 0x100;
1023 i++;
1024 }
1025
1026 DesEncrypt(clear, key, cipher);
1027 outp += b64enc(&b64, cipher, 8, outp);
1028 }
1029 outp += b64flush(&b64, outp);
1030
1031 /* Set length and pad out to next 20 octet boundary */
1032 i = outp - optr - 1;
1033 *optr = i;
1034 i %= SHA_DIGEST_LENGTH;
1035 if (i != 0) {
1036 while (i < SHA_DIGEST_LENGTH) {
1037 *outp++ = drand48() * 0x100;
1038 i++;
1039 }
1040 }
1041
1042 /* Obscure the pseudonym with SHA1 hash */
1043 ctxt = PPP_MD_CTX_new();
1044 if (ctxt) {
1045
1046 PPP_DigestInit(ctxt, PPP_sha1());
1047 PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1);
1048 PPP_DigestUpdate(ctxt, &esp->es_server.ea_skey,
1049 SESSION_KEY_LEN);
1050 PPP_DigestUpdate(ctxt, esp->es_server.ea_peer,
1051 esp->es_server.ea_peerlen);
1052 while (optr < outp) {
1053 diglen = SHA_DIGEST_LENGTH;
1054 PPP_DigestFinal(ctxt, dig, &diglen);
1055 cp = dig;
1056 while (cp < dig + SHA_DIGEST_LENGTH)
1057 *optr++ ^= *cp++;
1058
1059 PPP_DigestInit(ctxt, PPP_sha1());
1060 PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1);
1061 PPP_DigestUpdate(ctxt, esp->es_server.ea_skey,
1062 SESSION_KEY_LEN);
1063 PPP_DigestUpdate(ctxt, optr - SHA_DIGEST_LENGTH,
1064 SHA_DIGEST_LENGTH);
1065 }
1066
1067 PPP_MD_CTX_free(ctxt);
1068 }
1069 }
1070 break;
1071
1072 case eapSRP4:
1073 PUTCHAR(EAPT_SRP, outp);
1074 PUTCHAR(EAPSRP_LWRECHALLENGE, outp);
1075 challen = MIN_CHALLENGE_LENGTH +
1076 ((MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH) * drand48());
1077 esp->es_challen = challen;
1078 ptr = esp->es_challenge;
1079 while (--challen >= 0)
1080 *ptr++ = drand48() * 0x100;
1081 BCOPY(esp->es_challenge, outp, esp->es_challen);
1082 INCPTR(esp->es_challen, outp);
1083 break;
1084 #endif /* PPP_WITH_SRP */
1085
1086 default:
1087 return;
1088 }
1089
1090 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1091 PUTSHORT(outlen, lenloc);
1092
1093 output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
1094
1095 esp->es_server.ea_requests++;
1096
1097 if (esp->es_server.ea_timeout > 0)
1098 TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
1099 }
1100
1101 /*
1102 * eap_authpeer - Authenticate our peer (behave as server).
1103 *
1104 * Start server state and send first request. This is called only
1105 * after eap_lowerup.
1106 */
1107 void
1108 eap_authpeer(int unit, char *localname)
1109 {
1110 eap_state *esp = &eap_states[unit];
1111
1112 /* Save the name we're given. */
1113 esp->es_server.ea_name = localname;
1114 esp->es_server.ea_namelen = strlen(localname);
1115
1116 esp->es_savedtime = esp->es_server.ea_timeout;
1117
1118 /* Lower layer up yet? */
1119 if (esp->es_server.ea_state == eapInitial ||
1120 esp->es_server.ea_state == eapPending) {
1121 esp->es_server.ea_state = eapPending;
1122 return;
1123 }
1124
1125 esp->es_server.ea_state = eapPending;
1126
1127 /* ID number not updated here intentionally; hashed into M1 */
1128 eap_send_request(esp);
1129 }
1130
1131 /*
1132 * eap_server_timeout - Retransmission timer for sending Requests
1133 * expired.
1134 */
1135 static void
1136 eap_server_timeout(void *arg)
1137 {
1138 #ifdef PPP_WITH_EAPTLS
1139 u_char *outp;
1140 u_char *lenloc;
1141 int outlen;
1142 #endif /* PPP_WITH_EAPTLS */
1143
1144 eap_state *esp = (eap_state *) arg;
1145
1146 if (!eap_server_active(esp))
1147 return;
1148
1149 #ifdef PPP_WITH_EAPTLS
1150 switch(esp->es_server.ea_prev_state) {
1151
1152 /*
1153 * In eap-tls the state changes after a request, so we return to
1154 * previous state ...
1155 */
1156 case(eapTlsStart):
1157 case(eapTlsSendAck):
1158 esp->es_server.ea_state = esp->es_server.ea_prev_state;
1159 break;
1160
1161 /*
1162 * ... or resend the stored data
1163 */
1164 case(eapTlsSend):
1165 case(eapTlsSendAlert):
1166 outp = outpacket_buf;
1167 MAKEHEADER(outp, PPP_EAP);
1168 PUTCHAR(EAP_REQUEST, outp);
1169 PUTCHAR(esp->es_server.ea_id, outp);
1170 lenloc = outp;
1171 INCPTR(2, outp);
1172
1173 eaptls_retransmit(esp->es_server.ea_session, &outp);
1174
1175 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1176 PUTSHORT(outlen, lenloc);
1177 output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
1178 esp->es_server.ea_requests++;
1179
1180 if (esp->es_server.ea_timeout > 0)
1181 TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
1182
1183 return;
1184 default:
1185 break;
1186 }
1187 #endif /* PPP_WITH_EAPTLS */
1188
1189 /* EAP ID number must not change on timeout. */
1190 eap_send_request(esp);
1191 }
1192
1193 /*
1194 * When it's time to send rechallenge the peer, this timeout is
1195 * called. Once the rechallenge is successful, the response handler
1196 * will restart the timer. If it fails, then the link is dropped.
1197 */
1198 static void
1199 eap_rechallenge(void *arg)
1200 {
1201 eap_state *esp = (eap_state *)arg;
1202
1203 if (esp->es_server.ea_state != eapOpen &&
1204 esp->es_server.ea_state != eapSRP4)
1205 return;
1206
1207 esp->es_server.ea_requests = 0;
1208 esp->es_server.ea_state = eapIdentify;
1209 eap_figure_next_state(esp, 0);
1210 esp->es_server.ea_id++;
1211 eap_send_request(esp);
1212 }
1213
1214 static void
1215 srp_lwrechallenge(void *arg)
1216 {
1217 eap_state *esp = (eap_state *)arg;
1218
1219 if (esp->es_server.ea_state != eapOpen ||
1220 esp->es_server.ea_type != EAPT_SRP)
1221 return;
1222
1223 esp->es_server.ea_requests = 0;
1224 esp->es_server.ea_state = eapSRP4;
1225 esp->es_server.ea_id++;
1226 eap_send_request(esp);
1227 }
1228
1229 /*
1230 * eap_lowerup - The lower layer is now up.
1231 *
1232 * This is called before either eap_authpeer or eap_authwithpeer. See
1233 * link_established() in auth.c. All that's necessary here is to
1234 * return to closed state so that those two routines will do the right
1235 * thing.
1236 */
1237 static void
1238 eap_lowerup(int unit)
1239 {
1240 eap_state *esp = &eap_states[unit];
1241
1242 /* Discard any (possibly authenticated) peer name. */
1243 if (esp->es_server.ea_peer != NULL &&
1244 esp->es_server.ea_peer != remote_name)
1245 free(esp->es_server.ea_peer);
1246 esp->es_server.ea_peer = NULL;
1247 if (esp->es_client.ea_peer != NULL)
1248 free(esp->es_client.ea_peer);
1249 esp->es_client.ea_peer = NULL;
1250
1251 esp->es_client.ea_state = eapClosed;
1252 esp->es_server.ea_state = eapClosed;
1253 }
1254
1255 /*
1256 * eap_lowerdown - The lower layer is now down.
1257 *
1258 * Cancel all timeouts and return to initial state.
1259 */
1260 static void
1261 eap_lowerdown(int unit)
1262 {
1263 eap_state *esp = &eap_states[unit];
1264
1265 if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) {
1266 UNTIMEOUT(eap_client_timeout, (void *)esp);
1267 }
1268 if (eap_server_active(esp)) {
1269 if (esp->es_server.ea_timeout > 0) {
1270 UNTIMEOUT(eap_server_timeout, (void *)esp);
1271 }
1272 } else {
1273 if ((esp->es_server.ea_state == eapOpen ||
1274 esp->es_server.ea_state == eapSRP4) &&
1275 esp->es_rechallenge > 0) {
1276 UNTIMEOUT(eap_rechallenge, (void *)esp);
1277 }
1278 if (esp->es_server.ea_state == eapOpen &&
1279 esp->es_lwrechallenge > 0) {
1280 UNTIMEOUT(srp_lwrechallenge, (void *)esp);
1281 }
1282 }
1283
1284 esp->es_client.ea_state = esp->es_server.ea_state = eapInitial;
1285 esp->es_client.ea_requests = esp->es_server.ea_requests = 0;
1286 }
1287
1288 /*
1289 * eap_protrej - Peer doesn't speak this protocol.
1290 *
1291 * This shouldn't happen. If it does, it represents authentication
1292 * failure.
1293 */
1294 static void
1295 eap_protrej(int unit)
1296 {
1297 eap_state *esp = &eap_states[unit];
1298
1299 if (eap_client_active(esp)) {
1300 error("EAP authentication failed due to Protocol-Reject");
1301 auth_withpeer_fail(unit, PPP_EAP);
1302 }
1303 if (eap_server_active(esp)) {
1304 error("EAP authentication of peer failed on Protocol-Reject");
1305 auth_peer_fail(unit, PPP_EAP);
1306 }
1307 eap_lowerdown(unit);
1308 }
1309
1310 /*
1311 * Format and send a regular EAP Response message.
1312 */
1313 static void
1314 eap_send_response(eap_state *esp, u_char id, u_char typenum,
1315 u_char *str, int lenstr)
1316 {
1317 u_char *outp;
1318 int msglen;
1319
1320 outp = outpacket_buf;
1321
1322 MAKEHEADER(outp, PPP_EAP);
1323
1324 PUTCHAR(EAP_RESPONSE, outp);
1325 PUTCHAR(id, outp);
1326 esp->es_client.ea_id = id;
1327 msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr;
1328 PUTSHORT(msglen, outp);
1329 PUTCHAR(typenum, outp);
1330 if (lenstr > 0) {
1331 BCOPY(str, outp, lenstr);
1332 }
1333
1334 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1335 }
1336
1337 /*
1338 * Format and send an MD5-Challenge EAP Response message.
1339 */
1340 static void
1341 eap_chap_response(eap_state *esp, u_char id, u_char *hash,
1342 char *name, int namelen)
1343 {
1344 u_char *outp;
1345 int msglen;
1346
1347 outp = outpacket_buf;
1348
1349 MAKEHEADER(outp, PPP_EAP);
1350
1351 PUTCHAR(EAP_RESPONSE, outp);
1352 PUTCHAR(id, outp);
1353 esp->es_client.ea_id = id;
1354 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_DIGEST_LENGTH +
1355 namelen;
1356 PUTSHORT(msglen, outp);
1357 PUTCHAR(EAPT_MD5CHAP, outp);
1358 PUTCHAR(MD5_DIGEST_LENGTH, outp);
1359 BCOPY(hash, outp, MD5_DIGEST_LENGTH);
1360 INCPTR(MD5_DIGEST_LENGTH, outp);
1361 if (namelen > 0) {
1362 BCOPY(name, outp, namelen);
1363 }
1364
1365 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1366 }
1367
1368 #ifdef PPP_WITH_SRP
1369 /*
1370 * Format and send a SRP EAP Response message.
1371 */
1372 static void
1373 eap_srp_response(eap_state *esp, u_char id, u_char subtypenum,
1374 u_char *str, int lenstr)
1375 {
1376 u_char *outp;
1377 int msglen;
1378
1379 outp = outpacket_buf;
1380
1381 MAKEHEADER(outp, PPP_EAP);
1382
1383 PUTCHAR(EAP_RESPONSE, outp);
1384 PUTCHAR(id, outp);
1385 esp->es_client.ea_id = id;
1386 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr;
1387 PUTSHORT(msglen, outp);
1388 PUTCHAR(EAPT_SRP, outp);
1389 PUTCHAR(subtypenum, outp);
1390 if (lenstr > 0) {
1391 BCOPY(str, outp, lenstr);
1392 }
1393
1394 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1395 }
1396
1397 /*
1398 * Format and send a SRP EAP Client Validator Response message.
1399 */
1400 static void
1401 eap_srpval_response(eap_state *esp, u_char id, u_int32_t flags, u_char *str)
1402 {
1403 u_char *outp;
1404 int msglen;
1405
1406 outp = outpacket_buf;
1407
1408 MAKEHEADER(outp, PPP_EAP);
1409
1410 PUTCHAR(EAP_RESPONSE, outp);
1411 PUTCHAR(id, outp);
1412 esp->es_client.ea_id = id;
1413 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) +
1414 SHA_DIGEST_LENGTH;
1415 PUTSHORT(msglen, outp);
1416 PUTCHAR(EAPT_SRP, outp);
1417 PUTCHAR(EAPSRP_CVALIDATOR, outp);
1418 PUTLONG(flags, outp);
1419 BCOPY(str, outp, SHA_DIGEST_LENGTH);
1420
1421 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1422 }
1423 #endif /* PPP_WITH_SRP */
1424
1425 #ifdef PPP_WITH_EAPTLS
1426 /*
1427 * Send an EAP-TLS response message with tls data
1428 */
1429 static void
1430 eap_tls_response(eap_state *esp, u_char id)
1431 {
1432 u_char *outp;
1433 int outlen;
1434 u_char *lenloc;
1435
1436 outp = outpacket_buf;
1437
1438 MAKEHEADER(outp, PPP_EAP);
1439
1440 PUTCHAR(EAP_RESPONSE, outp);
1441 PUTCHAR(id, outp);
1442
1443 lenloc = outp;
1444 INCPTR(2, outp);
1445
1446 /*
1447 If the id in the request is unchanged, we must retransmit
1448 the old data
1449 */
1450 if(id == esp->es_client.ea_id)
1451 eaptls_retransmit(esp->es_client.ea_session, &outp);
1452 else
1453 eaptls_send(esp->es_client.ea_session, &outp);
1454
1455 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1456 PUTSHORT(outlen, lenloc);
1457
1458 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1459
1460 esp->es_client.ea_id = id;
1461 }
1462
1463 /*
1464 * Send an EAP-TLS ack
1465 */
1466 static void
1467 eap_tls_sendack(eap_state *esp, u_char id)
1468 {
1469 u_char *outp;
1470 int outlen;
1471 u_char *lenloc;
1472
1473 outp = outpacket_buf;
1474
1475 MAKEHEADER(outp, PPP_EAP);
1476
1477 PUTCHAR(EAP_RESPONSE, outp);
1478 PUTCHAR(id, outp);
1479 esp->es_client.ea_id = id;
1480
1481 lenloc = outp;
1482 INCPTR(2, outp);
1483
1484 PUTCHAR(EAPT_TLS, outp);
1485 PUTCHAR(0, outp);
1486
1487 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1488 PUTSHORT(outlen, lenloc);
1489
1490 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1491 }
1492 #endif /* PPP_WITH_EAPTLS */
1493
1494 static void
1495 eap_send_nak(eap_state *esp, u_char id, u_char type)
1496 {
1497 u_char *outp;
1498 int msglen;
1499
1500 outp = outpacket_buf;
1501
1502 MAKEHEADER(outp, PPP_EAP);
1503
1504 PUTCHAR(EAP_RESPONSE, outp);
1505 PUTCHAR(id, outp);
1506 esp->es_client.ea_id = id;
1507 msglen = EAP_HEADERLEN + 2 * sizeof (u_char);
1508 PUTSHORT(msglen, outp);
1509 PUTCHAR(EAPT_NAK, outp);
1510 PUTCHAR(type, outp);
1511
1512 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1513 }
1514
1515 #ifdef PPP_WITH_SRP
1516 static char *
1517 name_of_pn_file(void)
1518 {
1519 char *user, *path, *file;
1520 struct passwd *pw;
1521 size_t pl;
1522 static bool pnlogged = 0;
1523
1524 pw = getpwuid(getuid());
1525 if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
1526 errno = EINVAL;
1527 return (NULL);
1528 }
1529 file = PPP_PATH_PSEUDONYM;
1530 pl = strlen(user) + strlen(file) + 2;
1531 path = malloc(pl);
1532 if (path == NULL)
1533 return (NULL);
1534 (void) slprintf(path, pl, "%s/%s", user, file);
1535 if (!pnlogged) {
1536 dbglog("pseudonym file: %s", path);
1537 pnlogged = 1;
1538 }
1539 return (path);
1540 }
1541
1542 static int
1543 open_pn_file(mode_t modebits)
1544 {
1545 char *path;
1546 int fd, err;
1547
1548 if ((path = name_of_pn_file()) == NULL)
1549 return (-1);
1550 fd = open(path, modebits, S_IRUSR | S_IWUSR);
1551 err = errno;
1552 free(path);
1553 errno = err;
1554 return (fd);
1555 }
1556
1557 static void
1558 remove_pn_file(void)
1559 {
1560 char *path;
1561
1562 if ((path = name_of_pn_file()) != NULL) {
1563 (void) unlink(path);
1564 (void) free(path);
1565 }
1566 }
1567
1568 static void
1569 write_pseudonym(eap_state *esp, u_char *inp, int len, int id)
1570 {
1571 u_char val;
1572 u_char *datp, *digp;
1573 PPP_MD_CTX *ctxt;
1574 u_char dig[SHA_DIGEST_LENGTH];
1575 int dsize, fd, olen = len, diglen = sizeof(dig);
1576
1577 /*
1578 * Do the decoding by working backwards. This eliminates the need
1579 * to save the decoded output in a separate buffer.
1580 */
1581 val = id;
1582 while (len > 0) {
1583 if ((dsize = len % SHA_DIGEST_LENGTH) == 0)
1584 dsize = SHA_DIGEST_LENGTH;
1585 len -= dsize;
1586 datp = inp + len;
1587 ctxt = PPP_MD_CTX_new();
1588 if (ctxt) {
1589
1590 PPP_DigestInit(ctxt, PPP_sha1());
1591 PPP_DigestUpdate(ctxt, &val, 1);
1592 PPP_DigestUpdate(ctxt, esp->es_client.ea_skey,
1593 SESSION_KEY_LEN);
1594 if (len > 0) {
1595 PPP_DigestUpdate(ctxt, datp, SHA_DIGEST_LENGTH);
1596 } else {
1597 PPP_DigestUpdate(ctxt, esp->es_client.ea_name,
1598 esp->es_client.ea_namelen);
1599 }
1600 PPP_DigestFinal(ctxt, dig, &diglen);
1601
1602 for (digp = dig; digp < dig + SHA_DIGEST_LENGTH; digp++)
1603 *datp++ ^= *digp;
1604
1605 PPP_MD_CTX_free(ctxt);
1606 }
1607 }
1608
1609 /* Now check that the result is sane */
1610 if (olen <= 0 || *inp + 1 > olen) {
1611 dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp);
1612 return;
1613 }
1614
1615 /* Save it away */
1616 fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);
1617 if (fd < 0) {
1618 dbglog("EAP: error saving pseudonym: %m");
1619 return;
1620 }
1621 len = write(fd, inp + 1, *inp);
1622 if (close(fd) != -1 && len == *inp) {
1623 dbglog("EAP: saved pseudonym");
1624 esp->es_usedpseudo = 0;
1625 } else {
1626 dbglog("EAP: failed to save pseudonym");
1627 remove_pn_file();
1628 }
1629 }
1630 #endif /* PPP_WITH_SRP */
1631
1632 #if PPP_WITH_CHAPMS
1633 /*
1634 * Format and send an CHAPV2-Challenge EAP Response message.
1635 */
1636 static void
1637 eap_chapv2_response(eap_state *esp, u_char id, u_char chapid, u_char *response, char *user, int user_len)
1638 {
1639 u_char *outp;
1640 int msglen;
1641
1642 outp = outpacket_buf;
1643
1644 MAKEHEADER(outp, PPP_EAP);
1645
1646 PUTCHAR(EAP_RESPONSE, outp);
1647 PUTCHAR(id, outp);
1648 esp->es_client.ea_id = id;
1649 msglen = EAP_HEADERLEN + 6 * sizeof (u_char) + MS_CHAP2_RESPONSE_LEN + user_len;
1650 PUTSHORT(msglen, outp);
1651 PUTCHAR(EAPT_MSCHAPV2, outp);
1652 PUTCHAR(CHAP_RESPONSE, outp);
1653 PUTCHAR(chapid, outp);
1654 PUTCHAR(0, outp);
1655 /* len */
1656 PUTCHAR(5 + user_len + MS_CHAP2_RESPONSE_LEN, outp);
1657 BCOPY(response, outp, MS_CHAP2_RESPONSE_LEN+1); // VLEN + VALUE
1658 INCPTR(MS_CHAP2_RESPONSE_LEN+1, outp);
1659 BCOPY(user, outp, user_len);
1660
1661 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1662 }
1663 #endif
1664
1665 /*
1666 * eap_request - Receive EAP Request message (client mode).
1667 */
1668 static void
1669 eap_request(eap_state *esp, u_char *inp, int id, int len)
1670 {
1671 u_char typenum;
1672 u_char vallen;
1673 int secret_len;
1674 char secret[MAXWORDLEN];
1675 char rhostname[256];
1676 PPP_MD_CTX *mdctx;
1677 u_char hash[MD5_DIGEST_LENGTH];
1678 int hashlen = MD5_DIGEST_LENGTH;
1679 #ifdef PPP_WITH_EAPTLS
1680 u_char flags;
1681 struct eaptls_session *ets = esp->es_client.ea_session;
1682 #endif /* PPP_WITH_EAPTLS */
1683
1684 #ifdef PPP_WITH_SRP
1685 struct t_client *tc;
1686 struct t_num sval, gval, Nval, *Ap, Bval;
1687 u_char vals[2];
1688 PPP_MD_CTX *ctxt;
1689 u_char dig[SHA_DIGEST_LENGTH];
1690 int diglen = sizeof(dig);
1691 int fd;
1692 #endif /* PPP_WITH_SRP */
1693
1694 /*
1695 * Ignore requests if we're not open
1696 */
1697 if (esp->es_client.ea_state <= eapClosed)
1698 return;
1699
1700 /*
1701 * Note: we update es_client.ea_id *only if* a Response
1702 * message is being generated. Otherwise, we leave it the
1703 * same for duplicate detection purposes.
1704 */
1705
1706 esp->es_client.ea_requests++;
1707 if (esp->es_client.ea_maxrequests != 0 &&
1708 esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {
1709 info("EAP: received too many Request messages");
1710 if (esp->es_client.ea_timeout > 0) {
1711 UNTIMEOUT(eap_client_timeout, (void *)esp);
1712 }
1713 auth_withpeer_fail(esp->es_unit, PPP_EAP);
1714 return;
1715 }
1716
1717 if (len <= 0) {
1718 error("EAP: empty Request message discarded");
1719 return;
1720 }
1721
1722 GETCHAR(typenum, inp);
1723 len--;
1724
1725 switch (typenum) {
1726 case EAPT_IDENTITY:
1727 if (len > 0)
1728 info("EAP: Identity prompt \"%.*q\"", len, inp);
1729 #ifdef PPP_WITH_SRP
1730 if (esp->es_usepseudo &&
1731 (esp->es_usedpseudo == 0 ||
1732 (esp->es_usedpseudo == 1 &&
1733 id == esp->es_client.ea_id))) {
1734 esp->es_usedpseudo = 1;
1735 /* Try to get a pseudonym */
1736 if ((fd = open_pn_file(O_RDONLY)) >= 0) {
1737 strcpy(rhostname, SRP_PSEUDO_ID);
1738 len = read(fd, rhostname + SRP_PSEUDO_LEN,
1739 sizeof (rhostname) - SRP_PSEUDO_LEN);
1740 /* XXX NAI unsupported */
1741 if (len > 0) {
1742 eap_send_response(esp, id, typenum,
1743 rhostname, len + SRP_PSEUDO_LEN);
1744 }
1745 (void) close(fd);
1746 if (len > 0)
1747 break;
1748 }
1749 }
1750 /* Stop using pseudonym now. */
1751 if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
1752 remove_pn_file();
1753 esp->es_usedpseudo = 2;
1754 }
1755 #endif /* PPP_WITH_SRP */
1756 eap_send_response(esp, id, typenum, (u_char *)esp->es_client.ea_name,
1757 esp->es_client.ea_namelen);
1758 break;
1759
1760 case EAPT_NOTIFICATION:
1761 if (len > 0)
1762 info("EAP: Notification \"%.*q\"", len, inp);
1763 eap_send_response(esp, id, typenum, NULL, 0);
1764 break;
1765
1766 case EAPT_NAK:
1767 /*
1768 * Avoid the temptation to send Response Nak in reply
1769 * to Request Nak here. It can only lead to trouble.
1770 */
1771 warn("EAP: unexpected Nak in Request; ignored");
1772 /* Return because we're waiting for something real. */
1773 return;
1774
1775 case EAPT_MD5CHAP:
1776 if (len < 1) {
1777 error("EAP: received MD5-Challenge with no data");
1778 /* Bogus request; wait for something real. */
1779 return;
1780 }
1781 GETCHAR(vallen, inp);
1782 len--;
1783 if (vallen < 8 || vallen > len) {
1784 error("EAP: MD5-Challenge with bad length %d (8..%d)",
1785 vallen, len);
1786 /* Try something better. */
1787 eap_send_nak(esp, id, EAPT_SRP);
1788 break;
1789 }
1790
1791 /* Not so likely to happen. */
1792 if (len - vallen >= sizeof (rhostname)) {
1793 dbglog("EAP: trimming really long peer name down");
1794 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1795 rhostname[sizeof (rhostname) - 1] = '\0';
1796 } else {
1797 BCOPY(inp + vallen, rhostname, len - vallen);
1798 rhostname[len - vallen] = '\0';
1799 }
1800
1801 /* In case the remote doesn't give us his name. */
1802 if (explicit_remote ||
1803 (remote_name[0] != '\0' && vallen == len))
1804 strlcpy(rhostname, remote_name, sizeof (rhostname));
1805
1806 /*
1807 * Get the secret for authenticating ourselves with
1808 * the specified host.
1809 */
1810 if (!get_secret(esp->es_unit, esp->es_client.ea_name,
1811 rhostname, secret, &secret_len, 0)) {
1812 dbglog("EAP: no MD5 secret for auth to %q", rhostname);
1813 eap_send_nak(esp, id, EAPT_SRP);
1814 break;
1815 }
1816
1817 mdctx = PPP_MD_CTX_new();
1818 if (mdctx != NULL) {
1819 if (PPP_DigestInit(mdctx, PPP_md5())) {
1820 typenum = id;
1821 if (PPP_DigestUpdate(mdctx, &typenum, 1)) {
1822 if (PPP_DigestUpdate(mdctx, secret, secret_len)) {
1823 BZERO(secret, sizeof(secret));
1824 if (PPP_DigestUpdate(mdctx, inp, vallen)) {
1825 if (PPP_DigestFinal(mdctx, hash, &hashlen)) {
1826 eap_chap_response(esp, id, hash, esp->es_client.ea_name,
1827 esp->es_client.ea_namelen);
1828 PPP_MD_CTX_free(mdctx);
1829 break;
1830 }
1831 }
1832 }
1833 }
1834 }
1835 PPP_MD_CTX_free(mdctx);
1836 }
1837 dbglog("EAP: Invalid MD5 checksum");
1838 eap_send_nak(esp, id, EAPT_SRP);
1839 break;
1840
1841 #ifdef PPP_WITH_EAPTLS
1842 case EAPT_TLS:
1843
1844 switch(esp->es_client.ea_state) {
1845
1846 case eapListen:
1847
1848 if (len < 1) {
1849 error("EAP: received EAP-TLS Listen packet with no data");
1850 /* Bogus request; wait for something real. */
1851 return;
1852 }
1853 GETCHAR(flags, inp);
1854 if(flags & EAP_TLS_FLAGS_START){
1855
1856 esp->es_client.ea_using_eaptls = 1;
1857
1858 if (explicit_remote){
1859 esp->es_client.ea_peer = strdup(remote_name);
1860 esp->es_client.ea_peerlen = strlen(remote_name);
1861 } else
1862 esp->es_client.ea_peer = NULL;
1863
1864 /* Init ssl session */
1865 if(!eaptls_init_ssl_client(esp)) {
1866 dbglog("cannot init ssl");
1867 eap_send_nak(esp, id, EAPT_MSCHAPV2);
1868 esp->es_client.ea_using_eaptls = 0;
1869 break;
1870 }
1871
1872 ets = esp->es_client.ea_session;
1873 eap_tls_response(esp, id);
1874 esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1875 break;
1876 }
1877
1878 /* The server has sent a bad start packet. */
1879 eap_send_nak(esp, id, EAPT_MSCHAPV2);
1880 break;
1881
1882 case eapTlsRecvAck:
1883 eap_tls_response(esp, id);
1884 esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1885 break;
1886
1887 case eapTlsRecv:
1888 if (len < 1) {
1889 error("EAP: discarding EAP-TLS Receive packet with no data");
1890 /* Bogus request; wait for something real. */
1891 return;
1892 }
1893 eaptls_receive(ets, inp, len);
1894
1895 if(ets->frag) {
1896 eap_tls_sendack(esp, id);
1897 esp->es_client.ea_state = eapTlsRecv;
1898 break;
1899 }
1900
1901 if(ets->alert_recv) {
1902 eap_tls_sendack(esp, id);
1903 esp->es_client.ea_state = eapTlsRecvFailure;
1904 break;
1905 }
1906
1907 /* Check if TLS handshake is finished */
1908 if(eaptls_is_init_finished(ets)) {
1909 #ifdef PPP_WITH_MPPE
1910 eaptls_gen_mppe_keys(ets, 1);
1911 #endif
1912 eaptls_free_session(ets);
1913 eap_tls_sendack(esp, id);
1914 esp->es_client.ea_state = eapTlsRecvSuccess;
1915 break;
1916 }
1917
1918 eap_tls_response(esp,id);
1919 esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1920 break;
1921
1922 default:
1923 eap_send_nak(esp, id, EAPT_MSCHAPV2);
1924 esp->es_client.ea_using_eaptls = 0;
1925 break;
1926 }
1927
1928 break;
1929 #endif /* PPP_WITH_EAPTLS */
1930
1931 #ifdef PPP_WITH_SRP
1932 case EAPT_SRP:
1933 if (len < 1) {
1934 error("EAP: received empty SRP Request");
1935 /* Bogus request; wait for something real. */
1936 return;
1937 }
1938
1939 /* Get subtype */
1940 GETCHAR(vallen, inp);
1941 len--;
1942 switch (vallen) {
1943 case EAPSRP_CHALLENGE:
1944 tc = NULL;
1945 if (esp->es_client.ea_session != NULL) {
1946 tc = (struct t_client *)esp->es_client.
1947 ea_session;
1948 /*
1949 * If this is a new challenge, then start
1950 * over with a new client session context.
1951 * Otherwise, just resend last response.
1952 */
1953 if (id != esp->es_client.ea_id) {
1954 t_clientclose(tc);
1955 esp->es_client.ea_session = NULL;
1956 tc = NULL;
1957 }
1958 }
1959 /* No session key just yet */
1960 esp->es_client.ea_skey = NULL;
1961 if (tc == NULL) {
1962 GETCHAR(vallen, inp);
1963 len--;
1964 if (vallen >= len) {
1965 error("EAP: badly-formed SRP Challenge"
1966 " (name)");
1967 /* Ignore badly-formed messages */
1968 return;
1969 }
1970 BCOPY(inp, rhostname, vallen);
1971 rhostname[vallen] = '\0';
1972 INCPTR(vallen, inp);
1973 len -= vallen;
1974
1975 /*
1976 * In case the remote doesn't give us his name,
1977 * use configured name.
1978 */
1979 if (explicit_remote ||
1980 (remote_name[0] != '\0' && vallen == 0)) {
1981 strlcpy(rhostname, remote_name,
1982 sizeof (rhostname));
1983 }
1984
1985 if (esp->es_client.ea_peer != NULL)
1986 free(esp->es_client.ea_peer);
1987 esp->es_client.ea_peer = strdup(rhostname);
1988 esp->es_client.ea_peerlen = strlen(rhostname);
1989
1990 GETCHAR(vallen, inp);
1991 len--;
1992 if (vallen >= len) {
1993 error("EAP: badly-formed SRP Challenge"
1994 " (s)");
1995 /* Ignore badly-formed messages */
1996 return;
1997 }
1998 sval.data = inp;
1999 sval.len = vallen;
2000 INCPTR(vallen, inp);
2001 len -= vallen;
2002
2003 GETCHAR(vallen, inp);
2004 len--;
2005 if (vallen > len) {
2006 error("EAP: badly-formed SRP Challenge"
2007 " (g)");
2008 /* Ignore badly-formed messages */
2009 return;
2010 }
2011 /* If no generator present, then use value 2 */
2012 if (vallen == 0) {
2013 gval.data = (u_char *)"\002";
2014 gval.len = 1;
2015 } else {
2016 gval.data = inp;
2017 gval.len = vallen;
2018 }
2019 INCPTR(vallen, inp);
2020 len -= vallen;
2021
2022 /*
2023 * If no modulus present, then use well-known
2024 * value.
2025 */
2026 if (len == 0) {
2027 Nval.data = (u_char *)wkmodulus;
2028 Nval.len = sizeof (wkmodulus);
2029 } else {
2030 Nval.data = inp;
2031 Nval.len = len;
2032 }
2033 tc = t_clientopen(esp->es_client.ea_name,
2034 &Nval, &gval, &sval);
2035 if (tc == NULL) {
2036 eap_send_nak(esp, id, EAPT_MD5CHAP);
2037 break;
2038 }
2039 esp->es_client.ea_session = (void *)tc;
2040
2041 /* Add Challenge ID & type to verifier */
2042 vals[0] = id;
2043 vals[1] = EAPT_SRP;
2044 t_clientaddexdata(tc, vals, 2);
2045 }
2046 Ap = t_clientgenexp(tc);
2047 eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
2048 Ap->len);
2049 break;
2050
2051 case EAPSRP_SKEY:
2052 tc = (struct t_client *)esp->es_client.ea_session;
2053 if (tc == NULL) {
2054 warn("EAP: peer sent Subtype 2 without 1");
2055 eap_send_nak(esp, id, EAPT_MD5CHAP);
2056 break;
2057 }
2058 if (esp->es_client.ea_skey != NULL) {
2059 /*
2060 * ID number should not change here. Warn
2061 * if it does (but otherwise ignore).
2062 */
2063 if (id != esp->es_client.ea_id) {
2064 warn("EAP: ID changed from %d to %d "
2065 "in SRP Subtype 2 rexmit",
2066 esp->es_client.ea_id, id);
2067 }
2068 } else {
2069 if (get_srp_secret(esp->es_unit,
2070 esp->es_client.ea_name,
2071 esp->es_client.ea_peer, secret, 0) == 0) {
2072 /*
2073 * Can't work with this peer because
2074 * the secret is missing. Just give
2075 * up.
2076 */
2077 eap_send_nak(esp, id, EAPT_MD5CHAP);
2078 break;
2079 }
2080 Bval.data = inp;
2081 Bval.len = len;
2082 t_clientpasswd(tc, secret);
2083 BZERO(secret, sizeof (secret));
2084 esp->es_client.ea_skey =
2085 t_clientgetkey(tc, &Bval);
2086 if (esp->es_client.ea_skey == NULL) {
2087 /* Server is rogue; stop now */
2088 error("EAP: SRP server is rogue");
2089 goto client_failure;
2090 }
2091 }
2092 eap_srpval_response(esp, id, SRPVAL_EBIT,
2093 t_clientresponse(tc));
2094 break;
2095
2096 case EAPSRP_SVALIDATOR:
2097 tc = (struct t_client *)esp->es_client.ea_session;
2098 if (tc == NULL || esp->es_client.ea_skey == NULL) {
2099 warn("EAP: peer sent Subtype 3 without 1/2");
2100 eap_send_nak(esp, id, EAPT_MD5CHAP);
2101 break;
2102 }
2103 /*
2104 * If we're already open, then this ought to be a
2105 * duplicate. Otherwise, check that the server is
2106 * who we think it is.
2107 */
2108 if (esp->es_client.ea_state == eapOpen) {
2109 if (id != esp->es_client.ea_id) {
2110 warn("EAP: ID changed from %d to %d "
2111 "in SRP Subtype 3 rexmit",
2112 esp->es_client.ea_id, id);
2113 }
2114 } else {
2115 len -= sizeof (u_int32_t) + SHA_DIGEST_LENGTH;
2116 if (len < 0 || t_clientverify(tc, inp +
2117 sizeof (u_int32_t)) != 0) {
2118 error("EAP: SRP server verification "
2119 "failed");
2120 goto client_failure;
2121 }
2122 GETLONG(esp->es_client.ea_keyflags, inp);
2123 /* Save pseudonym if user wants it. */
2124 if (len > 0 && esp->es_usepseudo) {
2125 INCPTR(SHA_DIGEST_LENGTH, inp);
2126 write_pseudonym(esp, inp, len, id);
2127 }
2128 }
2129 /*
2130 * We've verified our peer. We're now mostly done,
2131 * except for waiting on the regular EAP Success
2132 * message.
2133 */
2134 eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
2135 break;
2136
2137 case EAPSRP_LWRECHALLENGE:
2138 if (len < 4) {
2139 warn("EAP: malformed Lightweight rechallenge");
2140 return;
2141 }
2142 ctxt = PPP_MD_CTX_new();
2143 if (ctxt) {
2144
2145 vals[0] = id;
2146 PPP_DigestInit(ctxt, PPP_sha1());
2147 PPP_DigestUpdate(ctxt, vals, 1);
2148 PPP_DigestUpdate(ctxt, esp->es_client.ea_skey,
2149 SESSION_KEY_LEN);
2150 PPP_DigestUpdate(ctxt, inp, len);
2151 PPP_DigestUpdate(ctxt, esp->es_client.ea_name,
2152 esp->es_client.ea_namelen);
2153 PPP_DigestFinal(ctxt, dig, &diglen);
2154
2155 PPP_MD_CTX_free(ctxt);
2156
2157 eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
2158 SHA_DIGEST_LENGTH);
2159 }
2160 break;
2161
2162 default:
2163 error("EAP: unknown SRP Subtype %d", vallen);
2164 eap_send_nak(esp, id, EAPT_MD5CHAP);
2165 break;
2166 }
2167 break;
2168 #endif /* PPP_WITH_SRP */
2169
2170 #ifdef PPP_WITH_CHAPMS
2171 case EAPT_MSCHAPV2:
2172 if (len < 4) {
2173 error("EAP: received invalid MSCHAPv2 packet, too short");
2174 return;
2175 }
2176 unsigned char opcode;
2177 GETCHAR(opcode, inp);
2178 unsigned char chapid; /* Chapv2-ID */
2179 GETCHAR(chapid, inp);
2180 short mssize;
2181 GETSHORT(mssize, inp);
2182
2183 /* Validate the mssize field */
2184 if (len != mssize) {
2185 error("EAP: received invalid MSCHAPv2 packet, invalid length");
2186 return;
2187 }
2188 len -= 4;
2189
2190 /* If MSCHAPv2 digest was not found, NAK the packet */
2191 if (!esp->es_client.digest) {
2192 error("EAP MSCHAPv2 not supported");
2193 eap_send_nak(esp, id, EAPT_SRP);
2194 return;
2195 }
2196
2197 switch (opcode) {
2198 case CHAP_CHALLENGE: {
2199
2200 /* make_response() expects: VLEN + VALUE */
2201 u_char *challenge = inp;
2202
2203 unsigned char vsize;
2204 GETCHAR(vsize, inp);
2205 len -= 1;
2206
2207 /* Validate the VALUE field */
2208 if (vsize != MS_CHAP2_PEER_CHAL_LEN || len < MS_CHAP2_PEER_CHAL_LEN) {
2209 error("EAP: received invalid MSCHAPv2 packet, invalid value-length: %d", vsize);
2210 return;
2211 }
2212
2213 /* Increment past the VALUE field */
2214 INCPTR(MS_CHAP2_PEER_CHAL_LEN, inp);
2215 len -= MS_CHAP2_PEER_CHAL_LEN;
2216
2217 /* Extract the hostname */
2218 rhostname[0] = '\0';
2219 if (len > 0) {
2220 if (len >= sizeof (rhostname)) {
2221 dbglog("EAP: trimming really long peer name down");
2222 len = sizeof(rhostname) - 1;
2223 }
2224 BCOPY(inp, rhostname, len);
2225 rhostname[len] = '\0';
2226 }
2227
2228 /* In case the remote doesn't give us his name. */
2229 if (explicit_remote || (remote_name[0] != '\0' && len == 0))
2230 strlcpy(rhostname, remote_name, sizeof(rhostname));
2231
2232 /* Get the secret for authenticating ourselves with the specified host. */
2233 if (!get_secret(esp->es_unit, esp->es_client.ea_name,
2234 rhostname, secret, &secret_len, 0)) {
2235 dbglog("EAP: no CHAP secret for auth to %q", rhostname);
2236 eap_send_nak(esp, id, EAPT_SRP);
2237 break;
2238 }
2239 esp->es_client.ea_namelen = strlen(esp->es_client.ea_name);
2240
2241 /* Create the MSCHAPv2 response (and add to cache) */
2242 unsigned char response[MS_CHAP2_RESPONSE_LEN+1]; // VLEN + VALUE
2243 esp->es_client.digest->make_response(response, chapid, esp->es_client.ea_name,
2244 challenge, secret, secret_len, NULL);
2245
2246 eap_chapv2_response(esp, id, chapid, response, esp->es_client.ea_name, esp->es_client.ea_namelen);
2247 break;
2248 }
2249 case CHAP_SUCCESS: {
2250
2251 /* Check response for mutual authentication */
2252 u_char status = CHAP_FAILURE;
2253 if (esp->es_client.digest->check_success(chapid, inp, len) == 1) {
2254 info("Chap authentication succeeded! %.*v", len, inp);
2255 status = CHAP_SUCCESS;
2256 }
2257 eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
2258 break;
2259 }
2260 case CHAP_FAILURE: {
2261
2262 /* Process the failure string, and log appropriate information */
2263 esp->es_client.digest->handle_failure(inp, len);
2264
2265 u_char status = CHAP_FAILURE;
2266 eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
2267 goto client_failure; /* force termination */
2268 }
2269 default:
2270
2271 error("EAP: received invalid MSCHAPv2 packet, invalid or unsupported opcode: %d", opcode);
2272 eap_send_nak(esp, id, EAPT_SRP);
2273 }
2274
2275 break;
2276 #endif /* PPP_WITH_CHAPMS */
2277 #ifdef PPP_WITH_PEAP
2278 case EAPT_PEAP:
2279
2280 /* Initialize the PEAP context (if not already initialized) */
2281 if (!esp->ea_peap) {
2282 rhostname[0] = '\0';
2283 if (explicit_remote || (remote_name[0] != '\0')) {
2284 strlcpy(rhostname, remote_name, sizeof (rhostname));
2285 }
2286 if (peap_init(&esp->ea_peap, rhostname)) {
2287 eap_send_nak(esp, id, EAPT_TLS);
2288 break;
2289 }
2290 }
2291
2292 /* Process the PEAP packet */
2293 if (peap_process(esp, id, inp, len)) {
2294 eap_send_nak(esp, id, EAPT_TLS);
2295 }
2296
2297 break;
2298 #endif // PPP_WITH_PEAP
2299
2300 default:
2301 info("EAP: unknown authentication type %d; Naking", typenum);
2302 eap_send_nak(esp, id, EAPT_SRP);
2303 break;
2304 }
2305
2306 if (esp->es_client.ea_timeout > 0) {
2307 UNTIMEOUT(eap_client_timeout, (void *)esp);
2308 TIMEOUT(eap_client_timeout, (void *)esp,
2309 esp->es_client.ea_timeout);
2310 }
2311 return;
2312
2313 client_failure:
2314 esp->es_client.ea_state = eapBadAuth;
2315 if (esp->es_client.ea_timeout > 0) {
2316 UNTIMEOUT(eap_client_timeout, (void *)esp);
2317 }
2318 esp->es_client.ea_session = NULL;
2319 #ifdef PPP_WITH_SRP
2320 t_clientclose(tc);
2321 auth_withpeer_fail(esp->es_unit, PPP_EAP);
2322 #endif /* PPP_WITH_SRP */
2323 }
2324
2325 /*
2326 * eap_response - Receive EAP Response message (server mode).
2327 */
2328 static void
2329 eap_response(eap_state *esp, u_char *inp, int id, int len)
2330 {
2331 u_char typenum;
2332 u_char vallen;
2333 int secret_len;
2334 char secret[MAXSECRETLEN];
2335 char rhostname[256];
2336 PPP_MD_CTX *mdctx;
2337 u_char hash[MD5_DIGEST_LENGTH];
2338 int hashlen = MD5_DIGEST_LENGTH;
2339 #ifdef PPP_WITH_SRP
2340 struct t_server *ts;
2341 struct t_num A;
2342 PPP_MD_CTX *ctxt;
2343 u_char dig[SHA_DIGEST_LENGTH];
2344 int diglen = sizeof(dig);
2345 #endif /* PPP_WITH_SRP */
2346
2347 #ifdef PPP_WITH_EAPTLS
2348 struct eaptls_session *ets;
2349 u_char flags;
2350 #endif /* PPP_WITH_EAPTLS */
2351 #ifdef PPP_WITH_CHAPMS
2352 u_char opcode;
2353 chap_verify_hook_fn *chap_verifier;
2354 char response_message[256];
2355 #endif /* PPP_WITH_CHAPMS */
2356
2357 /*
2358 * Ignore responses if we're not open
2359 */
2360 if (esp->es_server.ea_state <= eapClosed)
2361 return;
2362
2363 if (esp->es_server.ea_id != id) {
2364 dbglog("EAP: discarding Response %d; expected ID %d", id,
2365 esp->es_server.ea_id);
2366 return;
2367 }
2368
2369 esp->es_server.ea_responses++;
2370
2371 if (len <= 0) {
2372 error("EAP: empty Response message discarded");
2373 return;
2374 }
2375
2376 GETCHAR(typenum, inp);
2377 len--;
2378
2379 switch (typenum) {
2380 case EAPT_IDENTITY:
2381 if (esp->es_server.ea_state != eapIdentify) {
2382 dbglog("EAP discarding unwanted Identify \"%.q\"", len,
2383 inp);
2384 break;
2385 }
2386 info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
2387 if (esp->es_server.ea_peer != NULL &&
2388 esp->es_server.ea_peer != remote_name)
2389 free(esp->es_server.ea_peer);
2390 esp->es_server.ea_peer = malloc(len + 1);
2391 if (esp->es_server.ea_peer == NULL) {
2392 esp->es_server.ea_peerlen = 0;
2393 eap_figure_next_state(esp, 1);
2394 break;
2395 }
2396 BCOPY(inp, esp->es_server.ea_peer, len);
2397 esp->es_server.ea_peer[len] = '\0';
2398 esp->es_server.ea_peerlen = len;
2399 eap_figure_next_state(esp, 0);
2400 break;
2401
2402 #ifdef PPP_WITH_EAPTLS
2403 case EAPT_TLS:
2404 switch(esp->es_server.ea_state) {
2405
2406 case eapTlsRecv:
2407
2408 ets = (struct eaptls_session *) esp->es_server.ea_session;
2409
2410 eap_figure_next_state(esp,
2411 eaptls_receive(esp->es_server.ea_session, inp, len));
2412
2413 if(ets->alert_recv) {
2414 eap_send_failure(esp);
2415 break;
2416 }
2417 break;
2418
2419 case eapTlsRecvAck:
2420 if(len > 1) {
2421 dbglog("EAP-TLS ACK with extra data");
2422 }
2423 eap_figure_next_state(esp, 0);
2424 break;
2425
2426 case eapTlsRecvClient:
2427 /* Receive authentication response from client */
2428 if (len > 0) {
2429 GETCHAR(flags, inp);
2430
2431 if(len == 1 && !flags) { /* Ack = ok */
2432 #ifdef PPP_WITH_MPPE
2433 eaptls_gen_mppe_keys( esp->es_server.ea_session, 0 );
2434 #endif
2435 eap_send_success(esp);
2436 }
2437 else { /* failure */
2438 warn("Server authentication failed");
2439 eap_send_failure(esp);
2440 }
2441 }
2442 else
2443 warn("Bogus EAP-TLS packet received from client");
2444
2445 eaptls_free_session(esp->es_server.ea_session);
2446
2447 break;
2448
2449 case eapTlsRecvAlertAck:
2450 eap_send_failure(esp);
2451 break;
2452
2453 default:
2454 eap_figure_next_state(esp, 1);
2455 break;
2456 }
2457 break;
2458 #endif /* PPP_WITH_EAPTLS */
2459
2460 case EAPT_NOTIFICATION:
2461 dbglog("EAP unexpected Notification; response discarded");
2462 break;
2463
2464 case EAPT_NAK:
2465 if (len < 1) {
2466 info("EAP: Nak Response with no suggested protocol");
2467 eap_figure_next_state(esp, 1);
2468 break;
2469 }
2470
2471 GETCHAR(vallen, inp);
2472 len--;
2473
2474 if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
2475 /* Peer cannot Nak Identify Request */
2476 eap_figure_next_state(esp, 1);
2477 break;
2478 }
2479
2480 switch (vallen) {
2481 case EAPT_SRP:
2482 /* Run through SRP validator selection again. */
2483 esp->es_server.ea_state = eapIdentify;
2484 eap_figure_next_state(esp, 0);
2485 break;
2486
2487 case EAPT_MD5CHAP:
2488 esp->es_server.ea_state = eapMD5Chall;
2489 break;
2490
2491 #ifdef PPP_WITH_EAPTLS
2492 /* Send EAP-TLS start packet */
2493 case EAPT_TLS:
2494 esp->es_server.ea_state = eapTlsStart;
2495 break;
2496 #endif /* PPP_WITH_EAPTLS */
2497
2498 #ifdef PPP_WITH_CHAPMS
2499 case EAPT_MSCHAPV2:
2500 info("EAP: peer proposes MSCHAPv2");
2501 /* If MSCHAPv2 digest was not found, NAK the packet */
2502 if (!esp->es_server.digest) {
2503 error("EAP MSCHAPv2 not supported");
2504 eap_send_nak(esp, id, EAPT_SRP);
2505 break;
2506 }
2507 esp->es_server.ea_state = eapMSCHAPv2Chall;
2508 break;
2509 #endif /* PPP_WITH_CHAPMS */
2510
2511 default:
2512 dbglog("EAP: peer requesting unknown Type %d", vallen);
2513 switch (esp->es_server.ea_state) {
2514 case eapSRP1:
2515 case eapSRP2:
2516 case eapSRP3:
2517 esp->es_server.ea_state = eapMD5Chall;
2518 break;
2519 case eapMD5Chall:
2520 case eapSRP4:
2521 esp->es_server.ea_state = eapIdentify;
2522 eap_figure_next_state(esp, 0);
2523 break;
2524 default:
2525 break;
2526 }
2527 break;
2528 }
2529 break;
2530
2531 case EAPT_MD5CHAP:
2532 if (esp->es_server.ea_state != eapMD5Chall) {
2533 error("EAP: unexpected MD5-Response");
2534 eap_figure_next_state(esp, 1);
2535 break;
2536 }
2537 if (len < 1) {
2538 error("EAP: received MD5-Response with no data");
2539 eap_figure_next_state(esp, 1);
2540 break;
2541 }
2542 GETCHAR(vallen, inp);
2543 len--;
2544 if (vallen != 16 || vallen > len) {
2545 error("EAP: MD5-Response with bad length %d", vallen);
2546 eap_figure_next_state(esp, 1);
2547 break;
2548 }
2549
2550 /* Not so likely to happen. */
2551 if (len - vallen >= sizeof (rhostname)) {
2552 dbglog("EAP: trimming really long peer name down");
2553 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2554 rhostname[sizeof (rhostname) - 1] = '\0';
2555 } else {
2556 BCOPY(inp + vallen, rhostname, len - vallen);
2557 rhostname[len - vallen] = '\0';
2558 }
2559
2560 /* In case the remote doesn't give us his name. */
2561 if (explicit_remote ||
2562 (remote_name[0] != '\0' && vallen == len))
2563 strlcpy(rhostname, remote_name, sizeof (rhostname));
2564
2565 /*
2566 * Get the secret for authenticating the specified
2567 * host.
2568 */
2569 if (!get_secret(esp->es_unit, rhostname,
2570 esp->es_server.ea_name, secret, &secret_len, 1)) {
2571 dbglog("EAP: no MD5 secret for auth of %q", rhostname);
2572 eap_send_failure(esp);
2573 break;
2574 }
2575
2576 mdctx = PPP_MD_CTX_new();
2577 if (mdctx != NULL) {
2578
2579 if (PPP_DigestInit(mdctx, PPP_md5())) {
2580
2581 if (PPP_DigestUpdate(mdctx, &esp->es_server.ea_id, 1)) {
2582
2583 if (PPP_DigestUpdate(mdctx, &secret, secret_len)) {
2584
2585 BZERO(secret, sizeof(secret));
2586 if (PPP_DigestUpdate(mdctx, esp->es_challenge, esp->es_challen)) {
2587
2588 if (PPP_DigestFinal(mdctx, hash, &hashlen)) {
2589
2590 if (BCMP(hash, inp, MD5_DIGEST_LENGTH) == 0) {
2591 esp->es_server.ea_type = EAPT_MD5CHAP;
2592 eap_send_success(esp);
2593 eap_figure_next_state(esp, 0);
2594
2595 if (esp->es_rechallenge != 0) {
2596 TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2597 }
2598 PPP_MD_CTX_free(mdctx);
2599 break;
2600 }
2601 }
2602 }
2603 }
2604 }
2605 }
2606
2607 PPP_MD_CTX_free(mdctx);
2608 }
2609
2610 eap_send_failure(esp);
2611 break;
2612
2613 #ifdef PPP_WITH_CHAPMS
2614 case EAPT_MSCHAPV2:
2615 if (len < 1) {
2616 error("EAP: received MSCHAPv2 with no data");
2617 eap_figure_next_state(esp, 1);
2618 break;
2619 }
2620 GETCHAR(opcode, inp);
2621 len--;
2622
2623 switch (opcode) {
2624 case CHAP_RESPONSE:
2625 if (esp->es_server.ea_state != eapMSCHAPv2Chall) {
2626 error("EAP: unexpected MSCHAPv2-Response");
2627 eap_figure_next_state(esp, 1);
2628 break;
2629 }
2630 /* skip MS ID + len */
2631 INCPTR(3, inp);
2632 GETCHAR(vallen, inp);
2633 len -= 4;
2634
2635 if (vallen != MS_CHAP2_RESPONSE_LEN || vallen > len) {
2636 error("EAP: Invalid MSCHAPv2-Response "
2637 "length %d", vallen);
2638 eap_figure_next_state(esp, 1);
2639 break;
2640 }
2641
2642 /* Not so likely to happen. */
2643 if (len - vallen >= sizeof (rhostname)) {
2644 dbglog("EAP: trimming really long peer name down");
2645 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2646 rhostname[sizeof (rhostname) - 1] = '\0';
2647 } else {
2648 BCOPY(inp + vallen, rhostname, len - vallen);
2649 rhostname[len - vallen] = '\0';
2650 }
2651
2652 /* In case the remote doesn't give us his name. */
2653 if (explicit_remote ||
2654 (remote_name[0] != '\0' && vallen == len))
2655 strlcpy(rhostname, remote_name, sizeof (rhostname));
2656
2657 /* strip the MS domain name */
2658 if (chapms_strip_domain && strrchr(rhostname, '\\')) {
2659 char tmp[MAXNAMELEN+1];
2660
2661 strcpy(tmp, strrchr(rhostname, '\\') + 1);
2662 strlcpy(rhostname, tmp, sizeof(rhostname));
2663 }
2664
2665 if (chap_verify_hook)
2666 chap_verifier = chap_verify_hook;
2667 else
2668 chap_verifier = eap_chap_verify_response;
2669
2670 esp->es_server.ea_id += 1;
2671 if ((*chap_verifier)(rhostname,
2672 esp->es_server.ea_name,
2673 id,
2674 esp->es_server.digest,
2675 esp->es_challenge,
2676 inp - 1,
2677 response_message,
2678 sizeof(response_message)))
2679 {
2680 info("EAP: MSCHAPv2 success for peer %q",
2681 rhostname);
2682 esp->es_server.ea_type = EAPT_MSCHAPV2;
2683 eap_chapms2_send_request(esp,
2684 esp->es_server.ea_id,
2685 CHAP_SUCCESS,
2686 esp->es_server.ea_id,
2687 response_message,
2688 strlen(response_message));
2689 eap_figure_next_state(esp, 0);
2690 if (esp->es_rechallenge != 0)
2691 TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2692 }
2693 else {
2694 warn("EAP: MSCHAPv2 failure for peer %q",
2695 rhostname);
2696 eap_chapms2_send_request(esp,
2697 esp->es_server.ea_id,
2698 CHAP_FAILURE,
2699 esp->es_server.ea_id,
2700 response_message,
2701 strlen(response_message));
2702 }
2703 break;
2704 case CHAP_SUCCESS:
2705 info("EAP: MSCHAPv2 success confirmed");
2706 break;
2707 case CHAP_FAILURE:
2708 info("EAP: MSCHAPv2 failure confirmed");
2709 break;
2710 default:
2711 error("EAP: Unhandled MSCHAPv2 opcode %d", opcode);
2712 eap_send_nak(esp, id, EAPT_SRP);
2713 }
2714
2715 break;
2716 #endif /* PPP_WITH_CHAPMS */
2717
2718 #ifdef PPP_WITH_SRP
2719 case EAPT_SRP:
2720 if (len < 1) {
2721 error("EAP: empty SRP Response");
2722 eap_figure_next_state(esp, 1);
2723 break;
2724 }
2725 GETCHAR(typenum, inp);
2726 len--;
2727 switch (typenum) {
2728 case EAPSRP_CKEY:
2729 if (esp->es_server.ea_state != eapSRP1) {
2730 error("EAP: unexpected SRP Subtype 1 Response");
2731 eap_figure_next_state(esp, 1);
2732 break;
2733 }
2734 A.data = inp;
2735 A.len = len;
2736 ts = (struct t_server *)esp->es_server.ea_session;
2737 assert(ts != NULL);
2738 esp->es_server.ea_skey = t_servergetkey(ts, &A);
2739 if (esp->es_server.ea_skey == NULL) {
2740 /* Client's A value is bogus; terminate now */
2741 error("EAP: bogus A value from client");
2742 eap_send_failure(esp);
2743 } else {
2744 eap_figure_next_state(esp, 0);
2745 }
2746 break;
2747
2748 case EAPSRP_CVALIDATOR:
2749 if (esp->es_server.ea_state != eapSRP2) {
2750 error("EAP: unexpected SRP Subtype 2 Response");
2751 eap_figure_next_state(esp, 1);
2752 break;
2753 }
2754 if (len < sizeof (u_int32_t) + SHA_DIGEST_LENGTH) {
2755 error("EAP: M1 length %d < %d", len,
2756 sizeof (u_int32_t) + SHA_DIGEST_LENGTH);
2757 eap_figure_next_state(esp, 1);
2758 break;
2759 }
2760 GETLONG(esp->es_server.ea_keyflags, inp);
2761 ts = (struct t_server *)esp->es_server.ea_session;
2762 assert(ts != NULL);
2763 if (t_serververify(ts, inp)) {
2764 info("EAP: unable to validate client identity");
2765 eap_send_failure(esp);
2766 break;
2767 }
2768 eap_figure_next_state(esp, 0);
2769 break;
2770
2771 case EAPSRP_ACK:
2772 if (esp->es_server.ea_state != eapSRP3) {
2773 error("EAP: unexpected SRP Subtype 3 Response");
2774 eap_send_failure(esp);
2775 break;
2776 }
2777 esp->es_server.ea_type = EAPT_SRP;
2778 eap_send_success(esp);
2779 eap_figure_next_state(esp, 0);
2780 if (esp->es_rechallenge != 0)
2781 TIMEOUT(eap_rechallenge, esp,
2782 esp->es_rechallenge);
2783 if (esp->es_lwrechallenge != 0)
2784 TIMEOUT(srp_lwrechallenge, esp,
2785 esp->es_lwrechallenge);
2786 break;
2787
2788 case EAPSRP_LWRECHALLENGE:
2789 if (esp->es_server.ea_state != eapSRP4) {
2790 info("EAP: unexpected SRP Subtype 4 Response");
2791 return;
2792 }
2793 if (len != SHA_DIGEST_LENGTH) {
2794 error("EAP: bad Lightweight rechallenge "
2795 "response");
2796 return;
2797 }
2798 ctxt = PPP_MD_CTX_new();
2799 if (ctxt) {
2800 vallen = id;
2801
2802 PPP_DigestInit(ctxt, PPP_sha1());
2803 PPP_DigestUpdate(ctxt, &vallen, 1);
2804 PPP_DigestUpdate(ctxt, esp->es_server.ea_skey,
2805 SESSION_KEY_LEN);
2806 PPP_DigestUpdate(ctxt, esp->es_challenge, esp->es_challen);
2807 PPP_DigestUpdate(ctxt, esp->es_server.ea_peer,
2808 esp->es_server.ea_peerlen);
2809 PPP_DigestFinal(ctxt, dig, &diglen);
2810
2811 PPP_MD_CTX_free(ctxt);
2812
2813 if (BCMP(dig, inp, SHA_DIGEST_LENGTH) != 0) {
2814 error("EAP: failed Lightweight rechallenge");
2815 eap_send_failure(esp);
2816 break;
2817 }
2818
2819 esp->es_server.ea_state = eapOpen;
2820 if (esp->es_lwrechallenge != 0)
2821 TIMEOUT(srp_lwrechallenge, esp,
2822 esp->es_lwrechallenge);
2823 }
2824 break;
2825 }
2826 break;
2827 #endif /* PPP_WITH_SRP */
2828
2829 default:
2830 /* This can't happen. */
2831 error("EAP: unknown Response type %d; ignored", typenum);
2832 return;
2833 }
2834
2835 if (esp->es_server.ea_timeout > 0) {
2836 UNTIMEOUT(eap_server_timeout, (void *)esp);
2837 }
2838
2839 if (esp->es_server.ea_state != eapBadAuth &&
2840 esp->es_server.ea_state != eapOpen) {
2841 esp->es_server.ea_id++;
2842 eap_send_request(esp);
2843 }
2844 }
2845
2846 /*
2847 * eap_success - Receive EAP Success message (client mode).
2848 */
2849 static void
2850 eap_success(eap_state *esp, u_char *inp, int id, int len)
2851 {
2852 if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
2853 #ifdef PPP_WITH_EAPTLS
2854 && esp->es_client.ea_state != eapTlsRecvSuccess
2855 #endif /* PPP_WITH_EAPTLS */
2856 ) {
2857 dbglog("EAP unexpected success message in state %s (%d)",
2858 eap_state_name(esp->es_client.ea_state),
2859 esp->es_client.ea_state);
2860 return;
2861 }
2862
2863 #ifdef PPP_WITH_EAPTLS
2864 if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state !=
2865 eapTlsRecvSuccess) {
2866 dbglog("EAP-TLS unexpected success message in state %s (%d)",
2867 eap_state_name(esp->es_client.ea_state),
2868 esp->es_client.ea_state);
2869 return;
2870 }
2871 #endif /* PPP_WITH_EAPTLS */
2872
2873 if (esp->es_client.ea_timeout > 0) {
2874 UNTIMEOUT(eap_client_timeout, (void *)esp);
2875 }
2876
2877 if (len > 0) {
2878 /* This is odd. The spec doesn't allow for this. */
2879 PRINTMSG(inp, len);
2880 }
2881
2882 #ifdef PPP_WITH_PEAP
2883 peap_finish(&esp->ea_peap);
2884 #endif
2885
2886 esp->es_client.ea_state = eapOpen;
2887 auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2888 }
2889
2890 /*
2891 * eap_failure - Receive EAP Failure message (client mode).
2892 */
2893 static void
2894 eap_failure(eap_state *esp, u_char *inp, int id, int len)
2895 {
2896 /*
2897 * Ignore failure messages if we're not open
2898 */
2899 if (esp->es_client.ea_state <= eapClosed)
2900 return;
2901
2902 if (!eap_client_active(esp)) {
2903 dbglog("EAP unexpected failure message in state %s (%d)",
2904 eap_state_name(esp->es_client.ea_state),
2905 esp->es_client.ea_state);
2906 }
2907
2908 if (esp->es_client.ea_timeout > 0) {
2909 UNTIMEOUT(eap_client_timeout, (void *)esp);
2910 }
2911
2912 if (len > 0) {
2913 /* This is odd. The spec doesn't allow for this. */
2914 PRINTMSG(inp, len);
2915 }
2916
2917 esp->es_client.ea_state = eapBadAuth;
2918
2919 error("EAP: peer reports authentication failure");
2920
2921 #ifdef PPP_WITH_PEAP
2922 peap_finish(&esp->ea_peap);
2923 #endif
2924
2925 auth_withpeer_fail(esp->es_unit, PPP_EAP);
2926 }
2927
2928 /*
2929 * eap_input - Handle received EAP message.
2930 */
2931 static void
2932 eap_input(int unit, u_char *inp, int inlen)
2933 {
2934 eap_state *esp = &eap_states[unit];
2935 u_char code, id;
2936 int len;
2937
2938 /*
2939 * Parse header (code, id and length). If packet too short,
2940 * drop it.
2941 */
2942 if (inlen < EAP_HEADERLEN) {
2943 error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2944 return;
2945 }
2946 GETCHAR(code, inp);
2947 GETCHAR(id, inp);
2948 GETSHORT(len, inp);
2949 if (len < EAP_HEADERLEN || len > inlen) {
2950 error("EAP: packet has illegal length field %d (%d..%d)", len,
2951 EAP_HEADERLEN, inlen);
2952 return;
2953 }
2954 len -= EAP_HEADERLEN;
2955
2956 /* Dispatch based on message code */
2957 switch (code) {
2958 case EAP_REQUEST:
2959 eap_request(esp, inp, id, len);
2960 break;
2961
2962 case EAP_RESPONSE:
2963 eap_response(esp, inp, id, len);
2964 break;
2965
2966 case EAP_SUCCESS:
2967 eap_success(esp, inp, id, len);
2968 break;
2969
2970 case EAP_FAILURE:
2971 eap_failure(esp, inp, id, len);
2972 break;
2973
2974 default: /* XXX Need code reject */
2975 /* Note: it's not legal to send EAP Nak here. */
2976 warn("EAP: unknown code %d received", code);
2977 break;
2978 }
2979 }
2980
2981 /*
2982 * eap_printpkt - print the contents of an EAP packet.
2983 */
2984 static char *eap_codenames[] = {
2985 "Request", "Response", "Success", "Failure"
2986 };
2987
2988 static char *eap_typenames[] = {
2989 "Identity", "Notification", "Nak", "MD5-Challenge",
2990 "OTP", "Generic-Token", NULL, NULL,
2991 "RSA", "DSS", "KEA", "KEA-Validate",
2992 "TLS", "Defender", "Windows 2000", "Arcot",
2993 "Cisco", "Nokia", "SRP", NULL,
2994 "TTLS", "RAS", "AKA", "3COM", "PEAP",
2995 "MSCHAPv2"
2996 };
2997
2998 static int
2999 eap_printpkt(u_char *inp, int inlen,
3000 void (*printer) (void *, char *, ...), void *arg)
3001 {
3002 int code, id, len, rtype, vallen;
3003 u_char *pstart;
3004 #ifdef PPP_WITH_SRP
3005 u_int32_t uval;
3006 #endif /* PPP_WITH_SRP */
3007 #ifdef PPP_WITH_EAPTLS
3008 u_char flags;
3009 #endif /* PPP_WITH_EAPTLS */
3010 #ifdef PPP_WITH_CHAPMS
3011 u_char opcode;
3012 #endif /* PPP_WITH_CHAPMS */
3013
3014 if (inlen < EAP_HEADERLEN)
3015 return (0);
3016 pstart = inp;
3017 GETCHAR(code, inp);
3018 GETCHAR(id, inp);
3019 GETSHORT(len, inp);
3020 if (len < EAP_HEADERLEN || len > inlen)
3021 return (0);
3022
3023 if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
3024 printer(arg, " %s", eap_codenames[code-1]);
3025 else
3026 printer(arg, " code=0x%x", code);
3027 printer(arg, " id=0x%x", id);
3028 len -= EAP_HEADERLEN;
3029 switch (code) {
3030 case EAP_REQUEST:
3031 if (len < 1) {
3032 printer(arg, " <missing type>");
3033 break;
3034 }
3035 GETCHAR(rtype, inp);
3036 len--;
3037 if (rtype >= 1 &&
3038 rtype <= sizeof (eap_typenames) / sizeof (char *))
3039 printer(arg, " %s", eap_typenames[rtype-1]);
3040 else
3041 printer(arg, " type=0x%x", rtype);
3042 switch (rtype) {
3043 case EAPT_IDENTITY:
3044 case EAPT_NOTIFICATION:
3045 if (len > 0) {
3046 printer(arg, " <Message ");
3047 print_string((char *)inp, len, printer, arg);
3048 printer(arg, ">");
3049 INCPTR(len, inp);
3050 len = 0;
3051 } else {
3052 printer(arg, " <No message>");
3053 }
3054 break;
3055
3056 case EAPT_MD5CHAP:
3057 if (len <= 0)
3058 break;
3059 GETCHAR(vallen, inp);
3060 len--;
3061 if (vallen > len)
3062 goto truncated;
3063 printer(arg, " <Value%.*B>", vallen, inp);
3064 INCPTR(vallen, inp);
3065 len -= vallen;
3066 if (len > 0) {
3067 printer(arg, " <Name ");
3068 print_string((char *)inp, len, printer, arg);
3069 printer(arg, ">");
3070 INCPTR(len, inp);
3071 len = 0;
3072 } else {
3073 printer(arg, " <No name>");
3074 }
3075 break;
3076
3077 #ifdef PPP_WITH_CHAPMS
3078 case EAPT_MSCHAPV2:
3079 if (len <= 0)
3080 break;
3081 GETCHAR(opcode, inp);
3082 len--;
3083 switch (opcode) {
3084 case CHAP_CHALLENGE:
3085 INCPTR(3, inp);
3086 len -= 3;
3087 GETCHAR(vallen, inp);
3088 len--;
3089 if (vallen > len)
3090 goto truncated;
3091 len -= vallen;
3092 printer(arg, " Challenge <");
3093 for (; vallen > 0; --vallen) {
3094 u_char val;
3095 GETCHAR(val, inp);
3096 printer(arg, "%.2x", val);
3097 }
3098 printer(arg, ">");
3099 if (len > 0) {
3100 printer(arg, ", <Name ");
3101 print_string((char *)inp, len, printer, arg);
3102 printer(arg, ">");
3103 INCPTR(len, inp);
3104 len = 0;
3105 } else {
3106 printer(arg, ", <No name>");
3107 }
3108 break;
3109 case CHAP_SUCCESS:
3110 INCPTR(3, inp);
3111 len -= 3;
3112 printer(arg, " Success <Message ");
3113 print_string((char *)inp, len, printer, arg);
3114 printer(arg, ">");
3115 break;
3116 case CHAP_FAILURE:
3117 INCPTR(3, inp);
3118 len -= 3;
3119 printer(arg, " Failure <Message ");
3120 print_string((char *)inp, len, printer, arg);
3121 printer(arg, ">");
3122 break;
3123 default:
3124 INCPTR(3, inp);
3125 len -= 3;
3126 printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
3127 break;
3128 }
3129 break;
3130 #endif /* PPP_WITH_CHAPMS */
3131
3132 #ifdef PPP_WITH_EAPTLS
3133 case EAPT_TLS:
3134 if (len < 1)
3135 break;
3136 GETCHAR(flags, inp);
3137 len--;
3138
3139 if(flags == 0 && len == 0){
3140 printer(arg, " Ack");
3141 break;
3142 }
3143
3144 printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
3145 printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
3146 printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
3147 break;
3148 #endif /* PPP_WITH_EAPTLS */
3149
3150 #ifdef PPP_WITH_SRP
3151 case EAPT_SRP:
3152 if (len < 3)
3153 goto truncated;
3154 GETCHAR(vallen, inp);
3155 len--;
3156 printer(arg, "-%d", vallen);
3157 switch (vallen) {
3158 case EAPSRP_CHALLENGE:
3159 GETCHAR(vallen, inp);
3160 len--;
3161 if (vallen >= len)
3162 goto truncated;
3163 if (vallen > 0) {
3164 printer(arg, " <Name ");
3165 print_string((char *)inp, vallen, printer,
3166 arg);
3167 printer(arg, ">");
3168 } else {
3169 printer(arg, " <No name>");
3170 }
3171 INCPTR(vallen, inp);
3172 len -= vallen;
3173 GETCHAR(vallen, inp);
3174 len--;
3175 if (vallen >= len)
3176 goto truncated;
3177 printer(arg, " <s%.*B>", vallen, inp);
3178 INCPTR(vallen, inp);
3179 len -= vallen;
3180 GETCHAR(vallen, inp);
3181 len--;
3182 if (vallen > len)
3183 goto truncated;
3184 if (vallen == 0) {
3185 printer(arg, " <Default g=2>");
3186 } else {
3187 printer(arg, " <g%.*B>", vallen, inp);
3188 }
3189 INCPTR(vallen, inp);
3190 len -= vallen;
3191 if (len == 0) {
3192 printer(arg, " <Default N>");
3193 } else {
3194 printer(arg, " <N%.*B>", len, inp);
3195 INCPTR(len, inp);
3196 len = 0;
3197 }
3198 break;
3199
3200 case EAPSRP_SKEY:
3201 printer(arg, " <B%.*B>", len, inp);
3202 INCPTR(len, inp);
3203 len = 0;
3204 break;
3205
3206 case EAPSRP_SVALIDATOR:
3207 if (len < sizeof (u_int32_t))
3208 break;
3209 GETLONG(uval, inp);
3210 len -= sizeof (u_int32_t);
3211 if (uval & SRPVAL_EBIT) {
3212 printer(arg, " E");
3213 uval &= ~SRPVAL_EBIT;
3214 }
3215 if (uval != 0) {
3216 printer(arg, " f<%X>", uval);
3217 }
3218 if ((vallen = len) > SHA_DIGEST_LENGTH)
3219 vallen = SHA_DIGEST_LENGTH;
3220 printer(arg, " <M2%.*B%s>", len, inp,
3221 len < SHA_DIGEST_LENGTH ? "?" : "");
3222 INCPTR(vallen, inp);
3223 len -= vallen;
3224 if (len > 0) {
3225 printer(arg, " <PN%.*B>", len, inp);
3226 INCPTR(len, inp);
3227 len = 0;
3228 }
3229 break;
3230
3231 case EAPSRP_LWRECHALLENGE:
3232 printer(arg, " <Challenge%.*B>", len, inp);
3233 INCPTR(len, inp);
3234 len = 0;
3235 break;
3236 }
3237 break;
3238 #endif /* PPP_WITH_SRP */
3239 }
3240 break;
3241
3242 case EAP_RESPONSE:
3243 if (len < 1)
3244 break;
3245 GETCHAR(rtype, inp);
3246 len--;
3247 if (rtype >= 1 &&
3248 rtype <= sizeof (eap_typenames) / sizeof (char *))
3249 printer(arg, " %s", eap_typenames[rtype-1]);
3250 else
3251 printer(arg, " type=0x%x", rtype);
3252 switch (rtype) {
3253 case EAPT_IDENTITY:
3254 if (len > 0) {
3255 printer(arg, " <Name ");
3256 print_string((char *)inp, len, printer, arg);
3257 printer(arg, ">");
3258 INCPTR(len, inp);
3259 len = 0;
3260 }
3261 break;
3262
3263 #ifdef PPP_WITH_EAPTLS
3264 case EAPT_TLS:
3265 if (len < 1)
3266 break;
3267 GETCHAR(flags, inp);
3268 len--;
3269
3270 if(flags == 0 && len == 0){
3271 printer(arg, " Ack");
3272 break;
3273 }
3274
3275 printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
3276 printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
3277 printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
3278
3279 break;
3280 #endif /* PPP_WITH_EAPTLS */
3281
3282 case EAPT_NAK:
3283 if (len <= 0) {
3284 printer(arg, " <missing hint>");
3285 break;
3286 }
3287 GETCHAR(rtype, inp);
3288 len--;
3289 printer(arg, " <Suggested-type %02X", rtype);
3290 if (rtype >= 1 &&
3291 rtype <= sizeof (eap_typenames) / sizeof (char *))
3292 printer(arg, " (%s)", eap_typenames[rtype-1]);
3293 printer(arg, ">");
3294 break;
3295
3296 case EAPT_MD5CHAP:
3297 if (len <= 0) {
3298 printer(arg, " <missing length>");
3299 break;
3300 }
3301 GETCHAR(vallen, inp);
3302 len--;
3303 if (vallen > len)
3304 goto truncated;
3305 printer(arg, " <Value%.*B>", vallen, inp);
3306 INCPTR(vallen, inp);
3307 len -= vallen;
3308 if (len > 0) {
3309 printer(arg, " <Name ");
3310 print_string((char *)inp, len, printer, arg);
3311 printer(arg, ">");
3312 INCPTR(len, inp);
3313 len = 0;
3314 } else {
3315 printer(arg, " <No name>");
3316 }
3317 break;
3318
3319 #ifdef PPP_WITH_CHAPMS
3320 case EAPT_MSCHAPV2:
3321 if (len <= 0)
3322 break;
3323 GETCHAR(opcode, inp);
3324 len--;
3325 switch (opcode) {
3326 case CHAP_RESPONSE:
3327 INCPTR(3, inp);
3328 len -= 3;
3329 GETCHAR(vallen, inp);
3330 len--;
3331 if (vallen > len)
3332 goto truncated;
3333 len -= vallen;
3334 printer(arg, " Response <");
3335 for (; vallen > 0; --vallen) {
3336 u_char val;
3337 GETCHAR(val, inp);
3338 printer(arg, "%.2x", val);
3339 }
3340 printer(arg, ">");
3341 if (len > 0) {
3342 printer(arg, ", <Name ");
3343 print_string((char *)inp, len, printer, arg);
3344 printer(arg, ">");
3345 INCPTR(len, inp);
3346 len = 0;
3347 } else {
3348 printer(arg, ", <No name>");
3349 }
3350 break;
3351 case CHAP_SUCCESS:
3352 printer(arg, " Success");
3353 break;
3354 case CHAP_FAILURE:
3355 printer(arg, " Failure");
3356 break;
3357 default:
3358 printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
3359 break;
3360 }
3361 break;
3362 #endif /* PPP_WITH_CHAPMS */
3363
3364 #ifdef PPP_WITH_SRP
3365 case EAPT_SRP:
3366 if (len < 1)
3367 goto truncated;
3368 GETCHAR(vallen, inp);
3369 len--;
3370 printer(arg, "-%d", vallen);
3371 switch (vallen) {
3372 case EAPSRP_CKEY:
3373 printer(arg, " <A%.*B>", len, inp);
3374 INCPTR(len, inp);
3375 len = 0;
3376 break;
3377
3378 case EAPSRP_CVALIDATOR:
3379 if (len < sizeof (u_int32_t))
3380 break;
3381 GETLONG(uval, inp);
3382 len -= sizeof (u_int32_t);
3383 if (uval & SRPVAL_EBIT) {
3384 printer(arg, " E");
3385 uval &= ~SRPVAL_EBIT;
3386 }
3387 if (uval != 0) {
3388 printer(arg, " f<%X>", uval);
3389 }
3390 printer(arg, " <M1%.*B%s>", len, inp,
3391 len == SHA_DIGEST_LENGTH ? "" : "?");
3392 INCPTR(len, inp);
3393 len = 0;
3394 break;
3395
3396 case EAPSRP_ACK:
3397 break;
3398
3399 case EAPSRP_LWRECHALLENGE:
3400 printer(arg, " <Response%.*B%s>", len, inp,
3401 len == SHA_DIGEST_LENGTH ? "" : "?");
3402 if ((vallen = len) > SHA_DIGEST_LENGTH)
3403 vallen = SHA_DIGEST_LENGTH;
3404 INCPTR(vallen, inp);
3405 len -= vallen;
3406 break;
3407 }
3408 break;
3409 #endif /* PPP_WITH_SRP */
3410 }
3411 break;
3412
3413 case EAP_SUCCESS: /* No payload expected for these! */
3414 case EAP_FAILURE:
3415 break;
3416
3417 truncated:
3418 printer(arg, " <truncated>");
3419 break;
3420 }
3421
3422 if (len > 8)
3423 printer(arg, "%8B...", inp);
3424 else if (len > 0)
3425 printer(arg, "%.*B", len, inp);
3426 INCPTR(len, inp);
3427
3428 return (inp - pstart);
3429 }
3430