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