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