source: S-port/trunk/Middlewares/Third_Party/LwIP/src/netif/ppp/eap.c

Last change on this file was 1, checked in by AlexLir, 3 years ago
File size: 63.1 KB
Line 
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
65static char *pn_secret = NULL; /* Pseudonym generating secret */
66#endif
67
68#if PPP_OPTIONS
69/*
70 * Command-line options.
71 */
72static 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 */
98static void eap_init(ppp_pcb *pcb);
99static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen);
100static void eap_protrej(ppp_pcb *pcb);
101static void eap_lowerup(ppp_pcb *pcb);
102static void eap_lowerdown(ppp_pcb *pcb);
103#if PRINTPKT_SUPPORT
104static int eap_printpkt(const u_char *inp, int inlen,
105 void (*)(void *arg, const char *fmt, ...), void *arg);
106#endif /* PRINTPKT_SUPPORT */
107
108const 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 */
141static 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. */
179static void eap_server_timeout(void *arg);
180#endif /* PPP_SERVER */
181
182/*
183 * Convert EAP state code to printable string for debug.
184 */
185static 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 */
196static 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 */
208static 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 */
225void 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 */
250static 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 */
281static 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 */
314static bool
315pncrypt_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
336static char base64[] =
337"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
338
339struct b64state {
340 u32_t bs_bits;
341 int bs_offs;
342};
343
344static int
345b64enc(bs, inp, inlen, outp)
346struct b64state *bs;
347u_char *inp;
348int inlen;
349u_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
370static int
371b64flush(bs, outp)
372struct b64state *bs;
373u_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
392static int
393b64dec(bs, inp, inlen, outp)
394struct b64state *bs;
395u_char *inp;
396int inlen;
397u_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 */
425static 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 */
638static 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 */
876void 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 */
901static 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 */
916static 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
930static 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 */
952static 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 */
964static 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 */
997static 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 */
1015static 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 */
1048static 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 */
1086static void
1087eap_srp_response(esp, id, subtypenum, str, lenstr)
1088eap_state *esp;
1089u_char id;
1090u_char subtypenum;
1091u_char *str;
1092int 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 */
1128static void
1129eap_srpval_response(esp, id, flags, str)
1130eap_state *esp;
1131u_char id;
1132u32_t flags;
1133u_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
1167static 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
1196static char *
1197name_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
1222static int
1223open_pn_file(modebits)
1224mode_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
1238static void
1239remove_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
1249static void
1250write_pseudonym(esp, inp, len, id)
1251eap_state *esp;
1252u_char *inp;
1253int 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 */
1311static 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
1710client_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 */
1725static 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 */
2017static 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 */
2043static 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 */
2070static 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 */
2123static const char* const eap_codenames[] = {
2124 "Request", "Response", "Success", "Failure"
2125};
2126
2127static 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
2135static 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 */
Note: See TracBrowser for help on using the repository browser.