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