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