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.
46 #define RCSID "$Id: eap.c,v 1.2 2002/11/14 21:50:12 fcusack Exp $"
57 #include <sys/types.h>
64 #include "pathnames.h"
66 /* For MD5_SIGNATURE_SIZE and MIN/MAX_CHALLENGE_LENGTH; should fix. */
77 #ifndef SHA_DIGESTSIZE
78 #define SHA_DIGESTSIZE 20
81 static const char rcsid[] = RCSID;
83 eap_state eap_states[NUM_PPP]; /* EAP state; one for each unit */
85 static char *pn_secret = NULL; /* Pseudonym generating secret */
89 * Command-line options.
91 static option_t eap_option_list[] = {
92 { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,
93 "Set retransmit timeout for EAP Requests (server)" },
94 { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,
95 "Set max number of EAP Requests sent (server)" },
96 { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,
97 "Set time limit for peer EAP authentication" },
98 { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,
99 "Set max number of EAP Requests allows (client)" },
100 { "eap-interval", o_int, &eap_states[0].es_rechallenge,
101 "Set interval for EAP rechallenge" },
103 { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,
104 "Set interval for SRP lightweight rechallenge" },
105 { "srp-pn-secret", o_string, &pn_secret,
106 "Long term pseudonym generation secret" },
107 { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,
108 "Use pseudonym if offered one by server", 1 },
114 * Protocol entry points.
116 static void eap_init __P((int unit));
117 static void eap_input __P((int unit, u_char *inp, int inlen));
118 static void eap_protrej __P((int unit));
119 static void eap_lowerup __P((int unit));
120 static void eap_lowerdown __P((int unit));
121 static int eap_printpkt __P((u_char *inp, int inlen,
122 void (*)(void *arg, char *fmt, ...), void *arg));
124 struct protent eap_protent = {
125 PPP_EAP, /* protocol number */
126 eap_init, /* initialization procedure */
127 eap_input, /* process a received packet */
128 eap_protrej, /* process a received protocol-reject */
129 eap_lowerup, /* lower layer has gone up */
130 eap_lowerdown, /* lower layer has gone down */
131 NULL, /* open the protocol */
132 NULL, /* close the protocol */
133 eap_printpkt, /* print a packet in readable form */
134 NULL, /* process a received data packet */
135 1, /* protocol enabled */
136 "EAP", /* text name of protocol */
137 NULL, /* text name of corresponding data protocol */
138 eap_option_list, /* list of command-line options */
139 NULL, /* check requested options; assign defaults */
140 NULL, /* configure interface for demand-dial */
141 NULL /* say whether to bring up link for this pkt */
145 * A well-known 2048 bit modulus.
147 static const u_char wkmodulus[] = {
148 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
149 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
150 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
151 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
152 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
153 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
154 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
155 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
156 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
157 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
158 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
159 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
160 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
161 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
162 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
163 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
164 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
165 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
166 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
167 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
168 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
169 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
170 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
171 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
172 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
173 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
174 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
175 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
176 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
177 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
178 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
179 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
182 /* Local forward declarations. */
183 static void eap_server_timeout __P((void *arg));
186 * Convert EAP state code to printable string for debug.
190 enum eap_state_code esc;
192 static const char *state_names[] = { EAP_STATES };
194 return (state_names[(int)esc]);
198 * eap_init - Initialize state for an EAP user. This is currently
199 * called once by main() during start-up.
205 eap_state *esp = &eap_states[unit];
207 BZERO(esp, sizeof (*esp));
209 esp->es_server.ea_timeout = EAP_DEFTIMEOUT;
210 esp->es_server.ea_maxrequests = EAP_DEFTRANSMITS;
211 esp->es_server.ea_id = (u_char)(drand48() * 0x100);
212 esp->es_client.ea_timeout = EAP_DEFREQTIME;
213 esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
217 * eap_client_timeout - Give up waiting for the peer to send any
221 eap_client_timeout(arg)
224 eap_state *esp = (eap_state *) arg;
226 if (!eap_client_active(esp))
229 error("EAP: timeout waiting for Request from peer");
230 auth_withpeer_fail(esp->es_unit, PPP_EAP);
231 esp->es_client.ea_state = eapBadAuth;
235 * eap_authwithpeer - Authenticate to our peer (behave as client).
237 * Start client state and wait for requests. This is called only
241 eap_authwithpeer(unit, localname)
245 eap_state *esp = &eap_states[unit];
247 /* Save the peer name we're given */
248 esp->es_client.ea_name = localname;
249 esp->es_client.ea_namelen = strlen(localname);
251 esp->es_client.ea_state = eapListen;
254 * Start a timer so that if the other end just goes
255 * silent, we don't sit here waiting forever.
257 if (esp->es_client.ea_timeout > 0)
258 TIMEOUT(eap_client_timeout, (void *)esp,
259 esp->es_client.ea_timeout);
263 * Format a standard EAP Failure message and send it to the peer.
267 eap_send_failure(esp)
272 outp = outpacket_buf;
274 MAKEHEADER(outp, PPP_EAP);
276 PUTCHAR(EAP_FAILURE, outp);
277 esp->es_server.ea_id++;
278 PUTCHAR(esp->es_server.ea_id, outp);
279 PUTSHORT(EAP_HEADERLEN, outp);
281 output(esp->es_unit, outpacket_buf, EAP_HEADERLEN + PPP_HDRLEN);
283 esp->es_server.ea_state = eapBadAuth;
284 auth_peer_fail(esp->es_unit, PPP_EAP);
288 * Format a standard EAP Success message and send it to the peer.
292 eap_send_success(esp)
297 outp = outpacket_buf;
299 MAKEHEADER(outp, PPP_EAP);
301 PUTCHAR(EAP_SUCCESS, outp);
302 esp->es_server.ea_id++;
303 PUTCHAR(esp->es_server.ea_id, outp);
304 PUTSHORT(EAP_HEADERLEN, outp);
306 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);
308 auth_peer_success(esp->es_unit, PPP_EAP, 0,
309 esp->es_server.ea_peer, esp->es_server.ea_peerlen);
314 * Set DES key according to pseudonym-generating secret and current
318 pncrypt_setkey(int timeoffs)
323 u_char dig[SHA_DIGESTSIZE];
326 if (pn_secret == NULL)
328 reftime = time(NULL) + timeoffs;
329 tp = localtime(&reftime);
331 SHA1Update(&ctxt, pn_secret, strlen(pn_secret));
332 strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp);
333 SHA1Update(&ctxt, tbuf, strlen(tbuf));
334 SHA1Final(dig, &ctxt);
335 return (DesSetkey(dig));
338 static char base64[] =
339 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
347 b64enc(bs, inp, inlen, outp)
356 bs->bs_bits = (bs->bs_bits << 8) | *inp++;
359 if (bs->bs_offs >= 24) {
360 *outp++ = base64[(bs->bs_bits >> 18) & 0x3F];
361 *outp++ = base64[(bs->bs_bits >> 12) & 0x3F];
362 *outp++ = base64[(bs->bs_bits >> 6) & 0x3F];
363 *outp++ = base64[bs->bs_bits & 0x3F];
379 if (bs->bs_offs == 8) {
380 *outp++ = base64[(bs->bs_bits >> 2) & 0x3F];
381 *outp++ = base64[(bs->bs_bits << 4) & 0x3F];
383 } else if (bs->bs_offs == 16) {
384 *outp++ = base64[(bs->bs_bits >> 10) & 0x3F];
385 *outp++ = base64[(bs->bs_bits >> 4) & 0x3F];
386 *outp++ = base64[(bs->bs_bits << 2) & 0x3F];
395 b64dec(bs, inp, inlen, outp)
405 if ((cp = strchr(base64, *inp++)) == NULL)
407 bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);
410 if (bs->bs_offs >= 8) {
411 *outp++ = bs->bs_bits >> (bs->bs_offs - 8);
421 * Assume that current waiting server state is complete and figure
422 * next state to use based on available authentication data. 'status'
423 * indicates if there was an error in handling the last query. It is
424 * 0 for success and non-zero for failure.
427 eap_figure_next_state(esp, status)
432 unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp;
434 struct t_confent *tce, mytce;
437 int id, i, plen, toffs;
442 esp->es_server.ea_timeout = esp->es_savedtime;
443 switch (esp->es_server.ea_state) {
449 /* Discard any previous session. */
450 ts = (struct t_server *)esp->es_server.ea_session;
453 esp->es_server.ea_session = NULL;
454 esp->es_server.ea_skey = NULL;
458 esp->es_server.ea_state = eapBadAuth;
462 /* If we've got a pseudonym, try to decode to real name. */
463 if (esp->es_server.ea_peerlen > SRP_PSEUDO_LEN &&
464 strncmp(esp->es_server.ea_peer, SRP_PSEUDO_ID,
465 SRP_PSEUDO_LEN) == 0 &&
466 (esp->es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 <
468 BZERO(&bs, sizeof (bs));
470 esp->es_server.ea_peer + SRP_PSEUDO_LEN,
471 esp->es_server.ea_peerlen - SRP_PSEUDO_LEN,
474 for (i = 0; i < 5; i++) {
475 pncrypt_setkey(toffs);
477 if (!DesDecrypt(secbuf, clear)) {
478 dbglog("no DES here; cannot decode "
482 id = *(unsigned char *)clear;
483 if (id + 1 <= plen && id + 9 > plen)
486 if (plen % 8 == 0 && i < 5) {
488 * Note that this is always shorter than the
489 * original stored string, so there's no need
492 if ((i = plen = *(unsigned char *)clear) > 7)
494 esp->es_server.ea_peerlen = plen;
495 dp = (unsigned char *)esp->es_server.ea_peer;
496 BCOPY(clear + 1, dp, i);
501 (void) DesDecrypt(sp, dp);
506 esp->es_server.ea_peer[
507 esp->es_server.ea_peerlen] = '\0';
508 dbglog("decoded pseudonym to \"%.*q\"",
509 esp->es_server.ea_peerlen,
510 esp->es_server.ea_peer);
512 dbglog("failed to decode real name");
513 /* Stay in eapIdentfy state; requery */
517 /* Look up user in secrets database. */
518 if (get_srp_secret(esp->es_unit, esp->es_server.ea_peer,
519 esp->es_server.ea_name, (char *)secbuf, 1) != 0) {
520 /* Set up default in case SRP entry is bad */
521 esp->es_server.ea_state = eapMD5Chall;
522 /* Get t_confent based on index in srp-secrets */
523 id = strtol((char *)secbuf, &cp, 10);
524 if (*cp++ != ':' || id < 0)
528 mytce.modulus.data = (u_char *)wkmodulus;
529 mytce.modulus.len = sizeof (wkmodulus);
530 mytce.generator.data = (u_char *)"\002";
531 mytce.generator.len = 1;
533 } else if ((tce = gettcid(id)) != NULL) {
535 * Client will have to verify this modulus/
536 * generator combination, and that will take
537 * a while. Lengthen the timeout here.
539 if (esp->es_server.ea_timeout > 0 &&
540 esp->es_server.ea_timeout < 30)
541 esp->es_server.ea_timeout = 30;
545 if ((cp2 = strchr(cp, ':')) == NULL)
548 tpw.pebuf.name = esp->es_server.ea_peer;
549 tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,
551 tpw.pebuf.password.data = tpw.pwbuf;
552 tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,
554 tpw.pebuf.salt.data = tpw.saltbuf;
555 if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)
557 esp->es_server.ea_session = (void *)ts;
558 esp->es_server.ea_state = eapSRP1;
559 vals[0] = esp->es_server.ea_id + 1;
561 t_serveraddexdata(ts, vals, 2);
562 /* Generate B; must call before t_servergetkey() */
567 esp->es_server.ea_state = eapMD5Chall;
572 ts = (struct t_server *)esp->es_server.ea_session;
573 if (ts != NULL && status != 0) {
575 esp->es_server.ea_session = NULL;
576 esp->es_server.ea_skey = NULL;
580 esp->es_server.ea_state = eapMD5Chall;
581 } else if (status != 0 || esp->es_server.ea_session == NULL) {
582 esp->es_server.ea_state = eapBadAuth;
584 esp->es_server.ea_state = eapSRP2;
590 ts = (struct t_server *)esp->es_server.ea_session;
591 if (ts != NULL && status != 0) {
593 esp->es_server.ea_session = NULL;
594 esp->es_server.ea_skey = NULL;
597 if (status != 0 || esp->es_server.ea_session == NULL) {
598 esp->es_server.ea_state = eapBadAuth;
600 esp->es_server.ea_state = eapSRP3;
607 ts = (struct t_server *)esp->es_server.ea_session;
608 if (ts != NULL && status != 0) {
610 esp->es_server.ea_session = NULL;
611 esp->es_server.ea_skey = NULL;
614 if (status != 0 || esp->es_server.ea_session == NULL) {
615 esp->es_server.ea_state = eapBadAuth;
617 esp->es_server.ea_state = eapOpen;
623 esp->es_server.ea_state = eapBadAuth;
625 esp->es_server.ea_state = eapOpen;
630 esp->es_server.ea_state = eapBadAuth;
633 if (esp->es_server.ea_state == eapBadAuth)
634 eap_send_failure(esp);
638 * Format an EAP Request message and send it to the peer. Message
639 * type depends on current state. (Server operation)
642 eap_send_request(esp)
653 u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp;
659 /* Handle both initial auth and restart */
660 if (esp->es_server.ea_state < eapIdentify &&
661 esp->es_server.ea_state != eapInitial) {
662 esp->es_server.ea_state = eapIdentify;
663 if (explicit_remote) {
665 * If we already know the peer's
666 * unauthenticated name, then there's no
667 * reason to ask. Go to next state instead.
669 esp->es_server.ea_peer = remote_name;
670 esp->es_server.ea_peerlen = strlen(remote_name);
671 eap_figure_next_state(esp, 0);
675 if (esp->es_server.ea_maxrequests > 0 &&
676 esp->es_server.ea_requests >= esp->es_server.ea_maxrequests) {
677 if (esp->es_server.ea_responses > 0)
678 error("EAP: too many Requests sent");
680 error("EAP: no response to Requests");
681 eap_send_failure(esp);
685 outp = outpacket_buf;
687 MAKEHEADER(outp, PPP_EAP);
689 PUTCHAR(EAP_REQUEST, outp);
690 PUTCHAR(esp->es_server.ea_id, outp);
694 switch (esp->es_server.ea_state) {
696 PUTCHAR(EAPT_IDENTITY, outp);
698 challen = strlen(str);
699 BCOPY(str, outp, challen);
700 INCPTR(challen, outp);
704 PUTCHAR(EAPT_MD5CHAP, outp);
706 * pick a random challenge length between
707 * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
709 challen = (drand48() *
710 (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
711 MIN_CHALLENGE_LENGTH;
712 PUTCHAR(challen, outp);
713 esp->es_challen = challen;
714 ptr = esp->es_challenge;
715 while (--challen >= 0)
716 *ptr++ = (u_char) (drand48() * 0x100);
717 BCOPY(esp->es_challenge, outp, esp->es_challen);
718 INCPTR(esp->es_challen, outp);
719 BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
720 INCPTR(esp->es_server.ea_namelen, outp);
725 PUTCHAR(EAPT_SRP, outp);
726 PUTCHAR(EAPSRP_CHALLENGE, outp);
728 PUTCHAR(esp->es_server.ea_namelen, outp);
729 BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
730 INCPTR(esp->es_server.ea_namelen, outp);
732 ts = (struct t_server *)esp->es_server.ea_session;
734 PUTCHAR(ts->s.len, outp);
735 BCOPY(ts->s.data, outp, ts->s.len);
736 INCPTR(ts->s.len, outp);
738 if (ts->g.len == 1 && ts->g.data[0] == 2) {
741 PUTCHAR(ts->g.len, outp);
742 BCOPY(ts->g.data, outp, ts->g.len);
743 INCPTR(ts->g.len, outp);
746 if (ts->n.len != sizeof (wkmodulus) ||
747 BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) {
748 BCOPY(ts->n.data, outp, ts->n.len);
749 INCPTR(ts->n.len, outp);
754 PUTCHAR(EAPT_SRP, outp);
755 PUTCHAR(EAPSRP_SKEY, outp);
757 ts = (struct t_server *)esp->es_server.ea_session;
759 BCOPY(ts->B.data, outp, ts->B.len);
760 INCPTR(ts->B.len, outp);
764 PUTCHAR(EAPT_SRP, outp);
765 PUTCHAR(EAPSRP_SVALIDATOR, outp);
766 PUTLONG(SRPVAL_EBIT, outp);
767 ts = (struct t_server *)esp->es_server.ea_session;
769 BCOPY(t_serverresponse(ts), outp, SHA_DIGESTSIZE);
770 INCPTR(SHA_DIGESTSIZE, outp);
772 if (pncrypt_setkey(0)) {
773 /* Generate pseudonym */
775 cp = (unsigned char *)esp->es_server.ea_peer;
776 if ((j = i = esp->es_server.ea_peerlen) > 7)
779 BCOPY(cp, clear + 1, j);
782 if (!DesEncrypt(clear, cipher)) {
783 dbglog("no DES here; not generating pseudonym");
786 BZERO(&b64, sizeof (b64));
787 outp++; /* space for pseudonym length */
788 outp += b64enc(&b64, cipher, 8, outp);
790 (void) DesEncrypt(cp, cipher);
791 outp += b64enc(&b64, cipher, 8, outp);
799 *cp++ = drand48() * 0x100;
802 (void) DesEncrypt(clear, cipher);
803 outp += b64enc(&b64, cipher, 8, outp);
805 outp += b64flush(&b64, outp);
807 /* Set length and pad out to next 20 octet boundary */
812 while (i < SHA_DIGESTSIZE) {
813 *outp++ = drand48() * 0x100;
818 /* Obscure the pseudonym with SHA1 hash */
820 SHA1Update(&ctxt, &esp->es_server.ea_id, 1);
821 SHA1Update(&ctxt, esp->es_server.ea_skey,
823 SHA1Update(&ctxt, esp->es_server.ea_peer,
824 esp->es_server.ea_peerlen);
825 while (optr < outp) {
826 SHA1Final(dig, &ctxt);
828 while (cp < dig + SHA_DIGESTSIZE)
831 SHA1Update(&ctxt, &esp->es_server.ea_id, 1);
832 SHA1Update(&ctxt, esp->es_server.ea_skey,
834 SHA1Update(&ctxt, optr - SHA_DIGESTSIZE,
841 PUTCHAR(EAPT_SRP, outp);
842 PUTCHAR(EAPSRP_LWRECHALLENGE, outp);
843 challen = MIN_CHALLENGE_LENGTH +
844 ((MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH) * drand48());
845 esp->es_challen = challen;
846 ptr = esp->es_challenge;
847 while (--challen >= 0)
848 *ptr++ = drand48() * 0x100;
849 BCOPY(esp->es_challenge, outp, esp->es_challen);
850 INCPTR(esp->es_challen, outp);
858 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
859 PUTSHORT(outlen, lenloc);
861 output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
863 esp->es_server.ea_requests++;
865 if (esp->es_server.ea_timeout > 0)
866 TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
870 * eap_authpeer - Authenticate our peer (behave as server).
872 * Start server state and send first request. This is called only
876 eap_authpeer(unit, localname)
880 eap_state *esp = &eap_states[unit];
882 /* Save the name we're given. */
883 esp->es_server.ea_name = localname;
884 esp->es_server.ea_namelen = strlen(localname);
886 esp->es_savedtime = esp->es_server.ea_timeout;
888 /* Lower layer up yet? */
889 if (esp->es_server.ea_state == eapInitial ||
890 esp->es_server.ea_state == eapPending) {
891 esp->es_server.ea_state = eapPending;
895 esp->es_server.ea_state = eapPending;
897 /* ID number not updated here intentionally; hashed into M1 */
898 eap_send_request(esp);
902 * eap_server_timeout - Retransmission timer for sending Requests
906 eap_server_timeout(arg)
909 eap_state *esp = (eap_state *) arg;
911 if (!eap_server_active(esp))
914 /* EAP ID number must not change on timeout. */
915 eap_send_request(esp);
919 * When it's time to send rechallenge the peer, this timeout is
920 * called. Once the rechallenge is successful, the response handler
921 * will restart the timer. If it fails, then the link is dropped.
927 eap_state *esp = (eap_state *)arg;
929 if (esp->es_server.ea_state != eapOpen &&
930 esp->es_server.ea_state != eapSRP4)
933 esp->es_server.ea_requests = 0;
934 esp->es_server.ea_state = eapIdentify;
935 eap_figure_next_state(esp, 0);
936 esp->es_server.ea_id++;
937 eap_send_request(esp);
941 srp_lwrechallenge(arg)
944 eap_state *esp = (eap_state *)arg;
946 if (esp->es_server.ea_state != eapOpen ||
947 esp->es_server.ea_type != EAPT_SRP)
950 esp->es_server.ea_requests = 0;
951 esp->es_server.ea_state = eapSRP4;
952 esp->es_server.ea_id++;
953 eap_send_request(esp);
957 * eap_lowerup - The lower layer is now up.
959 * This is called before either eap_authpeer or eap_authwithpeer. See
960 * link_established() in auth.c. All that's necessary here is to
961 * return to closed state so that those two routines will do the right
968 eap_state *esp = &eap_states[unit];
970 /* Discard any (possibly authenticated) peer name. */
971 if (esp->es_server.ea_peer != NULL &&
972 esp->es_server.ea_peer != remote_name)
973 free(esp->es_server.ea_peer);
974 esp->es_server.ea_peer = NULL;
975 if (esp->es_client.ea_peer != NULL)
976 free(esp->es_client.ea_peer);
977 esp->es_client.ea_peer = NULL;
979 esp->es_client.ea_state = eapClosed;
980 esp->es_server.ea_state = eapClosed;
984 * eap_lowerdown - The lower layer is now down.
986 * Cancel all timeouts and return to initial state.
992 eap_state *esp = &eap_states[unit];
994 if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) {
995 UNTIMEOUT(eap_client_timeout, (void *)esp);
997 if (eap_server_active(esp)) {
998 if (esp->es_server.ea_timeout > 0) {
999 UNTIMEOUT(eap_server_timeout, (void *)esp);
1002 if ((esp->es_server.ea_state == eapOpen ||
1003 esp->es_server.ea_state == eapSRP4) &&
1004 esp->es_rechallenge > 0) {
1005 UNTIMEOUT(eap_rechallenge, (void *)esp);
1007 if (esp->es_server.ea_state == eapOpen &&
1008 esp->es_lwrechallenge > 0) {
1009 UNTIMEOUT(srp_lwrechallenge, (void *)esp);
1013 esp->es_client.ea_state = esp->es_server.ea_state = eapInitial;
1014 esp->es_client.ea_requests = esp->es_server.ea_requests = 0;
1018 * eap_protrej - Peer doesn't speak this protocol.
1020 * This shouldn't happen. If it does, it represents authentication
1027 eap_state *esp = &eap_states[unit];
1029 if (eap_client_active(esp)) {
1030 error("EAP authentication failed due to Protocol-Reject");
1031 auth_withpeer_fail(unit, PPP_EAP);
1033 if (eap_server_active(esp)) {
1034 error("EAP authentication of peer failed on Protocol-Reject");
1035 auth_peer_fail(unit, PPP_EAP);
1037 eap_lowerdown(unit);
1041 * Format and send a regular EAP Response message.
1044 eap_send_response(esp, id, typenum, str, lenstr)
1054 outp = outpacket_buf;
1056 MAKEHEADER(outp, PPP_EAP);
1058 PUTCHAR(EAP_RESPONSE, outp);
1060 esp->es_client.ea_id = id;
1061 msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr;
1062 PUTSHORT(msglen, outp);
1063 PUTCHAR(typenum, outp);
1065 BCOPY(str, outp, lenstr);
1068 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1072 * Format and send an MD5-Challenge EAP Response message.
1075 eap_chap_response(esp, id, hash, name, namelen)
1085 outp = outpacket_buf;
1087 MAKEHEADER(outp, PPP_EAP);
1089 PUTCHAR(EAP_RESPONSE, outp);
1091 esp->es_client.ea_id = id;
1092 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE +
1094 PUTSHORT(msglen, outp);
1095 PUTCHAR(EAPT_MD5CHAP, outp);
1096 PUTCHAR(MD5_SIGNATURE_SIZE, outp);
1097 BCOPY(hash, outp, MD5_SIGNATURE_SIZE);
1098 INCPTR(MD5_SIGNATURE_SIZE, outp);
1100 BCOPY(name, outp, namelen);
1103 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1108 * Format and send a SRP EAP Response message.
1111 eap_srp_response(esp, id, subtypenum, str, lenstr)
1121 outp = outpacket_buf;
1123 MAKEHEADER(outp, PPP_EAP);
1125 PUTCHAR(EAP_RESPONSE, outp);
1127 esp->es_client.ea_id = id;
1128 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr;
1129 PUTSHORT(msglen, outp);
1130 PUTCHAR(EAPT_SRP, outp);
1131 PUTCHAR(subtypenum, outp);
1133 BCOPY(str, outp, lenstr);
1136 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1140 * Format and send a SRP EAP Client Validator Response message.
1143 eap_srpval_response(esp, id, flags, str)
1152 outp = outpacket_buf;
1154 MAKEHEADER(outp, PPP_EAP);
1156 PUTCHAR(EAP_RESPONSE, outp);
1158 esp->es_client.ea_id = id;
1159 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) +
1161 PUTSHORT(msglen, outp);
1162 PUTCHAR(EAPT_SRP, outp);
1163 PUTCHAR(EAPSRP_CVALIDATOR, outp);
1164 PUTLONG(flags, outp);
1165 BCOPY(str, outp, SHA_DIGESTSIZE);
1167 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1169 #endif /* USE_SRP */
1172 eap_send_nak(esp, id, type)
1180 outp = outpacket_buf;
1182 MAKEHEADER(outp, PPP_EAP);
1184 PUTCHAR(EAP_RESPONSE, outp);
1186 esp->es_client.ea_id = id;
1187 msglen = EAP_HEADERLEN + 2 * sizeof (u_char);
1188 PUTSHORT(msglen, outp);
1189 PUTCHAR(EAPT_NAK, outp);
1190 PUTCHAR(type, outp);
1192 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1199 char *user, *path, *file;
1202 static bool pnlogged = 0;
1204 pw = getpwuid(getuid());
1205 if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
1209 file = _PATH_PSEUDONYM;
1210 pl = strlen(user) + strlen(file) + 2;
1214 (void) slprintf(path, pl, "%s/%s", user, file);
1216 dbglog("pseudonym file: %s", path);
1223 open_pn_file(modebits)
1229 if ((path = name_of_pn_file()) == NULL)
1231 fd = open(path, modebits, S_IRUSR | S_IWUSR);
1243 if ((path = name_of_pn_file()) != NULL) {
1244 (void) unlink(path);
1250 write_pseudonym(esp, inp, len, id)
1256 u_char *datp, *digp;
1258 u_char dig[SHA_DIGESTSIZE];
1259 int dsize, fd, olen = len;
1262 * Do the decoding by working backwards. This eliminates the need
1263 * to save the decoded output in a separate buffer.
1267 if ((dsize = len % SHA_DIGESTSIZE) == 0)
1268 dsize = SHA_DIGESTSIZE;
1272 SHA1Update(&ctxt, &val, 1);
1273 SHA1Update(&ctxt, esp->es_client.ea_skey, SESSION_KEY_LEN);
1275 SHA1Update(&ctxt, datp, SHA_DIGESTSIZE);
1277 SHA1Update(&ctxt, esp->es_client.ea_name,
1278 esp->es_client.ea_namelen);
1280 SHA1Final(dig, &ctxt);
1281 for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++)
1285 /* Now check that the result is sane */
1286 if (olen <= 0 || *inp + 1 > olen) {
1287 dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp);
1292 fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);
1294 dbglog("EAP: error saving pseudonym: %m");
1297 len = write(fd, inp + 1, *inp);
1298 if (close(fd) != -1 && len == *inp) {
1299 dbglog("EAP: saved pseudonym");
1300 esp->es_usedpseudo = 0;
1302 dbglog("EAP: failed to save pseudonym");
1306 #endif /* USE_SRP */
1309 * eap_request - Receive EAP Request message (client mode).
1312 eap_request(esp, inp, id, len)
1321 char secret[MAXWORDLEN];
1322 char rhostname[256];
1324 u_char hash[MD5_SIGNATURE_SIZE];
1326 struct t_client *tc;
1327 struct t_num sval, gval, Nval, *Ap, Bval;
1330 u_char dig[SHA_DIGESTSIZE];
1332 #endif /* USE_SRP */
1335 * Note: we update es_client.ea_id *only if* a Response
1336 * message is being generated. Otherwise, we leave it the
1337 * same for duplicate detection purposes.
1340 esp->es_client.ea_requests++;
1341 if (esp->es_client.ea_maxrequests != 0 &&
1342 esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {
1343 info("EAP: received too many Request messages");
1344 if (esp->es_client.ea_timeout > 0) {
1345 UNTIMEOUT(eap_client_timeout, (void *)esp);
1347 auth_withpeer_fail(esp->es_unit, PPP_EAP);
1352 error("EAP: empty Request message discarded");
1356 GETCHAR(typenum, inp);
1362 info("EAP: Identity prompt \"%.*q\"", len, inp);
1364 if (esp->es_usepseudo &&
1365 (esp->es_usedpseudo == 0 ||
1366 (esp->es_usedpseudo == 1 &&
1367 id == esp->es_client.ea_id))) {
1368 esp->es_usedpseudo = 1;
1369 /* Try to get a pseudonym */
1370 if ((fd = open_pn_file(O_RDONLY)) >= 0) {
1371 strcpy(rhostname, SRP_PSEUDO_ID);
1372 len = read(fd, rhostname + SRP_PSEUDO_LEN,
1373 sizeof (rhostname) - SRP_PSEUDO_LEN);
1374 /* XXX NAI unsupported */
1376 eap_send_response(esp, id, typenum,
1377 rhostname, len + SRP_PSEUDO_LEN);
1384 /* Stop using pseudonym now. */
1385 if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
1387 esp->es_usedpseudo = 2;
1389 #endif /* USE_SRP */
1390 eap_send_response(esp, id, typenum, esp->es_client.ea_name,
1391 esp->es_client.ea_namelen);
1394 case EAPT_NOTIFICATION:
1396 info("EAP: Notification \"%.*q\"", len, inp);
1397 eap_send_response(esp, id, typenum, NULL, 0);
1402 * Avoid the temptation to send Response Nak in reply
1403 * to Request Nak here. It can only lead to trouble.
1405 warn("EAP: unexpected Nak in Request; ignored");
1406 /* Return because we're waiting for something real. */
1411 error("EAP: received MD5-Challenge with no data");
1412 /* Bogus request; wait for something real. */
1415 GETCHAR(vallen, inp);
1417 if (vallen < 8 || vallen > len) {
1418 error("EAP: MD5-Challenge with bad length %d (8..%d)",
1420 /* Try something better. */
1421 eap_send_nak(esp, id, EAPT_SRP);
1425 /* Not so likely to happen. */
1426 if (vallen >= len + sizeof (rhostname)) {
1427 dbglog("EAP: trimming really long peer name down");
1428 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1429 rhostname[sizeof (rhostname) - 1] = '\0';
1431 BCOPY(inp + vallen, rhostname, len - vallen);
1432 rhostname[len - vallen] = '\0';
1435 /* In case the remote doesn't give us his name. */
1436 if (explicit_remote ||
1437 (remote_name[0] != '\0' && vallen == len))
1438 strlcpy(rhostname, remote_name, sizeof (rhostname));
1441 * Get the secret for authenticating ourselves with
1442 * the specified host.
1444 if (!get_secret(esp->es_unit, esp->es_client.ea_name,
1445 rhostname, secret, &secret_len, 0)) {
1446 dbglog("EAP: no MD5 secret for auth to %q", rhostname);
1447 eap_send_nak(esp, id, EAPT_SRP);
1450 MD5Init(&mdContext);
1452 MD5Update(&mdContext, &typenum, 1);
1453 MD5Update(&mdContext, secret, secret_len);
1454 BZERO(secret, sizeof (secret));
1455 MD5Update(&mdContext, inp, vallen);
1456 MD5Final(hash, &mdContext);
1457 eap_chap_response(esp, id, hash, esp->es_client.ea_name,
1458 esp->es_client.ea_namelen);
1464 error("EAP: received empty SRP Request");
1465 /* Bogus request; wait for something real. */
1470 GETCHAR(vallen, inp);
1473 case EAPSRP_CHALLENGE:
1475 if (esp->es_client.ea_session != NULL) {
1476 tc = (struct t_client *)esp->es_client.
1479 * If this is a new challenge, then start
1480 * over with a new client session context.
1481 * Otherwise, just resend last response.
1483 if (id != esp->es_client.ea_id) {
1485 esp->es_client.ea_session = NULL;
1489 /* No session key just yet */
1490 esp->es_client.ea_skey = NULL;
1492 GETCHAR(vallen, inp);
1494 if (vallen >= len) {
1495 error("EAP: badly-formed SRP Challenge"
1497 /* Ignore badly-formed messages */
1500 BCOPY(inp, rhostname, vallen);
1501 rhostname[vallen] = '\0';
1502 INCPTR(vallen, inp);
1506 * In case the remote doesn't give us his name,
1507 * use configured name.
1509 if (explicit_remote ||
1510 (remote_name[0] != '\0' && vallen == 0)) {
1511 strlcpy(rhostname, remote_name,
1512 sizeof (rhostname));
1515 if (esp->es_client.ea_peer != NULL)
1516 free(esp->es_client.ea_peer);
1517 esp->es_client.ea_peer = strdup(rhostname);
1518 esp->es_client.ea_peerlen = strlen(rhostname);
1520 GETCHAR(vallen, inp);
1522 if (vallen >= len) {
1523 error("EAP: badly-formed SRP Challenge"
1525 /* Ignore badly-formed messages */
1530 INCPTR(vallen, inp);
1533 GETCHAR(vallen, inp);
1536 error("EAP: badly-formed SRP Challenge"
1538 /* Ignore badly-formed messages */
1541 /* If no generator present, then use value 2 */
1543 gval.data = (u_char *)"\002";
1549 INCPTR(vallen, inp);
1553 * If no modulus present, then use well-known
1557 Nval.data = (u_char *)wkmodulus;
1558 Nval.len = sizeof (wkmodulus);
1563 tc = t_clientopen(esp->es_client.ea_name,
1564 &Nval, &gval, &sval);
1566 eap_send_nak(esp, id, EAPT_MD5CHAP);
1569 esp->es_client.ea_session = (void *)tc;
1571 /* Add Challenge ID & type to verifier */
1574 t_clientaddexdata(tc, vals, 2);
1576 Ap = t_clientgenexp(tc);
1577 eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
1582 tc = (struct t_client *)esp->es_client.ea_session;
1584 warn("EAP: peer sent Subtype 2 without 1");
1585 eap_send_nak(esp, id, EAPT_MD5CHAP);
1588 if (esp->es_client.ea_skey != NULL) {
1590 * ID number should not change here. Warn
1591 * if it does (but otherwise ignore).
1593 if (id != esp->es_client.ea_id) {
1594 warn("EAP: ID changed from %d to %d "
1595 "in SRP Subtype 2 rexmit",
1596 esp->es_client.ea_id, id);
1599 if (get_srp_secret(esp->es_unit,
1600 esp->es_client.ea_name,
1601 esp->es_client.ea_peer, secret, 0) == 0) {
1603 * Can't work with this peer because
1604 * the secret is missing. Just give
1607 eap_send_nak(esp, id, EAPT_MD5CHAP);
1612 t_clientpasswd(tc, secret);
1613 BZERO(secret, sizeof (secret));
1614 esp->es_client.ea_skey =
1615 t_clientgetkey(tc, &Bval);
1616 if (esp->es_client.ea_skey == NULL) {
1617 /* Server is rogue; stop now */
1618 error("EAP: SRP server is rogue");
1619 goto client_failure;
1622 eap_srpval_response(esp, id, SRPVAL_EBIT,
1623 t_clientresponse(tc));
1626 case EAPSRP_SVALIDATOR:
1627 tc = (struct t_client *)esp->es_client.ea_session;
1628 if (tc == NULL || esp->es_client.ea_skey == NULL) {
1629 warn("EAP: peer sent Subtype 3 without 1/2");
1630 eap_send_nak(esp, id, EAPT_MD5CHAP);
1634 * If we're already open, then this ought to be a
1635 * duplicate. Otherwise, check that the server is
1636 * who we think it is.
1638 if (esp->es_client.ea_state == eapOpen) {
1639 if (id != esp->es_client.ea_id) {
1640 warn("EAP: ID changed from %d to %d "
1641 "in SRP Subtype 3 rexmit",
1642 esp->es_client.ea_id, id);
1645 len -= sizeof (u_int32_t) + SHA_DIGESTSIZE;
1646 if (len < 0 || t_clientverify(tc, inp +
1647 sizeof (u_int32_t)) != 0) {
1648 error("EAP: SRP server verification "
1650 goto client_failure;
1652 GETLONG(esp->es_client.ea_keyflags, inp);
1653 /* Save pseudonym if user wants it. */
1654 if (len > 0 && esp->es_usepseudo) {
1655 INCPTR(SHA_DIGESTSIZE, inp);
1656 write_pseudonym(esp, inp, len, id);
1660 * We've verified our peer. We're now mostly done,
1661 * except for waiting on the regular EAP Success
1664 eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
1667 case EAPSRP_LWRECHALLENGE:
1669 warn("EAP: malformed Lightweight rechallenge");
1674 SHA1Update(&ctxt, vals, 1);
1675 SHA1Update(&ctxt, esp->es_client.ea_skey,
1677 SHA1Update(&ctxt, inp, len);
1678 SHA1Update(&ctxt, esp->es_client.ea_name,
1679 esp->es_client.ea_namelen);
1680 SHA1Final(dig, &ctxt);
1681 eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
1686 error("EAP: unknown SRP Subtype %d", vallen);
1687 eap_send_nak(esp, id, EAPT_MD5CHAP);
1691 #endif /* USE_SRP */
1694 info("EAP: unknown authentication type %d; Naking", typenum);
1695 eap_send_nak(esp, id, EAPT_SRP);
1699 if (esp->es_client.ea_timeout > 0) {
1700 UNTIMEOUT(eap_client_timeout, (void *)esp);
1701 TIMEOUT(eap_client_timeout, (void *)esp,
1702 esp->es_client.ea_timeout);
1708 esp->es_client.ea_state = eapBadAuth;
1709 if (esp->es_client.ea_timeout > 0) {
1710 UNTIMEOUT(eap_client_timeout, (void *)esp);
1712 esp->es_client.ea_session = NULL;
1714 auth_withpeer_fail(esp->es_unit, PPP_EAP);
1715 #endif /* USE_SRP */
1719 * eap_response - Receive EAP Response message (server mode).
1722 eap_response(esp, inp, id, len)
1731 char secret[MAXSECRETLEN];
1732 char rhostname[256];
1734 u_char hash[MD5_SIGNATURE_SIZE];
1736 struct t_server *ts;
1739 u_char dig[SHA_DIGESTSIZE];
1740 #endif /* USE_SRP */
1742 if (esp->es_server.ea_id != id) {
1743 dbglog("EAP: discarding Response %d; expected ID %d", id,
1744 esp->es_server.ea_id);
1748 esp->es_server.ea_responses++;
1751 error("EAP: empty Response message discarded");
1755 GETCHAR(typenum, inp);
1760 if (esp->es_server.ea_state != eapIdentify) {
1761 dbglog("EAP discarding unwanted Identify \"%.q\"", len,
1765 info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
1766 if (esp->es_server.ea_peer != NULL &&
1767 esp->es_server.ea_peer != remote_name)
1768 free(esp->es_server.ea_peer);
1769 esp->es_server.ea_peer = malloc(len + 1);
1770 if (esp->es_server.ea_peer == NULL) {
1771 esp->es_server.ea_peerlen = 0;
1772 eap_figure_next_state(esp, 1);
1775 BCOPY(inp, esp->es_server.ea_peer, len);
1776 esp->es_server.ea_peer[len] = '\0';
1777 esp->es_server.ea_peerlen = len;
1778 eap_figure_next_state(esp, 0);
1781 case EAPT_NOTIFICATION:
1782 dbglog("EAP unexpected Notification; response discarded");
1787 info("EAP: Nak Response with no suggested protocol");
1788 eap_figure_next_state(esp, 1);
1792 GETCHAR(vallen, inp);
1795 if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
1796 /* Peer cannot Nak Identify Request */
1797 eap_figure_next_state(esp, 1);
1803 /* Run through SRP validator selection again. */
1804 esp->es_server.ea_state = eapIdentify;
1805 eap_figure_next_state(esp, 0);
1809 esp->es_server.ea_state = eapMD5Chall;
1813 dbglog("EAP: peer requesting unknown Type %d", vallen);
1814 switch (esp->es_server.ea_state) {
1818 esp->es_server.ea_state = eapMD5Chall;
1822 esp->es_server.ea_state = eapIdentify;
1823 eap_figure_next_state(esp, 0);
1833 if (esp->es_server.ea_state != eapMD5Chall) {
1834 error("EAP: unexpected MD5-Response");
1835 eap_figure_next_state(esp, 1);
1839 error("EAP: received MD5-Response with no data");
1840 eap_figure_next_state(esp, 1);
1843 GETCHAR(vallen, inp);
1845 if (vallen != 16 || vallen > len) {
1846 error("EAP: MD5-Response with bad length %d", vallen);
1847 eap_figure_next_state(esp, 1);
1851 /* Not so likely to happen. */
1852 if (vallen >= len + sizeof (rhostname)) {
1853 dbglog("EAP: trimming really long peer name down");
1854 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1855 rhostname[sizeof (rhostname) - 1] = '\0';
1857 BCOPY(inp + vallen, rhostname, len - vallen);
1858 rhostname[len - vallen] = '\0';
1861 /* In case the remote doesn't give us his name. */
1862 if (explicit_remote ||
1863 (remote_name[0] != '\0' && vallen == len))
1864 strlcpy(rhostname, remote_name, sizeof (rhostname));
1867 * Get the secret for authenticating the specified
1870 if (!get_secret(esp->es_unit, rhostname,
1871 esp->es_server.ea_name, secret, &secret_len, 1)) {
1872 dbglog("EAP: no MD5 secret for auth of %q", rhostname);
1873 eap_send_failure(esp);
1876 MD5Init(&mdContext);
1877 MD5Update(&mdContext, &esp->es_server.ea_id, 1);
1878 MD5Update(&mdContext, secret, secret_len);
1879 BZERO(secret, sizeof (secret));
1880 MD5Update(&mdContext, esp->es_challenge, esp->es_challen);
1881 MD5Final(hash, &mdContext);
1882 if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) {
1883 eap_send_failure(esp);
1886 esp->es_server.ea_type = EAPT_MD5CHAP;
1887 eap_send_success(esp);
1888 eap_figure_next_state(esp, 0);
1889 if (esp->es_rechallenge != 0)
1890 TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
1896 error("EAP: empty SRP Response");
1897 eap_figure_next_state(esp, 1);
1900 GETCHAR(typenum, inp);
1904 if (esp->es_server.ea_state != eapSRP1) {
1905 error("EAP: unexpected SRP Subtype 1 Response");
1906 eap_figure_next_state(esp, 1);
1911 ts = (struct t_server *)esp->es_server.ea_session;
1913 esp->es_server.ea_skey = t_servergetkey(ts, &A);
1914 if (esp->es_server.ea_skey == NULL) {
1915 /* Client's A value is bogus; terminate now */
1916 error("EAP: bogus A value from client");
1917 eap_send_failure(esp);
1919 eap_figure_next_state(esp, 0);
1923 case EAPSRP_CVALIDATOR:
1924 if (esp->es_server.ea_state != eapSRP2) {
1925 error("EAP: unexpected SRP Subtype 2 Response");
1926 eap_figure_next_state(esp, 1);
1929 if (len < sizeof (u_int32_t) + SHA_DIGESTSIZE) {
1930 error("EAP: M1 length %d < %d", len,
1931 sizeof (u_int32_t) + SHA_DIGESTSIZE);
1932 eap_figure_next_state(esp, 1);
1935 GETLONG(esp->es_server.ea_keyflags, inp);
1936 ts = (struct t_server *)esp->es_server.ea_session;
1938 if (t_serververify(ts, inp)) {
1939 info("EAP: unable to validate client identity");
1940 eap_send_failure(esp);
1943 eap_figure_next_state(esp, 0);
1947 if (esp->es_server.ea_state != eapSRP3) {
1948 error("EAP: unexpected SRP Subtype 3 Response");
1949 eap_send_failure(esp);
1952 esp->es_server.ea_type = EAPT_SRP;
1953 eap_send_success(esp);
1954 eap_figure_next_state(esp, 0);
1955 if (esp->es_rechallenge != 0)
1956 TIMEOUT(eap_rechallenge, esp,
1957 esp->es_rechallenge);
1958 if (esp->es_lwrechallenge != 0)
1959 TIMEOUT(srp_lwrechallenge, esp,
1960 esp->es_lwrechallenge);
1963 case EAPSRP_LWRECHALLENGE:
1964 if (esp->es_server.ea_state != eapSRP4) {
1965 info("EAP: unexpected SRP Subtype 4 Response");
1968 if (len != SHA_DIGESTSIZE) {
1969 error("EAP: bad Lightweight rechallenge "
1975 SHA1Update(&ctxt, &vallen, 1);
1976 SHA1Update(&ctxt, esp->es_server.ea_skey,
1978 SHA1Update(&ctxt, esp->es_challenge, esp->es_challen);
1979 SHA1Update(&ctxt, esp->es_server.ea_peer,
1980 esp->es_server.ea_peerlen);
1981 SHA1Final(dig, &ctxt);
1982 if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) {
1983 error("EAP: failed Lightweight rechallenge");
1984 eap_send_failure(esp);
1987 esp->es_server.ea_state = eapOpen;
1988 if (esp->es_lwrechallenge != 0)
1989 TIMEOUT(srp_lwrechallenge, esp,
1990 esp->es_lwrechallenge);
1994 #endif /* USE_SRP */
1997 /* This can't happen. */
1998 error("EAP: unknown Response type %d; ignored", typenum);
2002 if (esp->es_server.ea_timeout > 0) {
2003 UNTIMEOUT(eap_server_timeout, (void *)esp);
2006 if (esp->es_server.ea_state != eapBadAuth &&
2007 esp->es_server.ea_state != eapOpen) {
2008 esp->es_server.ea_id++;
2009 eap_send_request(esp);
2014 * eap_success - Receive EAP Success message (client mode).
2017 eap_success(esp, inp, id, len)
2023 if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) {
2024 dbglog("EAP unexpected success message in state %s (%d)",
2025 eap_state_name(esp->es_client.ea_state),
2026 esp->es_client.ea_state);
2030 if (esp->es_client.ea_timeout > 0) {
2031 UNTIMEOUT(eap_client_timeout, (void *)esp);
2035 /* This is odd. The spec doesn't allow for this. */
2039 esp->es_client.ea_state = eapOpen;
2040 auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2044 * eap_failure - Receive EAP Failure message (client mode).
2047 eap_failure(esp, inp, id, len)
2053 if (!eap_client_active(esp)) {
2054 dbglog("EAP unexpected failure message in state %s (%d)",
2055 eap_state_name(esp->es_client.ea_state),
2056 esp->es_client.ea_state);
2059 if (esp->es_client.ea_timeout > 0) {
2060 UNTIMEOUT(eap_client_timeout, (void *)esp);
2064 /* This is odd. The spec doesn't allow for this. */
2068 esp->es_client.ea_state = eapBadAuth;
2070 error("EAP: peer reports authentication failure");
2071 auth_withpeer_fail(esp->es_unit, PPP_EAP);
2075 * eap_input - Handle received EAP message.
2078 eap_input(unit, inp, inlen)
2083 eap_state *esp = &eap_states[unit];
2088 * Parse header (code, id and length). If packet too short,
2091 if (inlen < EAP_HEADERLEN) {
2092 error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2098 if (len < EAP_HEADERLEN || len > inlen) {
2099 error("EAP: packet has illegal length field %d (%d..%d)", len,
2100 EAP_HEADERLEN, inlen);
2103 len -= EAP_HEADERLEN;
2105 /* Dispatch based on message code */
2108 eap_request(esp, inp, id, len);
2112 eap_response(esp, inp, id, len);
2116 eap_success(esp, inp, id, len);
2120 eap_failure(esp, inp, id, len);
2123 default: /* XXX Need code reject */
2124 /* Note: it's not legal to send EAP Nak here. */
2125 warn("EAP: unknown code %d received", code);
2131 * eap_printpkt - print the contents of an EAP packet.
2133 static char *eap_codenames[] = {
2134 "Request", "Response", "Success", "Failure"
2137 static char *eap_typenames[] = {
2138 "Identity", "Notification", "Nak", "MD5-Challenge",
2139 "OTP", "Generic-Token", NULL, NULL,
2140 "RSA", "DSS", "KEA", "KEA-Validate",
2141 "TLS", "Defender", "Windows 2000", "Arcot",
2142 "Cisco", "Nokia", "SRP"
2146 eap_printpkt(inp, inlen, printer, arg)
2149 void (*printer) __P((void *, char *, ...));
2152 int code, id, len, rtype, vallen;
2156 if (inlen < EAP_HEADERLEN)
2162 if (len < EAP_HEADERLEN || len > inlen)
2165 if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
2166 printer(arg, " %s", eap_codenames[code-1]);
2168 printer(arg, " code=0x%x", code);
2169 printer(arg, " id=0x%x", id);
2170 len -= EAP_HEADERLEN;
2174 printer(arg, " <missing type>");
2177 GETCHAR(rtype, inp);
2180 rtype <= sizeof (eap_typenames) / sizeof (char *))
2181 printer(arg, " %s", eap_typenames[rtype-1]);
2183 printer(arg, " type=0x%x", rtype);
2186 case EAPT_NOTIFICATION:
2188 printer(arg, " <Message ");
2189 print_string((char *)inp, len, printer, arg);
2194 printer(arg, " <No message>");
2201 GETCHAR(vallen, inp);
2205 printer(arg, " <Value%.*B>", vallen, inp);
2206 INCPTR(vallen, inp);
2209 printer(arg, " <Name ");
2210 print_string((char *)inp, len, printer, arg);
2215 printer(arg, " <No name>");
2222 GETCHAR(vallen, inp);
2224 printer(arg, "-%d", vallen);
2226 case EAPSRP_CHALLENGE:
2227 GETCHAR(vallen, inp);
2232 printer(arg, " <Name ");
2233 print_string((char *)inp, vallen, printer,
2237 printer(arg, " <No name>");
2239 INCPTR(vallen, inp);
2241 GETCHAR(vallen, inp);
2245 printer(arg, " <s%.*B>", vallen, inp);
2246 INCPTR(vallen, inp);
2248 GETCHAR(vallen, inp);
2253 printer(arg, " <Default g=2>");
2255 printer(arg, " <g%.*B>", vallen, inp);
2257 INCPTR(vallen, inp);
2260 printer(arg, " <Default N>");
2262 printer(arg, " <N%.*B>", len, inp);
2269 printer(arg, " <B%.*B>", len, inp);
2274 case EAPSRP_SVALIDATOR:
2275 if (len < sizeof (u_int32_t))
2278 len -= sizeof (u_int32_t);
2279 if (uval & SRPVAL_EBIT) {
2281 uval &= ~SRPVAL_EBIT;
2284 printer(arg, " f<%X>", uval);
2286 if ((vallen = len) > SHA_DIGESTSIZE)
2287 vallen = SHA_DIGESTSIZE;
2288 printer(arg, " <M2%.*B%s>", len, inp,
2289 len < SHA_DIGESTSIZE ? "?" : "");
2290 INCPTR(vallen, inp);
2293 printer(arg, " <PN%.*B>", len, inp);
2299 case EAPSRP_LWRECHALLENGE:
2300 printer(arg, " <Challenge%.*B>", len, inp);
2312 GETCHAR(rtype, inp);
2315 rtype <= sizeof (eap_typenames) / sizeof (char *))
2316 printer(arg, " %s", eap_typenames[rtype-1]);
2318 printer(arg, " type=0x%x", rtype);
2322 printer(arg, " <Name ");
2323 print_string((char *)inp, len, printer, arg);
2332 printer(arg, " <missing hint>");
2335 GETCHAR(rtype, inp);
2337 printer(arg, " <Suggested-type %02X", rtype);
2339 rtype < sizeof (eap_typenames) / sizeof (char *))
2340 printer(arg, " (%s)", eap_typenames[rtype-1]);
2346 printer(arg, " <missing length>");
2349 GETCHAR(vallen, inp);
2353 printer(arg, " <Value%.*B>", vallen, inp);
2354 INCPTR(vallen, inp);
2357 printer(arg, " <Name ");
2358 print_string((char *)inp, len, printer, arg);
2363 printer(arg, " <No name>");
2370 GETCHAR(vallen, inp);
2372 printer(arg, "-%d", vallen);
2375 printer(arg, " <A%.*B>", len, inp);
2380 case EAPSRP_CVALIDATOR:
2381 if (len < sizeof (u_int32_t))
2384 len -= sizeof (u_int32_t);
2385 if (uval & SRPVAL_EBIT) {
2387 uval &= ~SRPVAL_EBIT;
2390 printer(arg, " f<%X>", uval);
2392 printer(arg, " <M1%.*B%s>", len, inp,
2393 len == SHA_DIGESTSIZE ? "" : "?");
2401 case EAPSRP_LWRECHALLENGE:
2402 printer(arg, " <Response%.*B%s>", len, inp,
2403 len == SHA_DIGESTSIZE ? "" : "?");
2404 if ((vallen = len) > SHA_DIGESTSIZE)
2405 vallen = SHA_DIGESTSIZE;
2406 INCPTR(vallen, inp);
2414 case EAP_SUCCESS: /* No payload expected for these! */
2419 printer(arg, " <truncated>");
2424 printer(arg, "%8B...", inp);
2426 printer(arg, "%.*B", len, inp);
2429 return (inp - pstart);