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.4 2004/11/09 22:39:25 paulus Exp $"
57 #include <sys/types.h>
64 #include "pathnames.h"
75 #ifndef SHA_DIGESTSIZE
76 #define SHA_DIGESTSIZE 20
80 eap_state eap_states[NUM_PPP]; /* EAP state; one for each unit */
82 static char *pn_secret = NULL; /* Pseudonym generating secret */
86 * Command-line options.
88 static option_t eap_option_list[] = {
89 { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,
90 "Set retransmit timeout for EAP Requests (server)" },
91 { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,
92 "Set max number of EAP Requests sent (server)" },
93 { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,
94 "Set time limit for peer EAP authentication" },
95 { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,
96 "Set max number of EAP Requests allows (client)" },
97 { "eap-interval", o_int, &eap_states[0].es_rechallenge,
98 "Set interval for EAP rechallenge" },
100 { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,
101 "Set interval for SRP lightweight rechallenge" },
102 { "srp-pn-secret", o_string, &pn_secret,
103 "Long term pseudonym generation secret" },
104 { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,
105 "Use pseudonym if offered one by server", 1 },
111 * Protocol entry points.
113 static void eap_init __P((int unit));
114 static void eap_input __P((int unit, u_char *inp, int inlen));
115 static void eap_protrej __P((int unit));
116 static void eap_lowerup __P((int unit));
117 static void eap_lowerdown __P((int unit));
118 static int eap_printpkt __P((u_char *inp, int inlen,
119 void (*)(void *arg, char *fmt, ...), void *arg));
121 struct protent eap_protent = {
122 PPP_EAP, /* protocol number */
123 eap_init, /* initialization procedure */
124 eap_input, /* process a received packet */
125 eap_protrej, /* process a received protocol-reject */
126 eap_lowerup, /* lower layer has gone up */
127 eap_lowerdown, /* lower layer has gone down */
128 NULL, /* open the protocol */
129 NULL, /* close the protocol */
130 eap_printpkt, /* print a packet in readable form */
131 NULL, /* process a received data packet */
132 1, /* protocol enabled */
133 "EAP", /* text name of protocol */
134 NULL, /* text name of corresponding data protocol */
135 eap_option_list, /* list of command-line options */
136 NULL, /* check requested options; assign defaults */
137 NULL, /* configure interface for demand-dial */
138 NULL /* say whether to bring up link for this pkt */
142 * A well-known 2048 bit modulus.
144 static const u_char wkmodulus[] = {
145 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
146 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
147 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
148 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
149 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
150 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
151 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
152 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
153 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
154 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
155 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
156 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
157 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
158 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
159 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
160 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
161 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
162 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
163 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
164 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
165 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
166 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
167 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
168 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
169 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
170 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
171 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
172 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
173 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
174 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
175 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
176 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
179 /* Local forward declarations. */
180 static void eap_server_timeout __P((void *arg));
183 * Convert EAP state code to printable string for debug.
187 enum eap_state_code esc;
189 static const char *state_names[] = { EAP_STATES };
191 return (state_names[(int)esc]);
195 * eap_init - Initialize state for an EAP user. This is currently
196 * called once by main() during start-up.
202 eap_state *esp = &eap_states[unit];
204 BZERO(esp, sizeof (*esp));
206 esp->es_server.ea_timeout = EAP_DEFTIMEOUT;
207 esp->es_server.ea_maxrequests = EAP_DEFTRANSMITS;
208 esp->es_server.ea_id = (u_char)(drand48() * 0x100);
209 esp->es_client.ea_timeout = EAP_DEFREQTIME;
210 esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
214 * eap_client_timeout - Give up waiting for the peer to send any
218 eap_client_timeout(arg)
221 eap_state *esp = (eap_state *) arg;
223 if (!eap_client_active(esp))
226 error("EAP: timeout waiting for Request from peer");
227 auth_withpeer_fail(esp->es_unit, PPP_EAP);
228 esp->es_client.ea_state = eapBadAuth;
232 * eap_authwithpeer - Authenticate to our peer (behave as client).
234 * Start client state and wait for requests. This is called only
238 eap_authwithpeer(unit, localname)
242 eap_state *esp = &eap_states[unit];
244 /* Save the peer name we're given */
245 esp->es_client.ea_name = localname;
246 esp->es_client.ea_namelen = strlen(localname);
248 esp->es_client.ea_state = eapListen;
251 * Start a timer so that if the other end just goes
252 * silent, we don't sit here waiting forever.
254 if (esp->es_client.ea_timeout > 0)
255 TIMEOUT(eap_client_timeout, (void *)esp,
256 esp->es_client.ea_timeout);
260 * Format a standard EAP Failure message and send it to the peer.
264 eap_send_failure(esp)
269 outp = outpacket_buf;
271 MAKEHEADER(outp, PPP_EAP);
273 PUTCHAR(EAP_FAILURE, outp);
274 esp->es_server.ea_id++;
275 PUTCHAR(esp->es_server.ea_id, outp);
276 PUTSHORT(EAP_HEADERLEN, outp);
278 output(esp->es_unit, outpacket_buf, EAP_HEADERLEN + PPP_HDRLEN);
280 esp->es_server.ea_state = eapBadAuth;
281 auth_peer_fail(esp->es_unit, PPP_EAP);
285 * Format a standard EAP Success message and send it to the peer.
289 eap_send_success(esp)
294 outp = outpacket_buf;
296 MAKEHEADER(outp, PPP_EAP);
298 PUTCHAR(EAP_SUCCESS, outp);
299 esp->es_server.ea_id++;
300 PUTCHAR(esp->es_server.ea_id, outp);
301 PUTSHORT(EAP_HEADERLEN, outp);
303 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);
305 auth_peer_success(esp->es_unit, PPP_EAP, 0,
306 esp->es_server.ea_peer, esp->es_server.ea_peerlen);
311 * Set DES key according to pseudonym-generating secret and current
315 pncrypt_setkey(int timeoffs)
320 u_char dig[SHA_DIGESTSIZE];
323 if (pn_secret == NULL)
325 reftime = time(NULL) + timeoffs;
326 tp = localtime(&reftime);
328 SHA1Update(&ctxt, pn_secret, strlen(pn_secret));
329 strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp);
330 SHA1Update(&ctxt, tbuf, strlen(tbuf));
331 SHA1Final(dig, &ctxt);
332 return (DesSetkey(dig));
335 static char base64[] =
336 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
344 b64enc(bs, inp, inlen, outp)
353 bs->bs_bits = (bs->bs_bits << 8) | *inp++;
356 if (bs->bs_offs >= 24) {
357 *outp++ = base64[(bs->bs_bits >> 18) & 0x3F];
358 *outp++ = base64[(bs->bs_bits >> 12) & 0x3F];
359 *outp++ = base64[(bs->bs_bits >> 6) & 0x3F];
360 *outp++ = base64[bs->bs_bits & 0x3F];
376 if (bs->bs_offs == 8) {
377 *outp++ = base64[(bs->bs_bits >> 2) & 0x3F];
378 *outp++ = base64[(bs->bs_bits << 4) & 0x3F];
380 } else if (bs->bs_offs == 16) {
381 *outp++ = base64[(bs->bs_bits >> 10) & 0x3F];
382 *outp++ = base64[(bs->bs_bits >> 4) & 0x3F];
383 *outp++ = base64[(bs->bs_bits << 2) & 0x3F];
392 b64dec(bs, inp, inlen, outp)
402 if ((cp = strchr(base64, *inp++)) == NULL)
404 bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);
407 if (bs->bs_offs >= 8) {
408 *outp++ = bs->bs_bits >> (bs->bs_offs - 8);
418 * Assume that current waiting server state is complete and figure
419 * next state to use based on available authentication data. 'status'
420 * indicates if there was an error in handling the last query. It is
421 * 0 for success and non-zero for failure.
424 eap_figure_next_state(esp, status)
429 unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp;
431 struct t_confent *tce, mytce;
434 int id, i, plen, toffs;
439 esp->es_server.ea_timeout = esp->es_savedtime;
440 switch (esp->es_server.ea_state) {
446 /* Discard any previous session. */
447 ts = (struct t_server *)esp->es_server.ea_session;
450 esp->es_server.ea_session = NULL;
451 esp->es_server.ea_skey = NULL;
455 esp->es_server.ea_state = eapBadAuth;
459 /* If we've got a pseudonym, try to decode to real name. */
460 if (esp->es_server.ea_peerlen > SRP_PSEUDO_LEN &&
461 strncmp(esp->es_server.ea_peer, SRP_PSEUDO_ID,
462 SRP_PSEUDO_LEN) == 0 &&
463 (esp->es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 <
465 BZERO(&bs, sizeof (bs));
467 esp->es_server.ea_peer + SRP_PSEUDO_LEN,
468 esp->es_server.ea_peerlen - SRP_PSEUDO_LEN,
471 for (i = 0; i < 5; i++) {
472 pncrypt_setkey(toffs);
474 if (!DesDecrypt(secbuf, clear)) {
475 dbglog("no DES here; cannot decode "
479 id = *(unsigned char *)clear;
480 if (id + 1 <= plen && id + 9 > plen)
483 if (plen % 8 == 0 && i < 5) {
485 * Note that this is always shorter than the
486 * original stored string, so there's no need
489 if ((i = plen = *(unsigned char *)clear) > 7)
491 esp->es_server.ea_peerlen = plen;
492 dp = (unsigned char *)esp->es_server.ea_peer;
493 BCOPY(clear + 1, dp, i);
498 (void) DesDecrypt(sp, dp);
503 esp->es_server.ea_peer[
504 esp->es_server.ea_peerlen] = '\0';
505 dbglog("decoded pseudonym to \"%.*q\"",
506 esp->es_server.ea_peerlen,
507 esp->es_server.ea_peer);
509 dbglog("failed to decode real name");
510 /* Stay in eapIdentfy state; requery */
514 /* Look up user in secrets database. */
515 if (get_srp_secret(esp->es_unit, esp->es_server.ea_peer,
516 esp->es_server.ea_name, (char *)secbuf, 1) != 0) {
517 /* Set up default in case SRP entry is bad */
518 esp->es_server.ea_state = eapMD5Chall;
519 /* Get t_confent based on index in srp-secrets */
520 id = strtol((char *)secbuf, &cp, 10);
521 if (*cp++ != ':' || id < 0)
525 mytce.modulus.data = (u_char *)wkmodulus;
526 mytce.modulus.len = sizeof (wkmodulus);
527 mytce.generator.data = (u_char *)"\002";
528 mytce.generator.len = 1;
530 } else if ((tce = gettcid(id)) != NULL) {
532 * Client will have to verify this modulus/
533 * generator combination, and that will take
534 * a while. Lengthen the timeout here.
536 if (esp->es_server.ea_timeout > 0 &&
537 esp->es_server.ea_timeout < 30)
538 esp->es_server.ea_timeout = 30;
542 if ((cp2 = strchr(cp, ':')) == NULL)
545 tpw.pebuf.name = esp->es_server.ea_peer;
546 tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,
548 tpw.pebuf.password.data = tpw.pwbuf;
549 tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,
551 tpw.pebuf.salt.data = tpw.saltbuf;
552 if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)
554 esp->es_server.ea_session = (void *)ts;
555 esp->es_server.ea_state = eapSRP1;
556 vals[0] = esp->es_server.ea_id + 1;
558 t_serveraddexdata(ts, vals, 2);
559 /* Generate B; must call before t_servergetkey() */
564 esp->es_server.ea_state = eapMD5Chall;
569 ts = (struct t_server *)esp->es_server.ea_session;
570 if (ts != NULL && status != 0) {
572 esp->es_server.ea_session = NULL;
573 esp->es_server.ea_skey = NULL;
577 esp->es_server.ea_state = eapMD5Chall;
578 } else if (status != 0 || esp->es_server.ea_session == NULL) {
579 esp->es_server.ea_state = eapBadAuth;
581 esp->es_server.ea_state = eapSRP2;
587 ts = (struct t_server *)esp->es_server.ea_session;
588 if (ts != NULL && status != 0) {
590 esp->es_server.ea_session = NULL;
591 esp->es_server.ea_skey = NULL;
594 if (status != 0 || esp->es_server.ea_session == NULL) {
595 esp->es_server.ea_state = eapBadAuth;
597 esp->es_server.ea_state = eapSRP3;
604 ts = (struct t_server *)esp->es_server.ea_session;
605 if (ts != NULL && status != 0) {
607 esp->es_server.ea_session = NULL;
608 esp->es_server.ea_skey = NULL;
611 if (status != 0 || esp->es_server.ea_session == NULL) {
612 esp->es_server.ea_state = eapBadAuth;
614 esp->es_server.ea_state = eapOpen;
620 esp->es_server.ea_state = eapBadAuth;
622 esp->es_server.ea_state = eapOpen;
627 esp->es_server.ea_state = eapBadAuth;
630 if (esp->es_server.ea_state == eapBadAuth)
631 eap_send_failure(esp);
635 * Format an EAP Request message and send it to the peer. Message
636 * type depends on current state. (Server operation)
639 eap_send_request(esp)
650 u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp;
656 /* Handle both initial auth and restart */
657 if (esp->es_server.ea_state < eapIdentify &&
658 esp->es_server.ea_state != eapInitial) {
659 esp->es_server.ea_state = eapIdentify;
660 if (explicit_remote) {
662 * If we already know the peer's
663 * unauthenticated name, then there's no
664 * reason to ask. Go to next state instead.
666 esp->es_server.ea_peer = remote_name;
667 esp->es_server.ea_peerlen = strlen(remote_name);
668 eap_figure_next_state(esp, 0);
672 if (esp->es_server.ea_maxrequests > 0 &&
673 esp->es_server.ea_requests >= esp->es_server.ea_maxrequests) {
674 if (esp->es_server.ea_responses > 0)
675 error("EAP: too many Requests sent");
677 error("EAP: no response to Requests");
678 eap_send_failure(esp);
682 outp = outpacket_buf;
684 MAKEHEADER(outp, PPP_EAP);
686 PUTCHAR(EAP_REQUEST, outp);
687 PUTCHAR(esp->es_server.ea_id, outp);
691 switch (esp->es_server.ea_state) {
693 PUTCHAR(EAPT_IDENTITY, outp);
695 challen = strlen(str);
696 BCOPY(str, outp, challen);
697 INCPTR(challen, outp);
701 PUTCHAR(EAPT_MD5CHAP, outp);
703 * pick a random challenge length between
704 * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
706 challen = (drand48() *
707 (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
708 MIN_CHALLENGE_LENGTH;
709 PUTCHAR(challen, outp);
710 esp->es_challen = challen;
711 ptr = esp->es_challenge;
712 while (--challen >= 0)
713 *ptr++ = (u_char) (drand48() * 0x100);
714 BCOPY(esp->es_challenge, outp, esp->es_challen);
715 INCPTR(esp->es_challen, outp);
716 BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
717 INCPTR(esp->es_server.ea_namelen, outp);
722 PUTCHAR(EAPT_SRP, outp);
723 PUTCHAR(EAPSRP_CHALLENGE, outp);
725 PUTCHAR(esp->es_server.ea_namelen, outp);
726 BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
727 INCPTR(esp->es_server.ea_namelen, outp);
729 ts = (struct t_server *)esp->es_server.ea_session;
731 PUTCHAR(ts->s.len, outp);
732 BCOPY(ts->s.data, outp, ts->s.len);
733 INCPTR(ts->s.len, outp);
735 if (ts->g.len == 1 && ts->g.data[0] == 2) {
738 PUTCHAR(ts->g.len, outp);
739 BCOPY(ts->g.data, outp, ts->g.len);
740 INCPTR(ts->g.len, outp);
743 if (ts->n.len != sizeof (wkmodulus) ||
744 BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) {
745 BCOPY(ts->n.data, outp, ts->n.len);
746 INCPTR(ts->n.len, outp);
751 PUTCHAR(EAPT_SRP, outp);
752 PUTCHAR(EAPSRP_SKEY, outp);
754 ts = (struct t_server *)esp->es_server.ea_session;
756 BCOPY(ts->B.data, outp, ts->B.len);
757 INCPTR(ts->B.len, outp);
761 PUTCHAR(EAPT_SRP, outp);
762 PUTCHAR(EAPSRP_SVALIDATOR, outp);
763 PUTLONG(SRPVAL_EBIT, outp);
764 ts = (struct t_server *)esp->es_server.ea_session;
766 BCOPY(t_serverresponse(ts), outp, SHA_DIGESTSIZE);
767 INCPTR(SHA_DIGESTSIZE, outp);
769 if (pncrypt_setkey(0)) {
770 /* Generate pseudonym */
772 cp = (unsigned char *)esp->es_server.ea_peer;
773 if ((j = i = esp->es_server.ea_peerlen) > 7)
776 BCOPY(cp, clear + 1, j);
779 if (!DesEncrypt(clear, cipher)) {
780 dbglog("no DES here; not generating pseudonym");
783 BZERO(&b64, sizeof (b64));
784 outp++; /* space for pseudonym length */
785 outp += b64enc(&b64, cipher, 8, outp);
787 (void) DesEncrypt(cp, cipher);
788 outp += b64enc(&b64, cipher, 8, outp);
796 *cp++ = drand48() * 0x100;
799 (void) DesEncrypt(clear, cipher);
800 outp += b64enc(&b64, cipher, 8, outp);
802 outp += b64flush(&b64, outp);
804 /* Set length and pad out to next 20 octet boundary */
809 while (i < SHA_DIGESTSIZE) {
810 *outp++ = drand48() * 0x100;
815 /* Obscure the pseudonym with SHA1 hash */
817 SHA1Update(&ctxt, &esp->es_server.ea_id, 1);
818 SHA1Update(&ctxt, esp->es_server.ea_skey,
820 SHA1Update(&ctxt, esp->es_server.ea_peer,
821 esp->es_server.ea_peerlen);
822 while (optr < outp) {
823 SHA1Final(dig, &ctxt);
825 while (cp < dig + SHA_DIGESTSIZE)
828 SHA1Update(&ctxt, &esp->es_server.ea_id, 1);
829 SHA1Update(&ctxt, esp->es_server.ea_skey,
831 SHA1Update(&ctxt, optr - SHA_DIGESTSIZE,
838 PUTCHAR(EAPT_SRP, outp);
839 PUTCHAR(EAPSRP_LWRECHALLENGE, outp);
840 challen = MIN_CHALLENGE_LENGTH +
841 ((MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH) * drand48());
842 esp->es_challen = challen;
843 ptr = esp->es_challenge;
844 while (--challen >= 0)
845 *ptr++ = drand48() * 0x100;
846 BCOPY(esp->es_challenge, outp, esp->es_challen);
847 INCPTR(esp->es_challen, outp);
855 outlen = (outp - outpacket_buf) - PPP_HDRLEN;
856 PUTSHORT(outlen, lenloc);
858 output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
860 esp->es_server.ea_requests++;
862 if (esp->es_server.ea_timeout > 0)
863 TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
867 * eap_authpeer - Authenticate our peer (behave as server).
869 * Start server state and send first request. This is called only
873 eap_authpeer(unit, localname)
877 eap_state *esp = &eap_states[unit];
879 /* Save the name we're given. */
880 esp->es_server.ea_name = localname;
881 esp->es_server.ea_namelen = strlen(localname);
883 esp->es_savedtime = esp->es_server.ea_timeout;
885 /* Lower layer up yet? */
886 if (esp->es_server.ea_state == eapInitial ||
887 esp->es_server.ea_state == eapPending) {
888 esp->es_server.ea_state = eapPending;
892 esp->es_server.ea_state = eapPending;
894 /* ID number not updated here intentionally; hashed into M1 */
895 eap_send_request(esp);
899 * eap_server_timeout - Retransmission timer for sending Requests
903 eap_server_timeout(arg)
906 eap_state *esp = (eap_state *) arg;
908 if (!eap_server_active(esp))
911 /* EAP ID number must not change on timeout. */
912 eap_send_request(esp);
916 * When it's time to send rechallenge the peer, this timeout is
917 * called. Once the rechallenge is successful, the response handler
918 * will restart the timer. If it fails, then the link is dropped.
924 eap_state *esp = (eap_state *)arg;
926 if (esp->es_server.ea_state != eapOpen &&
927 esp->es_server.ea_state != eapSRP4)
930 esp->es_server.ea_requests = 0;
931 esp->es_server.ea_state = eapIdentify;
932 eap_figure_next_state(esp, 0);
933 esp->es_server.ea_id++;
934 eap_send_request(esp);
938 srp_lwrechallenge(arg)
941 eap_state *esp = (eap_state *)arg;
943 if (esp->es_server.ea_state != eapOpen ||
944 esp->es_server.ea_type != EAPT_SRP)
947 esp->es_server.ea_requests = 0;
948 esp->es_server.ea_state = eapSRP4;
949 esp->es_server.ea_id++;
950 eap_send_request(esp);
954 * eap_lowerup - The lower layer is now up.
956 * This is called before either eap_authpeer or eap_authwithpeer. See
957 * link_established() in auth.c. All that's necessary here is to
958 * return to closed state so that those two routines will do the right
965 eap_state *esp = &eap_states[unit];
967 /* Discard any (possibly authenticated) peer name. */
968 if (esp->es_server.ea_peer != NULL &&
969 esp->es_server.ea_peer != remote_name)
970 free(esp->es_server.ea_peer);
971 esp->es_server.ea_peer = NULL;
972 if (esp->es_client.ea_peer != NULL)
973 free(esp->es_client.ea_peer);
974 esp->es_client.ea_peer = NULL;
976 esp->es_client.ea_state = eapClosed;
977 esp->es_server.ea_state = eapClosed;
981 * eap_lowerdown - The lower layer is now down.
983 * Cancel all timeouts and return to initial state.
989 eap_state *esp = &eap_states[unit];
991 if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) {
992 UNTIMEOUT(eap_client_timeout, (void *)esp);
994 if (eap_server_active(esp)) {
995 if (esp->es_server.ea_timeout > 0) {
996 UNTIMEOUT(eap_server_timeout, (void *)esp);
999 if ((esp->es_server.ea_state == eapOpen ||
1000 esp->es_server.ea_state == eapSRP4) &&
1001 esp->es_rechallenge > 0) {
1002 UNTIMEOUT(eap_rechallenge, (void *)esp);
1004 if (esp->es_server.ea_state == eapOpen &&
1005 esp->es_lwrechallenge > 0) {
1006 UNTIMEOUT(srp_lwrechallenge, (void *)esp);
1010 esp->es_client.ea_state = esp->es_server.ea_state = eapInitial;
1011 esp->es_client.ea_requests = esp->es_server.ea_requests = 0;
1015 * eap_protrej - Peer doesn't speak this protocol.
1017 * This shouldn't happen. If it does, it represents authentication
1024 eap_state *esp = &eap_states[unit];
1026 if (eap_client_active(esp)) {
1027 error("EAP authentication failed due to Protocol-Reject");
1028 auth_withpeer_fail(unit, PPP_EAP);
1030 if (eap_server_active(esp)) {
1031 error("EAP authentication of peer failed on Protocol-Reject");
1032 auth_peer_fail(unit, PPP_EAP);
1034 eap_lowerdown(unit);
1038 * Format and send a regular EAP Response message.
1041 eap_send_response(esp, id, typenum, str, lenstr)
1051 outp = outpacket_buf;
1053 MAKEHEADER(outp, PPP_EAP);
1055 PUTCHAR(EAP_RESPONSE, outp);
1057 esp->es_client.ea_id = id;
1058 msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr;
1059 PUTSHORT(msglen, outp);
1060 PUTCHAR(typenum, outp);
1062 BCOPY(str, outp, lenstr);
1065 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1069 * Format and send an MD5-Challenge EAP Response message.
1072 eap_chap_response(esp, id, hash, name, namelen)
1082 outp = outpacket_buf;
1084 MAKEHEADER(outp, PPP_EAP);
1086 PUTCHAR(EAP_RESPONSE, outp);
1088 esp->es_client.ea_id = id;
1089 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE +
1091 PUTSHORT(msglen, outp);
1092 PUTCHAR(EAPT_MD5CHAP, outp);
1093 PUTCHAR(MD5_SIGNATURE_SIZE, outp);
1094 BCOPY(hash, outp, MD5_SIGNATURE_SIZE);
1095 INCPTR(MD5_SIGNATURE_SIZE, outp);
1097 BCOPY(name, outp, namelen);
1100 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1105 * Format and send a SRP EAP Response message.
1108 eap_srp_response(esp, id, subtypenum, str, lenstr)
1118 outp = outpacket_buf;
1120 MAKEHEADER(outp, PPP_EAP);
1122 PUTCHAR(EAP_RESPONSE, outp);
1124 esp->es_client.ea_id = id;
1125 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr;
1126 PUTSHORT(msglen, outp);
1127 PUTCHAR(EAPT_SRP, outp);
1128 PUTCHAR(subtypenum, outp);
1130 BCOPY(str, outp, lenstr);
1133 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1137 * Format and send a SRP EAP Client Validator Response message.
1140 eap_srpval_response(esp, id, flags, str)
1149 outp = outpacket_buf;
1151 MAKEHEADER(outp, PPP_EAP);
1153 PUTCHAR(EAP_RESPONSE, outp);
1155 esp->es_client.ea_id = id;
1156 msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) +
1158 PUTSHORT(msglen, outp);
1159 PUTCHAR(EAPT_SRP, outp);
1160 PUTCHAR(EAPSRP_CVALIDATOR, outp);
1161 PUTLONG(flags, outp);
1162 BCOPY(str, outp, SHA_DIGESTSIZE);
1164 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1166 #endif /* USE_SRP */
1169 eap_send_nak(esp, id, type)
1177 outp = outpacket_buf;
1179 MAKEHEADER(outp, PPP_EAP);
1181 PUTCHAR(EAP_RESPONSE, outp);
1183 esp->es_client.ea_id = id;
1184 msglen = EAP_HEADERLEN + 2 * sizeof (u_char);
1185 PUTSHORT(msglen, outp);
1186 PUTCHAR(EAPT_NAK, outp);
1187 PUTCHAR(type, outp);
1189 output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1196 char *user, *path, *file;
1199 static bool pnlogged = 0;
1201 pw = getpwuid(getuid());
1202 if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
1206 file = _PATH_PSEUDONYM;
1207 pl = strlen(user) + strlen(file) + 2;
1211 (void) slprintf(path, pl, "%s/%s", user, file);
1213 dbglog("pseudonym file: %s", path);
1220 open_pn_file(modebits)
1226 if ((path = name_of_pn_file()) == NULL)
1228 fd = open(path, modebits, S_IRUSR | S_IWUSR);
1240 if ((path = name_of_pn_file()) != NULL) {
1241 (void) unlink(path);
1247 write_pseudonym(esp, inp, len, id)
1253 u_char *datp, *digp;
1255 u_char dig[SHA_DIGESTSIZE];
1256 int dsize, fd, olen = len;
1259 * Do the decoding by working backwards. This eliminates the need
1260 * to save the decoded output in a separate buffer.
1264 if ((dsize = len % SHA_DIGESTSIZE) == 0)
1265 dsize = SHA_DIGESTSIZE;
1269 SHA1Update(&ctxt, &val, 1);
1270 SHA1Update(&ctxt, esp->es_client.ea_skey, SESSION_KEY_LEN);
1272 SHA1Update(&ctxt, datp, SHA_DIGESTSIZE);
1274 SHA1Update(&ctxt, esp->es_client.ea_name,
1275 esp->es_client.ea_namelen);
1277 SHA1Final(dig, &ctxt);
1278 for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++)
1282 /* Now check that the result is sane */
1283 if (olen <= 0 || *inp + 1 > olen) {
1284 dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp);
1289 fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);
1291 dbglog("EAP: error saving pseudonym: %m");
1294 len = write(fd, inp + 1, *inp);
1295 if (close(fd) != -1 && len == *inp) {
1296 dbglog("EAP: saved pseudonym");
1297 esp->es_usedpseudo = 0;
1299 dbglog("EAP: failed to save pseudonym");
1303 #endif /* USE_SRP */
1306 * eap_request - Receive EAP Request message (client mode).
1309 eap_request(esp, inp, id, len)
1318 char secret[MAXWORDLEN];
1319 char rhostname[256];
1321 u_char hash[MD5_SIGNATURE_SIZE];
1323 struct t_client *tc;
1324 struct t_num sval, gval, Nval, *Ap, Bval;
1327 u_char dig[SHA_DIGESTSIZE];
1329 #endif /* USE_SRP */
1332 * Ignore requests if we're not open
1334 if (esp->es_client.ea_state <= eapClosed)
1338 * Note: we update es_client.ea_id *only if* a Response
1339 * message is being generated. Otherwise, we leave it the
1340 * same for duplicate detection purposes.
1343 esp->es_client.ea_requests++;
1344 if (esp->es_client.ea_maxrequests != 0 &&
1345 esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {
1346 info("EAP: received too many Request messages");
1347 if (esp->es_client.ea_timeout > 0) {
1348 UNTIMEOUT(eap_client_timeout, (void *)esp);
1350 auth_withpeer_fail(esp->es_unit, PPP_EAP);
1355 error("EAP: empty Request message discarded");
1359 GETCHAR(typenum, inp);
1365 info("EAP: Identity prompt \"%.*q\"", len, inp);
1367 if (esp->es_usepseudo &&
1368 (esp->es_usedpseudo == 0 ||
1369 (esp->es_usedpseudo == 1 &&
1370 id == esp->es_client.ea_id))) {
1371 esp->es_usedpseudo = 1;
1372 /* Try to get a pseudonym */
1373 if ((fd = open_pn_file(O_RDONLY)) >= 0) {
1374 strcpy(rhostname, SRP_PSEUDO_ID);
1375 len = read(fd, rhostname + SRP_PSEUDO_LEN,
1376 sizeof (rhostname) - SRP_PSEUDO_LEN);
1377 /* XXX NAI unsupported */
1379 eap_send_response(esp, id, typenum,
1380 rhostname, len + SRP_PSEUDO_LEN);
1387 /* Stop using pseudonym now. */
1388 if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
1390 esp->es_usedpseudo = 2;
1392 #endif /* USE_SRP */
1393 eap_send_response(esp, id, typenum, esp->es_client.ea_name,
1394 esp->es_client.ea_namelen);
1397 case EAPT_NOTIFICATION:
1399 info("EAP: Notification \"%.*q\"", len, inp);
1400 eap_send_response(esp, id, typenum, NULL, 0);
1405 * Avoid the temptation to send Response Nak in reply
1406 * to Request Nak here. It can only lead to trouble.
1408 warn("EAP: unexpected Nak in Request; ignored");
1409 /* Return because we're waiting for something real. */
1414 error("EAP: received MD5-Challenge with no data");
1415 /* Bogus request; wait for something real. */
1418 GETCHAR(vallen, inp);
1420 if (vallen < 8 || vallen > len) {
1421 error("EAP: MD5-Challenge with bad length %d (8..%d)",
1423 /* Try something better. */
1424 eap_send_nak(esp, id, EAPT_SRP);
1428 /* Not so likely to happen. */
1429 if (len - vallen >= sizeof (rhostname)) {
1430 dbglog("EAP: trimming really long peer name down");
1431 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1432 rhostname[sizeof (rhostname) - 1] = '\0';
1434 BCOPY(inp + vallen, rhostname, len - vallen);
1435 rhostname[len - vallen] = '\0';
1438 /* In case the remote doesn't give us his name. */
1439 if (explicit_remote ||
1440 (remote_name[0] != '\0' && vallen == len))
1441 strlcpy(rhostname, remote_name, sizeof (rhostname));
1444 * Get the secret for authenticating ourselves with
1445 * the specified host.
1447 if (!get_secret(esp->es_unit, esp->es_client.ea_name,
1448 rhostname, secret, &secret_len, 0)) {
1449 dbglog("EAP: no MD5 secret for auth to %q", rhostname);
1450 eap_send_nak(esp, id, EAPT_SRP);
1453 MD5_Init(&mdContext);
1455 MD5_Update(&mdContext, &typenum, 1);
1456 MD5_Update(&mdContext, (u_char *)secret, secret_len);
1457 BZERO(secret, sizeof (secret));
1458 MD5_Update(&mdContext, inp, vallen);
1459 MD5_Final(hash, &mdContext);
1460 eap_chap_response(esp, id, hash, esp->es_client.ea_name,
1461 esp->es_client.ea_namelen);
1467 error("EAP: received empty SRP Request");
1468 /* Bogus request; wait for something real. */
1473 GETCHAR(vallen, inp);
1476 case EAPSRP_CHALLENGE:
1478 if (esp->es_client.ea_session != NULL) {
1479 tc = (struct t_client *)esp->es_client.
1482 * If this is a new challenge, then start
1483 * over with a new client session context.
1484 * Otherwise, just resend last response.
1486 if (id != esp->es_client.ea_id) {
1488 esp->es_client.ea_session = NULL;
1492 /* No session key just yet */
1493 esp->es_client.ea_skey = NULL;
1495 GETCHAR(vallen, inp);
1497 if (vallen >= len) {
1498 error("EAP: badly-formed SRP Challenge"
1500 /* Ignore badly-formed messages */
1503 BCOPY(inp, rhostname, vallen);
1504 rhostname[vallen] = '\0';
1505 INCPTR(vallen, inp);
1509 * In case the remote doesn't give us his name,
1510 * use configured name.
1512 if (explicit_remote ||
1513 (remote_name[0] != '\0' && vallen == 0)) {
1514 strlcpy(rhostname, remote_name,
1515 sizeof (rhostname));
1518 if (esp->es_client.ea_peer != NULL)
1519 free(esp->es_client.ea_peer);
1520 esp->es_client.ea_peer = strdup(rhostname);
1521 esp->es_client.ea_peerlen = strlen(rhostname);
1523 GETCHAR(vallen, inp);
1525 if (vallen >= len) {
1526 error("EAP: badly-formed SRP Challenge"
1528 /* Ignore badly-formed messages */
1533 INCPTR(vallen, inp);
1536 GETCHAR(vallen, inp);
1539 error("EAP: badly-formed SRP Challenge"
1541 /* Ignore badly-formed messages */
1544 /* If no generator present, then use value 2 */
1546 gval.data = (u_char *)"\002";
1552 INCPTR(vallen, inp);
1556 * If no modulus present, then use well-known
1560 Nval.data = (u_char *)wkmodulus;
1561 Nval.len = sizeof (wkmodulus);
1566 tc = t_clientopen(esp->es_client.ea_name,
1567 &Nval, &gval, &sval);
1569 eap_send_nak(esp, id, EAPT_MD5CHAP);
1572 esp->es_client.ea_session = (void *)tc;
1574 /* Add Challenge ID & type to verifier */
1577 t_clientaddexdata(tc, vals, 2);
1579 Ap = t_clientgenexp(tc);
1580 eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
1585 tc = (struct t_client *)esp->es_client.ea_session;
1587 warn("EAP: peer sent Subtype 2 without 1");
1588 eap_send_nak(esp, id, EAPT_MD5CHAP);
1591 if (esp->es_client.ea_skey != NULL) {
1593 * ID number should not change here. Warn
1594 * if it does (but otherwise ignore).
1596 if (id != esp->es_client.ea_id) {
1597 warn("EAP: ID changed from %d to %d "
1598 "in SRP Subtype 2 rexmit",
1599 esp->es_client.ea_id, id);
1602 if (get_srp_secret(esp->es_unit,
1603 esp->es_client.ea_name,
1604 esp->es_client.ea_peer, secret, 0) == 0) {
1606 * Can't work with this peer because
1607 * the secret is missing. Just give
1610 eap_send_nak(esp, id, EAPT_MD5CHAP);
1615 t_clientpasswd(tc, secret);
1616 BZERO(secret, sizeof (secret));
1617 esp->es_client.ea_skey =
1618 t_clientgetkey(tc, &Bval);
1619 if (esp->es_client.ea_skey == NULL) {
1620 /* Server is rogue; stop now */
1621 error("EAP: SRP server is rogue");
1622 goto client_failure;
1625 eap_srpval_response(esp, id, SRPVAL_EBIT,
1626 t_clientresponse(tc));
1629 case EAPSRP_SVALIDATOR:
1630 tc = (struct t_client *)esp->es_client.ea_session;
1631 if (tc == NULL || esp->es_client.ea_skey == NULL) {
1632 warn("EAP: peer sent Subtype 3 without 1/2");
1633 eap_send_nak(esp, id, EAPT_MD5CHAP);
1637 * If we're already open, then this ought to be a
1638 * duplicate. Otherwise, check that the server is
1639 * who we think it is.
1641 if (esp->es_client.ea_state == eapOpen) {
1642 if (id != esp->es_client.ea_id) {
1643 warn("EAP: ID changed from %d to %d "
1644 "in SRP Subtype 3 rexmit",
1645 esp->es_client.ea_id, id);
1648 len -= sizeof (u_int32_t) + SHA_DIGESTSIZE;
1649 if (len < 0 || t_clientverify(tc, inp +
1650 sizeof (u_int32_t)) != 0) {
1651 error("EAP: SRP server verification "
1653 goto client_failure;
1655 GETLONG(esp->es_client.ea_keyflags, inp);
1656 /* Save pseudonym if user wants it. */
1657 if (len > 0 && esp->es_usepseudo) {
1658 INCPTR(SHA_DIGESTSIZE, inp);
1659 write_pseudonym(esp, inp, len, id);
1663 * We've verified our peer. We're now mostly done,
1664 * except for waiting on the regular EAP Success
1667 eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
1670 case EAPSRP_LWRECHALLENGE:
1672 warn("EAP: malformed Lightweight rechallenge");
1677 SHA1Update(&ctxt, vals, 1);
1678 SHA1Update(&ctxt, esp->es_client.ea_skey,
1680 SHA1Update(&ctxt, inp, len);
1681 SHA1Update(&ctxt, esp->es_client.ea_name,
1682 esp->es_client.ea_namelen);
1683 SHA1Final(dig, &ctxt);
1684 eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
1689 error("EAP: unknown SRP Subtype %d", vallen);
1690 eap_send_nak(esp, id, EAPT_MD5CHAP);
1694 #endif /* USE_SRP */
1697 info("EAP: unknown authentication type %d; Naking", typenum);
1698 eap_send_nak(esp, id, EAPT_SRP);
1702 if (esp->es_client.ea_timeout > 0) {
1703 UNTIMEOUT(eap_client_timeout, (void *)esp);
1704 TIMEOUT(eap_client_timeout, (void *)esp,
1705 esp->es_client.ea_timeout);
1711 esp->es_client.ea_state = eapBadAuth;
1712 if (esp->es_client.ea_timeout > 0) {
1713 UNTIMEOUT(eap_client_timeout, (void *)esp);
1715 esp->es_client.ea_session = NULL;
1717 auth_withpeer_fail(esp->es_unit, PPP_EAP);
1718 #endif /* USE_SRP */
1722 * eap_response - Receive EAP Response message (server mode).
1725 eap_response(esp, inp, id, len)
1734 char secret[MAXSECRETLEN];
1735 char rhostname[256];
1737 u_char hash[MD5_SIGNATURE_SIZE];
1739 struct t_server *ts;
1742 u_char dig[SHA_DIGESTSIZE];
1743 #endif /* USE_SRP */
1746 * Ignore responses if we're not open
1748 if (esp->es_server.ea_state <= eapClosed)
1751 if (esp->es_server.ea_id != id) {
1752 dbglog("EAP: discarding Response %d; expected ID %d", id,
1753 esp->es_server.ea_id);
1757 esp->es_server.ea_responses++;
1760 error("EAP: empty Response message discarded");
1764 GETCHAR(typenum, inp);
1769 if (esp->es_server.ea_state != eapIdentify) {
1770 dbglog("EAP discarding unwanted Identify \"%.q\"", len,
1774 info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
1775 if (esp->es_server.ea_peer != NULL &&
1776 esp->es_server.ea_peer != remote_name)
1777 free(esp->es_server.ea_peer);
1778 esp->es_server.ea_peer = malloc(len + 1);
1779 if (esp->es_server.ea_peer == NULL) {
1780 esp->es_server.ea_peerlen = 0;
1781 eap_figure_next_state(esp, 1);
1784 BCOPY(inp, esp->es_server.ea_peer, len);
1785 esp->es_server.ea_peer[len] = '\0';
1786 esp->es_server.ea_peerlen = len;
1787 eap_figure_next_state(esp, 0);
1790 case EAPT_NOTIFICATION:
1791 dbglog("EAP unexpected Notification; response discarded");
1796 info("EAP: Nak Response with no suggested protocol");
1797 eap_figure_next_state(esp, 1);
1801 GETCHAR(vallen, inp);
1804 if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
1805 /* Peer cannot Nak Identify Request */
1806 eap_figure_next_state(esp, 1);
1812 /* Run through SRP validator selection again. */
1813 esp->es_server.ea_state = eapIdentify;
1814 eap_figure_next_state(esp, 0);
1818 esp->es_server.ea_state = eapMD5Chall;
1822 dbglog("EAP: peer requesting unknown Type %d", vallen);
1823 switch (esp->es_server.ea_state) {
1827 esp->es_server.ea_state = eapMD5Chall;
1831 esp->es_server.ea_state = eapIdentify;
1832 eap_figure_next_state(esp, 0);
1842 if (esp->es_server.ea_state != eapMD5Chall) {
1843 error("EAP: unexpected MD5-Response");
1844 eap_figure_next_state(esp, 1);
1848 error("EAP: received MD5-Response with no data");
1849 eap_figure_next_state(esp, 1);
1852 GETCHAR(vallen, inp);
1854 if (vallen != 16 || vallen > len) {
1855 error("EAP: MD5-Response with bad length %d", vallen);
1856 eap_figure_next_state(esp, 1);
1860 /* Not so likely to happen. */
1861 if (len - vallen >= sizeof (rhostname)) {
1862 dbglog("EAP: trimming really long peer name down");
1863 BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1864 rhostname[sizeof (rhostname) - 1] = '\0';
1866 BCOPY(inp + vallen, rhostname, len - vallen);
1867 rhostname[len - vallen] = '\0';
1870 /* In case the remote doesn't give us his name. */
1871 if (explicit_remote ||
1872 (remote_name[0] != '\0' && vallen == len))
1873 strlcpy(rhostname, remote_name, sizeof (rhostname));
1876 * Get the secret for authenticating the specified
1879 if (!get_secret(esp->es_unit, rhostname,
1880 esp->es_server.ea_name, secret, &secret_len, 1)) {
1881 dbglog("EAP: no MD5 secret for auth of %q", rhostname);
1882 eap_send_failure(esp);
1885 MD5_Init(&mdContext);
1886 MD5_Update(&mdContext, &esp->es_server.ea_id, 1);
1887 MD5_Update(&mdContext, (u_char *)secret, secret_len);
1888 BZERO(secret, sizeof (secret));
1889 MD5_Update(&mdContext, esp->es_challenge, esp->es_challen);
1890 MD5_Final(hash, &mdContext);
1891 if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) {
1892 eap_send_failure(esp);
1895 esp->es_server.ea_type = EAPT_MD5CHAP;
1896 eap_send_success(esp);
1897 eap_figure_next_state(esp, 0);
1898 if (esp->es_rechallenge != 0)
1899 TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
1905 error("EAP: empty SRP Response");
1906 eap_figure_next_state(esp, 1);
1909 GETCHAR(typenum, inp);
1913 if (esp->es_server.ea_state != eapSRP1) {
1914 error("EAP: unexpected SRP Subtype 1 Response");
1915 eap_figure_next_state(esp, 1);
1920 ts = (struct t_server *)esp->es_server.ea_session;
1922 esp->es_server.ea_skey = t_servergetkey(ts, &A);
1923 if (esp->es_server.ea_skey == NULL) {
1924 /* Client's A value is bogus; terminate now */
1925 error("EAP: bogus A value from client");
1926 eap_send_failure(esp);
1928 eap_figure_next_state(esp, 0);
1932 case EAPSRP_CVALIDATOR:
1933 if (esp->es_server.ea_state != eapSRP2) {
1934 error("EAP: unexpected SRP Subtype 2 Response");
1935 eap_figure_next_state(esp, 1);
1938 if (len < sizeof (u_int32_t) + SHA_DIGESTSIZE) {
1939 error("EAP: M1 length %d < %d", len,
1940 sizeof (u_int32_t) + SHA_DIGESTSIZE);
1941 eap_figure_next_state(esp, 1);
1944 GETLONG(esp->es_server.ea_keyflags, inp);
1945 ts = (struct t_server *)esp->es_server.ea_session;
1947 if (t_serververify(ts, inp)) {
1948 info("EAP: unable to validate client identity");
1949 eap_send_failure(esp);
1952 eap_figure_next_state(esp, 0);
1956 if (esp->es_server.ea_state != eapSRP3) {
1957 error("EAP: unexpected SRP Subtype 3 Response");
1958 eap_send_failure(esp);
1961 esp->es_server.ea_type = EAPT_SRP;
1962 eap_send_success(esp);
1963 eap_figure_next_state(esp, 0);
1964 if (esp->es_rechallenge != 0)
1965 TIMEOUT(eap_rechallenge, esp,
1966 esp->es_rechallenge);
1967 if (esp->es_lwrechallenge != 0)
1968 TIMEOUT(srp_lwrechallenge, esp,
1969 esp->es_lwrechallenge);
1972 case EAPSRP_LWRECHALLENGE:
1973 if (esp->es_server.ea_state != eapSRP4) {
1974 info("EAP: unexpected SRP Subtype 4 Response");
1977 if (len != SHA_DIGESTSIZE) {
1978 error("EAP: bad Lightweight rechallenge "
1984 SHA1Update(&ctxt, &vallen, 1);
1985 SHA1Update(&ctxt, esp->es_server.ea_skey,
1987 SHA1Update(&ctxt, esp->es_challenge, esp->es_challen);
1988 SHA1Update(&ctxt, esp->es_server.ea_peer,
1989 esp->es_server.ea_peerlen);
1990 SHA1Final(dig, &ctxt);
1991 if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) {
1992 error("EAP: failed Lightweight rechallenge");
1993 eap_send_failure(esp);
1996 esp->es_server.ea_state = eapOpen;
1997 if (esp->es_lwrechallenge != 0)
1998 TIMEOUT(srp_lwrechallenge, esp,
1999 esp->es_lwrechallenge);
2003 #endif /* USE_SRP */
2006 /* This can't happen. */
2007 error("EAP: unknown Response type %d; ignored", typenum);
2011 if (esp->es_server.ea_timeout > 0) {
2012 UNTIMEOUT(eap_server_timeout, (void *)esp);
2015 if (esp->es_server.ea_state != eapBadAuth &&
2016 esp->es_server.ea_state != eapOpen) {
2017 esp->es_server.ea_id++;
2018 eap_send_request(esp);
2023 * eap_success - Receive EAP Success message (client mode).
2026 eap_success(esp, inp, id, len)
2032 if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) {
2033 dbglog("EAP unexpected success message in state %s (%d)",
2034 eap_state_name(esp->es_client.ea_state),
2035 esp->es_client.ea_state);
2039 if (esp->es_client.ea_timeout > 0) {
2040 UNTIMEOUT(eap_client_timeout, (void *)esp);
2044 /* This is odd. The spec doesn't allow for this. */
2048 esp->es_client.ea_state = eapOpen;
2049 auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2053 * eap_failure - Receive EAP Failure message (client mode).
2056 eap_failure(esp, inp, id, len)
2063 * Ignore failure messages if we're not open
2065 if (esp->es_client.ea_state <= eapClosed)
2068 if (!eap_client_active(esp)) {
2069 dbglog("EAP unexpected failure message in state %s (%d)",
2070 eap_state_name(esp->es_client.ea_state),
2071 esp->es_client.ea_state);
2074 if (esp->es_client.ea_timeout > 0) {
2075 UNTIMEOUT(eap_client_timeout, (void *)esp);
2079 /* This is odd. The spec doesn't allow for this. */
2083 esp->es_client.ea_state = eapBadAuth;
2085 error("EAP: peer reports authentication failure");
2086 auth_withpeer_fail(esp->es_unit, PPP_EAP);
2090 * eap_input - Handle received EAP message.
2093 eap_input(unit, inp, inlen)
2098 eap_state *esp = &eap_states[unit];
2103 * Parse header (code, id and length). If packet too short,
2106 if (inlen < EAP_HEADERLEN) {
2107 error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2113 if (len < EAP_HEADERLEN || len > inlen) {
2114 error("EAP: packet has illegal length field %d (%d..%d)", len,
2115 EAP_HEADERLEN, inlen);
2118 len -= EAP_HEADERLEN;
2120 /* Dispatch based on message code */
2123 eap_request(esp, inp, id, len);
2127 eap_response(esp, inp, id, len);
2131 eap_success(esp, inp, id, len);
2135 eap_failure(esp, inp, id, len);
2138 default: /* XXX Need code reject */
2139 /* Note: it's not legal to send EAP Nak here. */
2140 warn("EAP: unknown code %d received", code);
2146 * eap_printpkt - print the contents of an EAP packet.
2148 static char *eap_codenames[] = {
2149 "Request", "Response", "Success", "Failure"
2152 static char *eap_typenames[] = {
2153 "Identity", "Notification", "Nak", "MD5-Challenge",
2154 "OTP", "Generic-Token", NULL, NULL,
2155 "RSA", "DSS", "KEA", "KEA-Validate",
2156 "TLS", "Defender", "Windows 2000", "Arcot",
2157 "Cisco", "Nokia", "SRP"
2161 eap_printpkt(inp, inlen, printer, arg)
2164 void (*printer) __P((void *, char *, ...));
2167 int code, id, len, rtype, vallen;
2171 if (inlen < EAP_HEADERLEN)
2177 if (len < EAP_HEADERLEN || len > inlen)
2180 if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
2181 printer(arg, " %s", eap_codenames[code-1]);
2183 printer(arg, " code=0x%x", code);
2184 printer(arg, " id=0x%x", id);
2185 len -= EAP_HEADERLEN;
2189 printer(arg, " <missing type>");
2192 GETCHAR(rtype, inp);
2195 rtype <= sizeof (eap_typenames) / sizeof (char *))
2196 printer(arg, " %s", eap_typenames[rtype-1]);
2198 printer(arg, " type=0x%x", rtype);
2201 case EAPT_NOTIFICATION:
2203 printer(arg, " <Message ");
2204 print_string((char *)inp, len, printer, arg);
2209 printer(arg, " <No message>");
2216 GETCHAR(vallen, inp);
2220 printer(arg, " <Value%.*B>", vallen, inp);
2221 INCPTR(vallen, inp);
2224 printer(arg, " <Name ");
2225 print_string((char *)inp, len, printer, arg);
2230 printer(arg, " <No name>");
2237 GETCHAR(vallen, inp);
2239 printer(arg, "-%d", vallen);
2241 case EAPSRP_CHALLENGE:
2242 GETCHAR(vallen, inp);
2247 printer(arg, " <Name ");
2248 print_string((char *)inp, vallen, printer,
2252 printer(arg, " <No name>");
2254 INCPTR(vallen, inp);
2256 GETCHAR(vallen, inp);
2260 printer(arg, " <s%.*B>", vallen, inp);
2261 INCPTR(vallen, inp);
2263 GETCHAR(vallen, inp);
2268 printer(arg, " <Default g=2>");
2270 printer(arg, " <g%.*B>", vallen, inp);
2272 INCPTR(vallen, inp);
2275 printer(arg, " <Default N>");
2277 printer(arg, " <N%.*B>", len, inp);
2284 printer(arg, " <B%.*B>", len, inp);
2289 case EAPSRP_SVALIDATOR:
2290 if (len < sizeof (u_int32_t))
2293 len -= sizeof (u_int32_t);
2294 if (uval & SRPVAL_EBIT) {
2296 uval &= ~SRPVAL_EBIT;
2299 printer(arg, " f<%X>", uval);
2301 if ((vallen = len) > SHA_DIGESTSIZE)
2302 vallen = SHA_DIGESTSIZE;
2303 printer(arg, " <M2%.*B%s>", len, inp,
2304 len < SHA_DIGESTSIZE ? "?" : "");
2305 INCPTR(vallen, inp);
2308 printer(arg, " <PN%.*B>", len, inp);
2314 case EAPSRP_LWRECHALLENGE:
2315 printer(arg, " <Challenge%.*B>", len, inp);
2327 GETCHAR(rtype, inp);
2330 rtype <= sizeof (eap_typenames) / sizeof (char *))
2331 printer(arg, " %s", eap_typenames[rtype-1]);
2333 printer(arg, " type=0x%x", rtype);
2337 printer(arg, " <Name ");
2338 print_string((char *)inp, len, printer, arg);
2347 printer(arg, " <missing hint>");
2350 GETCHAR(rtype, inp);
2352 printer(arg, " <Suggested-type %02X", rtype);
2354 rtype < sizeof (eap_typenames) / sizeof (char *))
2355 printer(arg, " (%s)", eap_typenames[rtype-1]);
2361 printer(arg, " <missing length>");
2364 GETCHAR(vallen, inp);
2368 printer(arg, " <Value%.*B>", vallen, inp);
2369 INCPTR(vallen, inp);
2372 printer(arg, " <Name ");
2373 print_string((char *)inp, len, printer, arg);
2378 printer(arg, " <No name>");
2385 GETCHAR(vallen, inp);
2387 printer(arg, "-%d", vallen);
2390 printer(arg, " <A%.*B>", len, inp);
2395 case EAPSRP_CVALIDATOR:
2396 if (len < sizeof (u_int32_t))
2399 len -= sizeof (u_int32_t);
2400 if (uval & SRPVAL_EBIT) {
2402 uval &= ~SRPVAL_EBIT;
2405 printer(arg, " f<%X>", uval);
2407 printer(arg, " <M1%.*B%s>", len, inp,
2408 len == SHA_DIGESTSIZE ? "" : "?");
2416 case EAPSRP_LWRECHALLENGE:
2417 printer(arg, " <Response%.*B%s>", len, inp,
2418 len == SHA_DIGESTSIZE ? "" : "?");
2419 if ((vallen = len) > SHA_DIGESTSIZE)
2420 vallen = SHA_DIGESTSIZE;
2421 INCPTR(vallen, inp);
2429 case EAP_SUCCESS: /* No payload expected for these! */
2434 printer(arg, " <truncated>");
2439 printer(arg, "%8B...", inp);
2441 printer(arg, "%.*B", len, inp);
2444 return (inp - pstart);