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