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
51 #define RCSID "$Id: eap.c,v 1.4 2004/11/09 22:39:25 paulus Exp $"
62 #include <sys/types.h>
69 #include "pathnames.h"
80 #ifndef SHA_DIGESTSIZE
81 #define SHA_DIGESTSIZE 20
86 #endif /* USE_EAPTLS */
88 eap_state eap_states[NUM_PPP]; /* EAP state; one for each unit */
90 static char *pn_secret = NULL; /* Pseudonym generating secret */
94 * Command-line options.
96 static option_t eap_option_list[] = {
97 { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,
98 "Set retransmit timeout for EAP Requests (server)" },
99 { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,
100 "Set max number of EAP Requests sent (server)" },
101 { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,
102 "Set time limit for peer EAP authentication" },
103 { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,
104 "Set max number of EAP Requests allows (client)" },
105 { "eap-interval", o_int, &eap_states[0].es_rechallenge,
106 "Set interval for EAP rechallenge" },
108 { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,
109 "Set interval for SRP lightweight rechallenge" },
110 { "srp-pn-secret", o_string, &pn_secret,
111 "Long term pseudonym generation secret" },
112 { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,
113 "Use pseudonym if offered one by server", 1 },
119 * Protocol entry points.
121 static void eap_init __P((int unit));
122 static void eap_input __P((int unit, u_char *inp, int inlen));
123 static void eap_protrej __P((int unit));
124 static void eap_lowerup __P((int unit));
125 static void eap_lowerdown __P((int unit));
126 static int eap_printpkt __P((u_char *inp, int inlen,
127 void (*)(void *arg, char *fmt, ...), void *arg));
129 struct protent eap_protent = {
130 PPP_EAP, /* protocol number */
131 eap_init, /* initialization procedure */
132 eap_input, /* process a received packet */
133 eap_protrej, /* process a received protocol-reject */
134 eap_lowerup, /* lower layer has gone up */
135 eap_lowerdown, /* lower layer has gone down */
136 NULL, /* open the protocol */
137 NULL, /* close the protocol */
138 eap_printpkt, /* print a packet in readable form */
139 NULL, /* process a received data packet */
140 1, /* protocol enabled */
141 "EAP", /* text name of protocol */
142 NULL, /* text name of corresponding data protocol */
143 eap_option_list, /* list of command-line options */
144 NULL, /* check requested options; assign defaults */
145 NULL, /* configure interface for demand-dial */
146 NULL /* say whether to bring up link for this pkt */
150 * A well-known 2048 bit modulus.
152 static const u_char wkmodulus[] = {
153 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
154 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
155 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
156 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
157 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
158 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
159 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
160 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
161 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
162 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
163 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
164 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
165 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
166 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
167 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
168 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
169 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
170 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
171 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
172 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
173 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
174 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
175 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
176 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
177 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
178 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
179 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
180 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
181 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
182 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
183 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
184 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
187 /* Local forward declarations. */
188 static void eap_server_timeout __P((void *arg));
191 * Convert EAP state code to printable string for debug.
195 enum eap_state_code esc;
197 static const char *state_names[] = { EAP_STATES };
199 return (state_names[(int)esc]);
203 * eap_init - Initialize state for an EAP user. This is currently
204 * called once by main() during start-up.
210 eap_state *esp = &eap_states[unit];
212 BZERO(esp, sizeof (*esp));
214 esp->es_server.ea_timeout = EAP_DEFTIMEOUT;
215 esp->es_server.ea_maxrequests = EAP_DEFTRANSMITS;
216 esp->es_server.ea_id = (u_char)(drand48() * 0x100);
217 esp->es_client.ea_timeout = EAP_DEFREQTIME;
218 esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
220 esp->es_client.ea_using_eaptls = 0;
221 #endif /* USE_EAPTLS */
225 * eap_client_timeout - Give up waiting for the peer to send any
229 eap_client_timeout(arg)
232 eap_state *esp = (eap_state *) arg;
234 if (!eap_client_active(esp))
237 error("EAP: timeout waiting for Request from peer");
238 auth_withpeer_fail(esp->es_unit, PPP_EAP);
239 esp->es_client.ea_state = eapBadAuth;
243 * eap_authwithpeer - Authenticate to our peer (behave as client).
245 * Start client state and wait for requests. This is called only
249 eap_authwithpeer(unit, localname)
253 eap_state *esp = &eap_states[unit];
255 /* Save the peer name we're given */
256 esp->es_client.ea_name = localname;
257 esp->es_client.ea_namelen = strlen(localname);
259 esp->es_client.ea_state = eapListen;
262 * Start a timer so that if the other end just goes
263 * silent, we don't sit here waiting forever.
265 if (esp->es_client.ea_timeout > 0)
266 TIMEOUT(eap_client_timeout, (void *)esp,
267 esp->es_client.ea_timeout);
271 * Format a standard EAP Failure message and send it to the peer.
275 eap_send_failure(esp)
280 outp = outpacket_buf;
282 MAKEHEADER(outp, PPP_EAP);
284 PUTCHAR(EAP_FAILURE, outp);
285 esp->es_server.ea_id++;
286 PUTCHAR(esp->es_server.ea_id, outp);
287 PUTSHORT(EAP_HEADERLEN, outp);
289 output(esp->es_unit, outpacket_buf, EAP_HEADERLEN + PPP_HDRLEN);
291 esp->es_server.ea_state = eapBadAuth;
292 auth_peer_fail(esp->es_unit, PPP_EAP);
296 * Format a standard EAP Success message and send it to the peer.
300 eap_send_success(esp)
305 outp = outpacket_buf;
307 MAKEHEADER(outp, PPP_EAP);
309 PUTCHAR(EAP_SUCCESS, outp);
310 esp->es_server.ea_id++;
311 PUTCHAR(esp->es_server.ea_id, outp);
312 PUTSHORT(EAP_HEADERLEN, outp);
314 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);
316 auth_peer_success(esp->es_unit, PPP_EAP, 0,
317 esp->es_server.ea_peer, esp->es_server.ea_peerlen);
322 * Set DES key according to pseudonym-generating secret and current
326 pncrypt_setkey(int timeoffs)
331 u_char dig[SHA_DIGESTSIZE];
334 if (pn_secret == NULL)
336 reftime = time(NULL) + timeoffs;
337 tp = localtime(&reftime);
339 SHA1Update(&ctxt, pn_secret, strlen(pn_secret));
340 strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp);
341 SHA1Update(&ctxt, tbuf, strlen(tbuf));
342 SHA1Final(dig, &ctxt);
343 return (DesSetkey(dig));
346 static char base64[] =
347 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
355 b64enc(bs, inp, inlen, outp)
364 bs->bs_bits = (bs->bs_bits << 8) | *inp++;
367 if (bs->bs_offs >= 24) {
368 *outp++ = base64[(bs->bs_bits >> 18) & 0x3F];
369 *outp++ = base64[(bs->bs_bits >> 12) & 0x3F];
370 *outp++ = base64[(bs->bs_bits >> 6) & 0x3F];
371 *outp++ = base64[bs->bs_bits & 0x3F];
387 if (bs->bs_offs == 8) {
388 *outp++ = base64[(bs->bs_bits >> 2) & 0x3F];
389 *outp++ = base64[(bs->bs_bits << 4) & 0x3F];
391 } else if (bs->bs_offs == 16) {
392 *outp++ = base64[(bs->bs_bits >> 10) & 0x3F];
393 *outp++ = base64[(bs->bs_bits >> 4) & 0x3F];
394 *outp++ = base64[(bs->bs_bits << 2) & 0x3F];
403 b64dec(bs, inp, inlen, outp)
413 if ((cp = strchr(base64, *inp++)) == NULL)
415 bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);
418 if (bs->bs_offs >= 8) {
419 *outp++ = bs->bs_bits >> (bs->bs_offs - 8);
429 * Assume that current waiting server state is complete and figure
430 * next state to use based on available authentication data. 'status'
431 * indicates if there was an error in handling the last query. It is
432 * 0 for success and non-zero for failure.
435 eap_figure_next_state(esp, status)
440 unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp;
442 struct t_confent *tce, mytce;
445 int id, i, plen, toffs;
450 struct eaptls_session *ets;
452 char secret[MAXWORDLEN];
453 #endif /* USE_EAPTLS */
455 esp->es_server.ea_timeout = esp->es_savedtime;
457 esp->es_server.ea_prev_state = esp->es_server.ea_state;
458 #endif /* USE_EAPTLS */
459 switch (esp->es_server.ea_state) {
465 /* Discard any previous session. */
466 ts = (struct t_server *)esp->es_server.ea_session;
469 esp->es_server.ea_session = NULL;
470 esp->es_server.ea_skey = NULL;
474 esp->es_server.ea_state = eapBadAuth;
478 /* If we've got a pseudonym, try to decode to real name. */
479 if (esp->es_server.ea_peerlen > SRP_PSEUDO_LEN &&
480 strncmp(esp->es_server.ea_peer, SRP_PSEUDO_ID,
481 SRP_PSEUDO_LEN) == 0 &&
482 (esp->es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 <
484 BZERO(&bs, sizeof (bs));
486 esp->es_server.ea_peer + SRP_PSEUDO_LEN,
487 esp->es_server.ea_peerlen - SRP_PSEUDO_LEN,
490 for (i = 0; i < 5; i++) {
491 pncrypt_setkey(toffs);
493 if (!DesDecrypt(secbuf, clear)) {
494 dbglog("no DES here; cannot decode "
498 id = *(unsigned char *)clear;
499 if (id + 1 <= plen && id + 9 > plen)
502 if (plen % 8 == 0 && i < 5) {
504 * Note that this is always shorter than the
505 * original stored string, so there's no need
508 if ((i = plen = *(unsigned char *)clear) > 7)
510 esp->es_server.ea_peerlen = plen;
511 dp = (unsigned char *)esp->es_server.ea_peer;
512 BCOPY(clear + 1, dp, i);
517 (void) DesDecrypt(sp, dp);
522 esp->es_server.ea_peer[
523 esp->es_server.ea_peerlen] = '\0';
524 dbglog("decoded pseudonym to \"%.*q\"",
525 esp->es_server.ea_peerlen,
526 esp->es_server.ea_peer);
528 dbglog("failed to decode real name");
529 /* Stay in eapIdentfy state; requery */
533 /* Look up user in secrets database. */
534 if (get_srp_secret(esp->es_unit, esp->es_server.ea_peer,
535 esp->es_server.ea_name, (char *)secbuf, 1) != 0) {
536 /* Set up default in case SRP entry is bad */
537 esp->es_server.ea_state = eapMD5Chall;
538 /* Get t_confent based on index in srp-secrets */
539 id = strtol((char *)secbuf, &cp, 10);
540 if (*cp++ != ':' || id < 0)
544 mytce.modulus.data = (u_char *)wkmodulus;
545 mytce.modulus.len = sizeof (wkmodulus);
546 mytce.generator.data = (u_char *)"\002";
547 mytce.generator.len = 1;
549 } else if ((tce = gettcid(id)) != NULL) {
551 * Client will have to verify this modulus/
552 * generator combination, and that will take
553 * a while. Lengthen the timeout here.
555 if (esp->es_server.ea_timeout > 0 &&
556 esp->es_server.ea_timeout < 30)
557 esp->es_server.ea_timeout = 30;
561 if ((cp2 = strchr(cp, ':')) == NULL)
564 tpw.pebuf.name = esp->es_server.ea_peer;
565 tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,
567 tpw.pebuf.password.data = tpw.pwbuf;
568 tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,
570 tpw.pebuf.salt.data = tpw.saltbuf;
571 if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)
573 esp->es_server.ea_session = (void *)ts;
574 esp->es_server.ea_state = eapSRP1;
575 vals[0] = esp->es_server.ea_id + 1;
577 t_serveraddexdata(ts, vals, 2);
578 /* Generate B; must call before t_servergetkey() */
584 if (!get_secret(esp->es_unit, esp->es_server.ea_peer,
585 esp->es_server.ea_name, secret, &secret_len, 1)) {
587 esp->es_server.ea_state = eapTlsStart;
590 #endif /* USE_EAPTLS */
592 esp->es_server.ea_state = eapMD5Chall;
597 /* Initialize ssl session */
598 if(!eaptls_init_ssl_server(esp)) {
599 esp->es_server.ea_state = eapBadAuth;
603 esp->es_server.ea_state = eapTlsRecv;
607 ets = (struct eaptls_session *) esp->es_server.ea_session;
609 if(ets->alert_sent) {
610 esp->es_server.ea_state = eapTlsSendAlert;
615 esp->es_server.ea_state = eapBadAuth;
618 ets = (struct eaptls_session *) esp->es_server.ea_session;
621 esp->es_server.ea_state = eapTlsSendAck;
623 esp->es_server.ea_state = eapTlsSend;
627 ets = (struct eaptls_session *) esp->es_server.ea_session;
630 esp->es_server.ea_state = eapTlsRecvAck;
632 if(SSL_is_init_finished(ets->ssl))
633 esp->es_server.ea_state = eapTlsRecvClient;
635 /* JJK Add "TLS empty record" message here ??? */
636 esp->es_server.ea_state = eapTlsRecv;
640 esp->es_server.ea_state = eapTlsRecv;
646 esp->es_server.ea_state = eapBadAuth;
650 esp->es_server.ea_state = eapTlsSend;
653 case eapTlsSendAlert:
654 esp->es_server.ea_state = eapTlsRecvAlertAck;
656 #endif /* USE_EAPTLS */
660 ts = (struct t_server *)esp->es_server.ea_session;
661 if (ts != NULL && status != 0) {
663 esp->es_server.ea_session = NULL;
664 esp->es_server.ea_skey = NULL;
668 esp->es_server.ea_state = eapMD5Chall;
669 } else if (status != 0 || esp->es_server.ea_session == NULL) {
670 esp->es_server.ea_state = eapBadAuth;
672 esp->es_server.ea_state = eapSRP2;
678 ts = (struct t_server *)esp->es_server.ea_session;
679 if (ts != NULL && status != 0) {
681 esp->es_server.ea_session = NULL;
682 esp->es_server.ea_skey = NULL;
685 if (status != 0 || esp->es_server.ea_session == NULL) {
686 esp->es_server.ea_state = eapBadAuth;
688 esp->es_server.ea_state = eapSRP3;
695 ts = (struct t_server *)esp->es_server.ea_session;
696 if (ts != NULL && status != 0) {
698 esp->es_server.ea_session = NULL;
699 esp->es_server.ea_skey = NULL;
702 if (status != 0 || esp->es_server.ea_session == NULL) {
703 esp->es_server.ea_state = eapBadAuth;
705 esp->es_server.ea_state = eapOpen;
711 esp->es_server.ea_state = eapBadAuth;
713 esp->es_server.ea_state = eapOpen;
718 esp->es_server.ea_state = eapBadAuth;
721 if (esp->es_server.ea_state == eapBadAuth)
722 eap_send_failure(esp);
725 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));
726 #endif /* USE_EAPTLS */
730 * Format an EAP Request message and send it to the peer. Message
731 * type depends on current state. (Server operation)
734 eap_send_request(esp)
745 u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp;
751 /* Handle both initial auth and restart */
752 if (esp->es_server.ea_state < eapIdentify &&
753 esp->es_server.ea_state != eapInitial) {
754 esp->es_server.ea_state = eapIdentify;
755 if (explicit_remote) {
757 * If we already know the peer's
758 * unauthenticated name, then there's no
759 * reason to ask. Go to next state instead.
761 esp->es_server.ea_peer = remote_name;
762 esp->es_server.ea_peerlen = strlen(remote_name);
763 eap_figure_next_state(esp, 0);
767 if (esp->es_server.ea_maxrequests > 0 &&
768 esp->es_server.ea_requests >= esp->es_server.ea_maxrequests) {
769 if (esp->es_server.ea_responses > 0)
770 error("EAP: too many Requests sent");
772 error("EAP: no response to Requests");
773 eap_send_failure(esp);
777 outp = outpacket_buf;
779 MAKEHEADER(outp, PPP_EAP);
781 PUTCHAR(EAP_REQUEST, outp);
782 PUTCHAR(esp->es_server.ea_id, outp);
786 switch (esp->es_server.ea_state) {
788 PUTCHAR(EAPT_IDENTITY, outp);
790 challen = strlen(str);
791 BCOPY(str, outp, challen);
792 INCPTR(challen, outp);
796 PUTCHAR(EAPT_MD5CHAP, outp);
798 * pick a random challenge length between
799 * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
801 challen = (drand48() *
802 (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
803 MIN_CHALLENGE_LENGTH;
804 PUTCHAR(challen, outp);
805 esp->es_challen = challen;
806 ptr = esp->es_challenge;
807 while (--challen >= 0)
808 *ptr++ = (u_char) (drand48() * 0x100);
809 BCOPY(esp->es_challenge, outp, esp->es_challen);
810 INCPTR(esp->es_challen, outp);
811 BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
812 INCPTR(esp->es_server.ea_namelen, outp);
817 PUTCHAR(EAPT_TLS, outp);
818 PUTCHAR(EAP_TLS_FLAGS_START, outp);
819 eap_figure_next_state(esp, 0);
823 eaptls_send(esp->es_server.ea_session, &outp);
824 eap_figure_next_state(esp, 0);
828 PUTCHAR(EAPT_TLS, outp);
830 eap_figure_next_state(esp, 0);
833 case eapTlsSendAlert:
834 eaptls_send(esp->es_server.ea_session, &outp);
835 eap_figure_next_state(esp, 0);
837 #endif /* USE_EAPTLS */
841 PUTCHAR(EAPT_SRP, outp);
842 PUTCHAR(EAPSRP_CHALLENGE, outp);
844 PUTCHAR(esp->es_server.ea_namelen, outp);
845 BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
846 INCPTR(esp->es_server.ea_namelen, outp);
848 ts = (struct t_server *)esp->es_server.ea_session;
850 PUTCHAR(ts->s.len, outp);
851 BCOPY(ts->s.data, outp, ts->s.len);
852 INCPTR(ts->s.len, outp);
854 if (ts->g.len == 1 && ts->g.data[0] == 2) {
857 PUTCHAR(ts->g.len, outp);
858 BCOPY(ts->g.data, outp, ts->g.len);
859 INCPTR(ts->g.len, outp);
862 if (ts->n.len != sizeof (wkmodulus) ||
863 BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) {
864 BCOPY(ts->n.data, outp, ts->n.len);
865 INCPTR(ts->n.len, outp);
870 PUTCHAR(EAPT_SRP, outp);
871 PUTCHAR(EAPSRP_SKEY, outp);
873 ts = (struct t_server *)esp->es_server.ea_session;
875 BCOPY(ts->B.data, outp, ts->B.len);
876 INCPTR(ts->B.len, outp);
880 PUTCHAR(EAPT_SRP, outp);
881 PUTCHAR(EAPSRP_SVALIDATOR, outp);
882 PUTLONG(SRPVAL_EBIT, outp);
883 ts = (struct t_server *)esp->es_server.ea_session;
885 BCOPY(t_serverresponse(ts), outp, SHA_DIGESTSIZE);
886 INCPTR(SHA_DIGESTSIZE, outp);
888 if (pncrypt_setkey(0)) {
889 /* Generate pseudonym */
891 cp = (unsigned char *)esp->es_server.ea_peer;
892 if ((j = i = esp->es_server.ea_peerlen) > 7)
895 BCOPY(cp, clear + 1, j);
898 if (!DesEncrypt(clear, cipher)) {
899 dbglog("no DES here; not generating pseudonym");
902 BZERO(&b64, sizeof (b64));
903 outp++; /* space for pseudonym length */
904 outp += b64enc(&b64, cipher, 8, outp);
906 (void) DesEncrypt(cp, cipher);
907 outp += b64enc(&b64, cipher, 8, outp);
915 *cp++ = drand48() * 0x100;
918 (void) DesEncrypt(clear, cipher);
919 outp += b64enc(&b64, cipher, 8, outp);
921 outp += b64flush(&b64, outp);
923 /* Set length and pad out to next 20 octet boundary */
928 while (i < SHA_DIGESTSIZE) {
929 *outp++ = drand48() * 0x100;
934 /* Obscure the pseudonym with SHA1 hash */
936 SHA1Update(&ctxt, &esp->es_server.ea_id, 1);
937 SHA1Update(&ctxt, esp->es_server.ea_skey,
939 SHA1Update(&ctxt, esp->es_server.ea_peer,
940 esp->es_server.ea_peerlen);
941 while (optr < outp) {
942 SHA1Final(dig, &ctxt);
944 while (cp < dig + SHA_DIGESTSIZE)
947 SHA1Update(&ctxt, &esp->es_server.ea_id, 1);
948 SHA1Update(&ctxt, esp->es_server.ea_skey,
950 SHA1Update(&ctxt, optr - SHA_DIGESTSIZE,
957 PUTCHAR(EAPT_SRP, outp);
958 PUTCHAR(EAPSRP_LWRECHALLENGE, outp);
959 challen = MIN_CHALLENGE_LENGTH +
960 ((MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH) * drand48());
961 esp->es_challen = challen;
962 ptr = esp->es_challenge;
963 while (--challen >= 0)
964 *ptr++ = drand48() * 0x100;
965 BCOPY(esp->es_challenge, outp, esp->es_challen);
966 INCPTR(esp->es_challen, outp);
974 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
975 PUTSHORT(outlen, lenloc);
977 output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
979 esp->es_server.ea_requests++;
981 if (esp->es_server.ea_timeout > 0)
982 TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
986 * eap_authpeer - Authenticate our peer (behave as server).
988 * Start server state and send first request. This is called only
992 eap_authpeer(unit, localname)
996 eap_state *esp = &eap_states[unit];
998 /* Save the name we're given. */
999 esp->es_server.ea_name = localname;
1000 esp->es_server.ea_namelen = strlen(localname);
1002 esp->es_savedtime = esp->es_server.ea_timeout;
1004 /* Lower layer up yet? */
1005 if (esp->es_server.ea_state == eapInitial ||
1006 esp->es_server.ea_state == eapPending) {
1007 esp->es_server.ea_state = eapPending;
1011 esp->es_server.ea_state = eapPending;
1013 /* ID number not updated here intentionally; hashed into M1 */
1014 eap_send_request(esp);
1018 * eap_server_timeout - Retransmission timer for sending Requests
1022 eap_server_timeout(arg)
1029 #endif /* USE_EAPTLS */
1031 eap_state *esp = (eap_state *) arg;
1033 if (!eap_server_active(esp))
1037 switch(esp->es_server.ea_prev_state) {
1040 * In eap-tls the state changes after a request, so we return to
1041 * previous state ...
1044 case(eapTlsSendAck):
1045 esp->es_server.ea_state = esp->es_server.ea_prev_state;
1049 * ... or resend the stored data
1052 case(eapTlsSendAlert):
1053 outp = outpacket_buf;
1054 MAKEHEADER(outp, PPP_EAP);
1055 PUTCHAR(EAP_REQUEST, outp);
1056 PUTCHAR(esp->es_server.ea_id, outp);
1060 eaptls_retransmit(esp->es_server.ea_session, &outp);
1062 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1063 PUTSHORT(outlen, lenloc);
1064 output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
1065 esp->es_server.ea_requests++;
1067 if (esp->es_server.ea_timeout > 0)
1068 TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
1074 #endif /* USE_EAPTLS */
1076 /* EAP ID number must not change on timeout. */
1077 eap_send_request(esp);
1081 * When it's time to send rechallenge the peer, this timeout is
1082 * called. Once the rechallenge is successful, the response handler
1083 * will restart the timer. If it fails, then the link is dropped.
1086 eap_rechallenge(arg)
1089 eap_state *esp = (eap_state *)arg;
1091 if (esp->es_server.ea_state != eapOpen &&
1092 esp->es_server.ea_state != eapSRP4)
1095 esp->es_server.ea_requests = 0;
1096 esp->es_server.ea_state = eapIdentify;
1097 eap_figure_next_state(esp, 0);
1098 esp->es_server.ea_id++;
1099 eap_send_request(esp);
1103 srp_lwrechallenge(arg)
1106 eap_state *esp = (eap_state *)arg;
1108 if (esp->es_server.ea_state != eapOpen ||
1109 esp->es_server.ea_type != EAPT_SRP)
1112 esp->es_server.ea_requests = 0;
1113 esp->es_server.ea_state = eapSRP4;
1114 esp->es_server.ea_id++;
1115 eap_send_request(esp);
1119 * eap_lowerup - The lower layer is now up.
1121 * This is called before either eap_authpeer or eap_authwithpeer. See
1122 * link_established() in auth.c. All that's necessary here is to
1123 * return to closed state so that those two routines will do the right
1130 eap_state *esp = &eap_states[unit];
1132 /* Discard any (possibly authenticated) peer name. */
1133 if (esp->es_server.ea_peer != NULL &&
1134 esp->es_server.ea_peer != remote_name)
1135 free(esp->es_server.ea_peer);
1136 esp->es_server.ea_peer = NULL;
1137 if (esp->es_client.ea_peer != NULL)
1138 free(esp->es_client.ea_peer);
1139 esp->es_client.ea_peer = NULL;
1141 esp->es_client.ea_state = eapClosed;
1142 esp->es_server.ea_state = eapClosed;
1146 * eap_lowerdown - The lower layer is now down.
1148 * Cancel all timeouts and return to initial state.
1154 eap_state *esp = &eap_states[unit];
1156 if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) {
1157 UNTIMEOUT(eap_client_timeout, (void *)esp);
1159 if (eap_server_active(esp)) {
1160 if (esp->es_server.ea_timeout > 0) {
1161 UNTIMEOUT(eap_server_timeout, (void *)esp);
1164 if ((esp->es_server.ea_state == eapOpen ||
1165 esp->es_server.ea_state == eapSRP4) &&
1166 esp->es_rechallenge > 0) {
1167 UNTIMEOUT(eap_rechallenge, (void *)esp);
1169 if (esp->es_server.ea_state == eapOpen &&
1170 esp->es_lwrechallenge > 0) {
1171 UNTIMEOUT(srp_lwrechallenge, (void *)esp);
1175 esp->es_client.ea_state = esp->es_server.ea_state = eapInitial;
1176 esp->es_client.ea_requests = esp->es_server.ea_requests = 0;
1180 * eap_protrej - Peer doesn't speak this protocol.
1182 * This shouldn't happen. If it does, it represents authentication
1189 eap_state *esp = &eap_states[unit];
1191 if (eap_client_active(esp)) {
1192 error("EAP authentication failed due to Protocol-Reject");
1193 auth_withpeer_fail(unit, PPP_EAP);
1195 if (eap_server_active(esp)) {
1196 error("EAP authentication of peer failed on Protocol-Reject");
1197 auth_peer_fail(unit, PPP_EAP);
1199 eap_lowerdown(unit);
1203 * Format and send a regular EAP Response message.
1206 eap_send_response(esp, id, typenum, str, lenstr)
1216 outp = outpacket_buf;
1218 MAKEHEADER(outp, PPP_EAP);
1220 PUTCHAR(EAP_RESPONSE, outp);
1222 esp->es_client.ea_id = id;
1223 msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr;
1224 PUTSHORT(msglen, outp);
1225 PUTCHAR(typenum, outp);
1227 BCOPY(str, outp, lenstr);
1230 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1234 * Format and send an MD5-Challenge EAP Response message.
1237 eap_chap_response(esp, id, hash, name, namelen)
1247 outp = outpacket_buf;
1249 MAKEHEADER(outp, PPP_EAP);
1251 PUTCHAR(EAP_RESPONSE, outp);
1253 esp->es_client.ea_id = id;
1254 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE +
1256 PUTSHORT(msglen, outp);
1257 PUTCHAR(EAPT_MD5CHAP, outp);
1258 PUTCHAR(MD5_SIGNATURE_SIZE, outp);
1259 BCOPY(hash, outp, MD5_SIGNATURE_SIZE);
1260 INCPTR(MD5_SIGNATURE_SIZE, outp);
1262 BCOPY(name, outp, namelen);
1265 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1270 * Format and send a SRP EAP Response message.
1273 eap_srp_response(esp, id, subtypenum, str, lenstr)
1283 outp = outpacket_buf;
1285 MAKEHEADER(outp, PPP_EAP);
1287 PUTCHAR(EAP_RESPONSE, outp);
1289 esp->es_client.ea_id = id;
1290 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr;
1291 PUTSHORT(msglen, outp);
1292 PUTCHAR(EAPT_SRP, outp);
1293 PUTCHAR(subtypenum, outp);
1295 BCOPY(str, outp, lenstr);
1298 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1302 * Format and send a SRP EAP Client Validator Response message.
1305 eap_srpval_response(esp, id, flags, str)
1314 outp = outpacket_buf;
1316 MAKEHEADER(outp, PPP_EAP);
1318 PUTCHAR(EAP_RESPONSE, outp);
1320 esp->es_client.ea_id = id;
1321 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) +
1323 PUTSHORT(msglen, outp);
1324 PUTCHAR(EAPT_SRP, outp);
1325 PUTCHAR(EAPSRP_CVALIDATOR, outp);
1326 PUTLONG(flags, outp);
1327 BCOPY(str, outp, SHA_DIGESTSIZE);
1329 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1331 #endif /* USE_SRP */
1335 * Send an EAP-TLS response message with tls data
1338 eap_tls_response(esp, id)
1346 outp = outpacket_buf;
1348 MAKEHEADER(outp, PPP_EAP);
1350 PUTCHAR(EAP_RESPONSE, outp);
1357 If the id in the request is unchanged, we must retransmit
1360 if(id == esp->es_client.ea_id)
1361 eaptls_retransmit(esp->es_client.ea_session, &outp);
1363 eaptls_send(esp->es_client.ea_session, &outp);
1365 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1366 PUTSHORT(outlen, lenloc);
1368 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1370 esp->es_client.ea_id = id;
1374 * Send an EAP-TLS ack
1377 eap_tls_sendack(esp, id)
1385 outp = outpacket_buf;
1387 MAKEHEADER(outp, PPP_EAP);
1389 PUTCHAR(EAP_RESPONSE, outp);
1391 esp->es_client.ea_id = id;
1396 PUTCHAR(EAPT_TLS, outp);
1399 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1400 PUTSHORT(outlen, lenloc);
1402 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1404 #endif /* USE_EAPTLS */
1407 eap_send_nak(esp, id, type)
1415 outp = outpacket_buf;
1417 MAKEHEADER(outp, PPP_EAP);
1419 PUTCHAR(EAP_RESPONSE, outp);
1421 esp->es_client.ea_id = id;
1422 msglen = EAP_HEADERLEN + 2 * sizeof (u_char);
1423 PUTSHORT(msglen, outp);
1424 PUTCHAR(EAPT_NAK, outp);
1425 PUTCHAR(type, outp);
1427 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1434 char *user, *path, *file;
1437 static bool pnlogged = 0;
1439 pw = getpwuid(getuid());
1440 if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
1444 file = _PATH_PSEUDONYM;
1445 pl = strlen(user) + strlen(file) + 2;
1449 (void) slprintf(path, pl, "%s/%s", user, file);
1451 dbglog("pseudonym file: %s", path);
1458 open_pn_file(modebits)
1464 if ((path = name_of_pn_file()) == NULL)
1466 fd = open(path, modebits, S_IRUSR | S_IWUSR);
1478 if ((path = name_of_pn_file()) != NULL) {
1479 (void) unlink(path);
1485 write_pseudonym(esp, inp, len, id)
1491 u_char *datp, *digp;
1493 u_char dig[SHA_DIGESTSIZE];
1494 int dsize, fd, olen = len;
1497 * Do the decoding by working backwards. This eliminates the need
1498 * to save the decoded output in a separate buffer.
1502 if ((dsize = len % SHA_DIGESTSIZE) == 0)
1503 dsize = SHA_DIGESTSIZE;
1507 SHA1Update(&ctxt, &val, 1);
1508 SHA1Update(&ctxt, esp->es_client.ea_skey, SESSION_KEY_LEN);
1510 SHA1Update(&ctxt, datp, SHA_DIGESTSIZE);
1512 SHA1Update(&ctxt, esp->es_client.ea_name,
1513 esp->es_client.ea_namelen);
1515 SHA1Final(dig, &ctxt);
1516 for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++)
1520 /* Now check that the result is sane */
1521 if (olen <= 0 || *inp + 1 > olen) {
1522 dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp);
1527 fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);
1529 dbglog("EAP: error saving pseudonym: %m");
1532 len = write(fd, inp + 1, *inp);
1533 if (close(fd) != -1 && len == *inp) {
1534 dbglog("EAP: saved pseudonym");
1535 esp->es_usedpseudo = 0;
1537 dbglog("EAP: failed to save pseudonym");
1541 #endif /* USE_SRP */
1544 * eap_request - Receive EAP Request message (client mode).
1547 eap_request(esp, inp, id, len)
1556 char secret[MAXWORDLEN];
1557 char rhostname[256];
1559 u_char hash[MD5_SIGNATURE_SIZE];
1562 struct eaptls_session *ets = esp->es_client.ea_session;
1563 #endif /* USE_EAPTLS */
1566 struct t_client *tc;
1567 struct t_num sval, gval, Nval, *Ap, Bval;
1570 u_char dig[SHA_DIGESTSIZE];
1572 #endif /* USE_SRP */
1575 * Ignore requests if we're not open
1577 if (esp->es_client.ea_state <= eapClosed)
1581 * Note: we update es_client.ea_id *only if* a Response
1582 * message is being generated. Otherwise, we leave it the
1583 * same for duplicate detection purposes.
1586 esp->es_client.ea_requests++;
1587 if (esp->es_client.ea_maxrequests != 0 &&
1588 esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {
1589 info("EAP: received too many Request messages");
1590 if (esp->es_client.ea_timeout > 0) {
1591 UNTIMEOUT(eap_client_timeout, (void *)esp);
1593 auth_withpeer_fail(esp->es_unit, PPP_EAP);
1598 error("EAP: empty Request message discarded");
1602 GETCHAR(typenum, inp);
1608 info("EAP: Identity prompt \"%.*q\"", len, inp);
1610 if (esp->es_usepseudo &&
1611 (esp->es_usedpseudo == 0 ||
1612 (esp->es_usedpseudo == 1 &&
1613 id == esp->es_client.ea_id))) {
1614 esp->es_usedpseudo = 1;
1615 /* Try to get a pseudonym */
1616 if ((fd = open_pn_file(O_RDONLY)) >= 0) {
1617 strcpy(rhostname, SRP_PSEUDO_ID);
1618 len = read(fd, rhostname + SRP_PSEUDO_LEN,
1619 sizeof (rhostname) - SRP_PSEUDO_LEN);
1620 /* XXX NAI unsupported */
1622 eap_send_response(esp, id, typenum,
1623 rhostname, len + SRP_PSEUDO_LEN);
1630 /* Stop using pseudonym now. */
1631 if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
1633 esp->es_usedpseudo = 2;
1635 #endif /* USE_SRP */
1636 eap_send_response(esp, id, typenum, esp->es_client.ea_name,
1637 esp->es_client.ea_namelen);
1640 case EAPT_NOTIFICATION:
1642 info("EAP: Notification \"%.*q\"", len, inp);
1643 eap_send_response(esp, id, typenum, NULL, 0);
1648 * Avoid the temptation to send Response Nak in reply
1649 * to Request Nak here. It can only lead to trouble.
1651 warn("EAP: unexpected Nak in Request; ignored");
1652 /* Return because we're waiting for something real. */
1657 error("EAP: received MD5-Challenge with no data");
1658 /* Bogus request; wait for something real. */
1661 GETCHAR(vallen, inp);
1663 if (vallen < 8 || vallen > len) {
1664 error("EAP: MD5-Challenge with bad length %d (8..%d)",
1666 /* Try something better. */
1667 eap_send_nak(esp, id, EAPT_SRP);
1671 /* Not so likely to happen. */
1672 if (len - vallen >= sizeof (rhostname)) {
1673 dbglog("EAP: trimming really long peer name down");
1674 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1675 rhostname[sizeof (rhostname) - 1] = '\0';
1677 BCOPY(inp + vallen, rhostname, len - vallen);
1678 rhostname[len - vallen] = '\0';
1681 /* In case the remote doesn't give us his name. */
1682 if (explicit_remote ||
1683 (remote_name[0] != '\0' && vallen == len))
1684 strlcpy(rhostname, remote_name, sizeof (rhostname));
1687 * Get the secret for authenticating ourselves with
1688 * the specified host.
1690 if (!get_secret(esp->es_unit, esp->es_client.ea_name,
1691 rhostname, secret, &secret_len, 0)) {
1692 dbglog("EAP: no MD5 secret for auth to %q", rhostname);
1693 eap_send_nak(esp, id, EAPT_SRP);
1696 MD5_Init(&mdContext);
1698 MD5_Update(&mdContext, &typenum, 1);
1699 MD5_Update(&mdContext, (u_char *)secret, secret_len);
1700 BZERO(secret, sizeof (secret));
1701 MD5_Update(&mdContext, inp, vallen);
1702 MD5_Final(hash, &mdContext);
1703 eap_chap_response(esp, id, hash, esp->es_client.ea_name,
1704 esp->es_client.ea_namelen);
1710 switch(esp->es_client.ea_state) {
1715 error("EAP: received EAP-TLS Listen packet with no data");
1716 /* Bogus request; wait for something real. */
1719 GETCHAR(flags, inp);
1720 if(flags & EAP_TLS_FLAGS_START){
1722 esp->es_client.ea_using_eaptls = 1;
1724 if (explicit_remote){
1725 esp->es_client.ea_peer = strdup(remote_name);
1726 esp->es_client.ea_peerlen = strlen(remote_name);
1728 esp->es_client.ea_peer = NULL;
1730 /* Init ssl session */
1731 if(!eaptls_init_ssl_client(esp)) {
1732 dbglog("cannot init ssl");
1733 eap_send_nak(esp, id, EAPT_TLS);
1734 esp->es_client.ea_using_eaptls = 0;
1738 ets = esp->es_client.ea_session;
1739 eap_tls_response(esp, id);
1740 esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1744 /* The server has sent a bad start packet. */
1745 eap_send_nak(esp, id, EAPT_TLS);
1749 eap_tls_response(esp, id);
1750 esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1755 error("EAP: discarding EAP-TLS Receive packet with no data");
1756 /* Bogus request; wait for something real. */
1759 eaptls_receive(ets, inp, len);
1762 eap_tls_sendack(esp, id);
1763 esp->es_client.ea_state = eapTlsRecv;
1767 if(ets->alert_recv) {
1768 eap_tls_sendack(esp, id);
1769 esp->es_client.ea_state = eapTlsRecvFailure;
1773 /* Check if TLS handshake is finished */
1774 if(eaptls_is_init_finished(ets)) {
1776 eaptls_gen_mppe_keys(ets, 1);
1778 eaptls_free_session(ets);
1779 eap_tls_sendack(esp, id);
1780 esp->es_client.ea_state = eapTlsRecvSuccess;
1784 eap_tls_response(esp,id);
1785 esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1789 eap_send_nak(esp, id, EAPT_TLS);
1790 esp->es_client.ea_using_eaptls = 0;
1795 #endif /* USE_EAPTLS */
1800 error("EAP: received empty SRP Request");
1801 /* Bogus request; wait for something real. */
1806 GETCHAR(vallen, inp);
1809 case EAPSRP_CHALLENGE:
1811 if (esp->es_client.ea_session != NULL) {
1812 tc = (struct t_client *)esp->es_client.
1815 * If this is a new challenge, then start
1816 * over with a new client session context.
1817 * Otherwise, just resend last response.
1819 if (id != esp->es_client.ea_id) {
1821 esp->es_client.ea_session = NULL;
1825 /* No session key just yet */
1826 esp->es_client.ea_skey = NULL;
1828 GETCHAR(vallen, inp);
1830 if (vallen >= len) {
1831 error("EAP: badly-formed SRP Challenge"
1833 /* Ignore badly-formed messages */
1836 BCOPY(inp, rhostname, vallen);
1837 rhostname[vallen] = '\0';
1838 INCPTR(vallen, inp);
1842 * In case the remote doesn't give us his name,
1843 * use configured name.
1845 if (explicit_remote ||
1846 (remote_name[0] != '\0' && vallen == 0)) {
1847 strlcpy(rhostname, remote_name,
1848 sizeof (rhostname));
1851 if (esp->es_client.ea_peer != NULL)
1852 free(esp->es_client.ea_peer);
1853 esp->es_client.ea_peer = strdup(rhostname);
1854 esp->es_client.ea_peerlen = strlen(rhostname);
1856 GETCHAR(vallen, inp);
1858 if (vallen >= len) {
1859 error("EAP: badly-formed SRP Challenge"
1861 /* Ignore badly-formed messages */
1866 INCPTR(vallen, inp);
1869 GETCHAR(vallen, inp);
1872 error("EAP: badly-formed SRP Challenge"
1874 /* Ignore badly-formed messages */
1877 /* If no generator present, then use value 2 */
1879 gval.data = (u_char *)"\002";
1885 INCPTR(vallen, inp);
1889 * If no modulus present, then use well-known
1893 Nval.data = (u_char *)wkmodulus;
1894 Nval.len = sizeof (wkmodulus);
1899 tc = t_clientopen(esp->es_client.ea_name,
1900 &Nval, &gval, &sval);
1902 eap_send_nak(esp, id, EAPT_MD5CHAP);
1905 esp->es_client.ea_session = (void *)tc;
1907 /* Add Challenge ID & type to verifier */
1910 t_clientaddexdata(tc, vals, 2);
1912 Ap = t_clientgenexp(tc);
1913 eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
1918 tc = (struct t_client *)esp->es_client.ea_session;
1920 warn("EAP: peer sent Subtype 2 without 1");
1921 eap_send_nak(esp, id, EAPT_MD5CHAP);
1924 if (esp->es_client.ea_skey != NULL) {
1926 * ID number should not change here. Warn
1927 * if it does (but otherwise ignore).
1929 if (id != esp->es_client.ea_id) {
1930 warn("EAP: ID changed from %d to %d "
1931 "in SRP Subtype 2 rexmit",
1932 esp->es_client.ea_id, id);
1935 if (get_srp_secret(esp->es_unit,
1936 esp->es_client.ea_name,
1937 esp->es_client.ea_peer, secret, 0) == 0) {
1939 * Can't work with this peer because
1940 * the secret is missing. Just give
1943 eap_send_nak(esp, id, EAPT_MD5CHAP);
1948 t_clientpasswd(tc, secret);
1949 BZERO(secret, sizeof (secret));
1950 esp->es_client.ea_skey =
1951 t_clientgetkey(tc, &Bval);
1952 if (esp->es_client.ea_skey == NULL) {
1953 /* Server is rogue; stop now */
1954 error("EAP: SRP server is rogue");
1955 goto client_failure;
1958 eap_srpval_response(esp, id, SRPVAL_EBIT,
1959 t_clientresponse(tc));
1962 case EAPSRP_SVALIDATOR:
1963 tc = (struct t_client *)esp->es_client.ea_session;
1964 if (tc == NULL || esp->es_client.ea_skey == NULL) {
1965 warn("EAP: peer sent Subtype 3 without 1/2");
1966 eap_send_nak(esp, id, EAPT_MD5CHAP);
1970 * If we're already open, then this ought to be a
1971 * duplicate. Otherwise, check that the server is
1972 * who we think it is.
1974 if (esp->es_client.ea_state == eapOpen) {
1975 if (id != esp->es_client.ea_id) {
1976 warn("EAP: ID changed from %d to %d "
1977 "in SRP Subtype 3 rexmit",
1978 esp->es_client.ea_id, id);
1981 len -= sizeof (u_int32_t) + SHA_DIGESTSIZE;
1982 if (len < 0 || t_clientverify(tc, inp +
1983 sizeof (u_int32_t)) != 0) {
1984 error("EAP: SRP server verification "
1986 goto client_failure;
1988 GETLONG(esp->es_client.ea_keyflags, inp);
1989 /* Save pseudonym if user wants it. */
1990 if (len > 0 && esp->es_usepseudo) {
1991 INCPTR(SHA_DIGESTSIZE, inp);
1992 write_pseudonym(esp, inp, len, id);
1996 * We've verified our peer. We're now mostly done,
1997 * except for waiting on the regular EAP Success
2000 eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
2003 case EAPSRP_LWRECHALLENGE:
2005 warn("EAP: malformed Lightweight rechallenge");
2010 SHA1Update(&ctxt, vals, 1);
2011 SHA1Update(&ctxt, esp->es_client.ea_skey,
2013 SHA1Update(&ctxt, inp, len);
2014 SHA1Update(&ctxt, esp->es_client.ea_name,
2015 esp->es_client.ea_namelen);
2016 SHA1Final(dig, &ctxt);
2017 eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
2022 error("EAP: unknown SRP Subtype %d", vallen);
2023 eap_send_nak(esp, id, EAPT_MD5CHAP);
2027 #endif /* USE_SRP */
2030 info("EAP: unknown authentication type %d; Naking", typenum);
2031 eap_send_nak(esp, id, EAPT_SRP);
2035 if (esp->es_client.ea_timeout > 0) {
2036 UNTIMEOUT(eap_client_timeout, (void *)esp);
2037 TIMEOUT(eap_client_timeout, (void *)esp,
2038 esp->es_client.ea_timeout);
2044 esp->es_client.ea_state = eapBadAuth;
2045 if (esp->es_client.ea_timeout > 0) {
2046 UNTIMEOUT(eap_client_timeout, (void *)esp);
2048 esp->es_client.ea_session = NULL;
2050 auth_withpeer_fail(esp->es_unit, PPP_EAP);
2051 #endif /* USE_SRP */
2055 * eap_response - Receive EAP Response message (server mode).
2058 eap_response(esp, inp, id, len)
2067 char secret[MAXSECRETLEN];
2068 char rhostname[256];
2070 u_char hash[MD5_SIGNATURE_SIZE];
2072 struct t_server *ts;
2075 u_char dig[SHA_DIGESTSIZE];
2077 u_char dig[SHA_DIGESTSIZE];
2078 #endif /* USE_SRP */
2081 struct eaptls_session *ets;
2083 #endif /* USE_EAPTLS */
2086 * Ignore responses if we're not open
2088 if (esp->es_server.ea_state <= eapClosed)
2091 if (esp->es_server.ea_id != id) {
2092 dbglog("EAP: discarding Response %d; expected ID %d", id,
2093 esp->es_server.ea_id);
2097 esp->es_server.ea_responses++;
2100 error("EAP: empty Response message discarded");
2104 GETCHAR(typenum, inp);
2109 if (esp->es_server.ea_state != eapIdentify) {
2110 dbglog("EAP discarding unwanted Identify \"%.q\"", len,
2114 info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
2115 if (esp->es_server.ea_peer != NULL &&
2116 esp->es_server.ea_peer != remote_name)
2117 free(esp->es_server.ea_peer);
2118 esp->es_server.ea_peer = malloc(len + 1);
2119 if (esp->es_server.ea_peer == NULL) {
2120 esp->es_server.ea_peerlen = 0;
2121 eap_figure_next_state(esp, 1);
2124 BCOPY(inp, esp->es_server.ea_peer, len);
2125 esp->es_server.ea_peer[len] = '\0';
2126 esp->es_server.ea_peerlen = len;
2127 eap_figure_next_state(esp, 0);
2132 switch(esp->es_server.ea_state) {
2136 ets = (struct eaptls_session *) esp->es_server.ea_session;
2138 eap_figure_next_state(esp,
2139 eaptls_receive(esp->es_server.ea_session, inp, len));
2141 if(ets->alert_recv) {
2142 eap_send_failure(esp);
2149 dbglog("EAP-TLS ACK with extra data");
2151 eap_figure_next_state(esp, 0);
2154 case eapTlsRecvClient:
2155 /* Receive authentication response from client */
2157 GETCHAR(flags, inp);
2159 if(len == 1 && !flags) { /* Ack = ok */
2161 eaptls_gen_mppe_keys( esp->es_server.ea_session, 0 );
2163 eap_send_success(esp);
2165 else { /* failure */
2166 warn("Server authentication failed");
2167 eap_send_failure(esp);
2171 warn("Bogus EAP-TLS packet received from client");
2173 eaptls_free_session(esp->es_server.ea_session);
2177 case eapTlsRecvAlertAck:
2178 eap_send_failure(esp);
2182 eap_figure_next_state(esp, 1);
2186 #endif /* USE_EAPTLS */
2188 case EAPT_NOTIFICATION:
2189 dbglog("EAP unexpected Notification; response discarded");
2194 info("EAP: Nak Response with no suggested protocol");
2195 eap_figure_next_state(esp, 1);
2199 GETCHAR(vallen, inp);
2202 if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
2203 /* Peer cannot Nak Identify Request */
2204 eap_figure_next_state(esp, 1);
2210 /* Run through SRP validator selection again. */
2211 esp->es_server.ea_state = eapIdentify;
2212 eap_figure_next_state(esp, 0);
2216 esp->es_server.ea_state = eapMD5Chall;
2220 /* Send EAP-TLS start packet */
2222 esp->es_server.ea_state = eapTlsStart;
2224 #endif /* USE_EAPTLS */
2227 dbglog("EAP: peer requesting unknown Type %d", vallen);
2228 switch (esp->es_server.ea_state) {
2232 esp->es_server.ea_state = eapMD5Chall;
2236 esp->es_server.ea_state = eapIdentify;
2237 eap_figure_next_state(esp, 0);
2247 if (esp->es_server.ea_state != eapMD5Chall) {
2248 error("EAP: unexpected MD5-Response");
2249 eap_figure_next_state(esp, 1);
2253 error("EAP: received MD5-Response with no data");
2254 eap_figure_next_state(esp, 1);
2257 GETCHAR(vallen, inp);
2259 if (vallen != 16 || vallen > len) {
2260 error("EAP: MD5-Response with bad length %d", vallen);
2261 eap_figure_next_state(esp, 1);
2265 /* Not so likely to happen. */
2266 if (len - vallen >= sizeof (rhostname)) {
2267 dbglog("EAP: trimming really long peer name down");
2268 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2269 rhostname[sizeof (rhostname) - 1] = '\0';
2271 BCOPY(inp + vallen, rhostname, len - vallen);
2272 rhostname[len - vallen] = '\0';
2275 /* In case the remote doesn't give us his name. */
2276 if (explicit_remote ||
2277 (remote_name[0] != '\0' && vallen == len))
2278 strlcpy(rhostname, remote_name, sizeof (rhostname));
2281 * Get the secret for authenticating the specified
2284 if (!get_secret(esp->es_unit, rhostname,
2285 esp->es_server.ea_name, secret, &secret_len, 1)) {
2286 dbglog("EAP: no MD5 secret for auth of %q", rhostname);
2287 eap_send_failure(esp);
2290 MD5_Init(&mdContext);
2291 MD5_Update(&mdContext, &esp->es_server.ea_id, 1);
2292 MD5_Update(&mdContext, (u_char *)secret, secret_len);
2293 BZERO(secret, sizeof (secret));
2294 MD5_Update(&mdContext, esp->es_challenge, esp->es_challen);
2295 MD5_Final(hash, &mdContext);
2296 if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) {
2297 eap_send_failure(esp);
2300 esp->es_server.ea_type = EAPT_MD5CHAP;
2301 eap_send_success(esp);
2302 eap_figure_next_state(esp, 0);
2303 if (esp->es_rechallenge != 0)
2304 TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2310 error("EAP: empty SRP Response");
2311 eap_figure_next_state(esp, 1);
2314 GETCHAR(typenum, inp);
2318 if (esp->es_server.ea_state != eapSRP1) {
2319 error("EAP: unexpected SRP Subtype 1 Response");
2320 eap_figure_next_state(esp, 1);
2325 ts = (struct t_server *)esp->es_server.ea_session;
2327 esp->es_server.ea_skey = t_servergetkey(ts, &A);
2328 if (esp->es_server.ea_skey == NULL) {
2329 /* Client's A value is bogus; terminate now */
2330 error("EAP: bogus A value from client");
2331 eap_send_failure(esp);
2333 eap_figure_next_state(esp, 0);
2337 case EAPSRP_CVALIDATOR:
2338 if (esp->es_server.ea_state != eapSRP2) {
2339 error("EAP: unexpected SRP Subtype 2 Response");
2340 eap_figure_next_state(esp, 1);
2343 if (len < sizeof (u_int32_t) + SHA_DIGESTSIZE) {
2344 error("EAP: M1 length %d < %d", len,
2345 sizeof (u_int32_t) + SHA_DIGESTSIZE);
2346 eap_figure_next_state(esp, 1);
2349 GETLONG(esp->es_server.ea_keyflags, inp);
2350 ts = (struct t_server *)esp->es_server.ea_session;
2352 if (t_serververify(ts, inp)) {
2353 info("EAP: unable to validate client identity");
2354 eap_send_failure(esp);
2357 eap_figure_next_state(esp, 0);
2361 if (esp->es_server.ea_state != eapSRP3) {
2362 error("EAP: unexpected SRP Subtype 3 Response");
2363 eap_send_failure(esp);
2366 esp->es_server.ea_type = EAPT_SRP;
2367 eap_send_success(esp);
2368 eap_figure_next_state(esp, 0);
2369 if (esp->es_rechallenge != 0)
2370 TIMEOUT(eap_rechallenge, esp,
2371 esp->es_rechallenge);
2372 if (esp->es_lwrechallenge != 0)
2373 TIMEOUT(srp_lwrechallenge, esp,
2374 esp->es_lwrechallenge);
2377 case EAPSRP_LWRECHALLENGE:
2378 if (esp->es_server.ea_state != eapSRP4) {
2379 info("EAP: unexpected SRP Subtype 4 Response");
2382 if (len != SHA_DIGESTSIZE) {
2383 error("EAP: bad Lightweight rechallenge "
2389 SHA1Update(&ctxt, &vallen, 1);
2390 SHA1Update(&ctxt, esp->es_server.ea_skey,
2392 SHA1Update(&ctxt, esp->es_challenge, esp->es_challen);
2393 SHA1Update(&ctxt, esp->es_server.ea_peer,
2394 esp->es_server.ea_peerlen);
2395 SHA1Final(dig, &ctxt);
2396 if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) {
2397 error("EAP: failed Lightweight rechallenge");
2398 eap_send_failure(esp);
2401 esp->es_server.ea_state = eapOpen;
2402 if (esp->es_lwrechallenge != 0)
2403 TIMEOUT(srp_lwrechallenge, esp,
2404 esp->es_lwrechallenge);
2408 #endif /* USE_SRP */
2411 /* This can't happen. */
2412 error("EAP: unknown Response type %d; ignored", typenum);
2416 if (esp->es_server.ea_timeout > 0) {
2417 UNTIMEOUT(eap_server_timeout, (void *)esp);
2420 if (esp->es_server.ea_state != eapBadAuth &&
2421 esp->es_server.ea_state != eapOpen) {
2422 esp->es_server.ea_id++;
2423 eap_send_request(esp);
2428 * eap_success - Receive EAP Success message (client mode).
2431 eap_success(esp, inp, id, len)
2437 if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
2439 && esp->es_client.ea_state != eapTlsRecvSuccess
2440 #endif /* USE_EAPTLS */
2442 dbglog("EAP unexpected success message in state %s (%d)",
2443 eap_state_name(esp->es_client.ea_state),
2444 esp->es_client.ea_state);
2449 if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state !=
2450 eapTlsRecvSuccess) {
2451 dbglog("EAP-TLS unexpected success message in state %s (%d)",
2452 eap_state_name(esp->es_client.ea_state),
2453 esp->es_client.ea_state);
2456 #endif /* USE_EAPTLS */
2458 if (esp->es_client.ea_timeout > 0) {
2459 UNTIMEOUT(eap_client_timeout, (void *)esp);
2463 /* This is odd. The spec doesn't allow for this. */
2467 esp->es_client.ea_state = eapOpen;
2468 auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2472 * eap_failure - Receive EAP Failure message (client mode).
2475 eap_failure(esp, inp, id, len)
2482 * Ignore failure messages if we're not open
2484 if (esp->es_client.ea_state <= eapClosed)
2487 if (!eap_client_active(esp)) {
2488 dbglog("EAP unexpected failure message in state %s (%d)",
2489 eap_state_name(esp->es_client.ea_state),
2490 esp->es_client.ea_state);
2493 if (esp->es_client.ea_timeout > 0) {
2494 UNTIMEOUT(eap_client_timeout, (void *)esp);
2498 /* This is odd. The spec doesn't allow for this. */
2502 esp->es_client.ea_state = eapBadAuth;
2504 error("EAP: peer reports authentication failure");
2505 auth_withpeer_fail(esp->es_unit, PPP_EAP);
2509 * eap_input - Handle received EAP message.
2512 eap_input(unit, inp, inlen)
2517 eap_state *esp = &eap_states[unit];
2522 * Parse header (code, id and length). If packet too short,
2525 if (inlen < EAP_HEADERLEN) {
2526 error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2532 if (len < EAP_HEADERLEN || len > inlen) {
2533 error("EAP: packet has illegal length field %d (%d..%d)", len,
2534 EAP_HEADERLEN, inlen);
2537 len -= EAP_HEADERLEN;
2539 /* Dispatch based on message code */
2542 eap_request(esp, inp, id, len);
2546 eap_response(esp, inp, id, len);
2550 eap_success(esp, inp, id, len);
2554 eap_failure(esp, inp, id, len);
2557 default: /* XXX Need code reject */
2558 /* Note: it's not legal to send EAP Nak here. */
2559 warn("EAP: unknown code %d received", code);
2565 * eap_printpkt - print the contents of an EAP packet.
2567 static char *eap_codenames[] = {
2568 "Request", "Response", "Success", "Failure"
2571 static char *eap_typenames[] = {
2572 "Identity", "Notification", "Nak", "MD5-Challenge",
2573 "OTP", "Generic-Token", NULL, NULL,
2574 "RSA", "DSS", "KEA", "KEA-Validate",
2575 "TLS", "Defender", "Windows 2000", "Arcot",
2576 "Cisco", "Nokia", "SRP"
2580 eap_printpkt(inp, inlen, printer, arg)
2583 void (*printer) __P((void *, char *, ...));
2586 int code, id, len, rtype, vallen;
2591 #endif /* USE_EAPTLS */
2593 if (inlen < EAP_HEADERLEN)
2599 if (len < EAP_HEADERLEN || len > inlen)
2602 if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
2603 printer(arg, " %s", eap_codenames[code-1]);
2605 printer(arg, " code=0x%x", code);
2606 printer(arg, " id=0x%x", id);
2607 len -= EAP_HEADERLEN;
2611 printer(arg, " <missing type>");
2614 GETCHAR(rtype, inp);
2617 rtype <= sizeof (eap_typenames) / sizeof (char *))
2618 printer(arg, " %s", eap_typenames[rtype-1]);
2620 printer(arg, " type=0x%x", rtype);
2623 case EAPT_NOTIFICATION:
2625 printer(arg, " <Message ");
2626 print_string((char *)inp, len, printer, arg);
2631 printer(arg, " <No message>");
2638 GETCHAR(vallen, inp);
2642 printer(arg, " <Value%.*B>", vallen, inp);
2643 INCPTR(vallen, inp);
2646 printer(arg, " <Name ");
2647 print_string((char *)inp, len, printer, arg);
2652 printer(arg, " <No name>");
2660 GETCHAR(flags, inp);
2663 if(flags == 0 && len == 0){
2664 printer(arg, " Ack");
2668 printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
2669 printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
2670 printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
2672 #endif /* USE_EAPTLS */
2677 GETCHAR(vallen, inp);
2679 printer(arg, "-%d", vallen);
2681 case EAPSRP_CHALLENGE:
2682 GETCHAR(vallen, inp);
2687 printer(arg, " <Name ");
2688 print_string((char *)inp, vallen, printer,
2692 printer(arg, " <No name>");
2694 INCPTR(vallen, inp);
2696 GETCHAR(vallen, inp);
2700 printer(arg, " <s%.*B>", vallen, inp);
2701 INCPTR(vallen, inp);
2703 GETCHAR(vallen, inp);
2708 printer(arg, " <Default g=2>");
2710 printer(arg, " <g%.*B>", vallen, inp);
2712 INCPTR(vallen, inp);
2715 printer(arg, " <Default N>");
2717 printer(arg, " <N%.*B>", len, inp);
2724 printer(arg, " <B%.*B>", len, inp);
2729 case EAPSRP_SVALIDATOR:
2730 if (len < sizeof (u_int32_t))
2733 len -= sizeof (u_int32_t);
2734 if (uval & SRPVAL_EBIT) {
2736 uval &= ~SRPVAL_EBIT;
2739 printer(arg, " f<%X>", uval);
2741 if ((vallen = len) > SHA_DIGESTSIZE)
2742 vallen = SHA_DIGESTSIZE;
2743 printer(arg, " <M2%.*B%s>", len, inp,
2744 len < SHA_DIGESTSIZE ? "?" : "");
2745 INCPTR(vallen, inp);
2748 printer(arg, " <PN%.*B>", len, inp);
2754 case EAPSRP_LWRECHALLENGE:
2755 printer(arg, " <Challenge%.*B>", len, inp);
2767 GETCHAR(rtype, inp);
2770 rtype <= sizeof (eap_typenames) / sizeof (char *))
2771 printer(arg, " %s", eap_typenames[rtype-1]);
2773 printer(arg, " type=0x%x", rtype);
2777 printer(arg, " <Name ");
2778 print_string((char *)inp, len, printer, arg);
2789 GETCHAR(flags, inp);
2792 if(flags == 0 && len == 0){
2793 printer(arg, " Ack");
2797 printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
2798 printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
2799 printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
2802 #endif /* USE_EAPTLS */
2806 printer(arg, " <missing hint>");
2809 GETCHAR(rtype, inp);
2811 printer(arg, " <Suggested-type %02X", rtype);
2813 rtype < sizeof (eap_typenames) / sizeof (char *))
2814 printer(arg, " (%s)", eap_typenames[rtype-1]);
2820 printer(arg, " <missing length>");
2823 GETCHAR(vallen, inp);
2827 printer(arg, " <Value%.*B>", vallen, inp);
2828 INCPTR(vallen, inp);
2831 printer(arg, " <Name ");
2832 print_string((char *)inp, len, printer, arg);
2837 printer(arg, " <No name>");
2844 GETCHAR(vallen, inp);
2846 printer(arg, "-%d", vallen);
2849 printer(arg, " <A%.*B>", len, inp);
2854 case EAPSRP_CVALIDATOR:
2855 if (len < sizeof (u_int32_t))
2858 len -= sizeof (u_int32_t);
2859 if (uval & SRPVAL_EBIT) {
2861 uval &= ~SRPVAL_EBIT;
2864 printer(arg, " f<%X>", uval);
2866 printer(arg, " <M1%.*B%s>", len, inp,
2867 len == SHA_DIGESTSIZE ? "" : "?");
2875 case EAPSRP_LWRECHALLENGE:
2876 printer(arg, " <Response%.*B%s>", len, inp,
2877 len == SHA_DIGESTSIZE ? "" : "?");
2878 if ((vallen = len) > SHA_DIGESTSIZE)
2879 vallen = SHA_DIGESTSIZE;
2880 INCPTR(vallen, inp);
2888 case EAP_SUCCESS: /* No payload expected for these! */
2893 printer(arg, " <truncated>");
2898 printer(arg, "%8B...", inp);
2900 printer(arg, "%.*B", len, inp);
2903 return (inp - pstart);