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