1 /*        $NetBSD: eap.c,v 1.7 2025/01/08 19:59:39 christos Exp $     */
2 /*
3  * eap.c - Extensible Authentication Protocol for PPP (RFC 2284)
4  *
5  * Copyright (c) 2001 by Sun Microsystems, Inc.
6  * All rights reserved.
7  *
8  * Non-exclusive rights to redistribute, modify, translate, and use
9  * this software in source and binary forms, in whole or in part, is
10  * hereby granted, provided that the above copyright notice is
11  * duplicated in any source form, and that neither the name of the
12  * copyright holder nor the author is used to endorse or promote
13  * products derived from this software.
14  *
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * Original version by James Carlson
20  *
21  * This implementation of EAP supports MD5-Challenge and SRP-SHA1
22  * authentication styles.  Note that support of MD5-Challenge is a
23  * requirement of RFC 2284, and that it's essentially just a
24  * reimplementation of regular RFC 1994 CHAP using EAP messages.
25  *
26  * As an authenticator ("server"), there are multiple phases for each
27  * style.  In the first phase of each style, the unauthenticated peer
28  * name is queried using the EAP Identity request type.  If the
29  * "remotename" option is used, then this phase is skipped, because
30  * the peer's name is presumed to be known.
31  *
32  * For MD5-Challenge, there are two phases, and the second phase
33  * consists of sending the challenge itself and handling the
34  * associated response.
35  *
36  * For SRP-SHA1, there are four phases.  The second sends 's', 'N',
37  * and 'g'.  The reply contains 'A'.  The third sends 'B', and the
38  * reply contains 'M1'.  The forth sends the 'M2' value.
39  *
40  * As an authenticatee ("client"), there's just a single phase --
41  * responding to the queries generated by the peer.  EAP is an
42  * authenticator-driven protocol.
43  *
44  * Based on draft-ietf-pppext-eap-srp-03.txt.
45  */
46 
47 #include <sys/cdefs.h>
48 __RCSID("$NetBSD: eap.c,v 1.7 2025/01/08 19:59:39 christos Exp $");
49 
50 /*
51  * Modification by Beniamino Galvani, Mar 2005
52  * Implemented EAP-TLS authentication
53  */
54 
55 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58 
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <unistd.h>
63 #include <pwd.h>
64 #include <sys/types.h>
65 #include <sys/stat.h>
66 #include <fcntl.h>
67 #include <assert.h>
68 #include <errno.h>
69 #include <md5.h>
70 
71 #include "pppd-private.h"
72 #include "options.h"
73 #include "pathnames.h"
74 #include "crypto.h"
75 #include "crypto_ms.h"
76 #include "eap.h"
77 #ifdef PPP_WITH_PEAP
78 #include "peap.h"
79 #endif /* PPP_WITH_PEAP */
80 
81 #ifdef PPP_WITH_SRP
82 #ifdef HAVE_TIME_H
83 #include <time.h>
84 #endif
85 #include <t_pwd.h>
86 #include <t_server.h>
87 #include <t_client.h>
88 #endif /* PPP_WITH_SRP */
89 
90 #ifdef PPP_WITH_EAPTLS
91 #include "eap-tls.h"
92 #endif /* PPP_WITH_EAPTLS */
93 
94 #ifdef PPP_WITH_CHAPMS
95 #include "chap.h"
96 #include "chap_ms.h"
97 
98 extern int chapms_strip_domain;
99 #endif /* PPP_WITH_CHAPMS */
100 
101 eap_state eap_states[NUM_PPP];                    /* EAP state; one for each unit */
102 #ifdef PPP_WITH_SRP
103 static char *pn_secret = NULL;                    /* Pseudonym generating secret */
104 #endif
105 
106 /*
107  * Command-line options.
108  */
109 static struct option eap_option_list[] = {
110     { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,
111       "Set retransmit timeout for EAP Requests (server)" },
112     { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,
113       "Set max number of EAP Requests sent (server)" },
114     { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,
115       "Set time limit for peer EAP authentication" },
116     { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,
117       "Set max number of EAP Requests allows (client)" },
118     { "eap-interval", o_int, &eap_states[0].es_rechallenge,
119       "Set interval for EAP rechallenge" },
120 #ifdef PPP_WITH_SRP
121     { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,
122       "Set interval for SRP lightweight rechallenge" },
123     { "srp-pn-secret", o_string, &pn_secret,
124       "Long term pseudonym generation secret" },
125     { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,
126       "Use pseudonym if offered one by server", 1 },
127 #endif
128     { NULL }
129 };
130 
131 /*
132  * Protocol entry points.
133  */
134 static void eap_init (int unit);
135 static void eap_input (int unit, u_char *inp, int inlen);
136 static void eap_protrej (int unit);
137 static void eap_lowerup (int unit);
138 static void eap_lowerdown (int unit);
139 static int  eap_printpkt (u_char *inp, int inlen,
140     void (*)(void *arg, char *fmt, ...), void *arg);
141 
142 struct protent eap_protent = {
143           PPP_EAP,            /* protocol number */
144           eap_init,           /* initialization procedure */
145           eap_input,                    /* process a received packet */
146           eap_protrej,                  /* process a received protocol-reject */
147           eap_lowerup,                  /* lower layer has gone up */
148           eap_lowerdown,                /* lower layer has gone down */
149           NULL,                         /* open the protocol */
150           NULL,                         /* close the protocol */
151           eap_printpkt,                 /* print a packet in readable form */
152           NULL,                         /* process a received data packet */
153           1,                            /* protocol enabled */
154           "EAP",                        /* text name of protocol */
155           NULL,                         /* text name of corresponding data protocol */
156           eap_option_list,    /* list of command-line options */
157           NULL,                         /* check requested options; assign defaults */
158           NULL,                         /* configure interface for demand-dial */
159           NULL                          /* say whether to bring up link for this pkt */
160 };
161 
162 #ifdef PPP_WITH_SRP
163 /*
164  * A well-known 2048 bit modulus.
165  */
166 static const u_char wkmodulus[] = {
167           0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
168           0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
169           0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
170           0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
171           0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
172           0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
173           0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
174           0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
175           0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
176           0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
177           0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
178           0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
179           0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
180           0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
181           0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
182           0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
183           0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
184           0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
185           0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
186           0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
187           0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
188           0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
189           0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
190           0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
191           0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
192           0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
193           0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
194           0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
195           0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
196           0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
197           0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
198           0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
199 };
200 #endif /* PPP_WITH_SRP */
201 
202 /* Local forward declarations. */
203 static void eap_server_timeout (void *arg);
204 
205 /*
206  * Convert EAP state code to printable string for debug.
207  */
208 static const char *
eap_state_name(enum eap_state_code esc)209 eap_state_name(enum eap_state_code esc)
210 {
211           static const char *state_names[] = { EAP_STATES };
212 
213           return (state_names[(int)esc]);
214 }
215 
216 /*
217  * eap_init - Initialize state for an EAP user.  This is currently
218  * called once by main() during start-up.
219  */
220 static void
eap_init(int unit)221 eap_init(int unit)
222 {
223           eap_state *esp = &eap_states[unit];
224 
225           BZERO(esp, sizeof (*esp));
226           esp->es_unit = unit;
227           esp->es_server.ea_timeout = EAP_DEFTIMEOUT;
228           esp->es_server.ea_maxrequests = EAP_DEFTRANSMITS;
229           esp->es_server.ea_id = (u_char)(drand48() * 0x100);
230           esp->es_client.ea_timeout = EAP_DEFREQTIME;
231           esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
232 #ifdef PPP_WITH_EAPTLS
233           esp->es_client.ea_using_eaptls = 0;
234 #endif /* PPP_WITH_EAPTLS */
235 #ifdef PPP_WITH_CHAPMS
236           esp->es_client.digest = chap_find_digest(CHAP_MICROSOFT_V2);
237           esp->es_server.digest = chap_find_digest(CHAP_MICROSOFT_V2);
238 #endif
239 }
240 
241 /*
242  * eap_client_timeout - Give up waiting for the peer to send any
243  * Request messages.
244  */
245 static void
eap_client_timeout(void * arg)246 eap_client_timeout(void *arg)
247 {
248           eap_state *esp = (eap_state *) arg;
249 
250           if (!eap_client_active(esp))
251                     return;
252 
253           error("EAP: timeout waiting for Request from peer");
254           auth_withpeer_fail(esp->es_unit, PPP_EAP);
255           esp->es_client.ea_state = eapBadAuth;
256 }
257 
258 /*
259  * eap_authwithpeer - Authenticate to our peer (behave as client).
260  *
261  * Start client state and wait for requests.  This is called only
262  * after eap_lowerup.
263  */
264 void
eap_authwithpeer(int unit,char * localname)265 eap_authwithpeer(int unit, char *localname)
266 {
267           eap_state *esp = &eap_states[unit];
268 
269           /* Save the peer name we're given */
270           esp->es_client.ea_name = localname;
271           esp->es_client.ea_namelen = strlen(localname);
272 
273           esp->es_client.ea_state = eapListen;
274 
275           /*
276            * Start a timer so that if the other end just goes
277            * silent, we don't sit here waiting forever.
278            */
279           if (esp->es_client.ea_timeout > 0)
280                     TIMEOUT(eap_client_timeout, (void *)esp,
281                         esp->es_client.ea_timeout);
282 }
283 
284 /*
285  * Format a standard EAP Failure message and send it to the peer.
286  * (Server operation)
287  */
288 static void
eap_send_failure(eap_state * esp)289 eap_send_failure(eap_state *esp)
290 {
291           u_char *outp;
292 
293           outp = outpacket_buf;
294 
295           MAKEHEADER(outp, PPP_EAP);
296 
297           PUTCHAR(EAP_FAILURE, outp);
298           esp->es_server.ea_id++;
299           PUTCHAR(esp->es_server.ea_id, outp);
300           PUTSHORT(EAP_HEADERLEN, outp);
301 
302           output(esp->es_unit, outpacket_buf, EAP_HEADERLEN + PPP_HDRLEN);
303 
304           esp->es_server.ea_state = eapBadAuth;
305           auth_peer_fail(esp->es_unit, PPP_EAP);
306 }
307 
308 /*
309  * Format a standard EAP Success message and send it to the peer.
310  * (Server operation)
311  */
312 static void
eap_send_success(eap_state * esp)313 eap_send_success(eap_state *esp)
314 {
315           u_char *outp;
316 
317           outp = outpacket_buf;
318 
319           MAKEHEADER(outp, PPP_EAP);
320 
321           PUTCHAR(EAP_SUCCESS, outp);
322           esp->es_server.ea_id++;
323           PUTCHAR(esp->es_server.ea_id, outp);
324           PUTSHORT(EAP_HEADERLEN, outp);
325 
326           output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);
327 
328           auth_peer_success(esp->es_unit, PPP_EAP, 0,
329               esp->es_server.ea_peer, esp->es_server.ea_peerlen);
330 }
331 
332 #ifdef PPP_WITH_SRP
333 /*
334  * Set DES key according to pseudonym-generating secret and current
335  * date.
336  */
337 static bool
pncrypt_getkey(int timeoffs,unsigned char * key,int keylen)338 pncrypt_getkey(int timeoffs, unsigned char *key, int keylen)
339 {
340           struct tm *tp;
341           char tbuf[9];
342           PPP_MD_CTX *ctxt;
343           time_t reftime;
344 
345           if (pn_secret == NULL)
346                     return (0);
347           reftime = time(NULL) + timeoffs;
348           tp = localtime(&reftime);
349 
350           ctxt = PPP_MD_CTX_new();
351           if (ctxt) {
352 
353               strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp);
354 
355               PPP_DigestInit(ctxt, PPP_sha1());
356               PPP_DigestUpdate(ctxt, pn_secret, strlen(pn_secret));
357               PPP_DigestUpdate(ctxt, tbuf, strlen(tbuf));
358               PPP_DigestFinal(ctxt, key, &keylen);
359 
360               PPP_MD_CTX_free(ctxt);
361               return 1;
362           }
363 
364           return (0);
365 }
366 
367 static char base64[] =
368 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
369 
370 struct b64state {
371           u_int32_t bs_bits;
372           int bs_offs;
373 };
374 
375 static int
b64enc(struct b64state * bs,u_char * inp,int inlen,u_char * outp)376 b64enc(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
377 {
378           int outlen = 0;
379 
380           while (inlen > 0) {
381                     bs->bs_bits = (bs->bs_bits << 8) | *inp++;
382                     inlen--;
383                     bs->bs_offs += 8;
384                     if (bs->bs_offs >= 24) {
385                               *outp++ = base64[(bs->bs_bits >> 18) & 0x3F];
386                               *outp++ = base64[(bs->bs_bits >> 12) & 0x3F];
387                               *outp++ = base64[(bs->bs_bits >> 6) & 0x3F];
388                               *outp++ = base64[bs->bs_bits & 0x3F];
389                               outlen += 4;
390                               bs->bs_offs = 0;
391                               bs->bs_bits = 0;
392                     }
393           }
394           return (outlen);
395 }
396 
397 static int
b64flush(struct b64state * bs,u_char * outp)398 b64flush(struct b64state *bs, u_char *outp)
399 {
400           int outlen = 0;
401 
402           if (bs->bs_offs == 8) {
403                     *outp++ = base64[(bs->bs_bits >> 2) & 0x3F];
404                     *outp++ = base64[(bs->bs_bits << 4) & 0x3F];
405                     outlen = 2;
406           } else if (bs->bs_offs == 16) {
407                     *outp++ = base64[(bs->bs_bits >> 10) & 0x3F];
408                     *outp++ = base64[(bs->bs_bits >> 4) & 0x3F];
409                     *outp++ = base64[(bs->bs_bits << 2) & 0x3F];
410                     outlen = 3;
411           }
412           bs->bs_offs = 0;
413           bs->bs_bits = 0;
414           return (outlen);
415 }
416 
417 static int
b64dec(struct b64state * bs,u_char * inp,int inlen,u_char * outp)418 b64dec(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
419 {
420           int outlen = 0;
421           char *cp;
422 
423           while (inlen > 0) {
424                     if ((cp = strchr(base64, *inp++)) == NULL)
425                               break;
426                     bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);
427                     inlen--;
428                     bs->bs_offs += 6;
429                     if (bs->bs_offs >= 8) {
430                               *outp++ = bs->bs_bits >> (bs->bs_offs - 8);
431                               outlen++;
432                               bs->bs_offs -= 8;
433                     }
434           }
435           return (outlen);
436 }
437 #endif /* PPP_WITH_SRP */
438 
439 /*
440  * Assume that current waiting server state is complete and figure
441  * next state to use based on available authentication data.  'status'
442  * indicates if there was an error in handling the last query.  It is
443  * 0 for success and non-zero for failure.
444  */
445 static void
eap_figure_next_state(eap_state * esp,int status)446 eap_figure_next_state(eap_state *esp, int status)
447 {
448 #ifdef PPP_WITH_SRP
449           unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp, key[SHA_DIGEST_LENGTH];
450           struct t_pw tpw;
451           struct t_confent *tce, mytce;
452           char *cp, *cp2;
453           struct t_server *ts;
454           int id, i, plen, clen, toffs, keylen;
455           u_char vals[2];
456           struct b64state bs;
457 #endif /* PPP_WITH_SRP */
458 #ifdef PPP_WITH_EAPTLS
459           struct eaptls_session *ets;
460           int secret_len;
461           char secret[MAXWORDLEN];
462 #endif /* PPP_WITH_EAPTLS */
463 
464           esp->es_server.ea_timeout = esp->es_savedtime;
465 #ifdef PPP_WITH_EAPTLS
466           esp->es_server.ea_prev_state = esp->es_server.ea_state;
467 #endif /* PPP_WITH_EAPTLS */
468           switch (esp->es_server.ea_state) {
469           case eapBadAuth:
470                     return;
471 
472           case eapIdentify:
473 #ifdef PPP_WITH_SRP
474                     /* Discard any previous session. */
475                     ts = (struct t_server *)esp->es_server.ea_session;
476                     if (ts != NULL) {
477                               t_serverclose(ts);
478                               esp->es_server.ea_session = NULL;
479                               esp->es_server.ea_skey = NULL;
480                     }
481 #endif /* PPP_WITH_SRP */
482                     if (status != 0) {
483                               esp->es_server.ea_state = eapBadAuth;
484                               break;
485                     }
486 #ifdef PPP_WITH_SRP
487                     /* If we've got a pseudonym, try to decode to real name. */
488                     if (esp->es_server.ea_peerlen > SRP_PSEUDO_LEN &&
489                         strncmp(esp->es_server.ea_peer, SRP_PSEUDO_ID,
490                               SRP_PSEUDO_LEN) == 0 &&
491                         (esp->es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 <
492                         sizeof (secbuf)) {
493                               BZERO(&bs, sizeof (bs));
494                               plen = b64dec(&bs,
495                                   esp->es_server.ea_peer + SRP_PSEUDO_LEN,
496                                   esp->es_server.ea_peerlen - SRP_PSEUDO_LEN,
497                                   secbuf);
498                               toffs = 0;
499                               for (i = 0; i < 5; i++) {
500                                         pncrypt_getkey(toffs, key, keylen);
501                                         toffs -= 86400;
502 
503                                         if (!DesDecrypt(secbuf, key, clear)) {
504                                                   dbglog("no DES here; cannot decode "
505                                                             "pseudonym");
506                                                   return;
507                                         }
508                                         id = *(unsigned char *)clear;
509                                         if (id + 1 <= plen && id + 9 > plen)
510                                                   break;
511                               }
512                               if (plen % 8 == 0 && i < 5) {
513                                         /*
514                                          * Note that this is always shorter than the
515                                          * original stored string, so there's no need
516                                          * to realloc.
517                                          */
518                                         if ((i = plen = *(unsigned char *)clear) > 7)
519                                                   i = 7;
520                                         esp->es_server.ea_peerlen = plen;
521                                         dp = (unsigned char *)esp->es_server.ea_peer;
522                                         BCOPY(clear + 1, dp, i);
523                                         plen -= i;
524                                         dp += i;
525                                         sp = secbuf + 8;
526                                         while (plen > 0) {
527                                                   DesDecrypt(sp, key, dp);
528                                                   sp += 8;
529                                                   dp += 8;
530                                                   plen -= 8;
531                                         }
532                                         esp->es_server.ea_peer[
533                                                   esp->es_server.ea_peerlen] = '\0';
534                                         dbglog("decoded pseudonym to \"%.*q\"",
535                                             esp->es_server.ea_peerlen,
536                                             esp->es_server.ea_peer);
537                               } else {
538                                         dbglog("failed to decode real name");
539                                         /* Stay in eapIdentfy state; requery */
540                                         break;
541                               }
542                     }
543                     /* Look up user in secrets database. */
544                     if (get_srp_secret(esp->es_unit, esp->es_server.ea_peer,
545                         esp->es_server.ea_name, (char *)secbuf, 1) != 0) {
546                               /* Set up default in case SRP entry is bad */
547                               esp->es_server.ea_state = eapMD5Chall;
548                               /* Get t_confent based on index in srp-secrets */
549                               id = strtol((char *)secbuf, &cp, 10);
550                               if (*cp++ != ':' || id < 0)
551                                         break;
552                               if (id == 0) {
553                                         mytce.index = 0;
554                                         mytce.modulus.data = (u_char *)wkmodulus;
555                                         mytce.modulus.len = sizeof (wkmodulus);
556                                         mytce.generator.data = (u_char *)"\002";
557                                         mytce.generator.len = 1;
558                                         tce = &mytce;
559                               } else if ((tce = gettcid(id)) != NULL) {
560                                         /*
561                                          * Client will have to verify this modulus/
562                                          * generator combination, and that will take
563                                          * a while.  Lengthen the timeout here.
564                                          */
565                                         if (esp->es_server.ea_timeout > 0 &&
566                                             esp->es_server.ea_timeout < 30)
567                                                   esp->es_server.ea_timeout = 30;
568                               } else {
569                                         break;
570                               }
571                               if ((cp2 = strchr(cp, ':')) == NULL)
572                                         break;
573                               *cp2++ = '\0';
574                               tpw.pebuf.name = esp->es_server.ea_peer;
575                               tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,
576                                   cp);
577                               tpw.pebuf.password.data = (char*) tpw.pwbuf;
578                               tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,
579                                   cp2);
580                               tpw.pebuf.salt.data = tpw.saltbuf;
581                               if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)
582                                         break;
583                               esp->es_server.ea_session = (void *)ts;
584                               esp->es_server.ea_state = eapSRP1;
585                               vals[0] = esp->es_server.ea_id + 1;
586                               vals[1] = EAPT_SRP;
587                               t_serveraddexdata(ts, vals, 2);
588                               /* Generate B; must call before t_servergetkey() */
589                               t_servergenexp(ts);
590                               break;
591                     }
592 #endif /* PPP_WITH_SRP */
593 #ifdef PPP_WITH_EAPTLS
594                 if (!get_secret(esp->es_unit, esp->es_server.ea_peer,
595                     esp->es_server.ea_name, secret, &secret_len, 1)) {
596 
597                               esp->es_server.ea_state = eapTlsStart;
598                               break;
599                     }
600 #endif /* PPP_WITH_EAPTLS */
601 
602                     esp->es_server.ea_state = eapMD5Chall;
603                     break;
604 
605 #ifdef PPP_WITH_EAPTLS
606           case eapTlsStart:
607                     /* Initialize ssl session */
608                     if(!eaptls_init_ssl_server(esp)) {
609                               esp->es_server.ea_state = eapBadAuth;
610                               break;
611                     }
612 
613                     esp->es_server.ea_state = eapTlsRecv;
614                     break;
615 
616           case eapTlsRecv:
617                     ets = (struct eaptls_session *) esp->es_server.ea_session;
618 
619                     if(ets->alert_sent) {
620                               esp->es_server.ea_state = eapTlsSendAlert;
621                               break;
622                     }
623 
624                     if (status) {
625                               esp->es_server.ea_state = eapBadAuth;
626                               break;
627                     }
628                     ets = (struct eaptls_session *) esp->es_server.ea_session;
629 
630                     if(ets->frag)
631                               esp->es_server.ea_state = eapTlsSendAck;
632                     else
633                               esp->es_server.ea_state = eapTlsSend;
634                     break;
635 
636           case eapTlsSend:
637                     ets = (struct eaptls_session *) esp->es_server.ea_session;
638 
639                     if(ets->frag)
640                               esp->es_server.ea_state = eapTlsRecvAck;
641                     else
642                               if(SSL_is_init_finished(ets->ssl))
643                                         esp->es_server.ea_state = eapTlsRecvClient;
644                               else
645                                         /* JJK Add "TLS empty record" message here ??? */
646                                         esp->es_server.ea_state = eapTlsRecv;
647                     break;
648 
649           case eapTlsSendAck:
650                     esp->es_server.ea_state = eapTlsRecv;
651                     break;
652 
653           case eapTlsRecvAck:
654                     if (status)
655                     {
656                               esp->es_server.ea_state = eapBadAuth;
657                               break;
658                     }
659 
660                     esp->es_server.ea_state = eapTlsSend;
661                     break;
662 
663           case eapTlsSendAlert:
664                     esp->es_server.ea_state = eapTlsRecvAlertAck;
665                     break;
666 #endif /* PPP_WITH_EAPTLS */
667 
668           case eapSRP1:
669 #ifdef PPP_WITH_SRP
670                     ts = (struct t_server *)esp->es_server.ea_session;
671                     if (ts != NULL && status != 0) {
672                               t_serverclose(ts);
673                               esp->es_server.ea_session = NULL;
674                               esp->es_server.ea_skey = NULL;
675                     }
676 #endif /* PPP_WITH_SRP */
677                     if (status == 1) {
678                               esp->es_server.ea_state = eapMD5Chall;
679                     } else if (status != 0 || esp->es_server.ea_session == NULL) {
680                               esp->es_server.ea_state = eapBadAuth;
681                     } else {
682                               esp->es_server.ea_state = eapSRP2;
683                     }
684                     break;
685 
686           case eapSRP2:
687 #ifdef PPP_WITH_SRP
688                     ts = (struct t_server *)esp->es_server.ea_session;
689                     if (ts != NULL && status != 0) {
690                               t_serverclose(ts);
691                               esp->es_server.ea_session = NULL;
692                               esp->es_server.ea_skey = NULL;
693                     }
694 #endif /* PPP_WITH_SRP */
695                     if (status != 0 || esp->es_server.ea_session == NULL) {
696                               esp->es_server.ea_state = eapBadAuth;
697                     } else {
698                               esp->es_server.ea_state = eapSRP3;
699                     }
700                     break;
701 
702           case eapSRP3:
703           case eapSRP4:
704 #ifdef PPP_WITH_SRP
705                     ts = (struct t_server *)esp->es_server.ea_session;
706                     if (ts != NULL && status != 0) {
707                               t_serverclose(ts);
708                               esp->es_server.ea_session = NULL;
709                               esp->es_server.ea_skey = NULL;
710                     }
711 #endif /* PPP_WITH_SRP */
712                     if (status != 0 || esp->es_server.ea_session == NULL) {
713                               esp->es_server.ea_state = eapBadAuth;
714                     } else {
715                               esp->es_server.ea_state = eapOpen;
716                     }
717                     break;
718 
719 #ifdef PPP_WITH_CHAPMS
720           case eapMSCHAPv2Chall:
721 #endif
722           case eapMD5Chall:
723                     if (status != 0) {
724                               esp->es_server.ea_state = eapBadAuth;
725                     } else {
726                               esp->es_server.ea_state = eapOpen;
727                     }
728                     break;
729 
730           default:
731                     esp->es_server.ea_state = eapBadAuth;
732                     break;
733           }
734           if (esp->es_server.ea_state == eapBadAuth)
735                     eap_send_failure(esp);
736 
737 #ifdef PPP_WITH_EAPTLS
738           dbglog("EAP id=0x%2x '%s' -> '%s'", esp->es_server.ea_id, eap_state_name(esp->es_server.ea_prev_state), eap_state_name(esp->es_server.ea_state));
739 #endif /* PPP_WITH_EAPTLS */
740 }
741 
742 #if PPP_WITH_CHAPMS
743 /*
744  * eap_chap_verify_response - check whether the peer's response matches
745  * what we think it should be.  Returns 1 if it does (authentication
746  * succeeded), or 0 if it doesn't.
747  */
748 static int
eap_chap_verify_response(char * name,char * ourname,int id,struct chap_digest_type * digest,unsigned char * challenge,unsigned char * response,char * message,int message_space)749 eap_chap_verify_response(char *name, char *ourname, int id,
750                                struct chap_digest_type *digest,
751                                unsigned char *challenge, unsigned char *response,
752                                char *message, int message_space)
753 {
754           int ok;
755           unsigned char secret[MAXSECRETLEN];
756           int secret_len;
757 
758           /* Get the secret that the peer is supposed to know */
759           if (!get_secret(0, name, ourname, (char *)secret, &secret_len, 1)) {
760                     error("No CHAP secret found for authenticating %q", name);
761                     return 0;
762           }
763 
764           ok = digest->verify_response(id, name, secret, secret_len, challenge,
765                                              response, message, message_space);
766           memset(secret, 0, sizeof(secret));
767 
768           return ok;
769 }
770 
771 /*
772  * Format and send an CHAPV2-Success/Failure EAP Request message.
773  */
774 static void
eap_chapms2_send_request(eap_state * esp,u_char id,u_char opcode,u_char chapid,char * message,int message_len)775 eap_chapms2_send_request(eap_state *esp, u_char id,
776                                u_char opcode, u_char chapid,
777                                char *message, int message_len)
778 {
779           u_char *outp;
780           int msglen;
781 
782           outp = outpacket_buf;
783 
784           MAKEHEADER(outp, PPP_EAP);
785 
786           msglen = EAP_HEADERLEN + 5 * sizeof (u_char);
787           msglen += message_len;
788 
789           PUTCHAR(EAP_REQUEST, outp);
790           PUTCHAR(id, outp);
791           PUTSHORT(msglen, outp);
792           PUTCHAR(EAPT_MSCHAPV2, outp);
793           PUTCHAR(opcode, outp);
794           PUTCHAR(chapid, outp);
795           /* MS len */
796           PUTSHORT(msglen - 5, outp);
797           BCOPY(message, outp, message_len);
798 
799           output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
800 
801           if (opcode == CHAP_SUCCESS) {
802                     auth_peer_success(esp->es_unit, PPP_EAP, 0,
803                                         esp->es_server.ea_peer, esp->es_server.ea_peerlen);
804           }
805           else {
806                     esp->es_server.ea_state = eapBadAuth;
807                     auth_peer_fail(esp->es_unit, PPP_EAP);
808           }
809 }
810 #endif /* PPP_WITH_CHAPMS */
811 
812 /*
813  * Format an EAP Request message and send it to the peer.  Message
814  * type depends on current state.  (Server operation)
815  */
816 static void
eap_send_request(eap_state * esp)817 eap_send_request(eap_state *esp)
818 {
819           u_char *outp;
820           u_char *lenloc;
821           u_char *ptr;
822           int outlen;
823           int challen;
824           char *str;
825 #ifdef PPP_WITH_SRP
826           struct t_server *ts;
827           u_char clear[8], cipher[8], dig[SHA_DIGEST_LENGTH], *optr, *cp, key[SHA_DIGEST_LENGTH];
828           int i, j, diglen, clen, keylen = sizeof(key);
829           struct b64state b64;
830           PPP_MD_CTX *ctxt;
831 #endif /* PPP_WITH_SRP */
832 
833           /* Handle both initial auth and restart */
834           if (esp->es_server.ea_state < eapIdentify &&
835               esp->es_server.ea_state != eapInitial) {
836                     esp->es_server.ea_state = eapIdentify;
837                     if (explicit_remote) {
838                               /*
839                                * If we already know the peer's
840                                * unauthenticated name, then there's no
841                                * reason to ask.  Go to next state instead.
842                                */
843                               esp->es_server.ea_peer = remote_name;
844                               esp->es_server.ea_peerlen = strlen(remote_name);
845                               eap_figure_next_state(esp, 0);
846                     }
847           }
848 
849           if (esp->es_server.ea_maxrequests > 0 &&
850               esp->es_server.ea_requests >= esp->es_server.ea_maxrequests) {
851                     if (esp->es_server.ea_responses > 0)
852                               error("EAP: too many Requests sent");
853                     else
854                               error("EAP: no response to Requests");
855                     eap_send_failure(esp);
856                     return;
857           }
858 
859           outp = outpacket_buf;
860 
861           MAKEHEADER(outp, PPP_EAP);
862 
863           PUTCHAR(EAP_REQUEST, outp);
864           PUTCHAR(esp->es_server.ea_id, outp);
865           lenloc = outp;
866           INCPTR(2, outp);
867 
868           switch (esp->es_server.ea_state) {
869           case eapIdentify:
870                     PUTCHAR(EAPT_IDENTITY, outp);
871                     str = "Name";
872                     challen = strlen(str);
873                     BCOPY(str, outp, challen);
874                     INCPTR(challen, outp);
875                     break;
876 
877           case eapMD5Chall:
878                     PUTCHAR(EAPT_MD5CHAP, outp);
879                     /*
880                      * pick a random challenge length between
881                      * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
882                      */
883                     challen = (drand48() *
884                         (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
885                                   MIN_CHALLENGE_LENGTH;
886                     PUTCHAR(challen, outp);
887                     esp->es_challen = challen;
888                     ptr = esp->es_challenge;
889                     while (--challen >= 0)
890                               *ptr++ = (u_char) (drand48() * 0x100);
891                     BCOPY(esp->es_challenge, outp, esp->es_challen);
892                     INCPTR(esp->es_challen, outp);
893                     BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
894                     INCPTR(esp->es_server.ea_namelen, outp);
895                     break;
896 
897 #ifdef PPP_WITH_CHAPMS
898           case eapMSCHAPv2Chall:
899                     esp->es_server.digest->generate_challenge(esp->es_challenge);
900                     challen = esp->es_challenge[0];
901                     esp->es_challen = challen;
902 
903                     PUTCHAR(EAPT_MSCHAPV2, outp);
904                     PUTCHAR(CHAP_CHALLENGE, outp);
905                     PUTCHAR(esp->es_server.ea_id, outp);
906                     /* MS len */
907                     PUTSHORT(5 + challen +
908                                         esp->es_server.ea_namelen,
909                                         outp);
910                     /* challen + challenge */
911                     BCOPY(esp->es_challenge, outp, challen+1);
912                     INCPTR(challen+1, outp);
913                     BCOPY(esp->es_server.ea_name,
914                                         outp,
915                                         esp->es_server.ea_namelen);
916                     INCPTR(esp->es_server.ea_namelen, outp);
917                     break;
918 #endif /* PPP_WITH_CHAPMS */
919 
920 #ifdef PPP_WITH_EAPTLS
921           case eapTlsStart:
922                     PUTCHAR(EAPT_TLS, outp);
923                     PUTCHAR(EAP_TLS_FLAGS_START, outp);
924                     eap_figure_next_state(esp, 0);
925                     break;
926 
927           case eapTlsSend:
928                     eaptls_send(esp->es_server.ea_session, &outp);
929                     eap_figure_next_state(esp, 0);
930                     break;
931 
932           case eapTlsSendAck:
933                     PUTCHAR(EAPT_TLS, outp);
934                     PUTCHAR(0, outp);
935                     eap_figure_next_state(esp, 0);
936                     break;
937 
938           case eapTlsSendAlert:
939                     eaptls_send(esp->es_server.ea_session, &outp);
940                     eap_figure_next_state(esp, 0);
941                     break;
942 #endif /* PPP_WITH_EAPTLS */
943 
944 #ifdef PPP_WITH_SRP
945           case eapSRP1:
946                     PUTCHAR(EAPT_SRP, outp);
947                     PUTCHAR(EAPSRP_CHALLENGE, outp);
948 
949                     PUTCHAR(esp->es_server.ea_namelen, outp);
950                     BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
951                     INCPTR(esp->es_server.ea_namelen, outp);
952 
953                     ts = (struct t_server *)esp->es_server.ea_session;
954                     assert(ts != NULL);
955                     PUTCHAR(ts->s.len, outp);
956                     BCOPY(ts->s.data, outp, ts->s.len);
957                     INCPTR(ts->s.len, outp);
958 
959                     if (ts->g.len == 1 && ts->g.data[0] == 2) {
960                               PUTCHAR(0, outp);
961                     } else {
962                               PUTCHAR(ts->g.len, outp);
963                               BCOPY(ts->g.data, outp, ts->g.len);
964                               INCPTR(ts->g.len, outp);
965                     }
966 
967                     if (ts->n.len != sizeof (wkmodulus) ||
968                         BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) {
969                               BCOPY(ts->n.data, outp, ts->n.len);
970                               INCPTR(ts->n.len, outp);
971                     }
972                     break;
973 
974           case eapSRP2:
975                     PUTCHAR(EAPT_SRP, outp);
976                     PUTCHAR(EAPSRP_SKEY, outp);
977 
978                     ts = (struct t_server *)esp->es_server.ea_session;
979                     assert(ts != NULL);
980                     BCOPY(ts->B.data, outp, ts->B.len);
981                     INCPTR(ts->B.len, outp);
982                     break;
983 
984           case eapSRP3:
985                     PUTCHAR(EAPT_SRP, outp);
986                     PUTCHAR(EAPSRP_SVALIDATOR, outp);
987                     PUTLONG(SRPVAL_EBIT, outp);
988                     ts = (struct t_server *)esp->es_server.ea_session;
989                     assert(ts != NULL);
990                     BCOPY(t_serverresponse(ts), outp, SHA_DIGEST_LENGTH);
991                     INCPTR(SHA_DIGEST_LENGTH, outp);
992 
993                     if (pncrypt_getkey(0, key, keylen)) {
994                               /* Generate pseudonym */
995                               optr = outp;
996                               cp = (unsigned char *)esp->es_server.ea_peer;
997                               if ((j = i = esp->es_server.ea_peerlen) > 7)
998                                         j = 7;
999                               clear[0] = i;
1000                               BCOPY(cp, clear + 1, j);
1001                               i -= j;
1002                               cp += j;
1003 
1004                               if (!DesEncrypt(clear, key, cipher)) {
1005                                         dbglog("no DES here; not generating pseudonym");
1006                                         break;
1007             }
1008 
1009                               BZERO(&b64, sizeof (b64));
1010                               outp++;             /* space for pseudonym length */
1011                               outp += b64enc(&b64, cipher, 8, outp);
1012                               while (i >= 8) {
1013                                         DesEncrypt(cp, key, cipher);
1014                                         outp += b64enc(&b64, cipher, 8, outp);
1015                                         cp += 8;
1016                                         i -= 8;
1017                               }
1018                               if (i > 0) {
1019                                         BCOPY(cp, clear, i);
1020                                         cp += i;
1021                                         while (i < 8) {
1022                                                   *cp++ = drand48() * 0x100;
1023                                                   i++;
1024                                         }
1025 
1026                                         DesEncrypt(clear, key, cipher);
1027                                         outp += b64enc(&b64, cipher, 8, outp);
1028                               }
1029                               outp += b64flush(&b64, outp);
1030 
1031                               /* Set length and pad out to next 20 octet boundary */
1032                               i = outp - optr - 1;
1033                               *optr = i;
1034                               i %= SHA_DIGEST_LENGTH;
1035                               if (i != 0) {
1036                                         while (i < SHA_DIGEST_LENGTH) {
1037                                                   *outp++ = drand48() * 0x100;
1038                                                   i++;
1039                                         }
1040                               }
1041 
1042                               /* Obscure the pseudonym with SHA1 hash */
1043                               ctxt = PPP_MD_CTX_new();
1044                               if (ctxt) {
1045 
1046                                         PPP_DigestInit(ctxt, PPP_sha1());
1047                                         PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1);
1048                                         PPP_DigestUpdate(ctxt, &esp->es_server.ea_skey,
1049                                                   SESSION_KEY_LEN);
1050                                         PPP_DigestUpdate(ctxt,  esp->es_server.ea_peer,
1051                                                   esp->es_server.ea_peerlen);
1052                                         while (optr < outp) {
1053                                                   diglen = SHA_DIGEST_LENGTH;
1054                                                   PPP_DigestFinal(ctxt, dig, &diglen);
1055                                                   cp = dig;
1056                                                   while (cp < dig + SHA_DIGEST_LENGTH)
1057                                                             *optr++ ^= *cp++;
1058 
1059                                                   PPP_DigestInit(ctxt, PPP_sha1());
1060                                                   PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1);
1061                                                   PPP_DigestUpdate(ctxt, esp->es_server.ea_skey,
1062                                                             SESSION_KEY_LEN);
1063                                                   PPP_DigestUpdate(ctxt, optr - SHA_DIGEST_LENGTH,
1064                                                             SHA_DIGEST_LENGTH);
1065                                         }
1066 
1067                                         PPP_MD_CTX_free(ctxt);
1068                               }
1069                     }
1070                     break;
1071 
1072           case eapSRP4:
1073                     PUTCHAR(EAPT_SRP, outp);
1074                     PUTCHAR(EAPSRP_LWRECHALLENGE, outp);
1075                     challen = MIN_CHALLENGE_LENGTH +
1076                         ((MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH) * drand48());
1077                     esp->es_challen = challen;
1078                     ptr = esp->es_challenge;
1079                     while (--challen >= 0)
1080                               *ptr++ = drand48() * 0x100;
1081                     BCOPY(esp->es_challenge, outp, esp->es_challen);
1082                     INCPTR(esp->es_challen, outp);
1083                     break;
1084 #endif /* PPP_WITH_SRP */
1085 
1086           default:
1087                     return;
1088           }
1089 
1090           outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1091           PUTSHORT(outlen, lenloc);
1092 
1093           output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
1094 
1095           esp->es_server.ea_requests++;
1096 
1097           if (esp->es_server.ea_timeout > 0)
1098                     TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
1099 }
1100 
1101 /*
1102  * eap_authpeer - Authenticate our peer (behave as server).
1103  *
1104  * Start server state and send first request.  This is called only
1105  * after eap_lowerup.
1106  */
1107 void
eap_authpeer(int unit,char * localname)1108 eap_authpeer(int unit, char *localname)
1109 {
1110           eap_state *esp = &eap_states[unit];
1111 
1112           /* Save the name we're given. */
1113           esp->es_server.ea_name = localname;
1114           esp->es_server.ea_namelen = strlen(localname);
1115 
1116           esp->es_savedtime = esp->es_server.ea_timeout;
1117 
1118           /* Lower layer up yet? */
1119           if (esp->es_server.ea_state == eapInitial ||
1120               esp->es_server.ea_state == eapPending) {
1121                     esp->es_server.ea_state = eapPending;
1122                     return;
1123           }
1124 
1125           esp->es_server.ea_state = eapPending;
1126 
1127           /* ID number not updated here intentionally; hashed into M1 */
1128           eap_send_request(esp);
1129 }
1130 
1131 /*
1132  * eap_server_timeout - Retransmission timer for sending Requests
1133  * expired.
1134  */
1135 static void
eap_server_timeout(void * arg)1136 eap_server_timeout(void *arg)
1137 {
1138 #ifdef PPP_WITH_EAPTLS
1139           u_char *outp;
1140           u_char *lenloc;
1141           int outlen;
1142 #endif /* PPP_WITH_EAPTLS */
1143 
1144           eap_state *esp = (eap_state *) arg;
1145 
1146           if (!eap_server_active(esp))
1147                     return;
1148 
1149 #ifdef PPP_WITH_EAPTLS
1150           switch(esp->es_server.ea_prev_state) {
1151 
1152           /*
1153            *  In eap-tls the state changes after a request, so we return to
1154            *  previous state ...
1155            */
1156           case(eapTlsStart):
1157           case(eapTlsSendAck):
1158                     esp->es_server.ea_state = esp->es_server.ea_prev_state;
1159                     break;
1160 
1161           /*
1162            *  ... or resend the stored data
1163            */
1164           case(eapTlsSend):
1165           case(eapTlsSendAlert):
1166                     outp = outpacket_buf;
1167                     MAKEHEADER(outp, PPP_EAP);
1168                     PUTCHAR(EAP_REQUEST, outp);
1169                     PUTCHAR(esp->es_server.ea_id, outp);
1170                     lenloc = outp;
1171                     INCPTR(2, outp);
1172 
1173                     eaptls_retransmit(esp->es_server.ea_session, &outp);
1174 
1175                     outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1176                     PUTSHORT(outlen, lenloc);
1177                     output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
1178                     esp->es_server.ea_requests++;
1179 
1180                     if (esp->es_server.ea_timeout > 0)
1181                               TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
1182 
1183                     return;
1184           default:
1185                     break;
1186           }
1187 #endif /* PPP_WITH_EAPTLS */
1188 
1189           /* EAP ID number must not change on timeout. */
1190           eap_send_request(esp);
1191 }
1192 
1193 /*
1194  * When it's time to send rechallenge the peer, this timeout is
1195  * called.  Once the rechallenge is successful, the response handler
1196  * will restart the timer.  If it fails, then the link is dropped.
1197  */
1198 static void
eap_rechallenge(void * arg)1199 eap_rechallenge(void *arg)
1200 {
1201           eap_state *esp = (eap_state *)arg;
1202 
1203           if (esp->es_server.ea_state != eapOpen &&
1204               esp->es_server.ea_state != eapSRP4)
1205                     return;
1206 
1207           esp->es_server.ea_requests = 0;
1208           esp->es_server.ea_state = eapIdentify;
1209           eap_figure_next_state(esp, 0);
1210           esp->es_server.ea_id++;
1211           eap_send_request(esp);
1212 }
1213 
1214 static void
srp_lwrechallenge(void * arg)1215 srp_lwrechallenge(void *arg)
1216 {
1217           eap_state *esp = (eap_state *)arg;
1218 
1219           if (esp->es_server.ea_state != eapOpen ||
1220               esp->es_server.ea_type != EAPT_SRP)
1221                     return;
1222 
1223           esp->es_server.ea_requests = 0;
1224           esp->es_server.ea_state = eapSRP4;
1225           esp->es_server.ea_id++;
1226           eap_send_request(esp);
1227 }
1228 
1229 /*
1230  * eap_lowerup - The lower layer is now up.
1231  *
1232  * This is called before either eap_authpeer or eap_authwithpeer.  See
1233  * link_established() in auth.c.  All that's necessary here is to
1234  * return to closed state so that those two routines will do the right
1235  * thing.
1236  */
1237 static void
eap_lowerup(int unit)1238 eap_lowerup(int unit)
1239 {
1240           eap_state *esp = &eap_states[unit];
1241 
1242           /* Discard any (possibly authenticated) peer name. */
1243           if (esp->es_server.ea_peer != NULL &&
1244               esp->es_server.ea_peer != remote_name)
1245                     free(esp->es_server.ea_peer);
1246           esp->es_server.ea_peer = NULL;
1247           if (esp->es_client.ea_peer != NULL)
1248                     free(esp->es_client.ea_peer);
1249           esp->es_client.ea_peer = NULL;
1250 
1251           esp->es_client.ea_state = eapClosed;
1252           esp->es_server.ea_state = eapClosed;
1253 }
1254 
1255 /*
1256  * eap_lowerdown - The lower layer is now down.
1257  *
1258  * Cancel all timeouts and return to initial state.
1259  */
1260 static void
eap_lowerdown(int unit)1261 eap_lowerdown(int unit)
1262 {
1263           eap_state *esp = &eap_states[unit];
1264 
1265           if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) {
1266                     UNTIMEOUT(eap_client_timeout, (void *)esp);
1267           }
1268           if (eap_server_active(esp)) {
1269                     if (esp->es_server.ea_timeout > 0) {
1270                               UNTIMEOUT(eap_server_timeout, (void *)esp);
1271                     }
1272           } else {
1273                     if ((esp->es_server.ea_state == eapOpen ||
1274                         esp->es_server.ea_state == eapSRP4) &&
1275                         esp->es_rechallenge > 0) {
1276                               UNTIMEOUT(eap_rechallenge, (void *)esp);
1277                     }
1278                     if (esp->es_server.ea_state == eapOpen &&
1279                         esp->es_lwrechallenge > 0) {
1280                               UNTIMEOUT(srp_lwrechallenge, (void *)esp);
1281                     }
1282           }
1283 
1284           esp->es_client.ea_state = esp->es_server.ea_state = eapInitial;
1285           esp->es_client.ea_requests = esp->es_server.ea_requests = 0;
1286 }
1287 
1288 /*
1289  * eap_protrej - Peer doesn't speak this protocol.
1290  *
1291  * This shouldn't happen.  If it does, it represents authentication
1292  * failure.
1293  */
1294 static void
eap_protrej(int unit)1295 eap_protrej(int unit)
1296 {
1297           eap_state *esp = &eap_states[unit];
1298 
1299           if (eap_client_active(esp)) {
1300                     error("EAP authentication failed due to Protocol-Reject");
1301                     auth_withpeer_fail(unit, PPP_EAP);
1302           }
1303           if (eap_server_active(esp)) {
1304                     error("EAP authentication of peer failed on Protocol-Reject");
1305                     auth_peer_fail(unit, PPP_EAP);
1306           }
1307           eap_lowerdown(unit);
1308 }
1309 
1310 /*
1311  * Format and send a regular EAP Response message.
1312  */
1313 static void
eap_send_response(eap_state * esp,u_char id,u_char typenum,u_char * str,int lenstr)1314 eap_send_response(eap_state *esp, u_char id, u_char typenum,
1315                       u_char *str, int lenstr)
1316 {
1317           u_char *outp;
1318           int msglen;
1319 
1320           outp = outpacket_buf;
1321 
1322           MAKEHEADER(outp, PPP_EAP);
1323 
1324           PUTCHAR(EAP_RESPONSE, outp);
1325           PUTCHAR(id, outp);
1326           esp->es_client.ea_id = id;
1327           msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr;
1328           PUTSHORT(msglen, outp);
1329           PUTCHAR(typenum, outp);
1330           if (lenstr > 0) {
1331                     BCOPY(str, outp, lenstr);
1332           }
1333 
1334           output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1335 }
1336 
1337 /*
1338  * Format and send an MD5-Challenge EAP Response message.
1339  */
1340 static void
eap_chap_response(eap_state * esp,u_char id,u_char * hash,char * name,int namelen)1341 eap_chap_response(eap_state *esp, u_char id, u_char *hash,
1342                       char *name, int namelen)
1343 {
1344           u_char *outp;
1345           int msglen;
1346 
1347           outp = outpacket_buf;
1348 
1349           MAKEHEADER(outp, PPP_EAP);
1350 
1351           PUTCHAR(EAP_RESPONSE, outp);
1352           PUTCHAR(id, outp);
1353           esp->es_client.ea_id = id;
1354           msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_DIGEST_LENGTH +
1355               namelen;
1356           PUTSHORT(msglen, outp);
1357           PUTCHAR(EAPT_MD5CHAP, outp);
1358           PUTCHAR(MD5_DIGEST_LENGTH, outp);
1359           BCOPY(hash, outp, MD5_DIGEST_LENGTH);
1360           INCPTR(MD5_DIGEST_LENGTH, outp);
1361           if (namelen > 0) {
1362                     BCOPY(name, outp, namelen);
1363           }
1364 
1365           output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1366 }
1367 
1368 #ifdef PPP_WITH_SRP
1369 /*
1370  * Format and send a SRP EAP Response message.
1371  */
1372 static void
eap_srp_response(eap_state * esp,u_char id,u_char subtypenum,u_char * str,int lenstr)1373 eap_srp_response(eap_state *esp, u_char id, u_char subtypenum,
1374                      u_char *str, int lenstr)
1375 {
1376           u_char *outp;
1377           int msglen;
1378 
1379           outp = outpacket_buf;
1380 
1381           MAKEHEADER(outp, PPP_EAP);
1382 
1383           PUTCHAR(EAP_RESPONSE, outp);
1384           PUTCHAR(id, outp);
1385           esp->es_client.ea_id = id;
1386           msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr;
1387           PUTSHORT(msglen, outp);
1388           PUTCHAR(EAPT_SRP, outp);
1389           PUTCHAR(subtypenum, outp);
1390           if (lenstr > 0) {
1391                     BCOPY(str, outp, lenstr);
1392           }
1393 
1394           output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1395 }
1396 
1397 /*
1398  * Format and send a SRP EAP Client Validator Response message.
1399  */
1400 static void
eap_srpval_response(eap_state * esp,u_char id,u_int32_t flags,u_char * str)1401 eap_srpval_response(eap_state *esp, u_char id, u_int32_t flags, u_char *str)
1402 {
1403           u_char *outp;
1404           int msglen;
1405 
1406           outp = outpacket_buf;
1407 
1408           MAKEHEADER(outp, PPP_EAP);
1409 
1410           PUTCHAR(EAP_RESPONSE, outp);
1411           PUTCHAR(id, outp);
1412           esp->es_client.ea_id = id;
1413           msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) +
1414               SHA_DIGEST_LENGTH;
1415           PUTSHORT(msglen, outp);
1416           PUTCHAR(EAPT_SRP, outp);
1417           PUTCHAR(EAPSRP_CVALIDATOR, outp);
1418           PUTLONG(flags, outp);
1419           BCOPY(str, outp, SHA_DIGEST_LENGTH);
1420 
1421           output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1422 }
1423 #endif /* PPP_WITH_SRP */
1424 
1425 #ifdef PPP_WITH_EAPTLS
1426 /*
1427  * Send an EAP-TLS response message with tls data
1428  */
1429 static void
eap_tls_response(eap_state * esp,u_char id)1430 eap_tls_response(eap_state *esp, u_char id)
1431 {
1432           u_char *outp;
1433           int outlen;
1434           u_char *lenloc;
1435 
1436           outp = outpacket_buf;
1437 
1438           MAKEHEADER(outp, PPP_EAP);
1439 
1440           PUTCHAR(EAP_RESPONSE, outp);
1441           PUTCHAR(id, outp);
1442 
1443           lenloc = outp;
1444           INCPTR(2, outp);
1445 
1446           /*
1447              If the id in the request is unchanged, we must retransmit
1448              the old data
1449           */
1450           if(id == esp->es_client.ea_id)
1451                     eaptls_retransmit(esp->es_client.ea_session, &outp);
1452           else
1453                     eaptls_send(esp->es_client.ea_session, &outp);
1454 
1455           outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1456           PUTSHORT(outlen, lenloc);
1457 
1458           output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1459 
1460           esp->es_client.ea_id = id;
1461 }
1462 
1463 /*
1464  * Send an EAP-TLS ack
1465  */
1466 static void
eap_tls_sendack(eap_state * esp,u_char id)1467 eap_tls_sendack(eap_state *esp, u_char id)
1468 {
1469           u_char *outp;
1470           int outlen;
1471           u_char *lenloc;
1472 
1473           outp = outpacket_buf;
1474 
1475           MAKEHEADER(outp, PPP_EAP);
1476 
1477           PUTCHAR(EAP_RESPONSE, outp);
1478           PUTCHAR(id, outp);
1479           esp->es_client.ea_id = id;
1480 
1481           lenloc = outp;
1482           INCPTR(2, outp);
1483 
1484           PUTCHAR(EAPT_TLS, outp);
1485           PUTCHAR(0, outp);
1486 
1487           outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1488           PUTSHORT(outlen, lenloc);
1489 
1490           output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1491 }
1492 #endif /* PPP_WITH_EAPTLS */
1493 
1494 static void
eap_send_nak(eap_state * esp,u_char id,u_char type)1495 eap_send_nak(eap_state *esp, u_char id, u_char type)
1496 {
1497           u_char *outp;
1498           int msglen;
1499 
1500           outp = outpacket_buf;
1501 
1502           MAKEHEADER(outp, PPP_EAP);
1503 
1504           PUTCHAR(EAP_RESPONSE, outp);
1505           PUTCHAR(id, outp);
1506           esp->es_client.ea_id = id;
1507           msglen = EAP_HEADERLEN + 2 * sizeof (u_char);
1508           PUTSHORT(msglen, outp);
1509           PUTCHAR(EAPT_NAK, outp);
1510           PUTCHAR(type, outp);
1511 
1512           output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1513 }
1514 
1515 #ifdef PPP_WITH_SRP
1516 static char *
name_of_pn_file(void)1517 name_of_pn_file(void)
1518 {
1519           char *user, *path, *file;
1520           struct passwd *pw;
1521           size_t pl;
1522           static bool pnlogged = 0;
1523 
1524           pw = getpwuid(getuid());
1525           if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
1526                     errno = EINVAL;
1527                     return (NULL);
1528           }
1529           file = PPP_PATH_PSEUDONYM;
1530           pl = strlen(user) + strlen(file) + 2;
1531           path = malloc(pl);
1532           if (path == NULL)
1533                     return (NULL);
1534           (void) slprintf(path, pl, "%s/%s", user, file);
1535           if (!pnlogged) {
1536                     dbglog("pseudonym file: %s", path);
1537                     pnlogged = 1;
1538           }
1539           return (path);
1540 }
1541 
1542 static int
open_pn_file(mode_t modebits)1543 open_pn_file(mode_t modebits)
1544 {
1545           char *path;
1546           int fd, err;
1547 
1548           if ((path = name_of_pn_file()) == NULL)
1549                     return (-1);
1550           fd = open(path, modebits, S_IRUSR | S_IWUSR);
1551           err = errno;
1552           free(path);
1553           errno = err;
1554           return (fd);
1555 }
1556 
1557 static void
remove_pn_file(void)1558 remove_pn_file(void)
1559 {
1560           char *path;
1561 
1562           if ((path = name_of_pn_file()) != NULL) {
1563                     (void) unlink(path);
1564                     (void) free(path);
1565           }
1566 }
1567 
1568 static void
write_pseudonym(eap_state * esp,u_char * inp,int len,int id)1569 write_pseudonym(eap_state *esp, u_char *inp, int len, int id)
1570 {
1571           u_char val;
1572           u_char *datp, *digp;
1573           PPP_MD_CTX *ctxt;
1574           u_char dig[SHA_DIGEST_LENGTH];
1575           int dsize, fd, olen = len, diglen = sizeof(dig);
1576 
1577           /*
1578            * Do the decoding by working backwards.  This eliminates the need
1579            * to save the decoded output in a separate buffer.
1580            */
1581           val = id;
1582           while (len > 0) {
1583                     if ((dsize = len % SHA_DIGEST_LENGTH) == 0)
1584                               dsize = SHA_DIGEST_LENGTH;
1585                     len -= dsize;
1586                     datp = inp + len;
1587                     ctxt = PPP_MD_CTX_new();
1588                     if (ctxt) {
1589 
1590                               PPP_DigestInit(ctxt, PPP_sha1());
1591                               PPP_DigestUpdate(ctxt, &val, 1);
1592                               PPP_DigestUpdate(ctxt, esp->es_client.ea_skey,
1593                                                   SESSION_KEY_LEN);
1594                               if (len > 0) {
1595                                         PPP_DigestUpdate(ctxt, datp, SHA_DIGEST_LENGTH);
1596                               } else {
1597                                         PPP_DigestUpdate(ctxt, esp->es_client.ea_name,
1598                                                   esp->es_client.ea_namelen);
1599                               }
1600                               PPP_DigestFinal(ctxt, dig, &diglen);
1601 
1602                               for (digp = dig; digp < dig + SHA_DIGEST_LENGTH; digp++)
1603                                         *datp++ ^= *digp;
1604 
1605                               PPP_MD_CTX_free(ctxt);
1606                     }
1607           }
1608 
1609           /* Now check that the result is sane */
1610           if (olen <= 0 || *inp + 1 > olen) {
1611                     dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp);
1612                     return;
1613           }
1614 
1615           /* Save it away */
1616           fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);
1617           if (fd < 0) {
1618                     dbglog("EAP: error saving pseudonym: %m");
1619                     return;
1620           }
1621           len = write(fd, inp + 1, *inp);
1622           if (close(fd) != -1 && len == *inp) {
1623                     dbglog("EAP: saved pseudonym");
1624                     esp->es_usedpseudo = 0;
1625           } else {
1626                     dbglog("EAP: failed to save pseudonym");
1627                     remove_pn_file();
1628           }
1629 }
1630 #endif /* PPP_WITH_SRP */
1631 
1632 #if PPP_WITH_CHAPMS
1633 /*
1634  * Format and send an CHAPV2-Challenge EAP Response message.
1635  */
1636 static void
eap_chapv2_response(eap_state * esp,u_char id,u_char chapid,u_char * response,char * user,int user_len)1637 eap_chapv2_response(eap_state *esp, u_char id, u_char chapid, u_char *response, char *user, int user_len)
1638 {
1639     u_char *outp;
1640     int msglen;
1641 
1642     outp = outpacket_buf;
1643 
1644     MAKEHEADER(outp, PPP_EAP);
1645 
1646     PUTCHAR(EAP_RESPONSE, outp);
1647     PUTCHAR(id, outp);
1648     esp->es_client.ea_id = id;
1649     msglen = EAP_HEADERLEN + 6 * sizeof (u_char) + MS_CHAP2_RESPONSE_LEN + user_len;
1650     PUTSHORT(msglen, outp);
1651     PUTCHAR(EAPT_MSCHAPV2, outp);
1652     PUTCHAR(CHAP_RESPONSE, outp);
1653     PUTCHAR(chapid, outp);
1654     PUTCHAR(0, outp);
1655     /* len */
1656     PUTCHAR(5 + user_len + MS_CHAP2_RESPONSE_LEN, outp);
1657     BCOPY(response, outp, MS_CHAP2_RESPONSE_LEN+1); // VLEN + VALUE
1658     INCPTR(MS_CHAP2_RESPONSE_LEN+1, outp);
1659     BCOPY(user, outp, user_len);
1660 
1661     output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1662 }
1663 #endif
1664 
1665 /*
1666  * eap_request - Receive EAP Request message (client mode).
1667  */
1668 static void
eap_request(eap_state * esp,u_char * inp,int id,int len)1669 eap_request(eap_state *esp, u_char *inp, int id, int len)
1670 {
1671           u_char typenum;
1672           u_char vallen;
1673           int secret_len;
1674           char secret[MAXWORDLEN];
1675           char rhostname[256];
1676           PPP_MD_CTX *mdctx;
1677           u_char hash[MD5_DIGEST_LENGTH];
1678           int hashlen = MD5_DIGEST_LENGTH;
1679 #ifdef PPP_WITH_EAPTLS
1680           u_char flags;
1681           struct eaptls_session *ets = esp->es_client.ea_session;
1682 #endif /* PPP_WITH_EAPTLS */
1683 
1684 #ifdef PPP_WITH_SRP
1685           struct t_client *tc;
1686           struct t_num sval, gval, Nval, *Ap, Bval;
1687           u_char vals[2];
1688           PPP_MD_CTX *ctxt;
1689           u_char dig[SHA_DIGEST_LENGTH];
1690           int diglen = sizeof(dig);
1691           int fd;
1692 #endif /* PPP_WITH_SRP */
1693 
1694           /*
1695            * Ignore requests if we're not open
1696            */
1697           if (esp->es_client.ea_state <= eapClosed)
1698                     return;
1699 
1700           /*
1701            * Note: we update es_client.ea_id *only if* a Response
1702            * message is being generated.  Otherwise, we leave it the
1703            * same for duplicate detection purposes.
1704            */
1705 
1706           esp->es_client.ea_requests++;
1707           if (esp->es_client.ea_maxrequests != 0 &&
1708               esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {
1709                     info("EAP: received too many Request messages");
1710                     if (esp->es_client.ea_timeout > 0) {
1711                               UNTIMEOUT(eap_client_timeout, (void *)esp);
1712                     }
1713                     auth_withpeer_fail(esp->es_unit, PPP_EAP);
1714                     return;
1715           }
1716 
1717           if (len <= 0) {
1718                     error("EAP: empty Request message discarded");
1719                     return;
1720           }
1721 
1722           GETCHAR(typenum, inp);
1723           len--;
1724 
1725           switch (typenum) {
1726           case EAPT_IDENTITY:
1727                     if (len > 0)
1728                               info("EAP: Identity prompt \"%.*q\"", len, inp);
1729 #ifdef PPP_WITH_SRP
1730                     if (esp->es_usepseudo &&
1731                         (esp->es_usedpseudo == 0 ||
1732                               (esp->es_usedpseudo == 1 &&
1733                                   id == esp->es_client.ea_id))) {
1734                               esp->es_usedpseudo = 1;
1735                               /* Try to get a pseudonym */
1736                               if ((fd = open_pn_file(O_RDONLY)) >= 0) {
1737                                         strcpy(rhostname, SRP_PSEUDO_ID);
1738                                         len = read(fd, rhostname + SRP_PSEUDO_LEN,
1739                                             sizeof (rhostname) - SRP_PSEUDO_LEN);
1740                                         /* XXX NAI unsupported */
1741                                         if (len > 0) {
1742                                                   eap_send_response(esp, id, typenum,
1743                                                       rhostname, len + SRP_PSEUDO_LEN);
1744                                         }
1745                                         (void) close(fd);
1746                                         if (len > 0)
1747                                                   break;
1748                               }
1749                     }
1750                     /* Stop using pseudonym now. */
1751                     if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
1752                               remove_pn_file();
1753                               esp->es_usedpseudo = 2;
1754                     }
1755 #endif /* PPP_WITH_SRP */
1756                     eap_send_response(esp, id, typenum, (u_char *)esp->es_client.ea_name,
1757                         esp->es_client.ea_namelen);
1758                     break;
1759 
1760           case EAPT_NOTIFICATION:
1761                     if (len > 0)
1762                               info("EAP: Notification \"%.*q\"", len, inp);
1763                     eap_send_response(esp, id, typenum, NULL, 0);
1764                     break;
1765 
1766           case EAPT_NAK:
1767                     /*
1768                      * Avoid the temptation to send Response Nak in reply
1769                      * to Request Nak here.  It can only lead to trouble.
1770                      */
1771                     warn("EAP: unexpected Nak in Request; ignored");
1772                     /* Return because we're waiting for something real. */
1773                     return;
1774 
1775           case EAPT_MD5CHAP:
1776                     if (len < 1) {
1777                               error("EAP: received MD5-Challenge with no data");
1778                               /* Bogus request; wait for something real. */
1779                               return;
1780                     }
1781                     GETCHAR(vallen, inp);
1782                     len--;
1783                     if (vallen < 8 || vallen > len) {
1784                               error("EAP: MD5-Challenge with bad length %d (8..%d)",
1785                                   vallen, len);
1786                               /* Try something better. */
1787                               eap_send_nak(esp, id, EAPT_SRP);
1788                               break;
1789                     }
1790 
1791                     /* Not so likely to happen. */
1792                     if (len - vallen >= sizeof (rhostname)) {
1793                               dbglog("EAP: trimming really long peer name down");
1794                               BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1795                               rhostname[sizeof (rhostname) - 1] = '\0';
1796                     } else {
1797                               BCOPY(inp + vallen, rhostname, len - vallen);
1798                               rhostname[len - vallen] = '\0';
1799                     }
1800 
1801                     /* In case the remote doesn't give us his name. */
1802                     if (explicit_remote ||
1803                         (remote_name[0] != '\0' && vallen == len))
1804                               strlcpy(rhostname, remote_name, sizeof (rhostname));
1805 
1806                     /*
1807                      * Get the secret for authenticating ourselves with
1808                      * the specified host.
1809                      */
1810                     if (!get_secret(esp->es_unit, esp->es_client.ea_name,
1811                         rhostname, secret, &secret_len, 0)) {
1812                               dbglog("EAP: no MD5 secret for auth to %q", rhostname);
1813                               eap_send_nak(esp, id, EAPT_SRP);
1814                               break;
1815                     }
1816 
1817                     mdctx = PPP_MD_CTX_new();
1818                     if (mdctx != NULL) {
1819                               if (PPP_DigestInit(mdctx, PPP_md5())) {
1820                                         typenum = id;
1821                                         if (PPP_DigestUpdate(mdctx, &typenum, 1)) {
1822                                                   if (PPP_DigestUpdate(mdctx, secret, secret_len)) {
1823                                                             BZERO(secret, sizeof(secret));
1824                                                             if (PPP_DigestUpdate(mdctx, inp, vallen)) {
1825                                                                       if (PPP_DigestFinal(mdctx, hash, &hashlen)) {
1826                                                                                 eap_chap_response(esp, id, hash, esp->es_client.ea_name,
1827                                                                                                     esp->es_client.ea_namelen);
1828                                                                                 PPP_MD_CTX_free(mdctx);
1829                                                                                 break;
1830                                                                       }
1831                                                             }
1832                                                   }
1833                                         }
1834                               }
1835                               PPP_MD_CTX_free(mdctx);
1836                     }
1837                     dbglog("EAP: Invalid MD5 checksum");
1838         eap_send_nak(esp, id, EAPT_SRP);
1839                     break;
1840 
1841 #ifdef PPP_WITH_EAPTLS
1842           case EAPT_TLS:
1843 
1844                     switch(esp->es_client.ea_state) {
1845 
1846                     case eapListen:
1847 
1848                               if (len < 1) {
1849                                         error("EAP: received EAP-TLS Listen packet with no data");
1850                                         /* Bogus request; wait for something real. */
1851                                         return;
1852                               }
1853                               GETCHAR(flags, inp);
1854                               if(flags & EAP_TLS_FLAGS_START){
1855 
1856                                         esp->es_client.ea_using_eaptls = 1;
1857 
1858                                         if (explicit_remote){
1859                                                   esp->es_client.ea_peer = strdup(remote_name);
1860                                                   esp->es_client.ea_peerlen = strlen(remote_name);
1861                                         } else
1862                                                   esp->es_client.ea_peer = NULL;
1863 
1864                                         /* Init ssl session */
1865                                         if(!eaptls_init_ssl_client(esp)) {
1866                                                   dbglog("cannot init ssl");
1867                                                   eap_send_nak(esp, id, EAPT_MSCHAPV2);
1868                                                   esp->es_client.ea_using_eaptls = 0;
1869                                                   break;
1870                                         }
1871 
1872                                         ets = esp->es_client.ea_session;
1873                                         eap_tls_response(esp, id);
1874                                         esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1875                                         break;
1876                               }
1877 
1878                               /* The server has sent a bad start packet. */
1879                               eap_send_nak(esp, id, EAPT_MSCHAPV2);
1880                               break;
1881 
1882                     case eapTlsRecvAck:
1883                               eap_tls_response(esp, id);
1884                               esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1885                               break;
1886 
1887                     case eapTlsRecv:
1888                               if (len < 1) {
1889                                         error("EAP: discarding EAP-TLS Receive packet with no data");
1890                                         /* Bogus request; wait for something real. */
1891                                         return;
1892                               }
1893                               eaptls_receive(ets, inp, len);
1894 
1895                               if(ets->frag) {
1896                                         eap_tls_sendack(esp, id);
1897                                         esp->es_client.ea_state = eapTlsRecv;
1898                                         break;
1899                               }
1900 
1901                               if(ets->alert_recv) {
1902                                         eap_tls_sendack(esp, id);
1903                                         esp->es_client.ea_state = eapTlsRecvFailure;
1904                                         break;
1905                               }
1906 
1907                               /* Check if TLS handshake is finished */
1908                               if(eaptls_is_init_finished(ets)) {
1909 #ifdef PPP_WITH_MPPE
1910                                         eaptls_gen_mppe_keys(ets, 1);
1911 #endif
1912                                         eaptls_free_session(ets);
1913                                         eap_tls_sendack(esp, id);
1914                                         esp->es_client.ea_state = eapTlsRecvSuccess;
1915                                         break;
1916                               }
1917 
1918                               eap_tls_response(esp,id);
1919                               esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1920                               break;
1921 
1922                     default:
1923                               eap_send_nak(esp, id, EAPT_MSCHAPV2);
1924                               esp->es_client.ea_using_eaptls = 0;
1925                               break;
1926                     }
1927 
1928                     break;
1929 #endif /* PPP_WITH_EAPTLS */
1930 
1931 #ifdef PPP_WITH_SRP
1932           case EAPT_SRP:
1933                     if (len < 1) {
1934                               error("EAP: received empty SRP Request");
1935                               /* Bogus request; wait for something real. */
1936                               return;
1937                     }
1938 
1939                     /* Get subtype */
1940                     GETCHAR(vallen, inp);
1941                     len--;
1942                     switch (vallen) {
1943                     case EAPSRP_CHALLENGE:
1944                               tc = NULL;
1945                               if (esp->es_client.ea_session != NULL) {
1946                                         tc = (struct t_client *)esp->es_client.
1947                                             ea_session;
1948                                         /*
1949                                          * If this is a new challenge, then start
1950                                          * over with a new client session context.
1951                                          * Otherwise, just resend last response.
1952                                          */
1953                                         if (id != esp->es_client.ea_id) {
1954                                                   t_clientclose(tc);
1955                                                   esp->es_client.ea_session = NULL;
1956                                                   tc = NULL;
1957                                         }
1958                               }
1959                               /* No session key just yet */
1960                               esp->es_client.ea_skey = NULL;
1961                               if (tc == NULL) {
1962                                         GETCHAR(vallen, inp);
1963                                         len--;
1964                                         if (vallen >= len) {
1965                                                   error("EAP: badly-formed SRP Challenge"
1966                                                       " (name)");
1967                                                   /* Ignore badly-formed messages */
1968                                                   return;
1969                                         }
1970                                         BCOPY(inp, rhostname, vallen);
1971                                         rhostname[vallen] = '\0';
1972                                         INCPTR(vallen, inp);
1973                                         len -= vallen;
1974 
1975                                         /*
1976                                          * In case the remote doesn't give us his name,
1977                                          * use configured name.
1978                                          */
1979                                         if (explicit_remote ||
1980                                             (remote_name[0] != '\0' && vallen == 0)) {
1981                                                   strlcpy(rhostname, remote_name,
1982                                                       sizeof (rhostname));
1983                                         }
1984 
1985                                         if (esp->es_client.ea_peer != NULL)
1986                                                   free(esp->es_client.ea_peer);
1987                                         esp->es_client.ea_peer = strdup(rhostname);
1988                                         esp->es_client.ea_peerlen = strlen(rhostname);
1989 
1990                                         GETCHAR(vallen, inp);
1991                                         len--;
1992                                         if (vallen >= len) {
1993                                                   error("EAP: badly-formed SRP Challenge"
1994                                                       " (s)");
1995                                                   /* Ignore badly-formed messages */
1996                                                   return;
1997                                         }
1998                                         sval.data = inp;
1999                                         sval.len = vallen;
2000                                         INCPTR(vallen, inp);
2001                                         len -= vallen;
2002 
2003                                         GETCHAR(vallen, inp);
2004                                         len--;
2005                                         if (vallen > len) {
2006                                                   error("EAP: badly-formed SRP Challenge"
2007                                                       " (g)");
2008                                                   /* Ignore badly-formed messages */
2009                                                   return;
2010                                         }
2011                                         /* If no generator present, then use value 2 */
2012                                         if (vallen == 0) {
2013                                                   gval.data = (u_char *)"\002";
2014                                                   gval.len = 1;
2015                                         } else {
2016                                                   gval.data = inp;
2017                                                   gval.len = vallen;
2018                                         }
2019                                         INCPTR(vallen, inp);
2020                                         len -= vallen;
2021 
2022                                         /*
2023                                          * If no modulus present, then use well-known
2024                                          * value.
2025                                          */
2026                                         if (len == 0) {
2027                                                   Nval.data = (u_char *)wkmodulus;
2028                                                   Nval.len = sizeof (wkmodulus);
2029                                         } else {
2030                                                   Nval.data = inp;
2031                                                   Nval.len = len;
2032                                         }
2033                                         tc = t_clientopen(esp->es_client.ea_name,
2034                                             &Nval, &gval, &sval);
2035                                         if (tc == NULL) {
2036                                                   eap_send_nak(esp, id, EAPT_MD5CHAP);
2037                                                   break;
2038                                         }
2039                                         esp->es_client.ea_session = (void *)tc;
2040 
2041                                         /* Add Challenge ID & type to verifier */
2042                                         vals[0] = id;
2043                                         vals[1] = EAPT_SRP;
2044                                         t_clientaddexdata(tc, vals, 2);
2045                               }
2046                               Ap = t_clientgenexp(tc);
2047                               eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
2048                                   Ap->len);
2049                               break;
2050 
2051                     case EAPSRP_SKEY:
2052                               tc = (struct t_client *)esp->es_client.ea_session;
2053                               if (tc == NULL) {
2054                                         warn("EAP: peer sent Subtype 2 without 1");
2055                                         eap_send_nak(esp, id, EAPT_MD5CHAP);
2056                                         break;
2057                               }
2058                               if (esp->es_client.ea_skey != NULL) {
2059                                         /*
2060                                          * ID number should not change here.  Warn
2061                                          * if it does (but otherwise ignore).
2062                                          */
2063                                         if (id != esp->es_client.ea_id) {
2064                                                   warn("EAP: ID changed from %d to %d "
2065                                                       "in SRP Subtype 2 rexmit",
2066                                                       esp->es_client.ea_id, id);
2067                                         }
2068                               } else {
2069                                         if (get_srp_secret(esp->es_unit,
2070                                             esp->es_client.ea_name,
2071                                             esp->es_client.ea_peer, secret, 0) == 0) {
2072                                                   /*
2073                                                    * Can't work with this peer because
2074                                                    * the secret is missing.  Just give
2075                                                    * up.
2076                                                    */
2077                                                   eap_send_nak(esp, id, EAPT_MD5CHAP);
2078                                                   break;
2079                                         }
2080                                         Bval.data = inp;
2081                                         Bval.len = len;
2082                                         t_clientpasswd(tc, secret);
2083                                         BZERO(secret, sizeof (secret));
2084                                         esp->es_client.ea_skey =
2085                                             t_clientgetkey(tc, &Bval);
2086                                         if (esp->es_client.ea_skey == NULL) {
2087                                                   /* Server is rogue; stop now */
2088                                                   error("EAP: SRP server is rogue");
2089                                                   goto client_failure;
2090                                         }
2091                               }
2092                               eap_srpval_response(esp, id, SRPVAL_EBIT,
2093                                   t_clientresponse(tc));
2094                               break;
2095 
2096                     case EAPSRP_SVALIDATOR:
2097                               tc = (struct t_client *)esp->es_client.ea_session;
2098                               if (tc == NULL || esp->es_client.ea_skey == NULL) {
2099                                         warn("EAP: peer sent Subtype 3 without 1/2");
2100                                         eap_send_nak(esp, id, EAPT_MD5CHAP);
2101                                         break;
2102                               }
2103                               /*
2104                                * If we're already open, then this ought to be a
2105                                * duplicate.  Otherwise, check that the server is
2106                                * who we think it is.
2107                                */
2108                               if (esp->es_client.ea_state == eapOpen) {
2109                                         if (id != esp->es_client.ea_id) {
2110                                                   warn("EAP: ID changed from %d to %d "
2111                                                       "in SRP Subtype 3 rexmit",
2112                                                       esp->es_client.ea_id, id);
2113                                         }
2114                               } else {
2115                                         len -= sizeof (u_int32_t) + SHA_DIGEST_LENGTH;
2116                                         if (len < 0 || t_clientverify(tc, inp +
2117                                                   sizeof (u_int32_t)) != 0) {
2118                                                   error("EAP: SRP server verification "
2119                                                       "failed");
2120                                                   goto client_failure;
2121                                         }
2122                                         GETLONG(esp->es_client.ea_keyflags, inp);
2123                                         /* Save pseudonym if user wants it. */
2124                                         if (len > 0 && esp->es_usepseudo) {
2125                                                   INCPTR(SHA_DIGEST_LENGTH, inp);
2126                                                   write_pseudonym(esp, inp, len, id);
2127                                         }
2128                               }
2129                               /*
2130                                * We've verified our peer.  We're now mostly done,
2131                                * except for waiting on the regular EAP Success
2132                                * message.
2133                                */
2134                               eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
2135                               break;
2136 
2137                     case EAPSRP_LWRECHALLENGE:
2138                               if (len < 4) {
2139                                         warn("EAP: malformed Lightweight rechallenge");
2140                                         return;
2141                               }
2142                               ctxt = PPP_MD_CTX_new();
2143                               if (ctxt) {
2144 
2145                                         vals[0] = id;
2146                                         PPP_DigestInit(ctxt, PPP_sha1());
2147                                         PPP_DigestUpdate(ctxt, vals, 1);
2148                                         PPP_DigestUpdate(ctxt, esp->es_client.ea_skey,
2149                                                   SESSION_KEY_LEN);
2150                                         PPP_DigestUpdate(ctxt, inp, len);
2151                                         PPP_DigestUpdate(ctxt, esp->es_client.ea_name,
2152                                                   esp->es_client.ea_namelen);
2153                                         PPP_DigestFinal(ctxt, dig, &diglen);
2154 
2155                                         PPP_MD_CTX_free(ctxt);
2156 
2157                                         eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
2158                                                   SHA_DIGEST_LENGTH);
2159                               }
2160                               break;
2161 
2162                     default:
2163                               error("EAP: unknown SRP Subtype %d", vallen);
2164                               eap_send_nak(esp, id, EAPT_MD5CHAP);
2165                               break;
2166                     }
2167                     break;
2168 #endif /* PPP_WITH_SRP */
2169 
2170 #ifdef PPP_WITH_CHAPMS
2171         case EAPT_MSCHAPV2:
2172               if (len < 4) {
2173                     error("EAP: received invalid MSCHAPv2 packet, too short");
2174                     return;
2175               }
2176               unsigned char opcode;
2177               GETCHAR(opcode, inp);
2178               unsigned char chapid; /* Chapv2-ID */
2179               GETCHAR(chapid, inp);
2180               short mssize;
2181               GETSHORT(mssize, inp);
2182 
2183               /* Validate the mssize field */
2184               if (len != mssize) {
2185                     error("EAP: received invalid MSCHAPv2 packet, invalid length");
2186                     return;
2187               }
2188               len -= 4;
2189 
2190               /* If MSCHAPv2 digest was not found, NAK the packet */
2191               if (!esp->es_client.digest) {
2192                     error("EAP MSCHAPv2 not supported");
2193                     eap_send_nak(esp, id, EAPT_SRP);
2194                     return;
2195               }
2196 
2197               switch (opcode) {
2198               case CHAP_CHALLENGE: {
2199 
2200                     /* make_response() expects: VLEN + VALUE */
2201                     u_char *challenge = inp;
2202 
2203                     unsigned char vsize;
2204                     GETCHAR(vsize, inp);
2205                 len -= 1;
2206 
2207                     /* Validate the VALUE field */
2208                 if (vsize != MS_CHAP2_PEER_CHAL_LEN || len < MS_CHAP2_PEER_CHAL_LEN) {
2209                     error("EAP: received invalid MSCHAPv2 packet, invalid value-length: %d", vsize);
2210                     return;
2211                 }
2212 
2213                     /* Increment past the VALUE field */
2214                     INCPTR(MS_CHAP2_PEER_CHAL_LEN, inp);
2215                     len -= MS_CHAP2_PEER_CHAL_LEN;
2216 
2217                     /* Extract the hostname */
2218                     rhostname[0] = '\0';
2219                     if (len > 0) {
2220                         if (len >= sizeof (rhostname)) {
2221                               dbglog("EAP: trimming really long peer name down");
2222                               len = sizeof(rhostname) - 1;
2223                         }
2224                         BCOPY(inp, rhostname, len);
2225                         rhostname[len] = '\0';
2226                     }
2227 
2228                     /* In case the remote doesn't give us his name. */
2229                     if (explicit_remote || (remote_name[0] != '\0' && len == 0))
2230                         strlcpy(rhostname, remote_name, sizeof(rhostname));
2231 
2232                     /* Get the secret for authenticating ourselves with the specified host. */
2233                     if (!get_secret(esp->es_unit, esp->es_client.ea_name,
2234                         rhostname, secret, &secret_len, 0)) {
2235                         dbglog("EAP: no CHAP secret for auth to %q", rhostname);
2236                         eap_send_nak(esp, id, EAPT_SRP);
2237                         break;
2238                     }
2239                     esp->es_client.ea_namelen = strlen(esp->es_client.ea_name);
2240 
2241                     /* Create the MSCHAPv2 response (and add to cache) */
2242                     unsigned char response[MS_CHAP2_RESPONSE_LEN+1]; // VLEN + VALUE
2243                     esp->es_client.digest->make_response(response, chapid, esp->es_client.ea_name,
2244                               challenge, secret, secret_len, NULL);
2245 
2246                     eap_chapv2_response(esp, id, chapid, response, esp->es_client.ea_name, esp->es_client.ea_namelen);
2247                     break;
2248               }
2249               case CHAP_SUCCESS: {
2250 
2251                     /* Check response for mutual authentication */
2252                     u_char status = CHAP_FAILURE;
2253                     if (esp->es_client.digest->check_success(chapid, inp, len) == 1) {
2254                          info("Chap authentication succeeded! %.*v", len, inp);
2255                          status = CHAP_SUCCESS;
2256                     }
2257                     eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
2258                     break;
2259               }
2260               case CHAP_FAILURE: {
2261 
2262                     /* Process the failure string, and log appropriate information */
2263                     esp->es_client.digest->handle_failure(inp, len);
2264 
2265                     u_char status = CHAP_FAILURE;
2266                     eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
2267                     goto client_failure; /* force termination */
2268               }
2269               default:
2270 
2271                 error("EAP: received invalid MSCHAPv2 packet, invalid or unsupported opcode: %d", opcode);
2272                     eap_send_nak(esp, id, EAPT_SRP);
2273               }
2274 
2275               break;
2276 #endif /* PPP_WITH_CHAPMS */
2277 #ifdef PPP_WITH_PEAP
2278           case EAPT_PEAP:
2279 
2280                     /* Initialize the PEAP context (if not already initialized) */
2281                     if (!esp->ea_peap) {
2282                               rhostname[0] = '\0';
2283                               if (explicit_remote || (remote_name[0] != '\0')) {
2284                                         strlcpy(rhostname, remote_name, sizeof (rhostname));
2285                               }
2286                               if (peap_init(&esp->ea_peap, rhostname)) {
2287                                         eap_send_nak(esp, id, EAPT_TLS);
2288                                         break;
2289                               }
2290                     }
2291 
2292                     /* Process the PEAP packet */
2293                     if (peap_process(esp, id, inp, len)) {
2294                               eap_send_nak(esp, id, EAPT_TLS);
2295                     }
2296 
2297                     break;
2298 #endif // PPP_WITH_PEAP
2299 
2300           default:
2301                     info("EAP: unknown authentication type %d; Naking", typenum);
2302                     eap_send_nak(esp, id, EAPT_SRP);
2303                     break;
2304           }
2305 
2306           if (esp->es_client.ea_timeout > 0) {
2307                     UNTIMEOUT(eap_client_timeout, (void *)esp);
2308                     TIMEOUT(eap_client_timeout, (void *)esp,
2309                         esp->es_client.ea_timeout);
2310           }
2311           return;
2312 
2313 client_failure:
2314           esp->es_client.ea_state = eapBadAuth;
2315           if (esp->es_client.ea_timeout > 0) {
2316                     UNTIMEOUT(eap_client_timeout, (void *)esp);
2317           }
2318           esp->es_client.ea_session = NULL;
2319 #ifdef PPP_WITH_SRP
2320           t_clientclose(tc);
2321           auth_withpeer_fail(esp->es_unit, PPP_EAP);
2322 #endif /* PPP_WITH_SRP */
2323 }
2324 
2325 /*
2326  * eap_response - Receive EAP Response message (server mode).
2327  */
2328 static void
eap_response(eap_state * esp,u_char * inp,int id,int len)2329 eap_response(eap_state *esp, u_char *inp, int id, int len)
2330 {
2331           u_char typenum;
2332           u_char vallen;
2333           int secret_len;
2334           char secret[MAXSECRETLEN];
2335           char rhostname[256];
2336           PPP_MD_CTX *mdctx;
2337           u_char hash[MD5_DIGEST_LENGTH];
2338           int hashlen = MD5_DIGEST_LENGTH;
2339 #ifdef PPP_WITH_SRP
2340           struct t_server *ts;
2341           struct t_num A;
2342           PPP_MD_CTX *ctxt;
2343           u_char dig[SHA_DIGEST_LENGTH];
2344           int diglen = sizeof(dig);
2345 #endif /* PPP_WITH_SRP */
2346 
2347 #ifdef PPP_WITH_EAPTLS
2348           struct eaptls_session *ets;
2349           u_char flags;
2350 #endif /* PPP_WITH_EAPTLS */
2351 #ifdef PPP_WITH_CHAPMS
2352           u_char opcode;
2353         chap_verify_hook_fn *chap_verifier;
2354           char response_message[256];
2355 #endif /* PPP_WITH_CHAPMS */
2356 
2357           /*
2358            * Ignore responses if we're not open
2359            */
2360           if (esp->es_server.ea_state <= eapClosed)
2361                     return;
2362 
2363           if (esp->es_server.ea_id != id) {
2364                     dbglog("EAP: discarding Response %d; expected ID %d", id,
2365                         esp->es_server.ea_id);
2366                     return;
2367           }
2368 
2369           esp->es_server.ea_responses++;
2370 
2371           if (len <= 0) {
2372                     error("EAP: empty Response message discarded");
2373                     return;
2374           }
2375 
2376           GETCHAR(typenum, inp);
2377           len--;
2378 
2379           switch (typenum) {
2380           case EAPT_IDENTITY:
2381                     if (esp->es_server.ea_state != eapIdentify) {
2382                               dbglog("EAP discarding unwanted Identify \"%.q\"", len,
2383                                   inp);
2384                               break;
2385                     }
2386                     info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
2387                     if (esp->es_server.ea_peer != NULL &&
2388                         esp->es_server.ea_peer != remote_name)
2389                               free(esp->es_server.ea_peer);
2390                     esp->es_server.ea_peer = malloc(len + 1);
2391                     if (esp->es_server.ea_peer == NULL) {
2392                               esp->es_server.ea_peerlen = 0;
2393                               eap_figure_next_state(esp, 1);
2394                               break;
2395                     }
2396                     BCOPY(inp, esp->es_server.ea_peer, len);
2397                     esp->es_server.ea_peer[len] = '\0';
2398                     esp->es_server.ea_peerlen = len;
2399                     eap_figure_next_state(esp, 0);
2400                     break;
2401 
2402 #ifdef PPP_WITH_EAPTLS
2403           case EAPT_TLS:
2404                     switch(esp->es_server.ea_state) {
2405 
2406                     case eapTlsRecv:
2407 
2408                               ets = (struct eaptls_session *) esp->es_server.ea_session;
2409 
2410                               eap_figure_next_state(esp,
2411                                         eaptls_receive(esp->es_server.ea_session, inp, len));
2412 
2413                               if(ets->alert_recv) {
2414                                         eap_send_failure(esp);
2415                                         break;
2416                               }
2417                               break;
2418 
2419                     case eapTlsRecvAck:
2420                               if(len > 1) {
2421                                         dbglog("EAP-TLS ACK with extra data");
2422                               }
2423                               eap_figure_next_state(esp, 0);
2424                               break;
2425 
2426                     case eapTlsRecvClient:
2427                               /* Receive authentication response from client */
2428                               if (len > 0) {
2429                                         GETCHAR(flags, inp);
2430 
2431                                         if(len == 1 && !flags) {      /* Ack = ok */
2432 #ifdef PPP_WITH_MPPE
2433                                                   eaptls_gen_mppe_keys( esp->es_server.ea_session, 0 );
2434 #endif
2435                                                   eap_send_success(esp);
2436                                         }
2437                                         else {                        /* failure */
2438                                                   warn("Server authentication failed");
2439                                                   eap_send_failure(esp);
2440                                         }
2441                               }
2442                               else
2443                                         warn("Bogus EAP-TLS packet received from client");
2444 
2445                               eaptls_free_session(esp->es_server.ea_session);
2446 
2447                               break;
2448 
2449                     case eapTlsRecvAlertAck:
2450                               eap_send_failure(esp);
2451                               break;
2452 
2453                     default:
2454                               eap_figure_next_state(esp, 1);
2455                               break;
2456                     }
2457                     break;
2458 #endif /* PPP_WITH_EAPTLS */
2459 
2460           case EAPT_NOTIFICATION:
2461                     dbglog("EAP unexpected Notification; response discarded");
2462                     break;
2463 
2464           case EAPT_NAK:
2465                     if (len < 1) {
2466                               info("EAP: Nak Response with no suggested protocol");
2467                               eap_figure_next_state(esp, 1);
2468                               break;
2469                     }
2470 
2471                     GETCHAR(vallen, inp);
2472                     len--;
2473 
2474                     if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
2475                               /* Peer cannot Nak Identify Request */
2476                               eap_figure_next_state(esp, 1);
2477                               break;
2478                     }
2479 
2480                     switch (vallen) {
2481                     case EAPT_SRP:
2482                               /* Run through SRP validator selection again. */
2483                               esp->es_server.ea_state = eapIdentify;
2484                               eap_figure_next_state(esp, 0);
2485                               break;
2486 
2487                     case EAPT_MD5CHAP:
2488                               esp->es_server.ea_state = eapMD5Chall;
2489                               break;
2490 
2491 #ifdef PPP_WITH_EAPTLS
2492                               /* Send EAP-TLS start packet */
2493                     case EAPT_TLS:
2494                               esp->es_server.ea_state = eapTlsStart;
2495                               break;
2496 #endif /* PPP_WITH_EAPTLS */
2497 
2498 #ifdef PPP_WITH_CHAPMS
2499                     case EAPT_MSCHAPV2:
2500                               info("EAP: peer proposes MSCHAPv2");
2501                               /* If MSCHAPv2 digest was not found, NAK the packet */
2502                               if (!esp->es_server.digest) {
2503                                         error("EAP MSCHAPv2 not supported");
2504                                         eap_send_nak(esp, id, EAPT_SRP);
2505                                         break;
2506                               }
2507                               esp->es_server.ea_state = eapMSCHAPv2Chall;
2508                               break;
2509 #endif /* PPP_WITH_CHAPMS */
2510 
2511                     default:
2512                               dbglog("EAP: peer requesting unknown Type %d", vallen);
2513                               switch (esp->es_server.ea_state) {
2514                               case eapSRP1:
2515                               case eapSRP2:
2516                               case eapSRP3:
2517                                         esp->es_server.ea_state = eapMD5Chall;
2518                                         break;
2519                               case eapMD5Chall:
2520                               case eapSRP4:
2521                                         esp->es_server.ea_state = eapIdentify;
2522                                         eap_figure_next_state(esp, 0);
2523                                         break;
2524                               default:
2525                                         break;
2526                               }
2527                               break;
2528                     }
2529                     break;
2530 
2531           case EAPT_MD5CHAP:
2532                     if (esp->es_server.ea_state != eapMD5Chall) {
2533                               error("EAP: unexpected MD5-Response");
2534                               eap_figure_next_state(esp, 1);
2535                               break;
2536                     }
2537                     if (len < 1) {
2538                               error("EAP: received MD5-Response with no data");
2539                               eap_figure_next_state(esp, 1);
2540                               break;
2541                     }
2542                     GETCHAR(vallen, inp);
2543                     len--;
2544                     if (vallen != 16 || vallen > len) {
2545                               error("EAP: MD5-Response with bad length %d", vallen);
2546                               eap_figure_next_state(esp, 1);
2547                               break;
2548                     }
2549 
2550                     /* Not so likely to happen. */
2551                     if (len - vallen >= sizeof (rhostname)) {
2552                               dbglog("EAP: trimming really long peer name down");
2553                               BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2554                               rhostname[sizeof (rhostname) - 1] = '\0';
2555                     } else {
2556                               BCOPY(inp + vallen, rhostname, len - vallen);
2557                               rhostname[len - vallen] = '\0';
2558                     }
2559 
2560                     /* In case the remote doesn't give us his name. */
2561                     if (explicit_remote ||
2562                         (remote_name[0] != '\0' && vallen == len))
2563                               strlcpy(rhostname, remote_name, sizeof (rhostname));
2564 
2565                     /*
2566                      * Get the secret for authenticating the specified
2567                      * host.
2568                      */
2569                     if (!get_secret(esp->es_unit, rhostname,
2570                         esp->es_server.ea_name, secret, &secret_len, 1)) {
2571                               dbglog("EAP: no MD5 secret for auth of %q", rhostname);
2572                               eap_send_failure(esp);
2573                               break;
2574                     }
2575 
2576                     mdctx = PPP_MD_CTX_new();
2577                     if (mdctx != NULL) {
2578 
2579                               if (PPP_DigestInit(mdctx, PPP_md5())) {
2580 
2581                                         if (PPP_DigestUpdate(mdctx, &esp->es_server.ea_id, 1)) {
2582 
2583                                                   if (PPP_DigestUpdate(mdctx, &secret, secret_len)) {
2584 
2585                                                             BZERO(secret, sizeof(secret));
2586                                                             if (PPP_DigestUpdate(mdctx, esp->es_challenge, esp->es_challen)) {
2587 
2588                                                                       if (PPP_DigestFinal(mdctx, hash, &hashlen)) {
2589 
2590                                                                                 if (BCMP(hash, inp, MD5_DIGEST_LENGTH) == 0) {
2591                                                                                           esp->es_server.ea_type = EAPT_MD5CHAP;
2592                                                                                           eap_send_success(esp);
2593                                                                                           eap_figure_next_state(esp, 0);
2594 
2595                                                                                           if (esp->es_rechallenge != 0) {
2596                                                                                                     TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2597                                                                                           }
2598                                                                                           PPP_MD_CTX_free(mdctx);
2599                                                                                           break;
2600                                                                                 }
2601                                                                       }
2602                                                             }
2603                                                   }
2604                                         }
2605                               }
2606 
2607                               PPP_MD_CTX_free(mdctx);
2608                     }
2609 
2610                     eap_send_failure(esp);
2611                     break;
2612 
2613 #ifdef PPP_WITH_CHAPMS
2614           case EAPT_MSCHAPV2:
2615                     if (len < 1) {
2616                               error("EAP: received MSCHAPv2 with no data");
2617                               eap_figure_next_state(esp, 1);
2618                               break;
2619                     }
2620                     GETCHAR(opcode, inp);
2621                     len--;
2622 
2623                     switch (opcode) {
2624                     case CHAP_RESPONSE:
2625                               if (esp->es_server.ea_state != eapMSCHAPv2Chall) {
2626                                         error("EAP: unexpected MSCHAPv2-Response");
2627                                         eap_figure_next_state(esp, 1);
2628                                         break;
2629                               }
2630                               /* skip MS ID + len */
2631                               INCPTR(3, inp);
2632                               GETCHAR(vallen, inp);
2633                               len -= 4;
2634 
2635                               if (vallen != MS_CHAP2_RESPONSE_LEN || vallen > len) {
2636                                         error("EAP: Invalid MSCHAPv2-Response "
2637                                                             "length %d", vallen);
2638                                         eap_figure_next_state(esp, 1);
2639                                         break;
2640                               }
2641 
2642                               /* Not so likely to happen. */
2643                               if (len - vallen >= sizeof (rhostname)) {
2644                                         dbglog("EAP: trimming really long peer name down");
2645                                         BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2646                                         rhostname[sizeof (rhostname) - 1] = '\0';
2647                               } else {
2648                                         BCOPY(inp + vallen, rhostname, len - vallen);
2649                                         rhostname[len - vallen] = '\0';
2650                               }
2651 
2652                               /* In case the remote doesn't give us his name. */
2653                               if (explicit_remote ||
2654                                                   (remote_name[0] != '\0' && vallen == len))
2655                                         strlcpy(rhostname, remote_name, sizeof (rhostname));
2656 
2657                               /* strip the MS domain name */
2658                               if (chapms_strip_domain && strrchr(rhostname, '\\')) {
2659                                         char tmp[MAXNAMELEN+1];
2660 
2661                                         strcpy(tmp, strrchr(rhostname, '\\') + 1);
2662                                         strlcpy(rhostname, tmp, sizeof(rhostname));
2663                               }
2664 
2665                               if (chap_verify_hook)
2666                                         chap_verifier = chap_verify_hook;
2667                               else
2668                                         chap_verifier = eap_chap_verify_response;
2669 
2670                               esp->es_server.ea_id += 1;
2671                               if ((*chap_verifier)(rhostname,
2672                                                             esp->es_server.ea_name,
2673                                                             id,
2674                                                             esp->es_server.digest,
2675                                                             esp->es_challenge,
2676                                                             inp - 1,
2677                                                             response_message,
2678                                                             sizeof(response_message)))
2679                               {
2680                                         info("EAP: MSCHAPv2 success for peer %q",
2681                                                             rhostname);
2682                                         esp->es_server.ea_type = EAPT_MSCHAPV2;
2683                                         eap_chapms2_send_request(esp,
2684                                                             esp->es_server.ea_id,
2685                                                             CHAP_SUCCESS,
2686                                                             esp->es_server.ea_id,
2687                                                             response_message,
2688                                                             strlen(response_message));
2689                                         eap_figure_next_state(esp, 0);
2690                                         if (esp->es_rechallenge != 0)
2691                                                   TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2692                               }
2693                               else {
2694                                         warn("EAP: MSCHAPv2 failure for peer %q",
2695                                                             rhostname);
2696                                         eap_chapms2_send_request(esp,
2697                                                             esp->es_server.ea_id,
2698                                                             CHAP_FAILURE,
2699                                                             esp->es_server.ea_id,
2700                                                             response_message,
2701                                                             strlen(response_message));
2702                               }
2703                               break;
2704                     case CHAP_SUCCESS:
2705                               info("EAP: MSCHAPv2 success confirmed");
2706                               break;
2707                     case CHAP_FAILURE:
2708                               info("EAP: MSCHAPv2 failure confirmed");
2709                               break;
2710                     default:
2711                               error("EAP: Unhandled MSCHAPv2 opcode %d", opcode);
2712                               eap_send_nak(esp, id, EAPT_SRP);
2713                     }
2714 
2715                     break;
2716 #endif /* PPP_WITH_CHAPMS */
2717 
2718 #ifdef PPP_WITH_SRP
2719           case EAPT_SRP:
2720                     if (len < 1) {
2721                               error("EAP: empty SRP Response");
2722                               eap_figure_next_state(esp, 1);
2723                               break;
2724                     }
2725                     GETCHAR(typenum, inp);
2726                     len--;
2727                     switch (typenum) {
2728                     case EAPSRP_CKEY:
2729                               if (esp->es_server.ea_state != eapSRP1) {
2730                                         error("EAP: unexpected SRP Subtype 1 Response");
2731                                         eap_figure_next_state(esp, 1);
2732                                         break;
2733                               }
2734                               A.data = inp;
2735                               A.len = len;
2736                               ts = (struct t_server *)esp->es_server.ea_session;
2737                               assert(ts != NULL);
2738                               esp->es_server.ea_skey = t_servergetkey(ts, &A);
2739                               if (esp->es_server.ea_skey == NULL) {
2740                                         /* Client's A value is bogus; terminate now */
2741                                         error("EAP: bogus A value from client");
2742                                         eap_send_failure(esp);
2743                               } else {
2744                                         eap_figure_next_state(esp, 0);
2745                               }
2746                               break;
2747 
2748                     case EAPSRP_CVALIDATOR:
2749                               if (esp->es_server.ea_state != eapSRP2) {
2750                                         error("EAP: unexpected SRP Subtype 2 Response");
2751                                         eap_figure_next_state(esp, 1);
2752                                         break;
2753                               }
2754                               if (len < sizeof (u_int32_t) + SHA_DIGEST_LENGTH) {
2755                                         error("EAP: M1 length %d < %d", len,
2756                                             sizeof (u_int32_t) + SHA_DIGEST_LENGTH);
2757                                         eap_figure_next_state(esp, 1);
2758                                         break;
2759                               }
2760                               GETLONG(esp->es_server.ea_keyflags, inp);
2761                               ts = (struct t_server *)esp->es_server.ea_session;
2762                               assert(ts != NULL);
2763                               if (t_serververify(ts, inp)) {
2764                                         info("EAP: unable to validate client identity");
2765                                         eap_send_failure(esp);
2766                                         break;
2767                               }
2768                               eap_figure_next_state(esp, 0);
2769                               break;
2770 
2771                     case EAPSRP_ACK:
2772                               if (esp->es_server.ea_state != eapSRP3) {
2773                                         error("EAP: unexpected SRP Subtype 3 Response");
2774                                         eap_send_failure(esp);
2775                                         break;
2776                               }
2777                               esp->es_server.ea_type = EAPT_SRP;
2778                               eap_send_success(esp);
2779                               eap_figure_next_state(esp, 0);
2780                               if (esp->es_rechallenge != 0)
2781                                         TIMEOUT(eap_rechallenge, esp,
2782                                             esp->es_rechallenge);
2783                               if (esp->es_lwrechallenge != 0)
2784                                         TIMEOUT(srp_lwrechallenge, esp,
2785                                             esp->es_lwrechallenge);
2786                               break;
2787 
2788                     case EAPSRP_LWRECHALLENGE:
2789                               if (esp->es_server.ea_state != eapSRP4) {
2790                                         info("EAP: unexpected SRP Subtype 4 Response");
2791                                         return;
2792                               }
2793                               if (len != SHA_DIGEST_LENGTH) {
2794                                         error("EAP: bad Lightweight rechallenge "
2795                                             "response");
2796                                         return;
2797                               }
2798                               ctxt = PPP_MD_CTX_new();
2799                               if (ctxt) {
2800                                         vallen = id;
2801 
2802                                         PPP_DigestInit(ctxt, PPP_sha1());
2803                                         PPP_DigestUpdate(ctxt, &vallen, 1);
2804                                         PPP_DigestUpdate(ctxt, esp->es_server.ea_skey,
2805                                                   SESSION_KEY_LEN);
2806                                         PPP_DigestUpdate(ctxt, esp->es_challenge, esp->es_challen);
2807                                         PPP_DigestUpdate(ctxt, esp->es_server.ea_peer,
2808                                                   esp->es_server.ea_peerlen);
2809                                         PPP_DigestFinal(ctxt, dig, &diglen);
2810 
2811                                         PPP_MD_CTX_free(ctxt);
2812 
2813                                         if (BCMP(dig, inp, SHA_DIGEST_LENGTH) != 0) {
2814                                                   error("EAP: failed Lightweight rechallenge");
2815                                                   eap_send_failure(esp);
2816                                                   break;
2817                                         }
2818 
2819                                         esp->es_server.ea_state = eapOpen;
2820                                         if (esp->es_lwrechallenge != 0)
2821                                                   TIMEOUT(srp_lwrechallenge, esp,
2822                                                             esp->es_lwrechallenge);
2823                               }
2824                               break;
2825                     }
2826                     break;
2827 #endif /* PPP_WITH_SRP */
2828 
2829           default:
2830                     /* This can't happen. */
2831                     error("EAP: unknown Response type %d; ignored", typenum);
2832                     return;
2833           }
2834 
2835           if (esp->es_server.ea_timeout > 0) {
2836                     UNTIMEOUT(eap_server_timeout, (void *)esp);
2837           }
2838 
2839           if (esp->es_server.ea_state != eapBadAuth &&
2840               esp->es_server.ea_state != eapOpen) {
2841                     esp->es_server.ea_id++;
2842                     eap_send_request(esp);
2843           }
2844 }
2845 
2846 /*
2847  * eap_success - Receive EAP Success message (client mode).
2848  */
2849 static void
eap_success(eap_state * esp,u_char * inp,int id,int len)2850 eap_success(eap_state *esp, u_char *inp, int id, int len)
2851 {
2852           if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
2853 #ifdef PPP_WITH_EAPTLS
2854                     && esp->es_client.ea_state != eapTlsRecvSuccess
2855 #endif /* PPP_WITH_EAPTLS */
2856                     ) {
2857                     dbglog("EAP unexpected success message in state %s (%d)",
2858                         eap_state_name(esp->es_client.ea_state),
2859                         esp->es_client.ea_state);
2860                     return;
2861           }
2862 
2863 #ifdef PPP_WITH_EAPTLS
2864           if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state !=
2865                     eapTlsRecvSuccess) {
2866                     dbglog("EAP-TLS unexpected success message in state %s (%d)",
2867                     eap_state_name(esp->es_client.ea_state),
2868                     esp->es_client.ea_state);
2869                     return;
2870           }
2871 #endif /* PPP_WITH_EAPTLS */
2872 
2873           if (esp->es_client.ea_timeout > 0) {
2874                     UNTIMEOUT(eap_client_timeout, (void *)esp);
2875           }
2876 
2877           if (len > 0) {
2878                     /* This is odd.  The spec doesn't allow for this. */
2879                     PRINTMSG(inp, len);
2880           }
2881 
2882 #ifdef PPP_WITH_PEAP
2883           peap_finish(&esp->ea_peap);
2884 #endif
2885 
2886           esp->es_client.ea_state = eapOpen;
2887           auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2888 }
2889 
2890 /*
2891  * eap_failure - Receive EAP Failure message (client mode).
2892  */
2893 static void
eap_failure(eap_state * esp,u_char * inp,int id,int len)2894 eap_failure(eap_state *esp, u_char *inp, int id, int len)
2895 {
2896           /*
2897            * Ignore failure messages if we're not open
2898            */
2899           if (esp->es_client.ea_state <= eapClosed)
2900                     return;
2901 
2902           if (!eap_client_active(esp)) {
2903                     dbglog("EAP unexpected failure message in state %s (%d)",
2904                         eap_state_name(esp->es_client.ea_state),
2905                         esp->es_client.ea_state);
2906           }
2907 
2908           if (esp->es_client.ea_timeout > 0) {
2909                     UNTIMEOUT(eap_client_timeout, (void *)esp);
2910           }
2911 
2912           if (len > 0) {
2913                     /* This is odd.  The spec doesn't allow for this. */
2914                     PRINTMSG(inp, len);
2915           }
2916 
2917           esp->es_client.ea_state = eapBadAuth;
2918 
2919           error("EAP: peer reports authentication failure");
2920 
2921 #ifdef PPP_WITH_PEAP
2922           peap_finish(&esp->ea_peap);
2923 #endif
2924 
2925           auth_withpeer_fail(esp->es_unit, PPP_EAP);
2926 }
2927 
2928 /*
2929  * eap_input - Handle received EAP message.
2930  */
2931 static void
eap_input(int unit,u_char * inp,int inlen)2932 eap_input(int unit, u_char *inp, int inlen)
2933 {
2934           eap_state *esp = &eap_states[unit];
2935           u_char code, id;
2936           int len;
2937 
2938           /*
2939            * Parse header (code, id and length).  If packet too short,
2940            * drop it.
2941            */
2942           if (inlen < EAP_HEADERLEN) {
2943                     error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2944                     return;
2945           }
2946           GETCHAR(code, inp);
2947           GETCHAR(id, inp);
2948           GETSHORT(len, inp);
2949           if (len < EAP_HEADERLEN || len > inlen) {
2950                     error("EAP: packet has illegal length field %d (%d..%d)", len,
2951                         EAP_HEADERLEN, inlen);
2952                     return;
2953           }
2954           len -= EAP_HEADERLEN;
2955 
2956           /* Dispatch based on message code */
2957           switch (code) {
2958           case EAP_REQUEST:
2959                     eap_request(esp, inp, id, len);
2960                     break;
2961 
2962           case EAP_RESPONSE:
2963                     eap_response(esp, inp, id, len);
2964                     break;
2965 
2966           case EAP_SUCCESS:
2967                     eap_success(esp, inp, id, len);
2968                     break;
2969 
2970           case EAP_FAILURE:
2971                     eap_failure(esp, inp, id, len);
2972                     break;
2973 
2974           default:                                /* XXX Need code reject */
2975                     /* Note: it's not legal to send EAP Nak here. */
2976                     warn("EAP: unknown code %d received", code);
2977                     break;
2978           }
2979 }
2980 
2981 /*
2982  * eap_printpkt - print the contents of an EAP packet.
2983  */
2984 static char *eap_codenames[] = {
2985           "Request", "Response", "Success", "Failure"
2986 };
2987 
2988 static char *eap_typenames[] = {
2989           "Identity", "Notification", "Nak", "MD5-Challenge",
2990           "OTP", "Generic-Token", NULL, NULL,
2991           "RSA", "DSS", "KEA", "KEA-Validate",
2992           "TLS", "Defender", "Windows 2000", "Arcot",
2993           "Cisco", "Nokia", "SRP", NULL,
2994           "TTLS", "RAS", "AKA", "3COM", "PEAP",
2995           "MSCHAPv2"
2996 };
2997 
2998 static int
eap_printpkt(u_char * inp,int inlen,void (* printer)(void *,char *,...),void * arg)2999 eap_printpkt(u_char *inp, int inlen,
3000                void (*printer) (void *, char *, ...), void *arg)
3001 {
3002           int code, id, len, rtype, vallen;
3003           u_char *pstart;
3004 #ifdef PPP_WITH_SRP
3005           u_int32_t uval;
3006 #endif /* PPP_WITH_SRP */
3007 #ifdef PPP_WITH_EAPTLS
3008           u_char flags;
3009 #endif /* PPP_WITH_EAPTLS */
3010 #ifdef PPP_WITH_CHAPMS
3011           u_char opcode;
3012 #endif /* PPP_WITH_CHAPMS */
3013 
3014           if (inlen < EAP_HEADERLEN)
3015                     return (0);
3016           pstart = inp;
3017           GETCHAR(code, inp);
3018           GETCHAR(id, inp);
3019           GETSHORT(len, inp);
3020           if (len < EAP_HEADERLEN || len > inlen)
3021                     return (0);
3022 
3023           if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
3024                     printer(arg, " %s", eap_codenames[code-1]);
3025           else
3026                     printer(arg, " code=0x%x", code);
3027           printer(arg, " id=0x%x", id);
3028           len -= EAP_HEADERLEN;
3029           switch (code) {
3030           case EAP_REQUEST:
3031                     if (len < 1) {
3032                               printer(arg, " <missing type>");
3033                               break;
3034                     }
3035                     GETCHAR(rtype, inp);
3036                     len--;
3037                     if (rtype >= 1 &&
3038                         rtype <= sizeof (eap_typenames) / sizeof (char *))
3039                               printer(arg, " %s", eap_typenames[rtype-1]);
3040                     else
3041                               printer(arg, " type=0x%x", rtype);
3042                     switch (rtype) {
3043                     case EAPT_IDENTITY:
3044                     case EAPT_NOTIFICATION:
3045                               if (len > 0) {
3046                                         printer(arg, " <Message ");
3047                                         print_string((char *)inp, len, printer, arg);
3048                                         printer(arg, ">");
3049                                         INCPTR(len, inp);
3050                                         len = 0;
3051                               } else {
3052                                         printer(arg, " <No message>");
3053                               }
3054                               break;
3055 
3056                     case EAPT_MD5CHAP:
3057                               if (len <= 0)
3058                                         break;
3059                               GETCHAR(vallen, inp);
3060                               len--;
3061                               if (vallen > len)
3062                                         goto truncated;
3063                               printer(arg, " <Value%.*B>", vallen, inp);
3064                               INCPTR(vallen, inp);
3065                               len -= vallen;
3066                               if (len > 0) {
3067                                         printer(arg, " <Name ");
3068                                         print_string((char *)inp, len, printer, arg);
3069                                         printer(arg, ">");
3070                                         INCPTR(len, inp);
3071                                         len = 0;
3072                               } else {
3073                                         printer(arg, " <No name>");
3074                               }
3075                               break;
3076 
3077 #ifdef PPP_WITH_CHAPMS
3078                     case EAPT_MSCHAPV2:
3079                               if (len <= 0)
3080                                         break;
3081                               GETCHAR(opcode, inp);
3082                               len--;
3083                               switch (opcode) {
3084                               case CHAP_CHALLENGE:
3085                                         INCPTR(3, inp);
3086                                         len -= 3;
3087                                         GETCHAR(vallen, inp);
3088                                         len--;
3089                                         if (vallen > len)
3090                                                   goto truncated;
3091                                         len -= vallen;
3092                                         printer(arg, " Challenge <");
3093                                         for (; vallen > 0; --vallen) {
3094                                                   u_char val;
3095                                                   GETCHAR(val, inp);
3096                                                   printer(arg, "%.2x", val);
3097                                         }
3098                                         printer(arg, ">");
3099                                         if (len > 0) {
3100                                                   printer(arg, ", <Name ");
3101                                                   print_string((char *)inp, len, printer, arg);
3102                                                   printer(arg, ">");
3103                                                   INCPTR(len, inp);
3104                                                   len = 0;
3105                                         } else {
3106                                                   printer(arg, ", <No name>");
3107                                         }
3108                                         break;
3109                               case CHAP_SUCCESS:
3110                                         INCPTR(3, inp);
3111                                         len -= 3;
3112                                         printer(arg, " Success <Message ");
3113                                         print_string((char *)inp, len, printer, arg);
3114                                         printer(arg, ">");
3115                                         break;
3116                               case CHAP_FAILURE:
3117                                         INCPTR(3, inp);
3118                                         len -= 3;
3119                                         printer(arg, " Failure <Message ");
3120                                         print_string((char *)inp, len, printer, arg);
3121                                         printer(arg, ">");
3122                                         break;
3123                               default:
3124                                         INCPTR(3, inp);
3125                                         len -= 3;
3126                                         printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
3127                                         break;
3128                               }
3129                               break;
3130 #endif /* PPP_WITH_CHAPMS */
3131 
3132 #ifdef PPP_WITH_EAPTLS
3133                     case EAPT_TLS:
3134                               if (len < 1)
3135                                         break;
3136                               GETCHAR(flags, inp);
3137                               len--;
3138 
3139                         if(flags == 0 && len == 0){
3140                                 printer(arg, " Ack");
3141                                 break;
3142                         }
3143 
3144                               printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
3145                               printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
3146                               printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
3147                               break;
3148 #endif /* PPP_WITH_EAPTLS */
3149 
3150 #ifdef PPP_WITH_SRP
3151                     case EAPT_SRP:
3152                               if (len < 3)
3153                                         goto truncated;
3154                               GETCHAR(vallen, inp);
3155                               len--;
3156                               printer(arg, "-%d", vallen);
3157                               switch (vallen) {
3158                               case EAPSRP_CHALLENGE:
3159                                         GETCHAR(vallen, inp);
3160                                         len--;
3161                                         if (vallen >= len)
3162                                                   goto truncated;
3163                                         if (vallen > 0) {
3164                                                   printer(arg, " <Name ");
3165                                                   print_string((char *)inp, vallen, printer,
3166                                                       arg);
3167                                                   printer(arg, ">");
3168                                         } else {
3169                                                   printer(arg, " <No name>");
3170                                         }
3171                                         INCPTR(vallen, inp);
3172                                         len -= vallen;
3173                                         GETCHAR(vallen, inp);
3174                                         len--;
3175                                         if (vallen >= len)
3176                                                   goto truncated;
3177                                         printer(arg, " <s%.*B>", vallen, inp);
3178                                         INCPTR(vallen, inp);
3179                                         len -= vallen;
3180                                         GETCHAR(vallen, inp);
3181                                         len--;
3182                                         if (vallen > len)
3183                                                   goto truncated;
3184                                         if (vallen == 0) {
3185                                                   printer(arg, " <Default g=2>");
3186                                         } else {
3187                                                   printer(arg, " <g%.*B>", vallen, inp);
3188                                         }
3189                                         INCPTR(vallen, inp);
3190                                         len -= vallen;
3191                                         if (len == 0) {
3192                                                   printer(arg, " <Default N>");
3193                                         } else {
3194                                                   printer(arg, " <N%.*B>", len, inp);
3195                                                   INCPTR(len, inp);
3196                                                   len = 0;
3197                                         }
3198                                         break;
3199 
3200                               case EAPSRP_SKEY:
3201                                         printer(arg, " <B%.*B>", len, inp);
3202                                         INCPTR(len, inp);
3203                                         len = 0;
3204                                         break;
3205 
3206                               case EAPSRP_SVALIDATOR:
3207                                         if (len < sizeof (u_int32_t))
3208                                                   break;
3209                                         GETLONG(uval, inp);
3210                                         len -= sizeof (u_int32_t);
3211                                         if (uval & SRPVAL_EBIT) {
3212                                                   printer(arg, " E");
3213                                                   uval &= ~SRPVAL_EBIT;
3214                                         }
3215                                         if (uval != 0) {
3216                                                   printer(arg, " f<%X>", uval);
3217                                         }
3218                                         if ((vallen = len) > SHA_DIGEST_LENGTH)
3219                                                   vallen = SHA_DIGEST_LENGTH;
3220                                         printer(arg, " <M2%.*B%s>", len, inp,
3221                                             len < SHA_DIGEST_LENGTH ? "?" : "");
3222                                         INCPTR(vallen, inp);
3223                                         len -= vallen;
3224                                         if (len > 0) {
3225                                                   printer(arg, " <PN%.*B>", len, inp);
3226                                                   INCPTR(len, inp);
3227                                                   len = 0;
3228                                         }
3229                                         break;
3230 
3231                               case EAPSRP_LWRECHALLENGE:
3232                                         printer(arg, " <Challenge%.*B>", len, inp);
3233                                         INCPTR(len, inp);
3234                                         len = 0;
3235                                         break;
3236                               }
3237                               break;
3238 #endif  /* PPP_WITH_SRP */
3239                     }
3240                     break;
3241 
3242           case EAP_RESPONSE:
3243                     if (len < 1)
3244                               break;
3245                     GETCHAR(rtype, inp);
3246                     len--;
3247                     if (rtype >= 1 &&
3248                         rtype <= sizeof (eap_typenames) / sizeof (char *))
3249                               printer(arg, " %s", eap_typenames[rtype-1]);
3250                     else
3251                               printer(arg, " type=0x%x", rtype);
3252                     switch (rtype) {
3253                     case EAPT_IDENTITY:
3254                               if (len > 0) {
3255                                         printer(arg, " <Name ");
3256                                         print_string((char *)inp, len, printer, arg);
3257                                         printer(arg, ">");
3258                                         INCPTR(len, inp);
3259                                         len = 0;
3260                               }
3261                               break;
3262 
3263 #ifdef PPP_WITH_EAPTLS
3264                     case EAPT_TLS:
3265                               if (len < 1)
3266                                         break;
3267                               GETCHAR(flags, inp);
3268                               len--;
3269 
3270                         if(flags == 0 && len == 0){
3271                                 printer(arg, " Ack");
3272                                 break;
3273                         }
3274 
3275                               printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
3276                               printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
3277                               printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
3278 
3279                               break;
3280 #endif /* PPP_WITH_EAPTLS */
3281 
3282                     case EAPT_NAK:
3283                               if (len <= 0) {
3284                                         printer(arg, " <missing hint>");
3285                                         break;
3286                               }
3287                               GETCHAR(rtype, inp);
3288                               len--;
3289                               printer(arg, " <Suggested-type %02X", rtype);
3290                               if (rtype >= 1 &&
3291                                   rtype <= sizeof (eap_typenames) / sizeof (char *))
3292                                         printer(arg, " (%s)", eap_typenames[rtype-1]);
3293                               printer(arg, ">");
3294                               break;
3295 
3296                     case EAPT_MD5CHAP:
3297                               if (len <= 0) {
3298                                         printer(arg, " <missing length>");
3299                                         break;
3300                               }
3301                               GETCHAR(vallen, inp);
3302                               len--;
3303                               if (vallen > len)
3304                                         goto truncated;
3305                               printer(arg, " <Value%.*B>", vallen, inp);
3306                               INCPTR(vallen, inp);
3307                               len -= vallen;
3308                               if (len > 0) {
3309                                         printer(arg, " <Name ");
3310                                         print_string((char *)inp, len, printer, arg);
3311                                         printer(arg, ">");
3312                                         INCPTR(len, inp);
3313                                         len = 0;
3314                               } else {
3315                                         printer(arg, " <No name>");
3316                               }
3317                               break;
3318 
3319 #ifdef PPP_WITH_CHAPMS
3320                     case EAPT_MSCHAPV2:
3321                               if (len <= 0)
3322                                         break;
3323                               GETCHAR(opcode, inp);
3324                               len--;
3325                               switch (opcode) {
3326                               case CHAP_RESPONSE:
3327                                         INCPTR(3, inp);
3328                                         len -= 3;
3329                                         GETCHAR(vallen, inp);
3330                                         len--;
3331                                         if (vallen > len)
3332                                                   goto truncated;
3333                                         len -= vallen;
3334                                         printer(arg, " Response <");
3335                                         for (; vallen > 0; --vallen) {
3336                                                   u_char val;
3337                                                   GETCHAR(val, inp);
3338                                                   printer(arg, "%.2x", val);
3339                                         }
3340                                         printer(arg, ">");
3341                                         if (len > 0) {
3342                                                   printer(arg, ", <Name ");
3343                                                   print_string((char *)inp, len, printer, arg);
3344                                                   printer(arg, ">");
3345                                                   INCPTR(len, inp);
3346                                                   len = 0;
3347                                         } else {
3348                                                   printer(arg, ", <No name>");
3349                                         }
3350                                         break;
3351                               case CHAP_SUCCESS:
3352                                         printer(arg, " Success");
3353                                         break;
3354                               case CHAP_FAILURE:
3355                                         printer(arg, " Failure");
3356                                         break;
3357                               default:
3358                                         printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
3359                                         break;
3360                               }
3361                               break;
3362 #endif /* PPP_WITH_CHAPMS */
3363 
3364 #ifdef PPP_WITH_SRP
3365                     case EAPT_SRP:
3366                               if (len < 1)
3367                                         goto truncated;
3368                               GETCHAR(vallen, inp);
3369                               len--;
3370                               printer(arg, "-%d", vallen);
3371                               switch (vallen) {
3372                               case EAPSRP_CKEY:
3373                                         printer(arg, " <A%.*B>", len, inp);
3374                                         INCPTR(len, inp);
3375                                         len = 0;
3376                                         break;
3377 
3378                               case EAPSRP_CVALIDATOR:
3379                                         if (len < sizeof (u_int32_t))
3380                                                   break;
3381                                         GETLONG(uval, inp);
3382                                         len -= sizeof (u_int32_t);
3383                                         if (uval & SRPVAL_EBIT) {
3384                                                   printer(arg, " E");
3385                                                   uval &= ~SRPVAL_EBIT;
3386                                         }
3387                                         if (uval != 0) {
3388                                                   printer(arg, " f<%X>", uval);
3389                                         }
3390                                         printer(arg, " <M1%.*B%s>", len, inp,
3391                                             len == SHA_DIGEST_LENGTH ? "" : "?");
3392                                         INCPTR(len, inp);
3393                                         len = 0;
3394                                         break;
3395 
3396                               case EAPSRP_ACK:
3397                                         break;
3398 
3399                               case EAPSRP_LWRECHALLENGE:
3400                                         printer(arg, " <Response%.*B%s>", len, inp,
3401                                             len == SHA_DIGEST_LENGTH ? "" : "?");
3402                                         if ((vallen = len) > SHA_DIGEST_LENGTH)
3403                                                   vallen = SHA_DIGEST_LENGTH;
3404                                         INCPTR(vallen, inp);
3405                                         len -= vallen;
3406                                         break;
3407                               }
3408                               break;
3409 #endif  /* PPP_WITH_SRP */
3410                     }
3411                     break;
3412 
3413           case EAP_SUCCESS:   /* No payload expected for these! */
3414           case EAP_FAILURE:
3415                     break;
3416 
3417           truncated:
3418                     printer(arg, " <truncated>");
3419                     break;
3420           }
3421 
3422           if (len > 8)
3423                     printer(arg, "%8B...", inp);
3424           else if (len > 0)
3425                     printer(arg, "%.*B", len, inp);
3426           INCPTR(len, inp);
3427 
3428           return (inp - pstart);
3429 }
3430