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