]> git.ozlabs.org Git - ppp.git/blob - pppd/eap.c
pppd: Add support for registering ppp interface via Linux rtnetlink API
[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                 esp->es_client.ea_namelen = strlen(esp->es_client.ea_name);
2186
2187                 /* Create the MSCHAPv2 response (and add to cache) */
2188                 unsigned char response[MS_CHAP2_RESPONSE_LEN+1]; // VLEN + VALUE
2189                 esp->es_client.digest->make_response(response, chapid, esp->es_client.ea_name,
2190                         challenge, secret, secret_len, NULL);
2191
2192                 eap_chapv2_response(esp, id, chapid, response, esp->es_client.ea_name, esp->es_client.ea_namelen);
2193                 break;
2194             }
2195             case CHAP_SUCCESS: {
2196
2197                 /* Check response for mutual authentication */
2198                 u_char status = CHAP_FAILURE;
2199                 if (esp->es_client.digest->check_success(chapid, inp, len) == 1) {
2200                      info("Chap authentication succeeded! %.*v", len, inp);
2201                      status = CHAP_SUCCESS;
2202                 }
2203                 eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
2204                 break;
2205             }
2206             case CHAP_FAILURE: {
2207
2208                 /* Process the failure string, and log appropriate information */
2209                 esp->es_client.digest->handle_failure(inp, len);
2210
2211                 u_char status = CHAP_FAILURE;
2212                 eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
2213                 goto client_failure; /* force termination */
2214             }
2215             default:
2216
2217                 error("EAP: received invalid MSCHAPv2 packet, invalid or unsupported opcode: %d", opcode);
2218                 eap_send_nak(esp, id, EAPT_SRP);
2219             }
2220
2221             break;
2222 #endif /* CHAPMS */
2223 #ifdef USE_PEAP
2224         case EAPT_PEAP:
2225
2226                 /* Initialize the PEAP context (if not already initialized) */
2227                 if (!esp->ea_peap) {
2228                         rhostname[0] = '\0';
2229                         if (explicit_remote || (remote_name[0] != '\0')) {
2230                                 strlcpy(rhostname, remote_name, sizeof (rhostname));
2231                         }
2232                         if (peap_init(&esp->ea_peap, rhostname)) {
2233                                 eap_send_nak(esp, id, EAPT_TLS);
2234                                 break;
2235                         }
2236                 }
2237
2238                 /* Process the PEAP packet */
2239                 if (peap_process(esp, id, inp, len)) {
2240                         eap_send_nak(esp, id, EAPT_TLS);
2241                 }
2242
2243                 break;
2244 #endif /* USE_PEAP */
2245
2246         default:
2247                 info("EAP: unknown authentication type %d; Naking", typenum);
2248                 eap_send_nak(esp, id, EAPT_SRP);
2249                 break;
2250         }
2251
2252         if (esp->es_client.ea_timeout > 0) {
2253                 UNTIMEOUT(eap_client_timeout, (void *)esp);
2254                 TIMEOUT(eap_client_timeout, (void *)esp,
2255                     esp->es_client.ea_timeout);
2256         }
2257         return;
2258
2259 client_failure:
2260         esp->es_client.ea_state = eapBadAuth;
2261         if (esp->es_client.ea_timeout > 0) {
2262                 UNTIMEOUT(eap_client_timeout, (void *)esp);
2263         }
2264         esp->es_client.ea_session = NULL;
2265 #ifdef USE_SRP
2266         t_clientclose(tc);
2267         auth_withpeer_fail(esp->es_unit, PPP_EAP);
2268 #endif /* USE_SRP */
2269 }
2270
2271 /*
2272  * eap_response - Receive EAP Response message (server mode).
2273  */
2274 static void
2275 eap_response(eap_state *esp, u_char *inp, int id, int len)
2276 {
2277         u_char typenum;
2278         u_char vallen;
2279         int secret_len;
2280         char secret[MAXSECRETLEN];
2281         char rhostname[256];
2282         MD5_CTX mdContext;
2283         u_char hash[MD5_SIGNATURE_SIZE];
2284 #ifdef USE_SRP
2285         struct t_server *ts;
2286         struct t_num A;
2287         SHA1_CTX ctxt;
2288         u_char dig[SHA_DIGESTSIZE];
2289 #endif /* USE_SRP */
2290
2291 #ifdef USE_EAPTLS
2292         struct eaptls_session *ets;
2293         u_char flags;
2294 #endif /* USE_EAPTLS */
2295 #ifdef CHAPMS
2296         u_char opcode;
2297         int (*chap_verifier)(char *, char *, int, struct chap_digest_type *,
2298                 unsigned char *, unsigned char *, char *, int);
2299         char response_message[256];
2300 #endif /* CHAPMS */
2301
2302         /*
2303          * Ignore responses if we're not open
2304          */
2305         if (esp->es_server.ea_state <= eapClosed)
2306                 return;
2307
2308         if (esp->es_server.ea_id != id) {
2309                 dbglog("EAP: discarding Response %d; expected ID %d", id,
2310                     esp->es_server.ea_id);
2311                 return;
2312         }
2313
2314         esp->es_server.ea_responses++;
2315
2316         if (len <= 0) {
2317                 error("EAP: empty Response message discarded");
2318                 return;
2319         }
2320
2321         GETCHAR(typenum, inp);
2322         len--;
2323
2324         switch (typenum) {
2325         case EAPT_IDENTITY:
2326                 if (esp->es_server.ea_state != eapIdentify) {
2327                         dbglog("EAP discarding unwanted Identify \"%.q\"", len,
2328                             inp);
2329                         break;
2330                 }
2331                 info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
2332                 if (esp->es_server.ea_peer != NULL &&
2333                     esp->es_server.ea_peer != remote_name)
2334                         free(esp->es_server.ea_peer);
2335                 esp->es_server.ea_peer = malloc(len + 1);
2336                 if (esp->es_server.ea_peer == NULL) {
2337                         esp->es_server.ea_peerlen = 0;
2338                         eap_figure_next_state(esp, 1);
2339                         break;
2340                 }
2341                 BCOPY(inp, esp->es_server.ea_peer, len);
2342                 esp->es_server.ea_peer[len] = '\0';
2343                 esp->es_server.ea_peerlen = len;
2344                 eap_figure_next_state(esp, 0);
2345                 break;
2346
2347 #ifdef USE_EAPTLS
2348         case EAPT_TLS:
2349                 switch(esp->es_server.ea_state) {
2350
2351                 case eapTlsRecv:
2352
2353                         ets = (struct eaptls_session *) esp->es_server.ea_session;
2354
2355                         eap_figure_next_state(esp,
2356                                 eaptls_receive(esp->es_server.ea_session, inp, len));
2357
2358                         if(ets->alert_recv) {
2359                                 eap_send_failure(esp);
2360                                 break;
2361                         }
2362                         break;
2363
2364                 case eapTlsRecvAck:
2365                         if(len > 1) {
2366                                 dbglog("EAP-TLS ACK with extra data");
2367                         }
2368                         eap_figure_next_state(esp, 0);
2369                         break;
2370
2371                 case eapTlsRecvClient:
2372                         /* Receive authentication response from client */
2373                         if (len > 0) {
2374                                 GETCHAR(flags, inp);
2375
2376                                 if(len == 1 && !flags) {        /* Ack = ok */
2377 #ifdef MPPE
2378                                         eaptls_gen_mppe_keys( esp->es_server.ea_session, 0 );
2379 #endif
2380                                         eap_send_success(esp);
2381                                 }
2382                                 else {                  /* failure */
2383                                         warn("Server authentication failed");
2384                                         eap_send_failure(esp);
2385                                 }
2386                         }
2387                         else
2388                                 warn("Bogus EAP-TLS packet received from client");
2389
2390                         eaptls_free_session(esp->es_server.ea_session);
2391
2392                         break;
2393
2394                 case eapTlsRecvAlertAck:
2395                         eap_send_failure(esp);
2396                         break;
2397
2398                 default:
2399                         eap_figure_next_state(esp, 1);
2400                         break;
2401                 }
2402                 break;
2403 #endif /* USE_EAPTLS */
2404
2405         case EAPT_NOTIFICATION:
2406                 dbglog("EAP unexpected Notification; response discarded");
2407                 break;
2408
2409         case EAPT_NAK:
2410                 if (len < 1) {
2411                         info("EAP: Nak Response with no suggested protocol");
2412                         eap_figure_next_state(esp, 1);
2413                         break;
2414                 }
2415
2416                 GETCHAR(vallen, inp);
2417                 len--;
2418
2419                 if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
2420                         /* Peer cannot Nak Identify Request */
2421                         eap_figure_next_state(esp, 1);
2422                         break;
2423                 }
2424
2425                 switch (vallen) {
2426                 case EAPT_SRP:
2427                         /* Run through SRP validator selection again. */
2428                         esp->es_server.ea_state = eapIdentify;
2429                         eap_figure_next_state(esp, 0);
2430                         break;
2431
2432                 case EAPT_MD5CHAP:
2433                         esp->es_server.ea_state = eapMD5Chall;
2434                         break;
2435
2436 #ifdef USE_EAPTLS
2437                         /* Send EAP-TLS start packet */
2438                 case EAPT_TLS:
2439                         esp->es_server.ea_state = eapTlsStart;
2440                         break;
2441 #endif /* USE_EAPTLS */
2442
2443 #ifdef CHAPMS
2444                 case EAPT_MSCHAPV2:
2445                         info("EAP: peer proposes MSCHAPv2");
2446                         /* If MSCHAPv2 digest was not found, NAK the packet */
2447                         if (!esp->es_server.digest) {
2448                                 error("EAP MSCHAPv2 not supported");
2449                                 eap_send_nak(esp, id, EAPT_SRP);
2450                                 break;
2451                         }
2452                         esp->es_server.ea_state = eapMSCHAPv2Chall;
2453                         break;
2454 #endif /* CHAPMS */
2455
2456                 default:
2457                         dbglog("EAP: peer requesting unknown Type %d", vallen);
2458                         switch (esp->es_server.ea_state) {
2459                         case eapSRP1:
2460                         case eapSRP2:
2461                         case eapSRP3:
2462                                 esp->es_server.ea_state = eapMD5Chall;
2463                                 break;
2464                         case eapMD5Chall:
2465                         case eapSRP4:
2466                                 esp->es_server.ea_state = eapIdentify;
2467                                 eap_figure_next_state(esp, 0);
2468                                 break;
2469                         default:
2470                                 break;
2471                         }
2472                         break;
2473                 }
2474                 break;
2475
2476         case EAPT_MD5CHAP:
2477                 if (esp->es_server.ea_state != eapMD5Chall) {
2478                         error("EAP: unexpected MD5-Response");
2479                         eap_figure_next_state(esp, 1);
2480                         break;
2481                 }
2482                 if (len < 1) {
2483                         error("EAP: received MD5-Response with no data");
2484                         eap_figure_next_state(esp, 1);
2485                         break;
2486                 }
2487                 GETCHAR(vallen, inp);
2488                 len--;
2489                 if (vallen != 16 || vallen > len) {
2490                         error("EAP: MD5-Response with bad length %d", vallen);
2491                         eap_figure_next_state(esp, 1);
2492                         break;
2493                 }
2494
2495                 /* Not so likely to happen. */
2496                 if (len - vallen >= sizeof (rhostname)) {
2497                         dbglog("EAP: trimming really long peer name down");
2498                         BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2499                         rhostname[sizeof (rhostname) - 1] = '\0';
2500                 } else {
2501                         BCOPY(inp + vallen, rhostname, len - vallen);
2502                         rhostname[len - vallen] = '\0';
2503                 }
2504
2505                 /* In case the remote doesn't give us his name. */
2506                 if (explicit_remote ||
2507                     (remote_name[0] != '\0' && vallen == len))
2508                         strlcpy(rhostname, remote_name, sizeof (rhostname));
2509
2510                 /*
2511                  * Get the secret for authenticating the specified
2512                  * host.
2513                  */
2514                 if (!get_secret(esp->es_unit, rhostname,
2515                     esp->es_server.ea_name, secret, &secret_len, 1)) {
2516                         dbglog("EAP: no MD5 secret for auth of %q", rhostname);
2517                         eap_send_failure(esp);
2518                         break;
2519                 }
2520                 MD5_Init(&mdContext);
2521                 MD5_Update(&mdContext, &esp->es_server.ea_id, 1);
2522                 MD5_Update(&mdContext, (u_char *)secret, secret_len);
2523                 BZERO(secret, sizeof (secret));
2524                 MD5_Update(&mdContext, esp->es_challenge, esp->es_challen);
2525                 MD5_Final(hash, &mdContext);
2526                 if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) {
2527                         eap_send_failure(esp);
2528                         break;
2529                 }
2530                 esp->es_server.ea_type = EAPT_MD5CHAP;
2531                 eap_send_success(esp);
2532                 eap_figure_next_state(esp, 0);
2533                 if (esp->es_rechallenge != 0)
2534                         TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2535                 break;
2536
2537 #ifdef CHAPMS
2538         case EAPT_MSCHAPV2:
2539                 if (len < 1) {
2540                         error("EAP: received MSCHAPv2 with no data");
2541                         eap_figure_next_state(esp, 1);
2542                         break;
2543                 }
2544                 GETCHAR(opcode, inp);
2545                 len--;
2546
2547                 switch (opcode) {
2548                 case CHAP_RESPONSE:
2549                         if (esp->es_server.ea_state != eapMSCHAPv2Chall) {
2550                                 error("EAP: unexpected MSCHAPv2-Response");
2551                                 eap_figure_next_state(esp, 1);
2552                                 break;
2553                         }
2554                         /* skip MS ID + len */
2555                         INCPTR(3, inp);
2556                         GETCHAR(vallen, inp);
2557                         len -= 4;
2558
2559                         if (vallen != MS_CHAP2_RESPONSE_LEN || vallen > len) {
2560                                 error("EAP: Invalid MSCHAPv2-Response "
2561                                                 "length %d", vallen);
2562                                 eap_figure_next_state(esp, 1);
2563                                 break;
2564                         }
2565
2566                         /* Not so likely to happen. */
2567                         if (len - vallen >= sizeof (rhostname)) {
2568                                 dbglog("EAP: trimming really long peer name down");
2569                                 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2570                                 rhostname[sizeof (rhostname) - 1] = '\0';
2571                         } else {
2572                                 BCOPY(inp + vallen, rhostname, len - vallen);
2573                                 rhostname[len - vallen] = '\0';
2574                         }
2575
2576                         /* In case the remote doesn't give us his name. */
2577                         if (explicit_remote ||
2578                                         (remote_name[0] != '\0' && vallen == len))
2579                                 strlcpy(rhostname, remote_name, sizeof (rhostname));
2580
2581                         /* strip the MS domain name */
2582                         if (chapms_strip_domain && strrchr(rhostname, '\\')) {
2583                                 char tmp[MAXNAMELEN+1];
2584
2585                                 strcpy(tmp, strrchr(rhostname, '\\') + 1);
2586                                 strcpy(rhostname, tmp);
2587                         }
2588
2589                         if (chap_verify_hook)
2590                                 chap_verifier = chap_verify_hook;
2591                         else
2592                                 chap_verifier = eap_chap_verify_response;
2593
2594                         esp->es_server.ea_id += 1;
2595                         if ((*chap_verifier)(rhostname,
2596                                                 esp->es_server.ea_name,
2597                                                 id,
2598                                                 esp->es_server.digest,
2599                                                 esp->es_challenge,
2600                                                 inp - 1,
2601                                                 response_message,
2602                                                 sizeof(response_message)))
2603                         {
2604                                 info("EAP: MSCHAPv2 success for peer %q",
2605                                                 rhostname);
2606                                 esp->es_server.ea_type = EAPT_MSCHAPV2;
2607                                 eap_chapms2_send_request(esp,
2608                                                 esp->es_server.ea_id,
2609                                                 CHAP_SUCCESS,
2610                                                 esp->es_server.ea_id,
2611                                                 response_message,
2612                                                 strlen(response_message));
2613                                 eap_figure_next_state(esp, 0);
2614                                 if (esp->es_rechallenge != 0)
2615                                         TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2616                         }
2617                         else {
2618                                 warn("EAP: MSCHAPv2 failure for peer %q",
2619                                                 rhostname);
2620                                 eap_chapms2_send_request(esp,
2621                                                 esp->es_server.ea_id,
2622                                                 CHAP_FAILURE,
2623                                                 esp->es_server.ea_id,
2624                                                 response_message,
2625                                                 strlen(response_message));
2626                         }
2627                         break;
2628                 case CHAP_SUCCESS:
2629                         info("EAP: MSCHAPv2 success confirmed");
2630                         break;
2631                 case CHAP_FAILURE:
2632                         info("EAP: MSCHAPv2 failure confirmed");
2633                         break;
2634                 default:
2635                         error("EAP: Unhandled MSCHAPv2 opcode %d", opcode);
2636                         eap_send_nak(esp, id, EAPT_SRP);
2637                 }
2638
2639                 break;
2640 #endif /* CHAPMS */
2641
2642 #ifdef USE_SRP
2643         case EAPT_SRP:
2644                 if (len < 1) {
2645                         error("EAP: empty SRP Response");
2646                         eap_figure_next_state(esp, 1);
2647                         break;
2648                 }
2649                 GETCHAR(typenum, inp);
2650                 len--;
2651                 switch (typenum) {
2652                 case EAPSRP_CKEY:
2653                         if (esp->es_server.ea_state != eapSRP1) {
2654                                 error("EAP: unexpected SRP Subtype 1 Response");
2655                                 eap_figure_next_state(esp, 1);
2656                                 break;
2657                         }
2658                         A.data = inp;
2659                         A.len = len;
2660                         ts = (struct t_server *)esp->es_server.ea_session;
2661                         assert(ts != NULL);
2662                         esp->es_server.ea_skey = t_servergetkey(ts, &A);
2663                         if (esp->es_server.ea_skey == NULL) {
2664                                 /* Client's A value is bogus; terminate now */
2665                                 error("EAP: bogus A value from client");
2666                                 eap_send_failure(esp);
2667                         } else {
2668                                 eap_figure_next_state(esp, 0);
2669                         }
2670                         break;
2671
2672                 case EAPSRP_CVALIDATOR:
2673                         if (esp->es_server.ea_state != eapSRP2) {
2674                                 error("EAP: unexpected SRP Subtype 2 Response");
2675                                 eap_figure_next_state(esp, 1);
2676                                 break;
2677                         }
2678                         if (len < sizeof (u_int32_t) + SHA_DIGESTSIZE) {
2679                                 error("EAP: M1 length %d < %d", len,
2680                                     sizeof (u_int32_t) + SHA_DIGESTSIZE);
2681                                 eap_figure_next_state(esp, 1);
2682                                 break;
2683                         }
2684                         GETLONG(esp->es_server.ea_keyflags, inp);
2685                         ts = (struct t_server *)esp->es_server.ea_session;
2686                         assert(ts != NULL);
2687                         if (t_serververify(ts, inp)) {
2688                                 info("EAP: unable to validate client identity");
2689                                 eap_send_failure(esp);
2690                                 break;
2691                         }
2692                         eap_figure_next_state(esp, 0);
2693                         break;
2694
2695                 case EAPSRP_ACK:
2696                         if (esp->es_server.ea_state != eapSRP3) {
2697                                 error("EAP: unexpected SRP Subtype 3 Response");
2698                                 eap_send_failure(esp);
2699                                 break;
2700                         }
2701                         esp->es_server.ea_type = EAPT_SRP;
2702                         eap_send_success(esp);
2703                         eap_figure_next_state(esp, 0);
2704                         if (esp->es_rechallenge != 0)
2705                                 TIMEOUT(eap_rechallenge, esp,
2706                                     esp->es_rechallenge);
2707                         if (esp->es_lwrechallenge != 0)
2708                                 TIMEOUT(srp_lwrechallenge, esp,
2709                                     esp->es_lwrechallenge);
2710                         break;
2711
2712                 case EAPSRP_LWRECHALLENGE:
2713                         if (esp->es_server.ea_state != eapSRP4) {
2714                                 info("EAP: unexpected SRP Subtype 4 Response");
2715                                 return;
2716                         }
2717                         if (len != SHA_DIGESTSIZE) {
2718                                 error("EAP: bad Lightweight rechallenge "
2719                                     "response");
2720                                 return;
2721                         }
2722                         SHA1Init(&ctxt);
2723                         vallen = id;
2724                         SHA1Update(&ctxt, &vallen, 1);
2725                         SHA1Update(&ctxt, esp->es_server.ea_skey,
2726                             SESSION_KEY_LEN);
2727                         SHA1Update(&ctxt, esp->es_challenge, esp->es_challen);
2728                         SHA1Update(&ctxt, esp->es_server.ea_peer,
2729                             esp->es_server.ea_peerlen);
2730                         SHA1Final(dig, &ctxt);
2731                         if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) {
2732                                 error("EAP: failed Lightweight rechallenge");
2733                                 eap_send_failure(esp);
2734                                 break;
2735                         }
2736                         esp->es_server.ea_state = eapOpen;
2737                         if (esp->es_lwrechallenge != 0)
2738                                 TIMEOUT(srp_lwrechallenge, esp,
2739                                     esp->es_lwrechallenge);
2740                         break;
2741                 }
2742                 break;
2743 #endif /* USE_SRP */
2744
2745         default:
2746                 /* This can't happen. */
2747                 error("EAP: unknown Response type %d; ignored", typenum);
2748                 return;
2749         }
2750
2751         if (esp->es_server.ea_timeout > 0) {
2752                 UNTIMEOUT(eap_server_timeout, (void *)esp);
2753         }
2754
2755         if (esp->es_server.ea_state != eapBadAuth &&
2756             esp->es_server.ea_state != eapOpen) {
2757                 esp->es_server.ea_id++;
2758                 eap_send_request(esp);
2759         }
2760 }
2761
2762 /*
2763  * eap_success - Receive EAP Success message (client mode).
2764  */
2765 static void
2766 eap_success(eap_state *esp, u_char *inp, int id, int len)
2767 {
2768         if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
2769 #ifdef USE_EAPTLS
2770                 && esp->es_client.ea_state != eapTlsRecvSuccess
2771 #endif /* USE_EAPTLS */
2772                 ) {
2773                 dbglog("EAP unexpected success message in state %s (%d)",
2774                     eap_state_name(esp->es_client.ea_state),
2775                     esp->es_client.ea_state);
2776                 return;
2777         }
2778
2779 #ifdef USE_EAPTLS
2780         if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state !=
2781                 eapTlsRecvSuccess) {
2782                 dbglog("EAP-TLS unexpected success message in state %s (%d)",
2783                     eap_state_name(esp->es_client.ea_state),
2784                     esp->es_client.ea_state);
2785                 return;
2786         }
2787 #endif /* USE_EAPTLS */
2788
2789         if (esp->es_client.ea_timeout > 0) {
2790                 UNTIMEOUT(eap_client_timeout, (void *)esp);
2791         }
2792
2793         if (len > 0) {
2794                 /* This is odd.  The spec doesn't allow for this. */
2795                 PRINTMSG(inp, len);
2796         }
2797
2798 #ifdef USE_PEAP
2799         peap_finish(&esp->ea_peap);
2800 #endif
2801
2802         esp->es_client.ea_state = eapOpen;
2803         auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2804 }
2805
2806 /*
2807  * eap_failure - Receive EAP Failure message (client mode).
2808  */
2809 static void
2810 eap_failure(eap_state *esp, u_char *inp, int id, int len)
2811 {
2812         /*
2813          * Ignore failure messages if we're not open
2814          */
2815         if (esp->es_client.ea_state <= eapClosed)
2816                 return;
2817
2818         if (!eap_client_active(esp)) {
2819                 dbglog("EAP unexpected failure message in state %s (%d)",
2820                     eap_state_name(esp->es_client.ea_state),
2821                     esp->es_client.ea_state);
2822         }
2823
2824         if (esp->es_client.ea_timeout > 0) {
2825                 UNTIMEOUT(eap_client_timeout, (void *)esp);
2826         }
2827
2828         if (len > 0) {
2829                 /* This is odd.  The spec doesn't allow for this. */
2830                 PRINTMSG(inp, len);
2831         }
2832
2833         esp->es_client.ea_state = eapBadAuth;
2834
2835         error("EAP: peer reports authentication failure");
2836
2837 #ifdef USE_PEAP
2838         peap_finish(&esp->ea_peap);
2839 #endif
2840
2841         auth_withpeer_fail(esp->es_unit, PPP_EAP);
2842 }
2843
2844 /*
2845  * eap_input - Handle received EAP message.
2846  */
2847 static void
2848 eap_input(int unit, u_char *inp, int inlen)
2849 {
2850         eap_state *esp = &eap_states[unit];
2851         u_char code, id;
2852         int len;
2853
2854         /*
2855          * Parse header (code, id and length).  If packet too short,
2856          * drop it.
2857          */
2858         if (inlen < EAP_HEADERLEN) {
2859                 error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2860                 return;
2861         }
2862         GETCHAR(code, inp);
2863         GETCHAR(id, inp);
2864         GETSHORT(len, inp);
2865         if (len < EAP_HEADERLEN || len > inlen) {
2866                 error("EAP: packet has illegal length field %d (%d..%d)", len,
2867                     EAP_HEADERLEN, inlen);
2868                 return;
2869         }
2870         len -= EAP_HEADERLEN;
2871
2872         /* Dispatch based on message code */
2873         switch (code) {
2874         case EAP_REQUEST:
2875                 eap_request(esp, inp, id, len);
2876                 break;
2877
2878         case EAP_RESPONSE:
2879                 eap_response(esp, inp, id, len);
2880                 break;
2881
2882         case EAP_SUCCESS:
2883                 eap_success(esp, inp, id, len);
2884                 break;
2885
2886         case EAP_FAILURE:
2887                 eap_failure(esp, inp, id, len);
2888                 break;
2889
2890         default:                                /* XXX Need code reject */
2891                 /* Note: it's not legal to send EAP Nak here. */
2892                 warn("EAP: unknown code %d received", code);
2893                 break;
2894         }
2895 }
2896
2897 /*
2898  * eap_printpkt - print the contents of an EAP packet.
2899  */
2900 static char *eap_codenames[] = {
2901         "Request", "Response", "Success", "Failure"
2902 };
2903
2904 static char *eap_typenames[] = {
2905         "Identity", "Notification", "Nak", "MD5-Challenge",
2906         "OTP", "Generic-Token", NULL, NULL,
2907         "RSA", "DSS", "KEA", "KEA-Validate",
2908         "TLS", "Defender", "Windows 2000", "Arcot",
2909         "Cisco", "Nokia", "SRP", NULL,
2910         "TTLS", "RAS", "AKA", "3COM", "PEAP",
2911         "MSCHAPv2"
2912 };
2913
2914 static int
2915 eap_printpkt(u_char *inp, int inlen,
2916              void (*printer) (void *, char *, ...), void *arg)
2917 {
2918         int code, id, len, rtype, vallen;
2919         u_char *pstart;
2920         u_int32_t uval;
2921 #ifdef USE_EAPTLS
2922         u_char flags;
2923 #endif /* USE_EAPTLS */
2924 #ifdef CHAPMS
2925         u_char opcode;
2926 #endif /* CHAPMS */
2927
2928         if (inlen < EAP_HEADERLEN)
2929                 return (0);
2930         pstart = inp;
2931         GETCHAR(code, inp);
2932         GETCHAR(id, inp);
2933         GETSHORT(len, inp);
2934         if (len < EAP_HEADERLEN || len > inlen)
2935                 return (0);
2936
2937         if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
2938                 printer(arg, " %s", eap_codenames[code-1]);
2939         else
2940                 printer(arg, " code=0x%x", code);
2941         printer(arg, " id=0x%x", id);
2942         len -= EAP_HEADERLEN;
2943         switch (code) {
2944         case EAP_REQUEST:
2945                 if (len < 1) {
2946                         printer(arg, " <missing type>");
2947                         break;
2948                 }
2949                 GETCHAR(rtype, inp);
2950                 len--;
2951                 if (rtype >= 1 &&
2952                     rtype <= sizeof (eap_typenames) / sizeof (char *))
2953                         printer(arg, " %s", eap_typenames[rtype-1]);
2954                 else
2955                         printer(arg, " type=0x%x", rtype);
2956                 switch (rtype) {
2957                 case EAPT_IDENTITY:
2958                 case EAPT_NOTIFICATION:
2959                         if (len > 0) {
2960                                 printer(arg, " <Message ");
2961                                 print_string((char *)inp, len, printer, arg);
2962                                 printer(arg, ">");
2963                                 INCPTR(len, inp);
2964                                 len = 0;
2965                         } else {
2966                                 printer(arg, " <No message>");
2967                         }
2968                         break;
2969
2970                 case EAPT_MD5CHAP:
2971                         if (len <= 0)
2972                                 break;
2973                         GETCHAR(vallen, inp);
2974                         len--;
2975                         if (vallen > len)
2976                                 goto truncated;
2977                         printer(arg, " <Value%.*B>", vallen, inp);
2978                         INCPTR(vallen, inp);
2979                         len -= vallen;
2980                         if (len > 0) {
2981                                 printer(arg, " <Name ");
2982                                 print_string((char *)inp, len, printer, arg);
2983                                 printer(arg, ">");
2984                                 INCPTR(len, inp);
2985                                 len = 0;
2986                         } else {
2987                                 printer(arg, " <No name>");
2988                         }
2989                         break;
2990
2991 #ifdef CHAPMS
2992                 case EAPT_MSCHAPV2:
2993                         if (len <= 0)
2994                                 break;
2995                         GETCHAR(opcode, inp);
2996                         len--;
2997                         switch (opcode) {
2998                         case CHAP_CHALLENGE:
2999                                 INCPTR(3, inp);
3000                                 len -= 3;
3001                                 GETCHAR(vallen, inp);
3002                                 len--;
3003                                 if (vallen > len)
3004                                         goto truncated;
3005                                 len -= vallen;
3006                                 printer(arg, " Challenge <");
3007                                 for (; vallen > 0; --vallen) {
3008                                         u_char val;
3009                                         GETCHAR(val, inp);
3010                                         printer(arg, "%.2x", val);
3011                                 }
3012                                 printer(arg, ">");
3013                                 if (len > 0) {
3014                                         printer(arg, ", <Name ");
3015                                         print_string((char *)inp, len, printer, arg);
3016                                         printer(arg, ">");
3017                                         INCPTR(len, inp);
3018                                         len = 0;
3019                                 } else {
3020                                         printer(arg, ", <No name>");
3021                                 }
3022                                 break;
3023                         case CHAP_SUCCESS:
3024                                 INCPTR(3, inp);
3025                                 len -= 3;
3026                                 printer(arg, " Success <Message ");
3027                                 print_string((char *)inp, len, printer, arg);
3028                                 printer(arg, ">");
3029                                 break;
3030                         case CHAP_FAILURE:
3031                                 INCPTR(3, inp);
3032                                 len -= 3;
3033                                 printer(arg, " Failure <Message ");
3034                                 print_string((char *)inp, len, printer, arg);
3035                                 printer(arg, ">");
3036                                 break;
3037                         default:
3038                                 INCPTR(3, inp);
3039                                 len -= 3;
3040                                 printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
3041                                 break;
3042                         }
3043                         break;
3044 #endif /* CHAPMS */
3045
3046 #ifdef USE_EAPTLS
3047                 case EAPT_TLS:
3048                         if (len < 1)
3049                                 break;
3050                         GETCHAR(flags, inp);
3051                         len--;
3052
3053                         if(flags == 0 && len == 0){
3054                                 printer(arg, " Ack");
3055                                 break;
3056                         }
3057
3058                         printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
3059                         printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
3060                         printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
3061                         break;
3062 #endif /* USE_EAPTLS */
3063
3064 #ifdef USE_SRP
3065                 case EAPT_SRP:
3066                         if (len < 3)
3067                                 goto truncated;
3068                         GETCHAR(vallen, inp);
3069                         len--;
3070                         printer(arg, "-%d", vallen);
3071                         switch (vallen) {
3072                         case EAPSRP_CHALLENGE:
3073                                 GETCHAR(vallen, inp);
3074                                 len--;
3075                                 if (vallen >= len)
3076                                         goto truncated;
3077                                 if (vallen > 0) {
3078                                         printer(arg, " <Name ");
3079                                         print_string((char *)inp, vallen, printer,
3080                                             arg);
3081                                         printer(arg, ">");
3082                                 } else {
3083                                         printer(arg, " <No name>");
3084                                 }
3085                                 INCPTR(vallen, inp);
3086                                 len -= vallen;
3087                                 GETCHAR(vallen, inp);
3088                                 len--;
3089                                 if (vallen >= len)
3090                                         goto truncated;
3091                                 printer(arg, " <s%.*B>", vallen, inp);
3092                                 INCPTR(vallen, inp);
3093                                 len -= vallen;
3094                                 GETCHAR(vallen, inp);
3095                                 len--;
3096                                 if (vallen > len)
3097                                         goto truncated;
3098                                 if (vallen == 0) {
3099                                         printer(arg, " <Default g=2>");
3100                                 } else {
3101                                         printer(arg, " <g%.*B>", vallen, inp);
3102                                 }
3103                                 INCPTR(vallen, inp);
3104                                 len -= vallen;
3105                                 if (len == 0) {
3106                                         printer(arg, " <Default N>");
3107                                 } else {
3108                                         printer(arg, " <N%.*B>", len, inp);
3109                                         INCPTR(len, inp);
3110                                         len = 0;
3111                                 }
3112                                 break;
3113
3114                         case EAPSRP_SKEY:
3115                                 printer(arg, " <B%.*B>", len, inp);
3116                                 INCPTR(len, inp);
3117                                 len = 0;
3118                                 break;
3119
3120                         case EAPSRP_SVALIDATOR:
3121                                 if (len < sizeof (u_int32_t))
3122                                         break;
3123                                 GETLONG(uval, inp);
3124                                 len -= sizeof (u_int32_t);
3125                                 if (uval & SRPVAL_EBIT) {
3126                                         printer(arg, " E");
3127                                         uval &= ~SRPVAL_EBIT;
3128                                 }
3129                                 if (uval != 0) {
3130                                         printer(arg, " f<%X>", uval);
3131                                 }
3132                                 if ((vallen = len) > SHA_DIGESTSIZE)
3133                                         vallen = SHA_DIGESTSIZE;
3134                                 printer(arg, " <M2%.*B%s>", len, inp,
3135                                     len < SHA_DIGESTSIZE ? "?" : "");
3136                                 INCPTR(vallen, inp);
3137                                 len -= vallen;
3138                                 if (len > 0) {
3139                                         printer(arg, " <PN%.*B>", len, inp);
3140                                         INCPTR(len, inp);
3141                                         len = 0;
3142                                 }
3143                                 break;
3144
3145                         case EAPSRP_LWRECHALLENGE:
3146                                 printer(arg, " <Challenge%.*B>", len, inp);
3147                                 INCPTR(len, inp);
3148                                 len = 0;
3149                                 break;
3150                         }
3151                         break;
3152 #endif  /* USE_SRP */
3153                 }
3154                 break;
3155
3156         case EAP_RESPONSE:
3157                 if (len < 1)
3158                         break;
3159                 GETCHAR(rtype, inp);
3160                 len--;
3161                 if (rtype >= 1 &&
3162                     rtype <= sizeof (eap_typenames) / sizeof (char *))
3163                         printer(arg, " %s", eap_typenames[rtype-1]);
3164                 else
3165                         printer(arg, " type=0x%x", rtype);
3166                 switch (rtype) {
3167                 case EAPT_IDENTITY:
3168                         if (len > 0) {
3169                                 printer(arg, " <Name ");
3170                                 print_string((char *)inp, len, printer, arg);
3171                                 printer(arg, ">");
3172                                 INCPTR(len, inp);
3173                                 len = 0;
3174                         }
3175                         break;
3176
3177 #ifdef USE_EAPTLS
3178                 case EAPT_TLS:
3179                         if (len < 1)
3180                                 break;
3181                         GETCHAR(flags, inp);
3182                         len--;
3183
3184                         if(flags == 0 && len == 0){
3185                                 printer(arg, " Ack");
3186                                 break;
3187                         }
3188
3189                         printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
3190                         printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
3191                         printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
3192
3193                         break;
3194 #endif /* USE_EAPTLS */
3195
3196                 case EAPT_NAK:
3197                         if (len <= 0) {
3198                                 printer(arg, " <missing hint>");
3199                                 break;
3200                         }
3201                         GETCHAR(rtype, inp);
3202                         len--;
3203                         printer(arg, " <Suggested-type %02X", rtype);
3204                         if (rtype >= 1 &&
3205                             rtype <= sizeof (eap_typenames) / sizeof (char *))
3206                                 printer(arg, " (%s)", eap_typenames[rtype-1]);
3207                         printer(arg, ">");
3208                         break;
3209
3210                 case EAPT_MD5CHAP:
3211                         if (len <= 0) {
3212                                 printer(arg, " <missing length>");
3213                                 break;
3214                         }
3215                         GETCHAR(vallen, inp);
3216                         len--;
3217                         if (vallen > len)
3218                                 goto truncated;
3219                         printer(arg, " <Value%.*B>", vallen, inp);
3220                         INCPTR(vallen, inp);
3221                         len -= vallen;
3222                         if (len > 0) {
3223                                 printer(arg, " <Name ");
3224                                 print_string((char *)inp, len, printer, arg);
3225                                 printer(arg, ">");
3226                                 INCPTR(len, inp);
3227                                 len = 0;
3228                         } else {
3229                                 printer(arg, " <No name>");
3230                         }
3231                         break;
3232
3233 #ifdef CHAPMS
3234                 case EAPT_MSCHAPV2:
3235                         if (len <= 0)
3236                                 break;
3237                         GETCHAR(opcode, inp);
3238                         len--;
3239                         switch (opcode) {
3240                         case CHAP_RESPONSE:
3241                                 INCPTR(3, inp);
3242                                 len -= 3;
3243                                 GETCHAR(vallen, inp);
3244                                 len--;
3245                                 if (vallen > len)
3246                                         goto truncated;
3247                                 len -= vallen;
3248                                 printer(arg, " Response <");
3249                                 for (; vallen > 0; --vallen) {
3250                                         u_char val;
3251                                         GETCHAR(val, inp);
3252                                         printer(arg, "%.2x", val);
3253                                 }
3254                                 printer(arg, ">");
3255                                 if (len > 0) {
3256                                         printer(arg, ", <Name ");
3257                                         print_string((char *)inp, len, printer, arg);
3258                                         printer(arg, ">");
3259                                         INCPTR(len, inp);
3260                                         len = 0;
3261                                 } else {
3262                                         printer(arg, ", <No name>");
3263                                 }
3264                                 break;
3265                         case CHAP_SUCCESS:
3266                                 printer(arg, " Success");
3267                                 break;
3268                         case CHAP_FAILURE:
3269                                 printer(arg, " Failure");
3270                                 break;
3271                         default:
3272                                 printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
3273                                 break;
3274                         }
3275                         break;
3276 #endif /* CHAPMS */
3277
3278 #ifdef USE_SRP
3279                 case EAPT_SRP:
3280                         if (len < 1)
3281                                 goto truncated;
3282                         GETCHAR(vallen, inp);
3283                         len--;
3284                         printer(arg, "-%d", vallen);
3285                         switch (vallen) {
3286                         case EAPSRP_CKEY:
3287                                 printer(arg, " <A%.*B>", len, inp);
3288                                 INCPTR(len, inp);
3289                                 len = 0;
3290                                 break;
3291
3292                         case EAPSRP_CVALIDATOR:
3293                                 if (len < sizeof (u_int32_t))
3294                                         break;
3295                                 GETLONG(uval, inp);
3296                                 len -= sizeof (u_int32_t);
3297                                 if (uval & SRPVAL_EBIT) {
3298                                         printer(arg, " E");
3299                                         uval &= ~SRPVAL_EBIT;
3300                                 }
3301                                 if (uval != 0) {
3302                                         printer(arg, " f<%X>", uval);
3303                                 }
3304                                 printer(arg, " <M1%.*B%s>", len, inp,
3305                                     len == SHA_DIGESTSIZE ? "" : "?");
3306                                 INCPTR(len, inp);
3307                                 len = 0;
3308                                 break;
3309
3310                         case EAPSRP_ACK:
3311                                 break;
3312
3313                         case EAPSRP_LWRECHALLENGE:
3314                                 printer(arg, " <Response%.*B%s>", len, inp,
3315                                     len == SHA_DIGESTSIZE ? "" : "?");
3316                                 if ((vallen = len) > SHA_DIGESTSIZE)
3317                                         vallen = SHA_DIGESTSIZE;
3318                                 INCPTR(vallen, inp);
3319                                 len -= vallen;
3320                                 break;
3321                         }
3322                         break;
3323 #endif  /* USE_SRP */
3324                 }
3325                 break;
3326
3327         case EAP_SUCCESS:       /* No payload expected for these! */
3328         case EAP_FAILURE:
3329                 break;
3330
3331         truncated:
3332                 printer(arg, " <truncated>");
3333                 break;
3334         }
3335
3336         if (len > 8)
3337                 printer(arg, "%8B...", inp);
3338         else if (len > 0)
3339                 printer(arg, "%.*B", len, inp);
3340         INCPTR(len, inp);
3341
3342         return (inp - pstart);
3343 }