]> git.ozlabs.org Git - ppp.git/blob - pppd/eap.c
94407f56a336b2d1d0609d67ed5f082a21dd8f63
[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          * Note: we update es_client.ea_id *only if* a Response
1333          * message is being generated.  Otherwise, we leave it the
1334          * same for duplicate detection purposes.
1335          */
1336
1337         esp->es_client.ea_requests++;
1338         if (esp->es_client.ea_maxrequests != 0 &&
1339             esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {
1340                 info("EAP: received too many Request messages");
1341                 if (esp->es_client.ea_timeout > 0) {
1342                         UNTIMEOUT(eap_client_timeout, (void *)esp);
1343                 }
1344                 auth_withpeer_fail(esp->es_unit, PPP_EAP);
1345                 return;
1346         }
1347
1348         if (len <= 0) {
1349                 error("EAP: empty Request message discarded");
1350                 return;
1351         }
1352
1353         GETCHAR(typenum, inp);
1354         len--;
1355
1356         switch (typenum) {
1357         case EAPT_IDENTITY:
1358                 if (len > 0)
1359                         info("EAP: Identity prompt \"%.*q\"", len, inp);
1360 #ifdef USE_SRP
1361                 if (esp->es_usepseudo &&
1362                     (esp->es_usedpseudo == 0 ||
1363                         (esp->es_usedpseudo == 1 &&
1364                             id == esp->es_client.ea_id))) {
1365                         esp->es_usedpseudo = 1;
1366                         /* Try to get a pseudonym */
1367                         if ((fd = open_pn_file(O_RDONLY)) >= 0) {
1368                                 strcpy(rhostname, SRP_PSEUDO_ID);
1369                                 len = read(fd, rhostname + SRP_PSEUDO_LEN,
1370                                     sizeof (rhostname) - SRP_PSEUDO_LEN);
1371                                 /* XXX NAI unsupported */
1372                                 if (len > 0) {
1373                                         eap_send_response(esp, id, typenum,
1374                                             rhostname, len + SRP_PSEUDO_LEN);
1375                                 }
1376                                 (void) close(fd);
1377                                 if (len > 0)
1378                                         break;
1379                         }
1380                 }
1381                 /* Stop using pseudonym now. */
1382                 if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
1383                         remove_pn_file();
1384                         esp->es_usedpseudo = 2;
1385                 }
1386 #endif /* USE_SRP */
1387                 eap_send_response(esp, id, typenum, esp->es_client.ea_name,
1388                     esp->es_client.ea_namelen);
1389                 break;
1390
1391         case EAPT_NOTIFICATION:
1392                 if (len > 0)
1393                         info("EAP: Notification \"%.*q\"", len, inp);
1394                 eap_send_response(esp, id, typenum, NULL, 0);
1395                 break;
1396
1397         case EAPT_NAK:
1398                 /*
1399                  * Avoid the temptation to send Response Nak in reply
1400                  * to Request Nak here.  It can only lead to trouble.
1401                  */
1402                 warn("EAP: unexpected Nak in Request; ignored");
1403                 /* Return because we're waiting for something real. */
1404                 return;
1405
1406         case EAPT_MD5CHAP:
1407                 if (len < 1) {
1408                         error("EAP: received MD5-Challenge with no data");
1409                         /* Bogus request; wait for something real. */
1410                         return;
1411                 }
1412                 GETCHAR(vallen, inp);
1413                 len--;
1414                 if (vallen < 8 || vallen > len) {
1415                         error("EAP: MD5-Challenge with bad length %d (8..%d)",
1416                             vallen, len);
1417                         /* Try something better. */
1418                         eap_send_nak(esp, id, EAPT_SRP);
1419                         break;
1420                 }
1421
1422                 /* Not so likely to happen. */
1423                 if (vallen >= len + sizeof (rhostname)) {
1424                         dbglog("EAP: trimming really long peer name down");
1425                         BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1426                         rhostname[sizeof (rhostname) - 1] = '\0';
1427                 } else {
1428                         BCOPY(inp + vallen, rhostname, len - vallen);
1429                         rhostname[len - vallen] = '\0';
1430                 }
1431
1432                 /* In case the remote doesn't give us his name. */
1433                 if (explicit_remote ||
1434                     (remote_name[0] != '\0' && vallen == len))
1435                         strlcpy(rhostname, remote_name, sizeof (rhostname));
1436
1437                 /*
1438                  * Get the secret for authenticating ourselves with
1439                  * the specified host.
1440                  */
1441                 if (!get_secret(esp->es_unit, esp->es_client.ea_name,
1442                     rhostname, secret, &secret_len, 0)) {
1443                         dbglog("EAP: no MD5 secret for auth to %q", rhostname);
1444                         eap_send_nak(esp, id, EAPT_SRP);
1445                         break;
1446                 }
1447                 MD5_Init(&mdContext);
1448                 typenum = id;
1449                 MD5_Update(&mdContext, &typenum, 1);
1450                 MD5_Update(&mdContext, (u_char *)secret, secret_len);
1451                 BZERO(secret, sizeof (secret));
1452                 MD5_Update(&mdContext, inp, vallen);
1453                 MD5_Final(hash, &mdContext);
1454                 eap_chap_response(esp, id, hash, esp->es_client.ea_name,
1455                     esp->es_client.ea_namelen);
1456                 break;
1457
1458 #ifdef USE_SRP
1459         case EAPT_SRP:
1460                 if (len < 1) {
1461                         error("EAP: received empty SRP Request");
1462                         /* Bogus request; wait for something real. */
1463                         return;
1464                 }
1465
1466                 /* Get subtype */
1467                 GETCHAR(vallen, inp);
1468                 len--;
1469                 switch (vallen) {
1470                 case EAPSRP_CHALLENGE:
1471                         tc = NULL;
1472                         if (esp->es_client.ea_session != NULL) {
1473                                 tc = (struct t_client *)esp->es_client.
1474                                     ea_session;
1475                                 /*
1476                                  * If this is a new challenge, then start
1477                                  * over with a new client session context.
1478                                  * Otherwise, just resend last response.
1479                                  */
1480                                 if (id != esp->es_client.ea_id) {
1481                                         t_clientclose(tc);
1482                                         esp->es_client.ea_session = NULL;
1483                                         tc = NULL;
1484                                 }
1485                         }
1486                         /* No session key just yet */
1487                         esp->es_client.ea_skey = NULL;
1488                         if (tc == NULL) {
1489                                 GETCHAR(vallen, inp);
1490                                 len--;
1491                                 if (vallen >= len) {
1492                                         error("EAP: badly-formed SRP Challenge"
1493                                             " (name)");
1494                                         /* Ignore badly-formed messages */
1495                                         return;
1496                                 }
1497                                 BCOPY(inp, rhostname, vallen);
1498                                 rhostname[vallen] = '\0';
1499                                 INCPTR(vallen, inp);
1500                                 len -= vallen;
1501
1502                                 /*
1503                                  * In case the remote doesn't give us his name,
1504                                  * use configured name.
1505                                  */
1506                                 if (explicit_remote ||
1507                                     (remote_name[0] != '\0' && vallen == 0)) {
1508                                         strlcpy(rhostname, remote_name,
1509                                             sizeof (rhostname));
1510                                 }
1511
1512                                 if (esp->es_client.ea_peer != NULL)
1513                                         free(esp->es_client.ea_peer);
1514                                 esp->es_client.ea_peer = strdup(rhostname);
1515                                 esp->es_client.ea_peerlen = strlen(rhostname);
1516
1517                                 GETCHAR(vallen, inp);
1518                                 len--;
1519                                 if (vallen >= len) {
1520                                         error("EAP: badly-formed SRP Challenge"
1521                                             " (s)");
1522                                         /* Ignore badly-formed messages */
1523                                         return;
1524                                 }
1525                                 sval.data = inp;
1526                                 sval.len = vallen;
1527                                 INCPTR(vallen, inp);
1528                                 len -= vallen;
1529
1530                                 GETCHAR(vallen, inp);
1531                                 len--;
1532                                 if (vallen > len) {
1533                                         error("EAP: badly-formed SRP Challenge"
1534                                             " (g)");
1535                                         /* Ignore badly-formed messages */
1536                                         return;
1537                                 }
1538                                 /* If no generator present, then use value 2 */
1539                                 if (vallen == 0) {
1540                                         gval.data = (u_char *)"\002";
1541                                         gval.len = 1;
1542                                 } else {
1543                                         gval.data = inp;
1544                                         gval.len = vallen;
1545                                 }
1546                                 INCPTR(vallen, inp);
1547                                 len -= vallen;
1548
1549                                 /*
1550                                  * If no modulus present, then use well-known
1551                                  * value.
1552                                  */
1553                                 if (len == 0) {
1554                                         Nval.data = (u_char *)wkmodulus;
1555                                         Nval.len = sizeof (wkmodulus);
1556                                 } else {
1557                                         Nval.data = inp;
1558                                         Nval.len = len;
1559                                 }
1560                                 tc = t_clientopen(esp->es_client.ea_name,
1561                                     &Nval, &gval, &sval);
1562                                 if (tc == NULL) {
1563                                         eap_send_nak(esp, id, EAPT_MD5CHAP);
1564                                         break;
1565                                 }
1566                                 esp->es_client.ea_session = (void *)tc;
1567
1568                                 /* Add Challenge ID & type to verifier */
1569                                 vals[0] = id;
1570                                 vals[1] = EAPT_SRP;
1571                                 t_clientaddexdata(tc, vals, 2);
1572                         }
1573                         Ap = t_clientgenexp(tc);
1574                         eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
1575                             Ap->len);
1576                         break;
1577
1578                 case EAPSRP_SKEY:
1579                         tc = (struct t_client *)esp->es_client.ea_session;
1580                         if (tc == NULL) {
1581                                 warn("EAP: peer sent Subtype 2 without 1");
1582                                 eap_send_nak(esp, id, EAPT_MD5CHAP);
1583                                 break;
1584                         }
1585                         if (esp->es_client.ea_skey != NULL) {
1586                                 /*
1587                                  * ID number should not change here.  Warn
1588                                  * if it does (but otherwise ignore).
1589                                  */
1590                                 if (id != esp->es_client.ea_id) {
1591                                         warn("EAP: ID changed from %d to %d "
1592                                             "in SRP Subtype 2 rexmit",
1593                                             esp->es_client.ea_id, id);
1594                                 }
1595                         } else {
1596                                 if (get_srp_secret(esp->es_unit,
1597                                     esp->es_client.ea_name,
1598                                     esp->es_client.ea_peer, secret, 0) == 0) {
1599                                         /*
1600                                          * Can't work with this peer because
1601                                          * the secret is missing.  Just give
1602                                          * up.
1603                                          */
1604                                         eap_send_nak(esp, id, EAPT_MD5CHAP);
1605                                         break;
1606                                 }
1607                                 Bval.data = inp;
1608                                 Bval.len = len;
1609                                 t_clientpasswd(tc, secret);
1610                                 BZERO(secret, sizeof (secret));
1611                                 esp->es_client.ea_skey =
1612                                     t_clientgetkey(tc, &Bval);
1613                                 if (esp->es_client.ea_skey == NULL) {
1614                                         /* Server is rogue; stop now */
1615                                         error("EAP: SRP server is rogue");
1616                                         goto client_failure;
1617                                 }
1618                         }
1619                         eap_srpval_response(esp, id, SRPVAL_EBIT,
1620                             t_clientresponse(tc));
1621                         break;
1622
1623                 case EAPSRP_SVALIDATOR:
1624                         tc = (struct t_client *)esp->es_client.ea_session;
1625                         if (tc == NULL || esp->es_client.ea_skey == NULL) {
1626                                 warn("EAP: peer sent Subtype 3 without 1/2");
1627                                 eap_send_nak(esp, id, EAPT_MD5CHAP);
1628                                 break;
1629                         }
1630                         /*
1631                          * If we're already open, then this ought to be a
1632                          * duplicate.  Otherwise, check that the server is
1633                          * who we think it is.
1634                          */
1635                         if (esp->es_client.ea_state == eapOpen) {
1636                                 if (id != esp->es_client.ea_id) {
1637                                         warn("EAP: ID changed from %d to %d "
1638                                             "in SRP Subtype 3 rexmit",
1639                                             esp->es_client.ea_id, id);
1640                                 }
1641                         } else {
1642                                 len -= sizeof (u_int32_t) + SHA_DIGESTSIZE;
1643                                 if (len < 0 || t_clientverify(tc, inp +
1644                                         sizeof (u_int32_t)) != 0) {
1645                                         error("EAP: SRP server verification "
1646                                             "failed");
1647                                         goto client_failure;
1648                                 }
1649                                 GETLONG(esp->es_client.ea_keyflags, inp);
1650                                 /* Save pseudonym if user wants it. */
1651                                 if (len > 0 && esp->es_usepseudo) {
1652                                         INCPTR(SHA_DIGESTSIZE, inp);
1653                                         write_pseudonym(esp, inp, len, id);
1654                                 }
1655                         }
1656                         /*
1657                          * We've verified our peer.  We're now mostly done,
1658                          * except for waiting on the regular EAP Success
1659                          * message.
1660                          */
1661                         eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
1662                         break;
1663
1664                 case EAPSRP_LWRECHALLENGE:
1665                         if (len < 4) {
1666                                 warn("EAP: malformed Lightweight rechallenge");
1667                                 return;
1668                         }
1669                         SHA1Init(&ctxt);
1670                         vals[0] = id;
1671                         SHA1Update(&ctxt, vals, 1);
1672                         SHA1Update(&ctxt, esp->es_client.ea_skey,
1673                             SESSION_KEY_LEN);
1674                         SHA1Update(&ctxt, inp, len);
1675                         SHA1Update(&ctxt, esp->es_client.ea_name,
1676                             esp->es_client.ea_namelen);
1677                         SHA1Final(dig, &ctxt);
1678                         eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
1679                             SHA_DIGESTSIZE);
1680                         break;
1681
1682                 default:
1683                         error("EAP: unknown SRP Subtype %d", vallen);
1684                         eap_send_nak(esp, id, EAPT_MD5CHAP);
1685                         break;
1686                 }
1687                 break;
1688 #endif /* USE_SRP */
1689
1690         default:
1691                 info("EAP: unknown authentication type %d; Naking", typenum);
1692                 eap_send_nak(esp, id, EAPT_SRP);
1693                 break;
1694         }
1695
1696         if (esp->es_client.ea_timeout > 0) {
1697                 UNTIMEOUT(eap_client_timeout, (void *)esp);
1698                 TIMEOUT(eap_client_timeout, (void *)esp,
1699                     esp->es_client.ea_timeout);
1700         }
1701         return;
1702
1703 #ifdef USE_SRP
1704 client_failure:
1705         esp->es_client.ea_state = eapBadAuth;
1706         if (esp->es_client.ea_timeout > 0) {
1707                 UNTIMEOUT(eap_client_timeout, (void *)esp);
1708         }
1709         esp->es_client.ea_session = NULL;
1710         t_clientclose(tc);
1711         auth_withpeer_fail(esp->es_unit, PPP_EAP);
1712 #endif /* USE_SRP */
1713 }
1714
1715 /*
1716  * eap_response - Receive EAP Response message (server mode).
1717  */
1718 static void
1719 eap_response(esp, inp, id, len)
1720 eap_state *esp;
1721 u_char *inp;
1722 int id;
1723 int len;
1724 {
1725         u_char typenum;
1726         u_char vallen;
1727         int secret_len;
1728         char secret[MAXSECRETLEN];
1729         char rhostname[256];
1730         MD5_CTX mdContext;
1731         u_char hash[MD5_SIGNATURE_SIZE];
1732 #ifdef USE_SRP
1733         struct t_server *ts;
1734         struct t_num A;
1735         SHA1_CTX ctxt;
1736         u_char dig[SHA_DIGESTSIZE];
1737 #endif /* USE_SRP */
1738
1739         if (esp->es_server.ea_id != id) {
1740                 dbglog("EAP: discarding Response %d; expected ID %d", id,
1741                     esp->es_server.ea_id);
1742                 return;
1743         }
1744
1745         esp->es_server.ea_responses++;
1746
1747         if (len <= 0) {
1748                 error("EAP: empty Response message discarded");
1749                 return;
1750         }
1751
1752         GETCHAR(typenum, inp);
1753         len--;
1754
1755         switch (typenum) {
1756         case EAPT_IDENTITY:
1757                 if (esp->es_server.ea_state != eapIdentify) {
1758                         dbglog("EAP discarding unwanted Identify \"%.q\"", len,
1759                             inp);
1760                         break;
1761                 }
1762                 info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
1763                 if (esp->es_server.ea_peer != NULL &&
1764                     esp->es_server.ea_peer != remote_name)
1765                         free(esp->es_server.ea_peer);
1766                 esp->es_server.ea_peer = malloc(len + 1);
1767                 if (esp->es_server.ea_peer == NULL) {
1768                         esp->es_server.ea_peerlen = 0;
1769                         eap_figure_next_state(esp, 1);
1770                         break;
1771                 }
1772                 BCOPY(inp, esp->es_server.ea_peer, len);
1773                 esp->es_server.ea_peer[len] = '\0';
1774                 esp->es_server.ea_peerlen = len;
1775                 eap_figure_next_state(esp, 0);
1776                 break;
1777
1778         case EAPT_NOTIFICATION:
1779                 dbglog("EAP unexpected Notification; response discarded");
1780                 break;
1781
1782         case EAPT_NAK:
1783                 if (len < 1) {
1784                         info("EAP: Nak Response with no suggested protocol");
1785                         eap_figure_next_state(esp, 1);
1786                         break;
1787                 }
1788
1789                 GETCHAR(vallen, inp);
1790                 len--;
1791
1792                 if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
1793                         /* Peer cannot Nak Identify Request */
1794                         eap_figure_next_state(esp, 1);
1795                         break;
1796                 }
1797
1798                 switch (vallen) {
1799                 case EAPT_SRP:
1800                         /* Run through SRP validator selection again. */
1801                         esp->es_server.ea_state = eapIdentify;
1802                         eap_figure_next_state(esp, 0);
1803                         break;
1804
1805                 case EAPT_MD5CHAP:
1806                         esp->es_server.ea_state = eapMD5Chall;
1807                         break;
1808
1809                 default:
1810                         dbglog("EAP: peer requesting unknown Type %d", vallen);
1811                         switch (esp->es_server.ea_state) {
1812                         case eapSRP1:
1813                         case eapSRP2:
1814                         case eapSRP3:
1815                                 esp->es_server.ea_state = eapMD5Chall;
1816                                 break;
1817                         case eapMD5Chall:
1818                         case eapSRP4:
1819                                 esp->es_server.ea_state = eapIdentify;
1820                                 eap_figure_next_state(esp, 0);
1821                                 break;
1822                         default:
1823                                 break;
1824                         }
1825                         break;
1826                 }
1827                 break;
1828
1829         case EAPT_MD5CHAP:
1830                 if (esp->es_server.ea_state != eapMD5Chall) {
1831                         error("EAP: unexpected MD5-Response");
1832                         eap_figure_next_state(esp, 1);
1833                         break;
1834                 }
1835                 if (len < 1) {
1836                         error("EAP: received MD5-Response with no data");
1837                         eap_figure_next_state(esp, 1);
1838                         break;
1839                 }
1840                 GETCHAR(vallen, inp);
1841                 len--;
1842                 if (vallen != 16 || vallen > len) {
1843                         error("EAP: MD5-Response with bad length %d", vallen);
1844                         eap_figure_next_state(esp, 1);
1845                         break;
1846                 }
1847
1848                 /* Not so likely to happen. */
1849                 if (vallen >= len + sizeof (rhostname)) {
1850                         dbglog("EAP: trimming really long peer name down");
1851                         BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1852                         rhostname[sizeof (rhostname) - 1] = '\0';
1853                 } else {
1854                         BCOPY(inp + vallen, rhostname, len - vallen);
1855                         rhostname[len - vallen] = '\0';
1856                 }
1857
1858                 /* In case the remote doesn't give us his name. */
1859                 if (explicit_remote ||
1860                     (remote_name[0] != '\0' && vallen == len))
1861                         strlcpy(rhostname, remote_name, sizeof (rhostname));
1862
1863                 /*
1864                  * Get the secret for authenticating the specified
1865                  * host.
1866                  */
1867                 if (!get_secret(esp->es_unit, rhostname,
1868                     esp->es_server.ea_name, secret, &secret_len, 1)) {
1869                         dbglog("EAP: no MD5 secret for auth of %q", rhostname);
1870                         eap_send_failure(esp);
1871                         break;
1872                 }
1873                 MD5_Init(&mdContext);
1874                 MD5_Update(&mdContext, &esp->es_server.ea_id, 1);
1875                 MD5_Update(&mdContext, (u_char *)secret, secret_len);
1876                 BZERO(secret, sizeof (secret));
1877                 MD5_Update(&mdContext, esp->es_challenge, esp->es_challen);
1878                 MD5_Final(hash, &mdContext);
1879                 if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) {
1880                         eap_send_failure(esp);
1881                         break;
1882                 }
1883                 esp->es_server.ea_type = EAPT_MD5CHAP;
1884                 eap_send_success(esp);
1885                 eap_figure_next_state(esp, 0);
1886                 if (esp->es_rechallenge != 0)
1887                         TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
1888                 break;
1889
1890 #ifdef USE_SRP
1891         case EAPT_SRP:
1892                 if (len < 1) {
1893                         error("EAP: empty SRP Response");
1894                         eap_figure_next_state(esp, 1);
1895                         break;
1896                 }
1897                 GETCHAR(typenum, inp);
1898                 len--;
1899                 switch (typenum) {
1900                 case EAPSRP_CKEY:
1901                         if (esp->es_server.ea_state != eapSRP1) {
1902                                 error("EAP: unexpected SRP Subtype 1 Response");
1903                                 eap_figure_next_state(esp, 1);
1904                                 break;
1905                         }
1906                         A.data = inp;
1907                         A.len = len;
1908                         ts = (struct t_server *)esp->es_server.ea_session;
1909                         assert(ts != NULL);
1910                         esp->es_server.ea_skey = t_servergetkey(ts, &A);
1911                         if (esp->es_server.ea_skey == NULL) {
1912                                 /* Client's A value is bogus; terminate now */
1913                                 error("EAP: bogus A value from client");
1914                                 eap_send_failure(esp);
1915                         } else {
1916                                 eap_figure_next_state(esp, 0);
1917                         }
1918                         break;
1919
1920                 case EAPSRP_CVALIDATOR:
1921                         if (esp->es_server.ea_state != eapSRP2) {
1922                                 error("EAP: unexpected SRP Subtype 2 Response");
1923                                 eap_figure_next_state(esp, 1);
1924                                 break;
1925                         }
1926                         if (len < sizeof (u_int32_t) + SHA_DIGESTSIZE) {
1927                                 error("EAP: M1 length %d < %d", len,
1928                                     sizeof (u_int32_t) + SHA_DIGESTSIZE);
1929                                 eap_figure_next_state(esp, 1);
1930                                 break;
1931                         }
1932                         GETLONG(esp->es_server.ea_keyflags, inp);
1933                         ts = (struct t_server *)esp->es_server.ea_session;
1934                         assert(ts != NULL);
1935                         if (t_serververify(ts, inp)) {
1936                                 info("EAP: unable to validate client identity");
1937                                 eap_send_failure(esp);
1938                                 break;
1939                         }
1940                         eap_figure_next_state(esp, 0);
1941                         break;
1942
1943                 case EAPSRP_ACK:
1944                         if (esp->es_server.ea_state != eapSRP3) {
1945                                 error("EAP: unexpected SRP Subtype 3 Response");
1946                                 eap_send_failure(esp);
1947                                 break;
1948                         }
1949                         esp->es_server.ea_type = EAPT_SRP;
1950                         eap_send_success(esp);
1951                         eap_figure_next_state(esp, 0);
1952                         if (esp->es_rechallenge != 0)
1953                                 TIMEOUT(eap_rechallenge, esp,
1954                                     esp->es_rechallenge);
1955                         if (esp->es_lwrechallenge != 0)
1956                                 TIMEOUT(srp_lwrechallenge, esp,
1957                                     esp->es_lwrechallenge);
1958                         break;
1959
1960                 case EAPSRP_LWRECHALLENGE:
1961                         if (esp->es_server.ea_state != eapSRP4) {
1962                                 info("EAP: unexpected SRP Subtype 4 Response");
1963                                 return;
1964                         }
1965                         if (len != SHA_DIGESTSIZE) {
1966                                 error("EAP: bad Lightweight rechallenge "
1967                                     "response");
1968                                 return;
1969                         }
1970                         SHA1Init(&ctxt);
1971                         vallen = id;
1972                         SHA1Update(&ctxt, &vallen, 1);
1973                         SHA1Update(&ctxt, esp->es_server.ea_skey,
1974                             SESSION_KEY_LEN);
1975                         SHA1Update(&ctxt, esp->es_challenge, esp->es_challen);
1976                         SHA1Update(&ctxt, esp->es_server.ea_peer,
1977                             esp->es_server.ea_peerlen);
1978                         SHA1Final(dig, &ctxt);
1979                         if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) {
1980                                 error("EAP: failed Lightweight rechallenge");
1981                                 eap_send_failure(esp);
1982                                 break;
1983                         }
1984                         esp->es_server.ea_state = eapOpen;
1985                         if (esp->es_lwrechallenge != 0)
1986                                 TIMEOUT(srp_lwrechallenge, esp,
1987                                     esp->es_lwrechallenge);
1988                         break;
1989                 }
1990                 break;
1991 #endif /* USE_SRP */
1992
1993         default:
1994                 /* This can't happen. */
1995                 error("EAP: unknown Response type %d; ignored", typenum);
1996                 return;
1997         }
1998
1999         if (esp->es_server.ea_timeout > 0) {
2000                 UNTIMEOUT(eap_server_timeout, (void *)esp);
2001         }
2002
2003         if (esp->es_server.ea_state != eapBadAuth &&
2004             esp->es_server.ea_state != eapOpen) {
2005                 esp->es_server.ea_id++;
2006                 eap_send_request(esp);
2007         }
2008 }
2009
2010 /*
2011  * eap_success - Receive EAP Success message (client mode).
2012  */
2013 static void
2014 eap_success(esp, inp, id, len)
2015 eap_state *esp;
2016 u_char *inp;
2017 int id;
2018 int len;
2019 {
2020         if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) {
2021                 dbglog("EAP unexpected success message in state %s (%d)",
2022                     eap_state_name(esp->es_client.ea_state),
2023                     esp->es_client.ea_state);
2024                 return;
2025         }
2026
2027         if (esp->es_client.ea_timeout > 0) {
2028                 UNTIMEOUT(eap_client_timeout, (void *)esp);
2029         }
2030
2031         if (len > 0) {
2032                 /* This is odd.  The spec doesn't allow for this. */
2033                 PRINTMSG(inp, len);
2034         }
2035
2036         esp->es_client.ea_state = eapOpen;
2037         auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2038 }
2039
2040 /*
2041  * eap_failure - Receive EAP Failure message (client mode).
2042  */
2043 static void
2044 eap_failure(esp, inp, id, len)
2045 eap_state *esp;
2046 u_char *inp;
2047 int id;
2048 int len;
2049 {
2050         if (!eap_client_active(esp)) {
2051                 dbglog("EAP unexpected failure message in state %s (%d)",
2052                     eap_state_name(esp->es_client.ea_state),
2053                     esp->es_client.ea_state);
2054         }
2055
2056         if (esp->es_client.ea_timeout > 0) {
2057                 UNTIMEOUT(eap_client_timeout, (void *)esp);
2058         }
2059
2060         if (len > 0) {
2061                 /* This is odd.  The spec doesn't allow for this. */
2062                 PRINTMSG(inp, len);
2063         }
2064
2065         esp->es_client.ea_state = eapBadAuth;
2066
2067         error("EAP: peer reports authentication failure");
2068         auth_withpeer_fail(esp->es_unit, PPP_EAP);
2069 }
2070
2071 /*
2072  * eap_input - Handle received EAP message.
2073  */
2074 static void
2075 eap_input(unit, inp, inlen)
2076 int unit;
2077 u_char *inp;
2078 int inlen;
2079 {
2080         eap_state *esp = &eap_states[unit];
2081         u_char code, id;
2082         int len;
2083
2084         /*
2085          * Parse header (code, id and length).  If packet too short,
2086          * drop it.
2087          */
2088         if (inlen < EAP_HEADERLEN) {
2089                 error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2090                 return;
2091         }
2092         GETCHAR(code, inp);
2093         GETCHAR(id, inp);
2094         GETSHORT(len, inp);
2095         if (len < EAP_HEADERLEN || len > inlen) {
2096                 error("EAP: packet has illegal length field %d (%d..%d)", len,
2097                     EAP_HEADERLEN, inlen);
2098                 return;
2099         }
2100         len -= EAP_HEADERLEN;
2101
2102         /* Dispatch based on message code */
2103         switch (code) {
2104         case EAP_REQUEST:
2105                 eap_request(esp, inp, id, len);
2106                 break;
2107
2108         case EAP_RESPONSE:
2109                 eap_response(esp, inp, id, len);
2110                 break;
2111
2112         case EAP_SUCCESS:
2113                 eap_success(esp, inp, id, len);
2114                 break;
2115
2116         case EAP_FAILURE:
2117                 eap_failure(esp, inp, id, len);
2118                 break;
2119
2120         default:                                /* XXX Need code reject */
2121                 /* Note: it's not legal to send EAP Nak here. */
2122                 warn("EAP: unknown code %d received", code);
2123                 break;
2124         }
2125 }
2126
2127 /*
2128  * eap_printpkt - print the contents of an EAP packet.
2129  */
2130 static char *eap_codenames[] = {
2131         "Request", "Response", "Success", "Failure"
2132 };
2133
2134 static char *eap_typenames[] = {
2135         "Identity", "Notification", "Nak", "MD5-Challenge",
2136         "OTP", "Generic-Token", NULL, NULL,
2137         "RSA", "DSS", "KEA", "KEA-Validate",
2138         "TLS", "Defender", "Windows 2000", "Arcot",
2139         "Cisco", "Nokia", "SRP"
2140 };
2141
2142 static int
2143 eap_printpkt(inp, inlen, printer, arg)
2144 u_char *inp;
2145 int inlen;
2146 void (*printer) __P((void *, char *, ...));
2147 void *arg;
2148 {
2149         int code, id, len, rtype, vallen;
2150         u_char *pstart;
2151         u_int32_t uval;
2152
2153         if (inlen < EAP_HEADERLEN)
2154                 return (0);
2155         pstart = inp;
2156         GETCHAR(code, inp);
2157         GETCHAR(id, inp);
2158         GETSHORT(len, inp);
2159         if (len < EAP_HEADERLEN || len > inlen)
2160                 return (0);
2161
2162         if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
2163                 printer(arg, " %s", eap_codenames[code-1]);
2164         else
2165                 printer(arg, " code=0x%x", code);
2166         printer(arg, " id=0x%x", id);
2167         len -= EAP_HEADERLEN;
2168         switch (code) {
2169         case EAP_REQUEST:
2170                 if (len < 1) {
2171                         printer(arg, " <missing type>");
2172                         break;
2173                 }
2174                 GETCHAR(rtype, inp);
2175                 len--;
2176                 if (rtype >= 1 &&
2177                     rtype <= sizeof (eap_typenames) / sizeof (char *))
2178                         printer(arg, " %s", eap_typenames[rtype-1]);
2179                 else
2180                         printer(arg, " type=0x%x", rtype);
2181                 switch (rtype) {
2182                 case EAPT_IDENTITY:
2183                 case EAPT_NOTIFICATION:
2184                         if (len > 0) {
2185                                 printer(arg, " <Message ");
2186                                 print_string((char *)inp, len, printer, arg);
2187                                 printer(arg, ">");
2188                                 INCPTR(len, inp);
2189                                 len = 0;
2190                         } else {
2191                                 printer(arg, " <No message>");
2192                         }
2193                         break;
2194
2195                 case EAPT_MD5CHAP:
2196                         if (len <= 0)
2197                                 break;
2198                         GETCHAR(vallen, inp);
2199                         len--;
2200                         if (vallen > len)
2201                                 goto truncated;
2202                         printer(arg, " <Value%.*B>", vallen, inp);
2203                         INCPTR(vallen, inp);
2204                         len -= vallen;
2205                         if (len > 0) {
2206                                 printer(arg, " <Name ");
2207                                 print_string((char *)inp, len, printer, arg);
2208                                 printer(arg, ">");
2209                                 INCPTR(len, inp);
2210                                 len = 0;
2211                         } else {
2212                                 printer(arg, " <No name>");
2213                         }
2214                         break;
2215
2216                 case EAPT_SRP:
2217                         if (len < 3)
2218                                 goto truncated;
2219                         GETCHAR(vallen, inp);
2220                         len--;
2221                         printer(arg, "-%d", vallen);
2222                         switch (vallen) {
2223                         case EAPSRP_CHALLENGE:
2224                                 GETCHAR(vallen, inp);
2225                                 len--;
2226                                 if (vallen >= len)
2227                                         goto truncated;
2228                                 if (vallen > 0) {
2229                                         printer(arg, " <Name ");
2230                                         print_string((char *)inp, vallen, printer,
2231                                             arg);
2232                                         printer(arg, ">");
2233                                 } else {
2234                                         printer(arg, " <No name>");
2235                                 }
2236                                 INCPTR(vallen, inp);
2237                                 len -= vallen;
2238                                 GETCHAR(vallen, inp);
2239                                 len--;
2240                                 if (vallen >= len)
2241                                         goto truncated;
2242                                 printer(arg, " <s%.*B>", vallen, inp);
2243                                 INCPTR(vallen, inp);
2244                                 len -= vallen;
2245                                 GETCHAR(vallen, inp);
2246                                 len--;
2247                                 if (vallen > len)
2248                                         goto truncated;
2249                                 if (vallen == 0) {
2250                                         printer(arg, " <Default g=2>");
2251                                 } else {
2252                                         printer(arg, " <g%.*B>", vallen, inp);
2253                                 }
2254                                 INCPTR(vallen, inp);
2255                                 len -= vallen;
2256                                 if (len == 0) {
2257                                         printer(arg, " <Default N>");
2258                                 } else {
2259                                         printer(arg, " <N%.*B>", len, inp);
2260                                         INCPTR(len, inp);
2261                                         len = 0;
2262                                 }
2263                                 break;
2264
2265                         case EAPSRP_SKEY:
2266                                 printer(arg, " <B%.*B>", len, inp);
2267                                 INCPTR(len, inp);
2268                                 len = 0;
2269                                 break;
2270
2271                         case EAPSRP_SVALIDATOR:
2272                                 if (len < sizeof (u_int32_t))
2273                                         break;
2274                                 GETLONG(uval, inp);
2275                                 len -= sizeof (u_int32_t);
2276                                 if (uval & SRPVAL_EBIT) {
2277                                         printer(arg, " E");
2278                                         uval &= ~SRPVAL_EBIT;
2279                                 }
2280                                 if (uval != 0) {
2281                                         printer(arg, " f<%X>", uval);
2282                                 }
2283                                 if ((vallen = len) > SHA_DIGESTSIZE)
2284                                         vallen = SHA_DIGESTSIZE;
2285                                 printer(arg, " <M2%.*B%s>", len, inp,
2286                                     len < SHA_DIGESTSIZE ? "?" : "");
2287                                 INCPTR(vallen, inp);
2288                                 len -= vallen;
2289                                 if (len > 0) {
2290                                         printer(arg, " <PN%.*B>", len, inp);
2291                                         INCPTR(len, inp);
2292                                         len = 0;
2293                                 }
2294                                 break;
2295
2296                         case EAPSRP_LWRECHALLENGE:
2297                                 printer(arg, " <Challenge%.*B>", len, inp);
2298                                 INCPTR(len, inp);
2299                                 len = 0;
2300                                 break;
2301                         }
2302                         break;
2303                 }
2304                 break;
2305
2306         case EAP_RESPONSE:
2307                 if (len < 1)
2308                         break;
2309                 GETCHAR(rtype, inp);
2310                 len--;
2311                 if (rtype >= 1 &&
2312                     rtype <= sizeof (eap_typenames) / sizeof (char *))
2313                         printer(arg, " %s", eap_typenames[rtype-1]);
2314                 else
2315                         printer(arg, " type=0x%x", rtype);
2316                 switch (rtype) {
2317                 case EAPT_IDENTITY:
2318                         if (len > 0) {
2319                                 printer(arg, " <Name ");
2320                                 print_string((char *)inp, len, printer, arg);
2321                                 printer(arg, ">");
2322                                 INCPTR(len, inp);
2323                                 len = 0;
2324                         }
2325                         break;
2326
2327                 case EAPT_NAK:
2328                         if (len <= 0) {
2329                                 printer(arg, " <missing hint>");
2330                                 break;
2331                         }
2332                         GETCHAR(rtype, inp);
2333                         len--;
2334                         printer(arg, " <Suggested-type %02X", rtype);
2335                         if (rtype >= 1 &&
2336                             rtype < sizeof (eap_typenames) / sizeof (char *))
2337                                 printer(arg, " (%s)", eap_typenames[rtype-1]);
2338                         printer(arg, ">");
2339                         break;
2340
2341                 case EAPT_MD5CHAP:
2342                         if (len <= 0) {
2343                                 printer(arg, " <missing length>");
2344                                 break;
2345                         }
2346                         GETCHAR(vallen, inp);
2347                         len--;
2348                         if (vallen > len)
2349                                 goto truncated;
2350                         printer(arg, " <Value%.*B>", vallen, inp);
2351                         INCPTR(vallen, inp);
2352                         len -= vallen;
2353                         if (len > 0) {
2354                                 printer(arg, " <Name ");
2355                                 print_string((char *)inp, len, printer, arg);
2356                                 printer(arg, ">");
2357                                 INCPTR(len, inp);
2358                                 len = 0;
2359                         } else {
2360                                 printer(arg, " <No name>");
2361                         }
2362                         break;
2363
2364                 case EAPT_SRP:
2365                         if (len < 1)
2366                                 goto truncated;
2367                         GETCHAR(vallen, inp);
2368                         len--;
2369                         printer(arg, "-%d", vallen);
2370                         switch (vallen) {
2371                         case EAPSRP_CKEY:
2372                                 printer(arg, " <A%.*B>", len, inp);
2373                                 INCPTR(len, inp);
2374                                 len = 0;
2375                                 break;
2376
2377                         case EAPSRP_CVALIDATOR:
2378                                 if (len < sizeof (u_int32_t))
2379                                         break;
2380                                 GETLONG(uval, inp);
2381                                 len -= sizeof (u_int32_t);
2382                                 if (uval & SRPVAL_EBIT) {
2383                                         printer(arg, " E");
2384                                         uval &= ~SRPVAL_EBIT;
2385                                 }
2386                                 if (uval != 0) {
2387                                         printer(arg, " f<%X>", uval);
2388                                 }
2389                                 printer(arg, " <M1%.*B%s>", len, inp,
2390                                     len == SHA_DIGESTSIZE ? "" : "?");
2391                                 INCPTR(len, inp);
2392                                 len = 0;
2393                                 break;
2394
2395                         case EAPSRP_ACK:
2396                                 break;
2397
2398                         case EAPSRP_LWRECHALLENGE:
2399                                 printer(arg, " <Response%.*B%s>", len, inp,
2400                                     len == SHA_DIGESTSIZE ? "" : "?");
2401                                 if ((vallen = len) > SHA_DIGESTSIZE)
2402                                         vallen = SHA_DIGESTSIZE;
2403                                 INCPTR(vallen, inp);
2404                                 len -= vallen;
2405                                 break;
2406                         }
2407                         break;
2408                 }
2409                 break;
2410
2411         case EAP_SUCCESS:       /* No payload expected for these! */
2412         case EAP_FAILURE:
2413                 break;
2414
2415         truncated:
2416                 printer(arg, " <truncated>");
2417                 break;
2418         }
2419
2420         if (len > 8)
2421                 printer(arg, "%8B...", inp);
2422         else if (len > 0)
2423                 printer(arg, "%.*B", len, inp);
2424         INCPTR(len, inp);
2425
2426         return (inp - pstart);
2427 }