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