2 * eap.c - Extensible Authentication Protocol for PPP (RFC 2284)
4 * Copyright (c) 2001 by Sun Microsystems, Inc.
7 * Non-exclusive rights to redistribute, modify, translate, and use
8 * this software in source and binary forms, in whole or in part, is
9 * hereby granted, provided that the above copyright notice is
10 * duplicated in any source form, and that neither the name of the
11 * copyright holder nor the author is used to endorse or promote
12 * products derived from this software.
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 * Original version by James Carlson
20 * This implementation of EAP supports MD5-Challenge and SRP-SHA1
21 * authentication styles. Note that support of MD5-Challenge is a
22 * requirement of RFC 2284, and that it's essentially just a
23 * reimplementation of regular RFC 1994 CHAP using EAP messages.
25 * As an authenticator ("server"), there are multiple phases for each
26 * style. In the first phase of each style, the unauthenticated peer
27 * name is queried using the EAP Identity request type. If the
28 * "remotename" option is used, then this phase is skipped, because
29 * the peer's name is presumed to be known.
31 * For MD5-Challenge, there are two phases, and the second phase
32 * consists of sending the challenge itself and handling the
33 * associated response.
35 * For SRP-SHA1, there are four phases. The second sends 's', 'N',
36 * and 'g'. The reply contains 'A'. The third sends 'B', and the
37 * reply contains 'M1'. The forth sends the 'M2' value.
39 * As an authenticatee ("client"), there's just a single phase --
40 * responding to the queries generated by the peer. EAP is an
41 * authenticator-driven protocol.
43 * Based on draft-ietf-pppext-eap-srp-03.txt.
47 * Modification by Beniamino Galvani, Mar 2005
48 * Implemented EAP-TLS authentication
60 #include <sys/types.h>
67 #include "pathnames.h"
78 #ifndef SHA_DIGESTSIZE
79 #define SHA_DIGESTSIZE 20
84 #endif /* USE_EAPTLS */
86 eap_state eap_states[NUM_PPP]; /* EAP state; one for each unit */
88 static char *pn_secret = NULL; /* Pseudonym generating secret */
92 * Command-line options.
94 static option_t eap_option_list[] = {
95 { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,
96 "Set retransmit timeout for EAP Requests (server)" },
97 { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,
98 "Set max number of EAP Requests sent (server)" },
99 { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,
100 "Set time limit for peer EAP authentication" },
101 { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,
102 "Set max number of EAP Requests allows (client)" },
103 { "eap-interval", o_int, &eap_states[0].es_rechallenge,
104 "Set interval for EAP rechallenge" },
106 { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,
107 "Set interval for SRP lightweight rechallenge" },
108 { "srp-pn-secret", o_string, &pn_secret,
109 "Long term pseudonym generation secret" },
110 { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,
111 "Use pseudonym if offered one by server", 1 },
117 * Protocol entry points.
119 static void eap_init (int unit);
120 static void eap_input (int unit, u_char *inp, int inlen);
121 static void eap_protrej (int unit);
122 static void eap_lowerup (int unit);
123 static void eap_lowerdown (int unit);
124 static int eap_printpkt (u_char *inp, int inlen,
125 void (*)(void *arg, char *fmt, ...), void *arg);
127 struct protent eap_protent = {
128 PPP_EAP, /* protocol number */
129 eap_init, /* initialization procedure */
130 eap_input, /* process a received packet */
131 eap_protrej, /* process a received protocol-reject */
132 eap_lowerup, /* lower layer has gone up */
133 eap_lowerdown, /* lower layer has gone down */
134 NULL, /* open the protocol */
135 NULL, /* close the protocol */
136 eap_printpkt, /* print a packet in readable form */
137 NULL, /* process a received data packet */
138 1, /* protocol enabled */
139 "EAP", /* text name of protocol */
140 NULL, /* text name of corresponding data protocol */
141 eap_option_list, /* list of command-line options */
142 NULL, /* check requested options; assign defaults */
143 NULL, /* configure interface for demand-dial */
144 NULL /* say whether to bring up link for this pkt */
149 * A well-known 2048 bit modulus.
151 static const u_char wkmodulus[] = {
152 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
153 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
154 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
155 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
156 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
157 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
158 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
159 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
160 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
161 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
162 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
163 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
164 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
165 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
166 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
167 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
168 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
169 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
170 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
171 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
172 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
173 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
174 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
175 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
176 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
177 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
178 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
179 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
180 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
181 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
182 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
183 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
187 /* Local forward declarations. */
188 static void eap_server_timeout (void *arg);
191 * Convert EAP state code to printable string for debug.
194 eap_state_name(enum eap_state_code esc)
196 static const char *state_names[] = { EAP_STATES };
198 return (state_names[(int)esc]);
202 * eap_init - Initialize state for an EAP user. This is currently
203 * called once by main() during start-up.
208 eap_state *esp = &eap_states[unit];
210 BZERO(esp, sizeof (*esp));
212 esp->es_server.ea_timeout = EAP_DEFTIMEOUT;
213 esp->es_server.ea_maxrequests = EAP_DEFTRANSMITS;
214 esp->es_server.ea_id = (u_char)(drand48() * 0x100);
215 esp->es_client.ea_timeout = EAP_DEFREQTIME;
216 esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
218 esp->es_client.ea_using_eaptls = 0;
219 #endif /* USE_EAPTLS */
223 * eap_client_timeout - Give up waiting for the peer to send any
227 eap_client_timeout(void *arg)
229 eap_state *esp = (eap_state *) arg;
231 if (!eap_client_active(esp))
234 error("EAP: timeout waiting for Request from peer");
235 auth_withpeer_fail(esp->es_unit, PPP_EAP);
236 esp->es_client.ea_state = eapBadAuth;
240 * eap_authwithpeer - Authenticate to our peer (behave as client).
242 * Start client state and wait for requests. This is called only
246 eap_authwithpeer(int unit, char *localname)
248 eap_state *esp = &eap_states[unit];
250 /* Save the peer name we're given */
251 esp->es_client.ea_name = localname;
252 esp->es_client.ea_namelen = strlen(localname);
254 esp->es_client.ea_state = eapListen;
257 * Start a timer so that if the other end just goes
258 * silent, we don't sit here waiting forever.
260 if (esp->es_client.ea_timeout > 0)
261 TIMEOUT(eap_client_timeout, (void *)esp,
262 esp->es_client.ea_timeout);
266 * Format a standard EAP Failure message and send it to the peer.
270 eap_send_failure(eap_state *esp)
274 outp = outpacket_buf;
276 MAKEHEADER(outp, PPP_EAP);
278 PUTCHAR(EAP_FAILURE, outp);
279 esp->es_server.ea_id++;
280 PUTCHAR(esp->es_server.ea_id, outp);
281 PUTSHORT(EAP_HEADERLEN, outp);
283 output(esp->es_unit, outpacket_buf, EAP_HEADERLEN + PPP_HDRLEN);
285 esp->es_server.ea_state = eapBadAuth;
286 auth_peer_fail(esp->es_unit, PPP_EAP);
290 * Format a standard EAP Success message and send it to the peer.
294 eap_send_success(eap_state *esp)
298 outp = outpacket_buf;
300 MAKEHEADER(outp, PPP_EAP);
302 PUTCHAR(EAP_SUCCESS, outp);
303 esp->es_server.ea_id++;
304 PUTCHAR(esp->es_server.ea_id, outp);
305 PUTSHORT(EAP_HEADERLEN, outp);
307 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);
309 auth_peer_success(esp->es_unit, PPP_EAP, 0,
310 esp->es_server.ea_peer, esp->es_server.ea_peerlen);
315 * Set DES key according to pseudonym-generating secret and current
319 pncrypt_setkey(int timeoffs)
324 u_char dig[SHA_DIGESTSIZE];
327 if (pn_secret == NULL)
329 reftime = time(NULL) + timeoffs;
330 tp = localtime(&reftime);
332 SHA1Update(&ctxt, pn_secret, strlen(pn_secret));
333 strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp);
334 SHA1Update(&ctxt, tbuf, strlen(tbuf));
335 SHA1Final(dig, &ctxt);
336 return (DesSetkey(dig));
339 static char base64[] =
340 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
348 b64enc(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
353 bs->bs_bits = (bs->bs_bits << 8) | *inp++;
356 if (bs->bs_offs >= 24) {
357 *outp++ = base64[(bs->bs_bits >> 18) & 0x3F];
358 *outp++ = base64[(bs->bs_bits >> 12) & 0x3F];
359 *outp++ = base64[(bs->bs_bits >> 6) & 0x3F];
360 *outp++ = base64[bs->bs_bits & 0x3F];
370 b64flush(struct b64state *bs, u_char *outp)
374 if (bs->bs_offs == 8) {
375 *outp++ = base64[(bs->bs_bits >> 2) & 0x3F];
376 *outp++ = base64[(bs->bs_bits << 4) & 0x3F];
378 } else if (bs->bs_offs == 16) {
379 *outp++ = base64[(bs->bs_bits >> 10) & 0x3F];
380 *outp++ = base64[(bs->bs_bits >> 4) & 0x3F];
381 *outp++ = base64[(bs->bs_bits << 2) & 0x3F];
390 b64dec(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
396 if ((cp = strchr(base64, *inp++)) == NULL)
398 bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);
401 if (bs->bs_offs >= 8) {
402 *outp++ = bs->bs_bits >> (bs->bs_offs - 8);
412 * Assume that current waiting server state is complete and figure
413 * next state to use based on available authentication data. 'status'
414 * indicates if there was an error in handling the last query. It is
415 * 0 for success and non-zero for failure.
418 eap_figure_next_state(eap_state *esp, int status)
421 unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp;
423 struct t_confent *tce, mytce;
426 int id, i, plen, toffs;
431 struct eaptls_session *ets;
433 char secret[MAXWORDLEN];
434 #endif /* USE_EAPTLS */
436 esp->es_server.ea_timeout = esp->es_savedtime;
438 esp->es_server.ea_prev_state = esp->es_server.ea_state;
439 #endif /* USE_EAPTLS */
440 switch (esp->es_server.ea_state) {
446 /* Discard any previous session. */
447 ts = (struct t_server *)esp->es_server.ea_session;
450 esp->es_server.ea_session = NULL;
451 esp->es_server.ea_skey = NULL;
455 esp->es_server.ea_state = eapBadAuth;
459 /* If we've got a pseudonym, try to decode to real name. */
460 if (esp->es_server.ea_peerlen > SRP_PSEUDO_LEN &&
461 strncmp(esp->es_server.ea_peer, SRP_PSEUDO_ID,
462 SRP_PSEUDO_LEN) == 0 &&
463 (esp->es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 <
465 BZERO(&bs, sizeof (bs));
467 esp->es_server.ea_peer + SRP_PSEUDO_LEN,
468 esp->es_server.ea_peerlen - SRP_PSEUDO_LEN,
471 for (i = 0; i < 5; i++) {
472 pncrypt_setkey(toffs);
474 if (!DesDecrypt(secbuf, clear)) {
475 dbglog("no DES here; cannot decode "
479 id = *(unsigned char *)clear;
480 if (id + 1 <= plen && id + 9 > plen)
483 if (plen % 8 == 0 && i < 5) {
485 * Note that this is always shorter than the
486 * original stored string, so there's no need
489 if ((i = plen = *(unsigned char *)clear) > 7)
491 esp->es_server.ea_peerlen = plen;
492 dp = (unsigned char *)esp->es_server.ea_peer;
493 BCOPY(clear + 1, dp, i);
498 (void) DesDecrypt(sp, dp);
503 esp->es_server.ea_peer[
504 esp->es_server.ea_peerlen] = '\0';
505 dbglog("decoded pseudonym to \"%.*q\"",
506 esp->es_server.ea_peerlen,
507 esp->es_server.ea_peer);
509 dbglog("failed to decode real name");
510 /* Stay in eapIdentfy state; requery */
514 /* Look up user in secrets database. */
515 if (get_srp_secret(esp->es_unit, esp->es_server.ea_peer,
516 esp->es_server.ea_name, (char *)secbuf, 1) != 0) {
517 /* Set up default in case SRP entry is bad */
518 esp->es_server.ea_state = eapMD5Chall;
519 /* Get t_confent based on index in srp-secrets */
520 id = strtol((char *)secbuf, &cp, 10);
521 if (*cp++ != ':' || id < 0)
525 mytce.modulus.data = (u_char *)wkmodulus;
526 mytce.modulus.len = sizeof (wkmodulus);
527 mytce.generator.data = (u_char *)"\002";
528 mytce.generator.len = 1;
530 } else if ((tce = gettcid(id)) != NULL) {
532 * Client will have to verify this modulus/
533 * generator combination, and that will take
534 * a while. Lengthen the timeout here.
536 if (esp->es_server.ea_timeout > 0 &&
537 esp->es_server.ea_timeout < 30)
538 esp->es_server.ea_timeout = 30;
542 if ((cp2 = strchr(cp, ':')) == NULL)
545 tpw.pebuf.name = esp->es_server.ea_peer;
546 tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,
548 tpw.pebuf.password.data = tpw.pwbuf;
549 tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,
551 tpw.pebuf.salt.data = tpw.saltbuf;
552 if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)
554 esp->es_server.ea_session = (void *)ts;
555 esp->es_server.ea_state = eapSRP1;
556 vals[0] = esp->es_server.ea_id + 1;
558 t_serveraddexdata(ts, vals, 2);
559 /* Generate B; must call before t_servergetkey() */
565 if (!get_secret(esp->es_unit, esp->es_server.ea_peer,
566 esp->es_server.ea_name, secret, &secret_len, 1)) {
568 esp->es_server.ea_state = eapTlsStart;
571 #endif /* USE_EAPTLS */
573 esp->es_server.ea_state = eapMD5Chall;
578 /* Initialize ssl session */
579 if(!eaptls_init_ssl_server(esp)) {
580 esp->es_server.ea_state = eapBadAuth;
584 esp->es_server.ea_state = eapTlsRecv;
588 ets = (struct eaptls_session *) esp->es_server.ea_session;
590 if(ets->alert_sent) {
591 esp->es_server.ea_state = eapTlsSendAlert;
596 esp->es_server.ea_state = eapBadAuth;
599 ets = (struct eaptls_session *) esp->es_server.ea_session;
602 esp->es_server.ea_state = eapTlsSendAck;
604 esp->es_server.ea_state = eapTlsSend;
608 ets = (struct eaptls_session *) esp->es_server.ea_session;
611 esp->es_server.ea_state = eapTlsRecvAck;
613 if(SSL_is_init_finished(ets->ssl))
614 esp->es_server.ea_state = eapTlsRecvClient;
616 /* JJK Add "TLS empty record" message here ??? */
617 esp->es_server.ea_state = eapTlsRecv;
621 esp->es_server.ea_state = eapTlsRecv;
627 esp->es_server.ea_state = eapBadAuth;
631 esp->es_server.ea_state = eapTlsSend;
634 case eapTlsSendAlert:
635 esp->es_server.ea_state = eapTlsRecvAlertAck;
637 #endif /* USE_EAPTLS */
641 ts = (struct t_server *)esp->es_server.ea_session;
642 if (ts != NULL && status != 0) {
644 esp->es_server.ea_session = NULL;
645 esp->es_server.ea_skey = NULL;
649 esp->es_server.ea_state = eapMD5Chall;
650 } else if (status != 0 || esp->es_server.ea_session == NULL) {
651 esp->es_server.ea_state = eapBadAuth;
653 esp->es_server.ea_state = eapSRP2;
659 ts = (struct t_server *)esp->es_server.ea_session;
660 if (ts != NULL && status != 0) {
662 esp->es_server.ea_session = NULL;
663 esp->es_server.ea_skey = NULL;
666 if (status != 0 || esp->es_server.ea_session == NULL) {
667 esp->es_server.ea_state = eapBadAuth;
669 esp->es_server.ea_state = eapSRP3;
676 ts = (struct t_server *)esp->es_server.ea_session;
677 if (ts != NULL && status != 0) {
679 esp->es_server.ea_session = NULL;
680 esp->es_server.ea_skey = NULL;
683 if (status != 0 || esp->es_server.ea_session == NULL) {
684 esp->es_server.ea_state = eapBadAuth;
686 esp->es_server.ea_state = eapOpen;
692 esp->es_server.ea_state = eapBadAuth;
694 esp->es_server.ea_state = eapOpen;
699 esp->es_server.ea_state = eapBadAuth;
702 if (esp->es_server.ea_state == eapBadAuth)
703 eap_send_failure(esp);
706 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));
707 #endif /* USE_EAPTLS */
711 * Format an EAP Request message and send it to the peer. Message
712 * type depends on current state. (Server operation)
715 eap_send_request(eap_state *esp)
725 u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp;
731 /* Handle both initial auth and restart */
732 if (esp->es_server.ea_state < eapIdentify &&
733 esp->es_server.ea_state != eapInitial) {
734 esp->es_server.ea_state = eapIdentify;
735 if (explicit_remote) {
737 * If we already know the peer's
738 * unauthenticated name, then there's no
739 * reason to ask. Go to next state instead.
741 esp->es_server.ea_peer = remote_name;
742 esp->es_server.ea_peerlen = strlen(remote_name);
743 eap_figure_next_state(esp, 0);
747 if (esp->es_server.ea_maxrequests > 0 &&
748 esp->es_server.ea_requests >= esp->es_server.ea_maxrequests) {
749 if (esp->es_server.ea_responses > 0)
750 error("EAP: too many Requests sent");
752 error("EAP: no response to Requests");
753 eap_send_failure(esp);
757 outp = outpacket_buf;
759 MAKEHEADER(outp, PPP_EAP);
761 PUTCHAR(EAP_REQUEST, outp);
762 PUTCHAR(esp->es_server.ea_id, outp);
766 switch (esp->es_server.ea_state) {
768 PUTCHAR(EAPT_IDENTITY, outp);
770 challen = strlen(str);
771 BCOPY(str, outp, challen);
772 INCPTR(challen, outp);
776 PUTCHAR(EAPT_MD5CHAP, outp);
778 * pick a random challenge length between
779 * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
781 challen = (drand48() *
782 (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
783 MIN_CHALLENGE_LENGTH;
784 PUTCHAR(challen, outp);
785 esp->es_challen = challen;
786 ptr = esp->es_challenge;
787 while (--challen >= 0)
788 *ptr++ = (u_char) (drand48() * 0x100);
789 BCOPY(esp->es_challenge, outp, esp->es_challen);
790 INCPTR(esp->es_challen, outp);
791 BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
792 INCPTR(esp->es_server.ea_namelen, outp);
797 PUTCHAR(EAPT_TLS, outp);
798 PUTCHAR(EAP_TLS_FLAGS_START, outp);
799 eap_figure_next_state(esp, 0);
803 eaptls_send(esp->es_server.ea_session, &outp);
804 eap_figure_next_state(esp, 0);
808 PUTCHAR(EAPT_TLS, outp);
810 eap_figure_next_state(esp, 0);
813 case eapTlsSendAlert:
814 eaptls_send(esp->es_server.ea_session, &outp);
815 eap_figure_next_state(esp, 0);
817 #endif /* USE_EAPTLS */
821 PUTCHAR(EAPT_SRP, outp);
822 PUTCHAR(EAPSRP_CHALLENGE, outp);
824 PUTCHAR(esp->es_server.ea_namelen, outp);
825 BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
826 INCPTR(esp->es_server.ea_namelen, outp);
828 ts = (struct t_server *)esp->es_server.ea_session;
830 PUTCHAR(ts->s.len, outp);
831 BCOPY(ts->s.data, outp, ts->s.len);
832 INCPTR(ts->s.len, outp);
834 if (ts->g.len == 1 && ts->g.data[0] == 2) {
837 PUTCHAR(ts->g.len, outp);
838 BCOPY(ts->g.data, outp, ts->g.len);
839 INCPTR(ts->g.len, outp);
842 if (ts->n.len != sizeof (wkmodulus) ||
843 BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) {
844 BCOPY(ts->n.data, outp, ts->n.len);
845 INCPTR(ts->n.len, outp);
850 PUTCHAR(EAPT_SRP, outp);
851 PUTCHAR(EAPSRP_SKEY, outp);
853 ts = (struct t_server *)esp->es_server.ea_session;
855 BCOPY(ts->B.data, outp, ts->B.len);
856 INCPTR(ts->B.len, outp);
860 PUTCHAR(EAPT_SRP, outp);
861 PUTCHAR(EAPSRP_SVALIDATOR, outp);
862 PUTLONG(SRPVAL_EBIT, outp);
863 ts = (struct t_server *)esp->es_server.ea_session;
865 BCOPY(t_serverresponse(ts), outp, SHA_DIGESTSIZE);
866 INCPTR(SHA_DIGESTSIZE, outp);
868 if (pncrypt_setkey(0)) {
869 /* Generate pseudonym */
871 cp = (unsigned char *)esp->es_server.ea_peer;
872 if ((j = i = esp->es_server.ea_peerlen) > 7)
875 BCOPY(cp, clear + 1, j);
878 if (!DesEncrypt(clear, cipher)) {
879 dbglog("no DES here; not generating pseudonym");
882 BZERO(&b64, sizeof (b64));
883 outp++; /* space for pseudonym length */
884 outp += b64enc(&b64, cipher, 8, outp);
886 (void) DesEncrypt(cp, cipher);
887 outp += b64enc(&b64, cipher, 8, outp);
895 *cp++ = drand48() * 0x100;
898 (void) DesEncrypt(clear, cipher);
899 outp += b64enc(&b64, cipher, 8, outp);
901 outp += b64flush(&b64, outp);
903 /* Set length and pad out to next 20 octet boundary */
908 while (i < SHA_DIGESTSIZE) {
909 *outp++ = drand48() * 0x100;
914 /* Obscure the pseudonym with SHA1 hash */
916 SHA1Update(&ctxt, &esp->es_server.ea_id, 1);
917 SHA1Update(&ctxt, esp->es_server.ea_skey,
919 SHA1Update(&ctxt, esp->es_server.ea_peer,
920 esp->es_server.ea_peerlen);
921 while (optr < outp) {
922 SHA1Final(dig, &ctxt);
924 while (cp < dig + SHA_DIGESTSIZE)
927 SHA1Update(&ctxt, &esp->es_server.ea_id, 1);
928 SHA1Update(&ctxt, esp->es_server.ea_skey,
930 SHA1Update(&ctxt, optr - SHA_DIGESTSIZE,
937 PUTCHAR(EAPT_SRP, outp);
938 PUTCHAR(EAPSRP_LWRECHALLENGE, outp);
939 challen = MIN_CHALLENGE_LENGTH +
940 ((MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH) * drand48());
941 esp->es_challen = challen;
942 ptr = esp->es_challenge;
943 while (--challen >= 0)
944 *ptr++ = drand48() * 0x100;
945 BCOPY(esp->es_challenge, outp, esp->es_challen);
946 INCPTR(esp->es_challen, outp);
954 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
955 PUTSHORT(outlen, lenloc);
957 output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
959 esp->es_server.ea_requests++;
961 if (esp->es_server.ea_timeout > 0)
962 TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
966 * eap_authpeer - Authenticate our peer (behave as server).
968 * Start server state and send first request. This is called only
972 eap_authpeer(int unit, char *localname)
974 eap_state *esp = &eap_states[unit];
976 /* Save the name we're given. */
977 esp->es_server.ea_name = localname;
978 esp->es_server.ea_namelen = strlen(localname);
980 esp->es_savedtime = esp->es_server.ea_timeout;
982 /* Lower layer up yet? */
983 if (esp->es_server.ea_state == eapInitial ||
984 esp->es_server.ea_state == eapPending) {
985 esp->es_server.ea_state = eapPending;
989 esp->es_server.ea_state = eapPending;
991 /* ID number not updated here intentionally; hashed into M1 */
992 eap_send_request(esp);
996 * eap_server_timeout - Retransmission timer for sending Requests
1000 eap_server_timeout(void *arg)
1006 #endif /* USE_EAPTLS */
1008 eap_state *esp = (eap_state *) arg;
1010 if (!eap_server_active(esp))
1014 switch(esp->es_server.ea_prev_state) {
1017 * In eap-tls the state changes after a request, so we return to
1018 * previous state ...
1021 case(eapTlsSendAck):
1022 esp->es_server.ea_state = esp->es_server.ea_prev_state;
1026 * ... or resend the stored data
1029 case(eapTlsSendAlert):
1030 outp = outpacket_buf;
1031 MAKEHEADER(outp, PPP_EAP);
1032 PUTCHAR(EAP_REQUEST, outp);
1033 PUTCHAR(esp->es_server.ea_id, outp);
1037 eaptls_retransmit(esp->es_server.ea_session, &outp);
1039 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1040 PUTSHORT(outlen, lenloc);
1041 output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
1042 esp->es_server.ea_requests++;
1044 if (esp->es_server.ea_timeout > 0)
1045 TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
1051 #endif /* USE_EAPTLS */
1053 /* EAP ID number must not change on timeout. */
1054 eap_send_request(esp);
1058 * When it's time to send rechallenge the peer, this timeout is
1059 * called. Once the rechallenge is successful, the response handler
1060 * will restart the timer. If it fails, then the link is dropped.
1063 eap_rechallenge(void *arg)
1065 eap_state *esp = (eap_state *)arg;
1067 if (esp->es_server.ea_state != eapOpen &&
1068 esp->es_server.ea_state != eapSRP4)
1071 esp->es_server.ea_requests = 0;
1072 esp->es_server.ea_state = eapIdentify;
1073 eap_figure_next_state(esp, 0);
1074 esp->es_server.ea_id++;
1075 eap_send_request(esp);
1079 srp_lwrechallenge(void *arg)
1081 eap_state *esp = (eap_state *)arg;
1083 if (esp->es_server.ea_state != eapOpen ||
1084 esp->es_server.ea_type != EAPT_SRP)
1087 esp->es_server.ea_requests = 0;
1088 esp->es_server.ea_state = eapSRP4;
1089 esp->es_server.ea_id++;
1090 eap_send_request(esp);
1094 * eap_lowerup - The lower layer is now up.
1096 * This is called before either eap_authpeer or eap_authwithpeer. See
1097 * link_established() in auth.c. All that's necessary here is to
1098 * return to closed state so that those two routines will do the right
1102 eap_lowerup(int unit)
1104 eap_state *esp = &eap_states[unit];
1106 /* Discard any (possibly authenticated) peer name. */
1107 if (esp->es_server.ea_peer != NULL &&
1108 esp->es_server.ea_peer != remote_name)
1109 free(esp->es_server.ea_peer);
1110 esp->es_server.ea_peer = NULL;
1111 if (esp->es_client.ea_peer != NULL)
1112 free(esp->es_client.ea_peer);
1113 esp->es_client.ea_peer = NULL;
1115 esp->es_client.ea_state = eapClosed;
1116 esp->es_server.ea_state = eapClosed;
1120 * eap_lowerdown - The lower layer is now down.
1122 * Cancel all timeouts and return to initial state.
1125 eap_lowerdown(int unit)
1127 eap_state *esp = &eap_states[unit];
1129 if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) {
1130 UNTIMEOUT(eap_client_timeout, (void *)esp);
1132 if (eap_server_active(esp)) {
1133 if (esp->es_server.ea_timeout > 0) {
1134 UNTIMEOUT(eap_server_timeout, (void *)esp);
1137 if ((esp->es_server.ea_state == eapOpen ||
1138 esp->es_server.ea_state == eapSRP4) &&
1139 esp->es_rechallenge > 0) {
1140 UNTIMEOUT(eap_rechallenge, (void *)esp);
1142 if (esp->es_server.ea_state == eapOpen &&
1143 esp->es_lwrechallenge > 0) {
1144 UNTIMEOUT(srp_lwrechallenge, (void *)esp);
1148 esp->es_client.ea_state = esp->es_server.ea_state = eapInitial;
1149 esp->es_client.ea_requests = esp->es_server.ea_requests = 0;
1153 * eap_protrej - Peer doesn't speak this protocol.
1155 * This shouldn't happen. If it does, it represents authentication
1159 eap_protrej(int unit)
1161 eap_state *esp = &eap_states[unit];
1163 if (eap_client_active(esp)) {
1164 error("EAP authentication failed due to Protocol-Reject");
1165 auth_withpeer_fail(unit, PPP_EAP);
1167 if (eap_server_active(esp)) {
1168 error("EAP authentication of peer failed on Protocol-Reject");
1169 auth_peer_fail(unit, PPP_EAP);
1171 eap_lowerdown(unit);
1175 * Format and send a regular EAP Response message.
1178 eap_send_response(eap_state *esp, u_char id, u_char typenum,
1179 u_char *str, int lenstr)
1184 outp = outpacket_buf;
1186 MAKEHEADER(outp, PPP_EAP);
1188 PUTCHAR(EAP_RESPONSE, outp);
1190 esp->es_client.ea_id = id;
1191 msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr;
1192 PUTSHORT(msglen, outp);
1193 PUTCHAR(typenum, outp);
1195 BCOPY(str, outp, lenstr);
1198 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1202 * Format and send an MD5-Challenge EAP Response message.
1205 eap_chap_response(eap_state *esp, u_char id, u_char *hash,
1206 char *name, int namelen)
1211 outp = outpacket_buf;
1213 MAKEHEADER(outp, PPP_EAP);
1215 PUTCHAR(EAP_RESPONSE, outp);
1217 esp->es_client.ea_id = id;
1218 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE +
1220 PUTSHORT(msglen, outp);
1221 PUTCHAR(EAPT_MD5CHAP, outp);
1222 PUTCHAR(MD5_SIGNATURE_SIZE, outp);
1223 BCOPY(hash, outp, MD5_SIGNATURE_SIZE);
1224 INCPTR(MD5_SIGNATURE_SIZE, outp);
1226 BCOPY(name, outp, namelen);
1229 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1234 * Format and send a SRP EAP Response message.
1237 eap_srp_response(eap_state *esp, u_char id, u_char subtypenum,
1238 u_char *str, int lenstr)
1243 outp = outpacket_buf;
1245 MAKEHEADER(outp, PPP_EAP);
1247 PUTCHAR(EAP_RESPONSE, outp);
1249 esp->es_client.ea_id = id;
1250 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr;
1251 PUTSHORT(msglen, outp);
1252 PUTCHAR(EAPT_SRP, outp);
1253 PUTCHAR(subtypenum, outp);
1255 BCOPY(str, outp, lenstr);
1258 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1262 * Format and send a SRP EAP Client Validator Response message.
1265 eap_srpval_response(eap_state *esp, u_char id, u_int32_t flags, u_char *str)
1270 outp = outpacket_buf;
1272 MAKEHEADER(outp, PPP_EAP);
1274 PUTCHAR(EAP_RESPONSE, outp);
1276 esp->es_client.ea_id = id;
1277 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) +
1279 PUTSHORT(msglen, outp);
1280 PUTCHAR(EAPT_SRP, outp);
1281 PUTCHAR(EAPSRP_CVALIDATOR, outp);
1282 PUTLONG(flags, outp);
1283 BCOPY(str, outp, SHA_DIGESTSIZE);
1285 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1287 #endif /* USE_SRP */
1291 * Send an EAP-TLS response message with tls data
1294 eap_tls_response(eap_state *esp, u_char id)
1300 outp = outpacket_buf;
1302 MAKEHEADER(outp, PPP_EAP);
1304 PUTCHAR(EAP_RESPONSE, outp);
1311 If the id in the request is unchanged, we must retransmit
1314 if(id == esp->es_client.ea_id)
1315 eaptls_retransmit(esp->es_client.ea_session, &outp);
1317 eaptls_send(esp->es_client.ea_session, &outp);
1319 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1320 PUTSHORT(outlen, lenloc);
1322 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1324 esp->es_client.ea_id = id;
1328 * Send an EAP-TLS ack
1331 eap_tls_sendack(eap_state *esp, u_char id)
1337 outp = outpacket_buf;
1339 MAKEHEADER(outp, PPP_EAP);
1341 PUTCHAR(EAP_RESPONSE, outp);
1343 esp->es_client.ea_id = id;
1348 PUTCHAR(EAPT_TLS, outp);
1351 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1352 PUTSHORT(outlen, lenloc);
1354 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1356 #endif /* USE_EAPTLS */
1359 eap_send_nak(eap_state *esp, u_char id, u_char type)
1364 outp = outpacket_buf;
1366 MAKEHEADER(outp, PPP_EAP);
1368 PUTCHAR(EAP_RESPONSE, outp);
1370 esp->es_client.ea_id = id;
1371 msglen = EAP_HEADERLEN + 2 * sizeof (u_char);
1372 PUTSHORT(msglen, outp);
1373 PUTCHAR(EAPT_NAK, outp);
1374 PUTCHAR(type, outp);
1376 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1381 name_of_pn_file(void)
1383 char *user, *path, *file;
1386 static bool pnlogged = 0;
1388 pw = getpwuid(getuid());
1389 if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
1393 file = _PATH_PSEUDONYM;
1394 pl = strlen(user) + strlen(file) + 2;
1398 (void) slprintf(path, pl, "%s/%s", user, file);
1400 dbglog("pseudonym file: %s", path);
1407 open_pn_file(mode_t modebits)
1412 if ((path = name_of_pn_file()) == NULL)
1414 fd = open(path, modebits, S_IRUSR | S_IWUSR);
1422 remove_pn_file(void)
1426 if ((path = name_of_pn_file()) != NULL) {
1427 (void) unlink(path);
1433 write_pseudonym(eap_state *esp, u_char *inp, int len, int id)
1436 u_char *datp, *digp;
1438 u_char dig[SHA_DIGESTSIZE];
1439 int dsize, fd, olen = len;
1442 * Do the decoding by working backwards. This eliminates the need
1443 * to save the decoded output in a separate buffer.
1447 if ((dsize = len % SHA_DIGESTSIZE) == 0)
1448 dsize = SHA_DIGESTSIZE;
1452 SHA1Update(&ctxt, &val, 1);
1453 SHA1Update(&ctxt, esp->es_client.ea_skey, SESSION_KEY_LEN);
1455 SHA1Update(&ctxt, datp, SHA_DIGESTSIZE);
1457 SHA1Update(&ctxt, esp->es_client.ea_name,
1458 esp->es_client.ea_namelen);
1460 SHA1Final(dig, &ctxt);
1461 for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++)
1465 /* Now check that the result is sane */
1466 if (olen <= 0 || *inp + 1 > olen) {
1467 dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp);
1472 fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);
1474 dbglog("EAP: error saving pseudonym: %m");
1477 len = write(fd, inp + 1, *inp);
1478 if (close(fd) != -1 && len == *inp) {
1479 dbglog("EAP: saved pseudonym");
1480 esp->es_usedpseudo = 0;
1482 dbglog("EAP: failed to save pseudonym");
1486 #endif /* USE_SRP */
1489 * eap_request - Receive EAP Request message (client mode).
1492 eap_request(eap_state *esp, u_char *inp, int id, int len)
1497 char secret[MAXWORDLEN];
1498 char rhostname[256];
1500 u_char hash[MD5_SIGNATURE_SIZE];
1503 struct eaptls_session *ets = esp->es_client.ea_session;
1504 #endif /* USE_EAPTLS */
1507 struct t_client *tc;
1508 struct t_num sval, gval, Nval, *Ap, Bval;
1511 u_char dig[SHA_DIGESTSIZE];
1513 #endif /* USE_SRP */
1516 * Ignore requests if we're not open
1518 if (esp->es_client.ea_state <= eapClosed)
1522 * Note: we update es_client.ea_id *only if* a Response
1523 * message is being generated. Otherwise, we leave it the
1524 * same for duplicate detection purposes.
1527 esp->es_client.ea_requests++;
1528 if (esp->es_client.ea_maxrequests != 0 &&
1529 esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {
1530 info("EAP: received too many Request messages");
1531 if (esp->es_client.ea_timeout > 0) {
1532 UNTIMEOUT(eap_client_timeout, (void *)esp);
1534 auth_withpeer_fail(esp->es_unit, PPP_EAP);
1539 error("EAP: empty Request message discarded");
1543 GETCHAR(typenum, inp);
1549 info("EAP: Identity prompt \"%.*q\"", len, inp);
1551 if (esp->es_usepseudo &&
1552 (esp->es_usedpseudo == 0 ||
1553 (esp->es_usedpseudo == 1 &&
1554 id == esp->es_client.ea_id))) {
1555 esp->es_usedpseudo = 1;
1556 /* Try to get a pseudonym */
1557 if ((fd = open_pn_file(O_RDONLY)) >= 0) {
1558 strcpy(rhostname, SRP_PSEUDO_ID);
1559 len = read(fd, rhostname + SRP_PSEUDO_LEN,
1560 sizeof (rhostname) - SRP_PSEUDO_LEN);
1561 /* XXX NAI unsupported */
1563 eap_send_response(esp, id, typenum,
1564 rhostname, len + SRP_PSEUDO_LEN);
1571 /* Stop using pseudonym now. */
1572 if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
1574 esp->es_usedpseudo = 2;
1576 #endif /* USE_SRP */
1577 eap_send_response(esp, id, typenum, (u_char *)esp->es_client.ea_name,
1578 esp->es_client.ea_namelen);
1581 case EAPT_NOTIFICATION:
1583 info("EAP: Notification \"%.*q\"", len, inp);
1584 eap_send_response(esp, id, typenum, NULL, 0);
1589 * Avoid the temptation to send Response Nak in reply
1590 * to Request Nak here. It can only lead to trouble.
1592 warn("EAP: unexpected Nak in Request; ignored");
1593 /* Return because we're waiting for something real. */
1598 error("EAP: received MD5-Challenge with no data");
1599 /* Bogus request; wait for something real. */
1602 GETCHAR(vallen, inp);
1604 if (vallen < 8 || vallen > len) {
1605 error("EAP: MD5-Challenge with bad length %d (8..%d)",
1607 /* Try something better. */
1608 eap_send_nak(esp, id, EAPT_SRP);
1612 /* Not so likely to happen. */
1613 if (len - vallen >= sizeof (rhostname)) {
1614 dbglog("EAP: trimming really long peer name down");
1615 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1616 rhostname[sizeof (rhostname) - 1] = '\0';
1618 BCOPY(inp + vallen, rhostname, len - vallen);
1619 rhostname[len - vallen] = '\0';
1622 /* In case the remote doesn't give us his name. */
1623 if (explicit_remote ||
1624 (remote_name[0] != '\0' && vallen == len))
1625 strlcpy(rhostname, remote_name, sizeof (rhostname));
1628 * Get the secret for authenticating ourselves with
1629 * the specified host.
1631 if (!get_secret(esp->es_unit, esp->es_client.ea_name,
1632 rhostname, secret, &secret_len, 0)) {
1633 dbglog("EAP: no MD5 secret for auth to %q", rhostname);
1634 eap_send_nak(esp, id, EAPT_SRP);
1637 MD5_Init(&mdContext);
1639 MD5_Update(&mdContext, &typenum, 1);
1640 MD5_Update(&mdContext, (u_char *)secret, secret_len);
1641 BZERO(secret, sizeof (secret));
1642 MD5_Update(&mdContext, inp, vallen);
1643 MD5_Final(hash, &mdContext);
1644 eap_chap_response(esp, id, hash, esp->es_client.ea_name,
1645 esp->es_client.ea_namelen);
1651 switch(esp->es_client.ea_state) {
1656 error("EAP: received EAP-TLS Listen packet with no data");
1657 /* Bogus request; wait for something real. */
1660 GETCHAR(flags, inp);
1661 if(flags & EAP_TLS_FLAGS_START){
1663 esp->es_client.ea_using_eaptls = 1;
1665 if (explicit_remote){
1666 esp->es_client.ea_peer = strdup(remote_name);
1667 esp->es_client.ea_peerlen = strlen(remote_name);
1669 esp->es_client.ea_peer = NULL;
1671 /* Init ssl session */
1672 if(!eaptls_init_ssl_client(esp)) {
1673 dbglog("cannot init ssl");
1674 eap_send_nak(esp, id, EAPT_TLS);
1675 esp->es_client.ea_using_eaptls = 0;
1679 ets = esp->es_client.ea_session;
1680 eap_tls_response(esp, id);
1681 esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1685 /* The server has sent a bad start packet. */
1686 eap_send_nak(esp, id, EAPT_TLS);
1690 eap_tls_response(esp, id);
1691 esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1696 error("EAP: discarding EAP-TLS Receive packet with no data");
1697 /* Bogus request; wait for something real. */
1700 eaptls_receive(ets, inp, len);
1703 eap_tls_sendack(esp, id);
1704 esp->es_client.ea_state = eapTlsRecv;
1708 if(ets->alert_recv) {
1709 eap_tls_sendack(esp, id);
1710 esp->es_client.ea_state = eapTlsRecvFailure;
1714 /* Check if TLS handshake is finished */
1715 if(eaptls_is_init_finished(ets)) {
1717 eaptls_gen_mppe_keys(ets, 1);
1719 eaptls_free_session(ets);
1720 eap_tls_sendack(esp, id);
1721 esp->es_client.ea_state = eapTlsRecvSuccess;
1725 eap_tls_response(esp,id);
1726 esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1730 eap_send_nak(esp, id, EAPT_TLS);
1731 esp->es_client.ea_using_eaptls = 0;
1736 #endif /* USE_EAPTLS */
1741 error("EAP: received empty SRP Request");
1742 /* Bogus request; wait for something real. */
1747 GETCHAR(vallen, inp);
1750 case EAPSRP_CHALLENGE:
1752 if (esp->es_client.ea_session != NULL) {
1753 tc = (struct t_client *)esp->es_client.
1756 * If this is a new challenge, then start
1757 * over with a new client session context.
1758 * Otherwise, just resend last response.
1760 if (id != esp->es_client.ea_id) {
1762 esp->es_client.ea_session = NULL;
1766 /* No session key just yet */
1767 esp->es_client.ea_skey = NULL;
1769 GETCHAR(vallen, inp);
1771 if (vallen >= len) {
1772 error("EAP: badly-formed SRP Challenge"
1774 /* Ignore badly-formed messages */
1777 BCOPY(inp, rhostname, vallen);
1778 rhostname[vallen] = '\0';
1779 INCPTR(vallen, inp);
1783 * In case the remote doesn't give us his name,
1784 * use configured name.
1786 if (explicit_remote ||
1787 (remote_name[0] != '\0' && vallen == 0)) {
1788 strlcpy(rhostname, remote_name,
1789 sizeof (rhostname));
1792 if (esp->es_client.ea_peer != NULL)
1793 free(esp->es_client.ea_peer);
1794 esp->es_client.ea_peer = strdup(rhostname);
1795 esp->es_client.ea_peerlen = strlen(rhostname);
1797 GETCHAR(vallen, inp);
1799 if (vallen >= len) {
1800 error("EAP: badly-formed SRP Challenge"
1802 /* Ignore badly-formed messages */
1807 INCPTR(vallen, inp);
1810 GETCHAR(vallen, inp);
1813 error("EAP: badly-formed SRP Challenge"
1815 /* Ignore badly-formed messages */
1818 /* If no generator present, then use value 2 */
1820 gval.data = (u_char *)"\002";
1826 INCPTR(vallen, inp);
1830 * If no modulus present, then use well-known
1834 Nval.data = (u_char *)wkmodulus;
1835 Nval.len = sizeof (wkmodulus);
1840 tc = t_clientopen(esp->es_client.ea_name,
1841 &Nval, &gval, &sval);
1843 eap_send_nak(esp, id, EAPT_MD5CHAP);
1846 esp->es_client.ea_session = (void *)tc;
1848 /* Add Challenge ID & type to verifier */
1851 t_clientaddexdata(tc, vals, 2);
1853 Ap = t_clientgenexp(tc);
1854 eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
1859 tc = (struct t_client *)esp->es_client.ea_session;
1861 warn("EAP: peer sent Subtype 2 without 1");
1862 eap_send_nak(esp, id, EAPT_MD5CHAP);
1865 if (esp->es_client.ea_skey != NULL) {
1867 * ID number should not change here. Warn
1868 * if it does (but otherwise ignore).
1870 if (id != esp->es_client.ea_id) {
1871 warn("EAP: ID changed from %d to %d "
1872 "in SRP Subtype 2 rexmit",
1873 esp->es_client.ea_id, id);
1876 if (get_srp_secret(esp->es_unit,
1877 esp->es_client.ea_name,
1878 esp->es_client.ea_peer, secret, 0) == 0) {
1880 * Can't work with this peer because
1881 * the secret is missing. Just give
1884 eap_send_nak(esp, id, EAPT_MD5CHAP);
1889 t_clientpasswd(tc, secret);
1890 BZERO(secret, sizeof (secret));
1891 esp->es_client.ea_skey =
1892 t_clientgetkey(tc, &Bval);
1893 if (esp->es_client.ea_skey == NULL) {
1894 /* Server is rogue; stop now */
1895 error("EAP: SRP server is rogue");
1896 goto client_failure;
1899 eap_srpval_response(esp, id, SRPVAL_EBIT,
1900 t_clientresponse(tc));
1903 case EAPSRP_SVALIDATOR:
1904 tc = (struct t_client *)esp->es_client.ea_session;
1905 if (tc == NULL || esp->es_client.ea_skey == NULL) {
1906 warn("EAP: peer sent Subtype 3 without 1/2");
1907 eap_send_nak(esp, id, EAPT_MD5CHAP);
1911 * If we're already open, then this ought to be a
1912 * duplicate. Otherwise, check that the server is
1913 * who we think it is.
1915 if (esp->es_client.ea_state == eapOpen) {
1916 if (id != esp->es_client.ea_id) {
1917 warn("EAP: ID changed from %d to %d "
1918 "in SRP Subtype 3 rexmit",
1919 esp->es_client.ea_id, id);
1922 len -= sizeof (u_int32_t) + SHA_DIGESTSIZE;
1923 if (len < 0 || t_clientverify(tc, inp +
1924 sizeof (u_int32_t)) != 0) {
1925 error("EAP: SRP server verification "
1927 goto client_failure;
1929 GETLONG(esp->es_client.ea_keyflags, inp);
1930 /* Save pseudonym if user wants it. */
1931 if (len > 0 && esp->es_usepseudo) {
1932 INCPTR(SHA_DIGESTSIZE, inp);
1933 write_pseudonym(esp, inp, len, id);
1937 * We've verified our peer. We're now mostly done,
1938 * except for waiting on the regular EAP Success
1941 eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
1944 case EAPSRP_LWRECHALLENGE:
1946 warn("EAP: malformed Lightweight rechallenge");
1951 SHA1Update(&ctxt, vals, 1);
1952 SHA1Update(&ctxt, esp->es_client.ea_skey,
1954 SHA1Update(&ctxt, inp, len);
1955 SHA1Update(&ctxt, esp->es_client.ea_name,
1956 esp->es_client.ea_namelen);
1957 SHA1Final(dig, &ctxt);
1958 eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
1963 error("EAP: unknown SRP Subtype %d", vallen);
1964 eap_send_nak(esp, id, EAPT_MD5CHAP);
1968 #endif /* USE_SRP */
1971 info("EAP: unknown authentication type %d; Naking", typenum);
1972 eap_send_nak(esp, id, EAPT_SRP);
1976 if (esp->es_client.ea_timeout > 0) {
1977 UNTIMEOUT(eap_client_timeout, (void *)esp);
1978 TIMEOUT(eap_client_timeout, (void *)esp,
1979 esp->es_client.ea_timeout);
1985 esp->es_client.ea_state = eapBadAuth;
1986 if (esp->es_client.ea_timeout > 0) {
1987 UNTIMEOUT(eap_client_timeout, (void *)esp);
1989 esp->es_client.ea_session = NULL;
1991 auth_withpeer_fail(esp->es_unit, PPP_EAP);
1992 #endif /* USE_SRP */
1996 * eap_response - Receive EAP Response message (server mode).
1999 eap_response(eap_state *esp, u_char *inp, int id, int len)
2004 char secret[MAXSECRETLEN];
2005 char rhostname[256];
2007 u_char hash[MD5_SIGNATURE_SIZE];
2009 struct t_server *ts;
2012 u_char dig[SHA_DIGESTSIZE];
2014 u_char dig[SHA_DIGESTSIZE];
2015 #endif /* USE_SRP */
2018 struct eaptls_session *ets;
2020 #endif /* USE_EAPTLS */
2023 * Ignore responses if we're not open
2025 if (esp->es_server.ea_state <= eapClosed)
2028 if (esp->es_server.ea_id != id) {
2029 dbglog("EAP: discarding Response %d; expected ID %d", id,
2030 esp->es_server.ea_id);
2034 esp->es_server.ea_responses++;
2037 error("EAP: empty Response message discarded");
2041 GETCHAR(typenum, inp);
2046 if (esp->es_server.ea_state != eapIdentify) {
2047 dbglog("EAP discarding unwanted Identify \"%.q\"", len,
2051 info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
2052 if (esp->es_server.ea_peer != NULL &&
2053 esp->es_server.ea_peer != remote_name)
2054 free(esp->es_server.ea_peer);
2055 esp->es_server.ea_peer = malloc(len + 1);
2056 if (esp->es_server.ea_peer == NULL) {
2057 esp->es_server.ea_peerlen = 0;
2058 eap_figure_next_state(esp, 1);
2061 BCOPY(inp, esp->es_server.ea_peer, len);
2062 esp->es_server.ea_peer[len] = '\0';
2063 esp->es_server.ea_peerlen = len;
2064 eap_figure_next_state(esp, 0);
2069 switch(esp->es_server.ea_state) {
2073 ets = (struct eaptls_session *) esp->es_server.ea_session;
2075 eap_figure_next_state(esp,
2076 eaptls_receive(esp->es_server.ea_session, inp, len));
2078 if(ets->alert_recv) {
2079 eap_send_failure(esp);
2086 dbglog("EAP-TLS ACK with extra data");
2088 eap_figure_next_state(esp, 0);
2091 case eapTlsRecvClient:
2092 /* Receive authentication response from client */
2094 GETCHAR(flags, inp);
2096 if(len == 1 && !flags) { /* Ack = ok */
2098 eaptls_gen_mppe_keys( esp->es_server.ea_session, 0 );
2100 eap_send_success(esp);
2102 else { /* failure */
2103 warn("Server authentication failed");
2104 eap_send_failure(esp);
2108 warn("Bogus EAP-TLS packet received from client");
2110 eaptls_free_session(esp->es_server.ea_session);
2114 case eapTlsRecvAlertAck:
2115 eap_send_failure(esp);
2119 eap_figure_next_state(esp, 1);
2123 #endif /* USE_EAPTLS */
2125 case EAPT_NOTIFICATION:
2126 dbglog("EAP unexpected Notification; response discarded");
2131 info("EAP: Nak Response with no suggested protocol");
2132 eap_figure_next_state(esp, 1);
2136 GETCHAR(vallen, inp);
2139 if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
2140 /* Peer cannot Nak Identify Request */
2141 eap_figure_next_state(esp, 1);
2147 /* Run through SRP validator selection again. */
2148 esp->es_server.ea_state = eapIdentify;
2149 eap_figure_next_state(esp, 0);
2153 esp->es_server.ea_state = eapMD5Chall;
2157 /* Send EAP-TLS start packet */
2159 esp->es_server.ea_state = eapTlsStart;
2161 #endif /* USE_EAPTLS */
2164 dbglog("EAP: peer requesting unknown Type %d", vallen);
2165 switch (esp->es_server.ea_state) {
2169 esp->es_server.ea_state = eapMD5Chall;
2173 esp->es_server.ea_state = eapIdentify;
2174 eap_figure_next_state(esp, 0);
2184 if (esp->es_server.ea_state != eapMD5Chall) {
2185 error("EAP: unexpected MD5-Response");
2186 eap_figure_next_state(esp, 1);
2190 error("EAP: received MD5-Response with no data");
2191 eap_figure_next_state(esp, 1);
2194 GETCHAR(vallen, inp);
2196 if (vallen != 16 || vallen > len) {
2197 error("EAP: MD5-Response with bad length %d", vallen);
2198 eap_figure_next_state(esp, 1);
2202 /* Not so likely to happen. */
2203 if (len - vallen >= sizeof (rhostname)) {
2204 dbglog("EAP: trimming really long peer name down");
2205 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2206 rhostname[sizeof (rhostname) - 1] = '\0';
2208 BCOPY(inp + vallen, rhostname, len - vallen);
2209 rhostname[len - vallen] = '\0';
2212 /* In case the remote doesn't give us his name. */
2213 if (explicit_remote ||
2214 (remote_name[0] != '\0' && vallen == len))
2215 strlcpy(rhostname, remote_name, sizeof (rhostname));
2218 * Get the secret for authenticating the specified
2221 if (!get_secret(esp->es_unit, rhostname,
2222 esp->es_server.ea_name, secret, &secret_len, 1)) {
2223 dbglog("EAP: no MD5 secret for auth of %q", rhostname);
2224 eap_send_failure(esp);
2227 MD5_Init(&mdContext);
2228 MD5_Update(&mdContext, &esp->es_server.ea_id, 1);
2229 MD5_Update(&mdContext, (u_char *)secret, secret_len);
2230 BZERO(secret, sizeof (secret));
2231 MD5_Update(&mdContext, esp->es_challenge, esp->es_challen);
2232 MD5_Final(hash, &mdContext);
2233 if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) {
2234 eap_send_failure(esp);
2237 esp->es_server.ea_type = EAPT_MD5CHAP;
2238 eap_send_success(esp);
2239 eap_figure_next_state(esp, 0);
2240 if (esp->es_rechallenge != 0)
2241 TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2247 error("EAP: empty SRP Response");
2248 eap_figure_next_state(esp, 1);
2251 GETCHAR(typenum, inp);
2255 if (esp->es_server.ea_state != eapSRP1) {
2256 error("EAP: unexpected SRP Subtype 1 Response");
2257 eap_figure_next_state(esp, 1);
2262 ts = (struct t_server *)esp->es_server.ea_session;
2264 esp->es_server.ea_skey = t_servergetkey(ts, &A);
2265 if (esp->es_server.ea_skey == NULL) {
2266 /* Client's A value is bogus; terminate now */
2267 error("EAP: bogus A value from client");
2268 eap_send_failure(esp);
2270 eap_figure_next_state(esp, 0);
2274 case EAPSRP_CVALIDATOR:
2275 if (esp->es_server.ea_state != eapSRP2) {
2276 error("EAP: unexpected SRP Subtype 2 Response");
2277 eap_figure_next_state(esp, 1);
2280 if (len < sizeof (u_int32_t) + SHA_DIGESTSIZE) {
2281 error("EAP: M1 length %d < %d", len,
2282 sizeof (u_int32_t) + SHA_DIGESTSIZE);
2283 eap_figure_next_state(esp, 1);
2286 GETLONG(esp->es_server.ea_keyflags, inp);
2287 ts = (struct t_server *)esp->es_server.ea_session;
2289 if (t_serververify(ts, inp)) {
2290 info("EAP: unable to validate client identity");
2291 eap_send_failure(esp);
2294 eap_figure_next_state(esp, 0);
2298 if (esp->es_server.ea_state != eapSRP3) {
2299 error("EAP: unexpected SRP Subtype 3 Response");
2300 eap_send_failure(esp);
2303 esp->es_server.ea_type = EAPT_SRP;
2304 eap_send_success(esp);
2305 eap_figure_next_state(esp, 0);
2306 if (esp->es_rechallenge != 0)
2307 TIMEOUT(eap_rechallenge, esp,
2308 esp->es_rechallenge);
2309 if (esp->es_lwrechallenge != 0)
2310 TIMEOUT(srp_lwrechallenge, esp,
2311 esp->es_lwrechallenge);
2314 case EAPSRP_LWRECHALLENGE:
2315 if (esp->es_server.ea_state != eapSRP4) {
2316 info("EAP: unexpected SRP Subtype 4 Response");
2319 if (len != SHA_DIGESTSIZE) {
2320 error("EAP: bad Lightweight rechallenge "
2326 SHA1Update(&ctxt, &vallen, 1);
2327 SHA1Update(&ctxt, esp->es_server.ea_skey,
2329 SHA1Update(&ctxt, esp->es_challenge, esp->es_challen);
2330 SHA1Update(&ctxt, esp->es_server.ea_peer,
2331 esp->es_server.ea_peerlen);
2332 SHA1Final(dig, &ctxt);
2333 if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) {
2334 error("EAP: failed Lightweight rechallenge");
2335 eap_send_failure(esp);
2338 esp->es_server.ea_state = eapOpen;
2339 if (esp->es_lwrechallenge != 0)
2340 TIMEOUT(srp_lwrechallenge, esp,
2341 esp->es_lwrechallenge);
2345 #endif /* USE_SRP */
2348 /* This can't happen. */
2349 error("EAP: unknown Response type %d; ignored", typenum);
2353 if (esp->es_server.ea_timeout > 0) {
2354 UNTIMEOUT(eap_server_timeout, (void *)esp);
2357 if (esp->es_server.ea_state != eapBadAuth &&
2358 esp->es_server.ea_state != eapOpen) {
2359 esp->es_server.ea_id++;
2360 eap_send_request(esp);
2365 * eap_success - Receive EAP Success message (client mode).
2368 eap_success(eap_state *esp, u_char *inp, int id, int len)
2370 if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
2372 && esp->es_client.ea_state != eapTlsRecvSuccess
2373 #endif /* USE_EAPTLS */
2375 dbglog("EAP unexpected success message in state %s (%d)",
2376 eap_state_name(esp->es_client.ea_state),
2377 esp->es_client.ea_state);
2382 if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state !=
2383 eapTlsRecvSuccess) {
2384 dbglog("EAP-TLS unexpected success message in state %s (%d)",
2385 eap_state_name(esp->es_client.ea_state),
2386 esp->es_client.ea_state);
2389 #endif /* USE_EAPTLS */
2391 if (esp->es_client.ea_timeout > 0) {
2392 UNTIMEOUT(eap_client_timeout, (void *)esp);
2396 /* This is odd. The spec doesn't allow for this. */
2400 esp->es_client.ea_state = eapOpen;
2401 auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2405 * eap_failure - Receive EAP Failure message (client mode).
2408 eap_failure(eap_state *esp, u_char *inp, int id, int len)
2411 * Ignore failure messages if we're not open
2413 if (esp->es_client.ea_state <= eapClosed)
2416 if (!eap_client_active(esp)) {
2417 dbglog("EAP unexpected failure message in state %s (%d)",
2418 eap_state_name(esp->es_client.ea_state),
2419 esp->es_client.ea_state);
2422 if (esp->es_client.ea_timeout > 0) {
2423 UNTIMEOUT(eap_client_timeout, (void *)esp);
2427 /* This is odd. The spec doesn't allow for this. */
2431 esp->es_client.ea_state = eapBadAuth;
2433 error("EAP: peer reports authentication failure");
2434 auth_withpeer_fail(esp->es_unit, PPP_EAP);
2438 * eap_input - Handle received EAP message.
2441 eap_input(int unit, u_char *inp, int inlen)
2443 eap_state *esp = &eap_states[unit];
2448 * Parse header (code, id and length). If packet too short,
2451 if (inlen < EAP_HEADERLEN) {
2452 error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2458 if (len < EAP_HEADERLEN || len > inlen) {
2459 error("EAP: packet has illegal length field %d (%d..%d)", len,
2460 EAP_HEADERLEN, inlen);
2463 len -= EAP_HEADERLEN;
2465 /* Dispatch based on message code */
2468 eap_request(esp, inp, id, len);
2472 eap_response(esp, inp, id, len);
2476 eap_success(esp, inp, id, len);
2480 eap_failure(esp, inp, id, len);
2483 default: /* XXX Need code reject */
2484 /* Note: it's not legal to send EAP Nak here. */
2485 warn("EAP: unknown code %d received", code);
2491 * eap_printpkt - print the contents of an EAP packet.
2493 static char *eap_codenames[] = {
2494 "Request", "Response", "Success", "Failure"
2497 static char *eap_typenames[] = {
2498 "Identity", "Notification", "Nak", "MD5-Challenge",
2499 "OTP", "Generic-Token", NULL, NULL,
2500 "RSA", "DSS", "KEA", "KEA-Validate",
2501 "TLS", "Defender", "Windows 2000", "Arcot",
2502 "Cisco", "Nokia", "SRP"
2506 eap_printpkt(u_char *inp, int inlen,
2507 void (*printer) (void *, char *, ...), void *arg)
2509 int code, id, len, rtype, vallen;
2514 #endif /* USE_EAPTLS */
2516 if (inlen < EAP_HEADERLEN)
2522 if (len < EAP_HEADERLEN || len > inlen)
2525 if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
2526 printer(arg, " %s", eap_codenames[code-1]);
2528 printer(arg, " code=0x%x", code);
2529 printer(arg, " id=0x%x", id);
2530 len -= EAP_HEADERLEN;
2534 printer(arg, " <missing type>");
2537 GETCHAR(rtype, inp);
2540 rtype <= sizeof (eap_typenames) / sizeof (char *))
2541 printer(arg, " %s", eap_typenames[rtype-1]);
2543 printer(arg, " type=0x%x", rtype);
2546 case EAPT_NOTIFICATION:
2548 printer(arg, " <Message ");
2549 print_string((char *)inp, len, printer, arg);
2554 printer(arg, " <No message>");
2561 GETCHAR(vallen, inp);
2565 printer(arg, " <Value%.*B>", vallen, inp);
2566 INCPTR(vallen, inp);
2569 printer(arg, " <Name ");
2570 print_string((char *)inp, len, printer, arg);
2575 printer(arg, " <No name>");
2583 GETCHAR(flags, inp);
2586 if(flags == 0 && len == 0){
2587 printer(arg, " Ack");
2591 printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
2592 printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
2593 printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
2595 #endif /* USE_EAPTLS */
2600 GETCHAR(vallen, inp);
2602 printer(arg, "-%d", vallen);
2604 case EAPSRP_CHALLENGE:
2605 GETCHAR(vallen, inp);
2610 printer(arg, " <Name ");
2611 print_string((char *)inp, vallen, printer,
2615 printer(arg, " <No name>");
2617 INCPTR(vallen, inp);
2619 GETCHAR(vallen, inp);
2623 printer(arg, " <s%.*B>", vallen, inp);
2624 INCPTR(vallen, inp);
2626 GETCHAR(vallen, inp);
2631 printer(arg, " <Default g=2>");
2633 printer(arg, " <g%.*B>", vallen, inp);
2635 INCPTR(vallen, inp);
2638 printer(arg, " <Default N>");
2640 printer(arg, " <N%.*B>", len, inp);
2647 printer(arg, " <B%.*B>", len, inp);
2652 case EAPSRP_SVALIDATOR:
2653 if (len < sizeof (u_int32_t))
2656 len -= sizeof (u_int32_t);
2657 if (uval & SRPVAL_EBIT) {
2659 uval &= ~SRPVAL_EBIT;
2662 printer(arg, " f<%X>", uval);
2664 if ((vallen = len) > SHA_DIGESTSIZE)
2665 vallen = SHA_DIGESTSIZE;
2666 printer(arg, " <M2%.*B%s>", len, inp,
2667 len < SHA_DIGESTSIZE ? "?" : "");
2668 INCPTR(vallen, inp);
2671 printer(arg, " <PN%.*B>", len, inp);
2677 case EAPSRP_LWRECHALLENGE:
2678 printer(arg, " <Challenge%.*B>", len, inp);
2690 GETCHAR(rtype, inp);
2693 rtype <= sizeof (eap_typenames) / sizeof (char *))
2694 printer(arg, " %s", eap_typenames[rtype-1]);
2696 printer(arg, " type=0x%x", rtype);
2700 printer(arg, " <Name ");
2701 print_string((char *)inp, len, printer, arg);
2712 GETCHAR(flags, inp);
2715 if(flags == 0 && len == 0){
2716 printer(arg, " Ack");
2720 printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
2721 printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
2722 printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
2725 #endif /* USE_EAPTLS */
2729 printer(arg, " <missing hint>");
2732 GETCHAR(rtype, inp);
2734 printer(arg, " <Suggested-type %02X", rtype);
2736 rtype < sizeof (eap_typenames) / sizeof (char *))
2737 printer(arg, " (%s)", eap_typenames[rtype-1]);
2743 printer(arg, " <missing length>");
2746 GETCHAR(vallen, inp);
2750 printer(arg, " <Value%.*B>", vallen, inp);
2751 INCPTR(vallen, inp);
2754 printer(arg, " <Name ");
2755 print_string((char *)inp, len, printer, arg);
2760 printer(arg, " <No name>");
2767 GETCHAR(vallen, inp);
2769 printer(arg, "-%d", vallen);
2772 printer(arg, " <A%.*B>", len, inp);
2777 case EAPSRP_CVALIDATOR:
2778 if (len < sizeof (u_int32_t))
2781 len -= sizeof (u_int32_t);
2782 if (uval & SRPVAL_EBIT) {
2784 uval &= ~SRPVAL_EBIT;
2787 printer(arg, " f<%X>", uval);
2789 printer(arg, " <M1%.*B%s>", len, inp,
2790 len == SHA_DIGESTSIZE ? "" : "?");
2798 case EAPSRP_LWRECHALLENGE:
2799 printer(arg, " <Response%.*B%s>", len, inp,
2800 len == SHA_DIGESTSIZE ? "" : "?");
2801 if ((vallen = len) > SHA_DIGESTSIZE)
2802 vallen = SHA_DIGESTSIZE;
2803 INCPTR(vallen, inp);
2811 case EAP_SUCCESS: /* No payload expected for these! */
2816 printer(arg, " <truncated>");
2821 printer(arg, "%8B...", inp);
2823 printer(arg, "%.*B", len, inp);
2826 return (inp - pstart);