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