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