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