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