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
79 static const char rcsid
[] = RCSID
;
81 eap_state eap_states
[NUM_PPP
]; /* EAP state; one for each unit */
83 static char *pn_secret
= NULL
; /* Pseudonym generating secret */
87 * Command-line options.
89 static option_t eap_option_list
[] = {
90 { "eap-restart", o_int
, &eap_states
[0].es_server
.ea_timeout
,
91 "Set retransmit timeout for EAP Requests (server)" },
92 { "eap-max-sreq", o_int
, &eap_states
[0].es_server
.ea_maxrequests
,
93 "Set max number of EAP Requests sent (server)" },
94 { "eap-timeout", o_int
, &eap_states
[0].es_client
.ea_timeout
,
95 "Set time limit for peer EAP authentication" },
96 { "eap-max-rreq", o_int
, &eap_states
[0].es_client
.ea_maxrequests
,
97 "Set max number of EAP Requests allows (client)" },
98 { "eap-interval", o_int
, &eap_states
[0].es_rechallenge
,
99 "Set interval for EAP rechallenge" },
101 { "srp-interval", o_int
, &eap_states
[0].es_lwrechallenge
,
102 "Set interval for SRP lightweight rechallenge" },
103 { "srp-pn-secret", o_string
, &pn_secret
,
104 "Long term pseudonym generation secret" },
105 { "srp-use-pseudonym", o_bool
, &eap_states
[0].es_usepseudo
,
106 "Use pseudonym if offered one by server", 1 },
112 * Protocol entry points.
114 static void eap_init
__P((int unit
));
115 static void eap_input
__P((int unit
, u_char
*inp
, int inlen
));
116 static void eap_protrej
__P((int unit
));
117 static void eap_lowerup
__P((int unit
));
118 static void eap_lowerdown
__P((int unit
));
119 static int eap_printpkt
__P((u_char
*inp
, int inlen
,
120 void (*)(void *arg
, char *fmt
, ...), void *arg
));
122 struct protent eap_protent
= {
123 PPP_EAP
, /* protocol number */
124 eap_init
, /* initialization procedure */
125 eap_input
, /* process a received packet */
126 eap_protrej
, /* process a received protocol-reject */
127 eap_lowerup
, /* lower layer has gone up */
128 eap_lowerdown
, /* lower layer has gone down */
129 NULL
, /* open the protocol */
130 NULL
, /* close the protocol */
131 eap_printpkt
, /* print a packet in readable form */
132 NULL
, /* process a received data packet */
133 1, /* protocol enabled */
134 "EAP", /* text name of protocol */
135 NULL
, /* text name of corresponding data protocol */
136 eap_option_list
, /* list of command-line options */
137 NULL
, /* check requested options; assign defaults */
138 NULL
, /* configure interface for demand-dial */
139 NULL
/* say whether to bring up link for this pkt */
143 * A well-known 2048 bit modulus.
145 static const u_char wkmodulus
[] = {
146 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
147 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
148 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
149 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
150 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
151 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
152 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
153 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
154 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
155 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
156 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
157 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
158 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
159 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
160 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
161 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
162 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
163 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
164 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
165 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
166 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
167 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
168 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
169 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
170 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
171 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
172 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
173 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
174 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
175 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
176 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
177 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
180 /* Local forward declarations. */
181 static void eap_server_timeout
__P((void *arg
));
184 * Convert EAP state code to printable string for debug.
188 enum eap_state_code esc
;
190 static const char *state_names
[] = { EAP_STATES
};
192 return (state_names
[(int)esc
]);
196 * eap_init - Initialize state for an EAP user. This is currently
197 * called once by main() during start-up.
203 eap_state
*esp
= &eap_states
[unit
];
205 BZERO(esp
, sizeof (*esp
));
207 esp
->es_server
.ea_timeout
= EAP_DEFTIMEOUT
;
208 esp
->es_server
.ea_maxrequests
= EAP_DEFTRANSMITS
;
209 esp
->es_server
.ea_id
= (u_char
)(drand48() * 0x100);
210 esp
->es_client
.ea_timeout
= EAP_DEFREQTIME
;
211 esp
->es_client
.ea_maxrequests
= EAP_DEFALLOWREQ
;
215 * eap_client_timeout - Give up waiting for the peer to send any
219 eap_client_timeout(arg
)
222 eap_state
*esp
= (eap_state
*) arg
;
224 if (!eap_client_active(esp
))
227 error("EAP: timeout waiting for Request from peer");
228 auth_withpeer_fail(esp
->es_unit
, PPP_EAP
);
229 esp
->es_client
.ea_state
= eapBadAuth
;
233 * eap_authwithpeer - Authenticate to our peer (behave as client).
235 * Start client state and wait for requests. This is called only
239 eap_authwithpeer(unit
, localname
)
243 eap_state
*esp
= &eap_states
[unit
];
245 /* Save the peer name we're given */
246 esp
->es_client
.ea_name
= localname
;
247 esp
->es_client
.ea_namelen
= strlen(localname
);
249 esp
->es_client
.ea_state
= eapListen
;
252 * Start a timer so that if the other end just goes
253 * silent, we don't sit here waiting forever.
255 if (esp
->es_client
.ea_timeout
> 0)
256 TIMEOUT(eap_client_timeout
, (void *)esp
,
257 esp
->es_client
.ea_timeout
);
261 * Format a standard EAP Failure message and send it to the peer.
265 eap_send_failure(esp
)
270 outp
= outpacket_buf
;
272 MAKEHEADER(outp
, PPP_EAP
);
274 PUTCHAR(EAP_FAILURE
, outp
);
275 esp
->es_server
.ea_id
++;
276 PUTCHAR(esp
->es_server
.ea_id
, outp
);
277 PUTSHORT(EAP_HEADERLEN
, outp
);
279 output(esp
->es_unit
, outpacket_buf
, EAP_HEADERLEN
+ PPP_HDRLEN
);
281 esp
->es_server
.ea_state
= eapBadAuth
;
282 auth_peer_fail(esp
->es_unit
, PPP_EAP
);
286 * Format a standard EAP Success message and send it to the peer.
290 eap_send_success(esp
)
295 outp
= outpacket_buf
;
297 MAKEHEADER(outp
, PPP_EAP
);
299 PUTCHAR(EAP_SUCCESS
, outp
);
300 esp
->es_server
.ea_id
++;
301 PUTCHAR(esp
->es_server
.ea_id
, outp
);
302 PUTSHORT(EAP_HEADERLEN
, outp
);
304 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ EAP_HEADERLEN
);
306 auth_peer_success(esp
->es_unit
, PPP_EAP
, 0,
307 esp
->es_server
.ea_peer
, esp
->es_server
.ea_peerlen
);
312 * Set DES key according to pseudonym-generating secret and current
316 pncrypt_setkey(int timeoffs
)
321 u_char dig
[SHA_DIGESTSIZE
];
324 if (pn_secret
== NULL
)
326 reftime
= time(NULL
) + timeoffs
;
327 tp
= localtime(&reftime
);
329 SHA1Update(&ctxt
, pn_secret
, strlen(pn_secret
));
330 strftime(tbuf
, sizeof (tbuf
), "%Y%m%d", tp
);
331 SHA1Update(&ctxt
, tbuf
, strlen(tbuf
));
332 SHA1Final(dig
, &ctxt
);
333 return (DesSetkey(dig
));
336 static char base64
[] =
337 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
345 b64enc(bs
, inp
, inlen
, outp
)
354 bs
->bs_bits
= (bs
->bs_bits
<< 8) | *inp
++;
357 if (bs
->bs_offs
>= 24) {
358 *outp
++ = base64
[(bs
->bs_bits
>> 18) & 0x3F];
359 *outp
++ = base64
[(bs
->bs_bits
>> 12) & 0x3F];
360 *outp
++ = base64
[(bs
->bs_bits
>> 6) & 0x3F];
361 *outp
++ = base64
[bs
->bs_bits
& 0x3F];
377 if (bs
->bs_offs
== 8) {
378 *outp
++ = base64
[(bs
->bs_bits
>> 2) & 0x3F];
379 *outp
++ = base64
[(bs
->bs_bits
<< 4) & 0x3F];
381 } else if (bs
->bs_offs
== 16) {
382 *outp
++ = base64
[(bs
->bs_bits
>> 10) & 0x3F];
383 *outp
++ = base64
[(bs
->bs_bits
>> 4) & 0x3F];
384 *outp
++ = base64
[(bs
->bs_bits
<< 2) & 0x3F];
393 b64dec(bs
, inp
, inlen
, outp
)
403 if ((cp
= strchr(base64
, *inp
++)) == NULL
)
405 bs
->bs_bits
= (bs
->bs_bits
<< 6) | (cp
- base64
);
408 if (bs
->bs_offs
>= 8) {
409 *outp
++ = bs
->bs_bits
>> (bs
->bs_offs
- 8);
419 * Assume that current waiting server state is complete and figure
420 * next state to use based on available authentication data. 'status'
421 * indicates if there was an error in handling the last query. It is
422 * 0 for success and non-zero for failure.
425 eap_figure_next_state(esp
, status
)
430 unsigned char secbuf
[MAXWORDLEN
], clear
[8], *sp
, *dp
;
432 struct t_confent
*tce
, mytce
;
435 int id
, i
, plen
, toffs
;
440 esp
->es_server
.ea_timeout
= esp
->es_savedtime
;
441 switch (esp
->es_server
.ea_state
) {
447 /* Discard any previous session. */
448 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
451 esp
->es_server
.ea_session
= NULL
;
452 esp
->es_server
.ea_skey
= NULL
;
456 esp
->es_server
.ea_state
= eapBadAuth
;
460 /* If we've got a pseudonym, try to decode to real name. */
461 if (esp
->es_server
.ea_peerlen
> SRP_PSEUDO_LEN
&&
462 strncmp(esp
->es_server
.ea_peer
, SRP_PSEUDO_ID
,
463 SRP_PSEUDO_LEN
) == 0 &&
464 (esp
->es_server
.ea_peerlen
- SRP_PSEUDO_LEN
) * 3 / 4 <
466 BZERO(&bs
, sizeof (bs
));
468 esp
->es_server
.ea_peer
+ SRP_PSEUDO_LEN
,
469 esp
->es_server
.ea_peerlen
- SRP_PSEUDO_LEN
,
472 for (i
= 0; i
< 5; i
++) {
473 pncrypt_setkey(toffs
);
475 if (!DesDecrypt(secbuf
, clear
)) {
476 dbglog("no DES here; cannot decode "
480 id
= *(unsigned char *)clear
;
481 if (id
+ 1 <= plen
&& id
+ 9 > plen
)
484 if (plen
% 8 == 0 && i
< 5) {
486 * Note that this is always shorter than the
487 * original stored string, so there's no need
490 if ((i
= plen
= *(unsigned char *)clear
) > 7)
492 esp
->es_server
.ea_peerlen
= plen
;
493 dp
= (unsigned char *)esp
->es_server
.ea_peer
;
494 BCOPY(clear
+ 1, dp
, i
);
499 (void) DesDecrypt(sp
, dp
);
504 esp
->es_server
.ea_peer
[
505 esp
->es_server
.ea_peerlen
] = '\0';
506 dbglog("decoded pseudonym to \"%.*q\"",
507 esp
->es_server
.ea_peerlen
,
508 esp
->es_server
.ea_peer
);
510 dbglog("failed to decode real name");
511 /* Stay in eapIdentfy state; requery */
515 /* Look up user in secrets database. */
516 if (get_srp_secret(esp
->es_unit
, esp
->es_server
.ea_peer
,
517 esp
->es_server
.ea_name
, (char *)secbuf
, 1) != 0) {
518 /* Set up default in case SRP entry is bad */
519 esp
->es_server
.ea_state
= eapMD5Chall
;
520 /* Get t_confent based on index in srp-secrets */
521 id
= strtol((char *)secbuf
, &cp
, 10);
522 if (*cp
++ != ':' || id
< 0)
526 mytce
.modulus
.data
= (u_char
*)wkmodulus
;
527 mytce
.modulus
.len
= sizeof (wkmodulus
);
528 mytce
.generator
.data
= (u_char
*)"\002";
529 mytce
.generator
.len
= 1;
531 } else if ((tce
= gettcid(id
)) != NULL
) {
533 * Client will have to verify this modulus/
534 * generator combination, and that will take
535 * a while. Lengthen the timeout here.
537 if (esp
->es_server
.ea_timeout
> 0 &&
538 esp
->es_server
.ea_timeout
< 30)
539 esp
->es_server
.ea_timeout
= 30;
543 if ((cp2
= strchr(cp
, ':')) == NULL
)
546 tpw
.pebuf
.name
= esp
->es_server
.ea_peer
;
547 tpw
.pebuf
.password
.len
= t_fromb64((char *)tpw
.pwbuf
,
549 tpw
.pebuf
.password
.data
= tpw
.pwbuf
;
550 tpw
.pebuf
.salt
.len
= t_fromb64((char *)tpw
.saltbuf
,
552 tpw
.pebuf
.salt
.data
= tpw
.saltbuf
;
553 if ((ts
= t_serveropenraw(&tpw
.pebuf
, tce
)) == NULL
)
555 esp
->es_server
.ea_session
= (void *)ts
;
556 esp
->es_server
.ea_state
= eapSRP1
;
557 vals
[0] = esp
->es_server
.ea_id
+ 1;
559 t_serveraddexdata(ts
, vals
, 2);
560 /* Generate B; must call before t_servergetkey() */
565 esp
->es_server
.ea_state
= eapMD5Chall
;
570 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
571 if (ts
!= NULL
&& status
!= 0) {
573 esp
->es_server
.ea_session
= NULL
;
574 esp
->es_server
.ea_skey
= NULL
;
578 esp
->es_server
.ea_state
= eapMD5Chall
;
579 } else if (status
!= 0 || esp
->es_server
.ea_session
== NULL
) {
580 esp
->es_server
.ea_state
= eapBadAuth
;
582 esp
->es_server
.ea_state
= eapSRP2
;
588 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
589 if (ts
!= NULL
&& status
!= 0) {
591 esp
->es_server
.ea_session
= NULL
;
592 esp
->es_server
.ea_skey
= NULL
;
595 if (status
!= 0 || esp
->es_server
.ea_session
== NULL
) {
596 esp
->es_server
.ea_state
= eapBadAuth
;
598 esp
->es_server
.ea_state
= eapSRP3
;
605 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
606 if (ts
!= NULL
&& status
!= 0) {
608 esp
->es_server
.ea_session
= NULL
;
609 esp
->es_server
.ea_skey
= NULL
;
612 if (status
!= 0 || esp
->es_server
.ea_session
== NULL
) {
613 esp
->es_server
.ea_state
= eapBadAuth
;
615 esp
->es_server
.ea_state
= eapOpen
;
621 esp
->es_server
.ea_state
= eapBadAuth
;
623 esp
->es_server
.ea_state
= eapOpen
;
628 esp
->es_server
.ea_state
= eapBadAuth
;
631 if (esp
->es_server
.ea_state
== eapBadAuth
)
632 eap_send_failure(esp
);
636 * Format an EAP Request message and send it to the peer. Message
637 * type depends on current state. (Server operation)
640 eap_send_request(esp
)
651 u_char clear
[8], cipher
[8], dig
[SHA_DIGESTSIZE
], *optr
, *cp
;
657 /* Handle both initial auth and restart */
658 if (esp
->es_server
.ea_state
< eapIdentify
&&
659 esp
->es_server
.ea_state
!= eapInitial
) {
660 esp
->es_server
.ea_state
= eapIdentify
;
661 if (explicit_remote
) {
663 * If we already know the peer's
664 * unauthenticated name, then there's no
665 * reason to ask. Go to next state instead.
667 esp
->es_server
.ea_peer
= remote_name
;
668 esp
->es_server
.ea_peerlen
= strlen(remote_name
);
669 eap_figure_next_state(esp
, 0);
673 if (esp
->es_server
.ea_maxrequests
> 0 &&
674 esp
->es_server
.ea_requests
>= esp
->es_server
.ea_maxrequests
) {
675 if (esp
->es_server
.ea_responses
> 0)
676 error("EAP: too many Requests sent");
678 error("EAP: no response to Requests");
679 eap_send_failure(esp
);
683 outp
= outpacket_buf
;
685 MAKEHEADER(outp
, PPP_EAP
);
687 PUTCHAR(EAP_REQUEST
, outp
);
688 PUTCHAR(esp
->es_server
.ea_id
, outp
);
692 switch (esp
->es_server
.ea_state
) {
694 PUTCHAR(EAPT_IDENTITY
, outp
);
696 challen
= strlen(str
);
697 BCOPY(str
, outp
, challen
);
698 INCPTR(challen
, outp
);
702 PUTCHAR(EAPT_MD5CHAP
, outp
);
704 * pick a random challenge length between
705 * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
707 challen
= (drand48() *
708 (MAX_CHALLENGE_LENGTH
- MIN_CHALLENGE_LENGTH
)) +
709 MIN_CHALLENGE_LENGTH
;
710 PUTCHAR(challen
, outp
);
711 esp
->es_challen
= challen
;
712 ptr
= esp
->es_challenge
;
713 while (--challen
>= 0)
714 *ptr
++ = (u_char
) (drand48() * 0x100);
715 BCOPY(esp
->es_challenge
, outp
, esp
->es_challen
);
716 INCPTR(esp
->es_challen
, outp
);
717 BCOPY(esp
->es_server
.ea_name
, outp
, esp
->es_server
.ea_namelen
);
718 INCPTR(esp
->es_server
.ea_namelen
, outp
);
723 PUTCHAR(EAPT_SRP
, outp
);
724 PUTCHAR(EAPSRP_CHALLENGE
, outp
);
726 PUTCHAR(esp
->es_server
.ea_namelen
, outp
);
727 BCOPY(esp
->es_server
.ea_name
, outp
, esp
->es_server
.ea_namelen
);
728 INCPTR(esp
->es_server
.ea_namelen
, outp
);
730 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
732 PUTCHAR(ts
->s
.len
, outp
);
733 BCOPY(ts
->s
.data
, outp
, ts
->s
.len
);
734 INCPTR(ts
->s
.len
, outp
);
736 if (ts
->g
.len
== 1 && ts
->g
.data
[0] == 2) {
739 PUTCHAR(ts
->g
.len
, outp
);
740 BCOPY(ts
->g
.data
, outp
, ts
->g
.len
);
741 INCPTR(ts
->g
.len
, outp
);
744 if (ts
->n
.len
!= sizeof (wkmodulus
) ||
745 BCMP(ts
->n
.data
, wkmodulus
, sizeof (wkmodulus
)) != 0) {
746 BCOPY(ts
->n
.data
, outp
, ts
->n
.len
);
747 INCPTR(ts
->n
.len
, outp
);
752 PUTCHAR(EAPT_SRP
, outp
);
753 PUTCHAR(EAPSRP_SKEY
, outp
);
755 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
757 BCOPY(ts
->B
.data
, outp
, ts
->B
.len
);
758 INCPTR(ts
->B
.len
, outp
);
762 PUTCHAR(EAPT_SRP
, outp
);
763 PUTCHAR(EAPSRP_SVALIDATOR
, outp
);
764 PUTLONG(SRPVAL_EBIT
, outp
);
765 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
767 BCOPY(t_serverresponse(ts
), outp
, SHA_DIGESTSIZE
);
768 INCPTR(SHA_DIGESTSIZE
, outp
);
770 if (pncrypt_setkey(0)) {
771 /* Generate pseudonym */
773 cp
= (unsigned char *)esp
->es_server
.ea_peer
;
774 if ((j
= i
= esp
->es_server
.ea_peerlen
) > 7)
777 BCOPY(cp
, clear
+ 1, j
);
780 if (!DesEncrypt(clear
, cipher
)) {
781 dbglog("no DES here; not generating pseudonym");
784 BZERO(&b64
, sizeof (b64
));
785 outp
++; /* space for pseudonym length */
786 outp
+= b64enc(&b64
, cipher
, 8, outp
);
788 (void) DesEncrypt(cp
, cipher
);
789 outp
+= b64enc(&b64
, cipher
, 8, outp
);
797 *cp
++ = drand48() * 0x100;
800 (void) DesEncrypt(clear
, cipher
);
801 outp
+= b64enc(&b64
, cipher
, 8, outp
);
803 outp
+= b64flush(&b64
, outp
);
805 /* Set length and pad out to next 20 octet boundary */
810 while (i
< SHA_DIGESTSIZE
) {
811 *outp
++ = drand48() * 0x100;
816 /* Obscure the pseudonym with SHA1 hash */
818 SHA1Update(&ctxt
, &esp
->es_server
.ea_id
, 1);
819 SHA1Update(&ctxt
, esp
->es_server
.ea_skey
,
821 SHA1Update(&ctxt
, esp
->es_server
.ea_peer
,
822 esp
->es_server
.ea_peerlen
);
823 while (optr
< outp
) {
824 SHA1Final(dig
, &ctxt
);
826 while (cp
< dig
+ SHA_DIGESTSIZE
)
829 SHA1Update(&ctxt
, &esp
->es_server
.ea_id
, 1);
830 SHA1Update(&ctxt
, esp
->es_server
.ea_skey
,
832 SHA1Update(&ctxt
, optr
- SHA_DIGESTSIZE
,
839 PUTCHAR(EAPT_SRP
, outp
);
840 PUTCHAR(EAPSRP_LWRECHALLENGE
, outp
);
841 challen
= MIN_CHALLENGE_LENGTH
+
842 ((MAX_CHALLENGE_LENGTH
- MIN_CHALLENGE_LENGTH
) * drand48());
843 esp
->es_challen
= challen
;
844 ptr
= esp
->es_challenge
;
845 while (--challen
>= 0)
846 *ptr
++ = drand48() * 0x100;
847 BCOPY(esp
->es_challenge
, outp
, esp
->es_challen
);
848 INCPTR(esp
->es_challen
, outp
);
856 outlen
= (outp
- outpacket_buf
) - PPP_HDRLEN
;
857 PUTSHORT(outlen
, lenloc
);
859 output(esp
->es_unit
, outpacket_buf
, outlen
+ PPP_HDRLEN
);
861 esp
->es_server
.ea_requests
++;
863 if (esp
->es_server
.ea_timeout
> 0)
864 TIMEOUT(eap_server_timeout
, esp
, esp
->es_server
.ea_timeout
);
868 * eap_authpeer - Authenticate our peer (behave as server).
870 * Start server state and send first request. This is called only
874 eap_authpeer(unit
, localname
)
878 eap_state
*esp
= &eap_states
[unit
];
880 /* Save the name we're given. */
881 esp
->es_server
.ea_name
= localname
;
882 esp
->es_server
.ea_namelen
= strlen(localname
);
884 esp
->es_savedtime
= esp
->es_server
.ea_timeout
;
886 /* Lower layer up yet? */
887 if (esp
->es_server
.ea_state
== eapInitial
||
888 esp
->es_server
.ea_state
== eapPending
) {
889 esp
->es_server
.ea_state
= eapPending
;
893 esp
->es_server
.ea_state
= eapPending
;
895 /* ID number not updated here intentionally; hashed into M1 */
896 eap_send_request(esp
);
900 * eap_server_timeout - Retransmission timer for sending Requests
904 eap_server_timeout(arg
)
907 eap_state
*esp
= (eap_state
*) arg
;
909 if (!eap_server_active(esp
))
912 /* EAP ID number must not change on timeout. */
913 eap_send_request(esp
);
917 * When it's time to send rechallenge the peer, this timeout is
918 * called. Once the rechallenge is successful, the response handler
919 * will restart the timer. If it fails, then the link is dropped.
925 eap_state
*esp
= (eap_state
*)arg
;
927 if (esp
->es_server
.ea_state
!= eapOpen
&&
928 esp
->es_server
.ea_state
!= eapSRP4
)
931 esp
->es_server
.ea_requests
= 0;
932 esp
->es_server
.ea_state
= eapIdentify
;
933 eap_figure_next_state(esp
, 0);
934 esp
->es_server
.ea_id
++;
935 eap_send_request(esp
);
939 srp_lwrechallenge(arg
)
942 eap_state
*esp
= (eap_state
*)arg
;
944 if (esp
->es_server
.ea_state
!= eapOpen
||
945 esp
->es_server
.ea_type
!= EAPT_SRP
)
948 esp
->es_server
.ea_requests
= 0;
949 esp
->es_server
.ea_state
= eapSRP4
;
950 esp
->es_server
.ea_id
++;
951 eap_send_request(esp
);
955 * eap_lowerup - The lower layer is now up.
957 * This is called before either eap_authpeer or eap_authwithpeer. See
958 * link_established() in auth.c. All that's necessary here is to
959 * return to closed state so that those two routines will do the right
966 eap_state
*esp
= &eap_states
[unit
];
968 /* Discard any (possibly authenticated) peer name. */
969 if (esp
->es_server
.ea_peer
!= NULL
&&
970 esp
->es_server
.ea_peer
!= remote_name
)
971 free(esp
->es_server
.ea_peer
);
972 esp
->es_server
.ea_peer
= NULL
;
973 if (esp
->es_client
.ea_peer
!= NULL
)
974 free(esp
->es_client
.ea_peer
);
975 esp
->es_client
.ea_peer
= NULL
;
977 esp
->es_client
.ea_state
= eapClosed
;
978 esp
->es_server
.ea_state
= eapClosed
;
982 * eap_lowerdown - The lower layer is now down.
984 * Cancel all timeouts and return to initial state.
990 eap_state
*esp
= &eap_states
[unit
];
992 if (eap_client_active(esp
) && esp
->es_client
.ea_timeout
> 0) {
993 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
995 if (eap_server_active(esp
)) {
996 if (esp
->es_server
.ea_timeout
> 0) {
997 UNTIMEOUT(eap_server_timeout
, (void *)esp
);
1000 if ((esp
->es_server
.ea_state
== eapOpen
||
1001 esp
->es_server
.ea_state
== eapSRP4
) &&
1002 esp
->es_rechallenge
> 0) {
1003 UNTIMEOUT(eap_rechallenge
, (void *)esp
);
1005 if (esp
->es_server
.ea_state
== eapOpen
&&
1006 esp
->es_lwrechallenge
> 0) {
1007 UNTIMEOUT(srp_lwrechallenge
, (void *)esp
);
1011 esp
->es_client
.ea_state
= esp
->es_server
.ea_state
= eapInitial
;
1012 esp
->es_client
.ea_requests
= esp
->es_server
.ea_requests
= 0;
1016 * eap_protrej - Peer doesn't speak this protocol.
1018 * This shouldn't happen. If it does, it represents authentication
1025 eap_state
*esp
= &eap_states
[unit
];
1027 if (eap_client_active(esp
)) {
1028 error("EAP authentication failed due to Protocol-Reject");
1029 auth_withpeer_fail(unit
, PPP_EAP
);
1031 if (eap_server_active(esp
)) {
1032 error("EAP authentication of peer failed on Protocol-Reject");
1033 auth_peer_fail(unit
, PPP_EAP
);
1035 eap_lowerdown(unit
);
1039 * Format and send a regular EAP Response message.
1042 eap_send_response(esp
, id
, typenum
, str
, lenstr
)
1052 outp
= outpacket_buf
;
1054 MAKEHEADER(outp
, PPP_EAP
);
1056 PUTCHAR(EAP_RESPONSE
, outp
);
1058 esp
->es_client
.ea_id
= id
;
1059 msglen
= EAP_HEADERLEN
+ sizeof (u_char
) + lenstr
;
1060 PUTSHORT(msglen
, outp
);
1061 PUTCHAR(typenum
, outp
);
1063 BCOPY(str
, outp
, lenstr
);
1066 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ msglen
);
1070 * Format and send an MD5-Challenge EAP Response message.
1073 eap_chap_response(esp
, id
, hash
, name
, namelen
)
1083 outp
= outpacket_buf
;
1085 MAKEHEADER(outp
, PPP_EAP
);
1087 PUTCHAR(EAP_RESPONSE
, outp
);
1089 esp
->es_client
.ea_id
= id
;
1090 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
) + MD5_SIGNATURE_SIZE
+
1092 PUTSHORT(msglen
, outp
);
1093 PUTCHAR(EAPT_MD5CHAP
, outp
);
1094 PUTCHAR(MD5_SIGNATURE_SIZE
, outp
);
1095 BCOPY(hash
, outp
, MD5_SIGNATURE_SIZE
);
1096 INCPTR(MD5_SIGNATURE_SIZE
, outp
);
1098 BCOPY(name
, outp
, namelen
);
1101 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ msglen
);
1106 * Format and send a SRP EAP Response message.
1109 eap_srp_response(esp
, id
, subtypenum
, str
, lenstr
)
1119 outp
= outpacket_buf
;
1121 MAKEHEADER(outp
, PPP_EAP
);
1123 PUTCHAR(EAP_RESPONSE
, outp
);
1125 esp
->es_client
.ea_id
= id
;
1126 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
) + lenstr
;
1127 PUTSHORT(msglen
, outp
);
1128 PUTCHAR(EAPT_SRP
, outp
);
1129 PUTCHAR(subtypenum
, outp
);
1131 BCOPY(str
, outp
, lenstr
);
1134 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ msglen
);
1138 * Format and send a SRP EAP Client Validator Response message.
1141 eap_srpval_response(esp
, id
, flags
, str
)
1150 outp
= outpacket_buf
;
1152 MAKEHEADER(outp
, PPP_EAP
);
1154 PUTCHAR(EAP_RESPONSE
, outp
);
1156 esp
->es_client
.ea_id
= id
;
1157 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
) + sizeof (u_int32_t
) +
1159 PUTSHORT(msglen
, outp
);
1160 PUTCHAR(EAPT_SRP
, outp
);
1161 PUTCHAR(EAPSRP_CVALIDATOR
, outp
);
1162 PUTLONG(flags
, outp
);
1163 BCOPY(str
, outp
, SHA_DIGESTSIZE
);
1165 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ msglen
);
1167 #endif /* USE_SRP */
1170 eap_send_nak(esp
, id
, type
)
1178 outp
= outpacket_buf
;
1180 MAKEHEADER(outp
, PPP_EAP
);
1182 PUTCHAR(EAP_RESPONSE
, outp
);
1184 esp
->es_client
.ea_id
= id
;
1185 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
);
1186 PUTSHORT(msglen
, outp
);
1187 PUTCHAR(EAPT_NAK
, outp
);
1188 PUTCHAR(type
, outp
);
1190 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ msglen
);
1197 char *user
, *path
, *file
;
1200 static bool pnlogged
= 0;
1202 pw
= getpwuid(getuid());
1203 if (pw
== NULL
|| (user
= pw
->pw_dir
) == NULL
|| user
[0] == 0) {
1207 file
= _PATH_PSEUDONYM
;
1208 pl
= strlen(user
) + strlen(file
) + 2;
1212 (void) slprintf(path
, pl
, "%s/%s", user
, file
);
1214 dbglog("pseudonym file: %s", path
);
1221 open_pn_file(modebits
)
1227 if ((path
= name_of_pn_file()) == NULL
)
1229 fd
= open(path
, modebits
, S_IRUSR
| S_IWUSR
);
1241 if ((path
= name_of_pn_file()) != NULL
) {
1242 (void) unlink(path
);
1248 write_pseudonym(esp
, inp
, len
, id
)
1254 u_char
*datp
, *digp
;
1256 u_char dig
[SHA_DIGESTSIZE
];
1257 int dsize
, fd
, olen
= len
;
1260 * Do the decoding by working backwards. This eliminates the need
1261 * to save the decoded output in a separate buffer.
1265 if ((dsize
= len
% SHA_DIGESTSIZE
) == 0)
1266 dsize
= SHA_DIGESTSIZE
;
1270 SHA1Update(&ctxt
, &val
, 1);
1271 SHA1Update(&ctxt
, esp
->es_client
.ea_skey
, SESSION_KEY_LEN
);
1273 SHA1Update(&ctxt
, datp
, SHA_DIGESTSIZE
);
1275 SHA1Update(&ctxt
, esp
->es_client
.ea_name
,
1276 esp
->es_client
.ea_namelen
);
1278 SHA1Final(dig
, &ctxt
);
1279 for (digp
= dig
; digp
< dig
+ SHA_DIGESTSIZE
; digp
++)
1283 /* Now check that the result is sane */
1284 if (olen
<= 0 || *inp
+ 1 > olen
) {
1285 dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen
, inp
);
1290 fd
= open_pn_file(O_WRONLY
| O_CREAT
| O_TRUNC
);
1292 dbglog("EAP: error saving pseudonym: %m");
1295 len
= write(fd
, inp
+ 1, *inp
);
1296 if (close(fd
) != -1 && len
== *inp
) {
1297 dbglog("EAP: saved pseudonym");
1298 esp
->es_usedpseudo
= 0;
1300 dbglog("EAP: failed to save pseudonym");
1304 #endif /* USE_SRP */
1307 * eap_request - Receive EAP Request message (client mode).
1310 eap_request(esp
, inp
, id
, len
)
1319 char secret
[MAXWORDLEN
];
1320 char rhostname
[256];
1322 u_char hash
[MD5_SIGNATURE_SIZE
];
1324 struct t_client
*tc
;
1325 struct t_num sval
, gval
, Nval
, *Ap
, Bval
;
1328 u_char dig
[SHA_DIGESTSIZE
];
1330 #endif /* USE_SRP */
1333 * Note: we update es_client.ea_id *only if* a Response
1334 * message is being generated. Otherwise, we leave it the
1335 * same for duplicate detection purposes.
1338 esp
->es_client
.ea_requests
++;
1339 if (esp
->es_client
.ea_maxrequests
!= 0 &&
1340 esp
->es_client
.ea_requests
> esp
->es_client
.ea_maxrequests
) {
1341 info("EAP: received too many Request messages");
1342 if (esp
->es_client
.ea_timeout
> 0) {
1343 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
1345 auth_withpeer_fail(esp
->es_unit
, PPP_EAP
);
1350 error("EAP: empty Request message discarded");
1354 GETCHAR(typenum
, inp
);
1360 info("EAP: Identity prompt \"%.*q\"", len
, inp
);
1362 if (esp
->es_usepseudo
&&
1363 (esp
->es_usedpseudo
== 0 ||
1364 (esp
->es_usedpseudo
== 1 &&
1365 id
== esp
->es_client
.ea_id
))) {
1366 esp
->es_usedpseudo
= 1;
1367 /* Try to get a pseudonym */
1368 if ((fd
= open_pn_file(O_RDONLY
)) >= 0) {
1369 strcpy(rhostname
, SRP_PSEUDO_ID
);
1370 len
= read(fd
, rhostname
+ SRP_PSEUDO_LEN
,
1371 sizeof (rhostname
) - SRP_PSEUDO_LEN
);
1372 /* XXX NAI unsupported */
1374 eap_send_response(esp
, id
, typenum
,
1375 rhostname
, len
+ SRP_PSEUDO_LEN
);
1382 /* Stop using pseudonym now. */
1383 if (esp
->es_usepseudo
&& esp
->es_usedpseudo
!= 2) {
1385 esp
->es_usedpseudo
= 2;
1387 #endif /* USE_SRP */
1388 eap_send_response(esp
, id
, typenum
, esp
->es_client
.ea_name
,
1389 esp
->es_client
.ea_namelen
);
1392 case EAPT_NOTIFICATION
:
1394 info("EAP: Notification \"%.*q\"", len
, inp
);
1395 eap_send_response(esp
, id
, typenum
, NULL
, 0);
1400 * Avoid the temptation to send Response Nak in reply
1401 * to Request Nak here. It can only lead to trouble.
1403 warn("EAP: unexpected Nak in Request; ignored");
1404 /* Return because we're waiting for something real. */
1409 error("EAP: received MD5-Challenge with no data");
1410 /* Bogus request; wait for something real. */
1413 GETCHAR(vallen
, inp
);
1415 if (vallen
< 8 || vallen
> len
) {
1416 error("EAP: MD5-Challenge with bad length %d (8..%d)",
1418 /* Try something better. */
1419 eap_send_nak(esp
, id
, EAPT_SRP
);
1423 /* Not so likely to happen. */
1424 if (vallen
>= len
+ sizeof (rhostname
)) {
1425 dbglog("EAP: trimming really long peer name down");
1426 BCOPY(inp
+ vallen
, rhostname
, sizeof (rhostname
) - 1);
1427 rhostname
[sizeof (rhostname
) - 1] = '\0';
1429 BCOPY(inp
+ vallen
, rhostname
, len
- vallen
);
1430 rhostname
[len
- vallen
] = '\0';
1433 /* In case the remote doesn't give us his name. */
1434 if (explicit_remote
||
1435 (remote_name
[0] != '\0' && vallen
== len
))
1436 strlcpy(rhostname
, remote_name
, sizeof (rhostname
));
1439 * Get the secret for authenticating ourselves with
1440 * the specified host.
1442 if (!get_secret(esp
->es_unit
, esp
->es_client
.ea_name
,
1443 rhostname
, secret
, &secret_len
, 0)) {
1444 dbglog("EAP: no MD5 secret for auth to %q", rhostname
);
1445 eap_send_nak(esp
, id
, EAPT_SRP
);
1448 MD5_Init(&mdContext
);
1450 MD5_Update(&mdContext
, &typenum
, 1);
1451 MD5_Update(&mdContext
, secret
, secret_len
);
1452 BZERO(secret
, sizeof (secret
));
1453 MD5_Update(&mdContext
, inp
, vallen
);
1454 MD5_Final(hash
, &mdContext
);
1455 eap_chap_response(esp
, id
, hash
, esp
->es_client
.ea_name
,
1456 esp
->es_client
.ea_namelen
);
1462 error("EAP: received empty SRP Request");
1463 /* Bogus request; wait for something real. */
1468 GETCHAR(vallen
, inp
);
1471 case EAPSRP_CHALLENGE
:
1473 if (esp
->es_client
.ea_session
!= NULL
) {
1474 tc
= (struct t_client
*)esp
->es_client
.
1477 * If this is a new challenge, then start
1478 * over with a new client session context.
1479 * Otherwise, just resend last response.
1481 if (id
!= esp
->es_client
.ea_id
) {
1483 esp
->es_client
.ea_session
= NULL
;
1487 /* No session key just yet */
1488 esp
->es_client
.ea_skey
= NULL
;
1490 GETCHAR(vallen
, inp
);
1492 if (vallen
>= len
) {
1493 error("EAP: badly-formed SRP Challenge"
1495 /* Ignore badly-formed messages */
1498 BCOPY(inp
, rhostname
, vallen
);
1499 rhostname
[vallen
] = '\0';
1500 INCPTR(vallen
, inp
);
1504 * In case the remote doesn't give us his name,
1505 * use configured name.
1507 if (explicit_remote
||
1508 (remote_name
[0] != '\0' && vallen
== 0)) {
1509 strlcpy(rhostname
, remote_name
,
1510 sizeof (rhostname
));
1513 if (esp
->es_client
.ea_peer
!= NULL
)
1514 free(esp
->es_client
.ea_peer
);
1515 esp
->es_client
.ea_peer
= strdup(rhostname
);
1516 esp
->es_client
.ea_peerlen
= strlen(rhostname
);
1518 GETCHAR(vallen
, inp
);
1520 if (vallen
>= len
) {
1521 error("EAP: badly-formed SRP Challenge"
1523 /* Ignore badly-formed messages */
1528 INCPTR(vallen
, inp
);
1531 GETCHAR(vallen
, inp
);
1534 error("EAP: badly-formed SRP Challenge"
1536 /* Ignore badly-formed messages */
1539 /* If no generator present, then use value 2 */
1541 gval
.data
= (u_char
*)"\002";
1547 INCPTR(vallen
, inp
);
1551 * If no modulus present, then use well-known
1555 Nval
.data
= (u_char
*)wkmodulus
;
1556 Nval
.len
= sizeof (wkmodulus
);
1561 tc
= t_clientopen(esp
->es_client
.ea_name
,
1562 &Nval
, &gval
, &sval
);
1564 eap_send_nak(esp
, id
, EAPT_MD5CHAP
);
1567 esp
->es_client
.ea_session
= (void *)tc
;
1569 /* Add Challenge ID & type to verifier */
1572 t_clientaddexdata(tc
, vals
, 2);
1574 Ap
= t_clientgenexp(tc
);
1575 eap_srp_response(esp
, id
, EAPSRP_CKEY
, Ap
->data
,
1580 tc
= (struct t_client
*)esp
->es_client
.ea_session
;
1582 warn("EAP: peer sent Subtype 2 without 1");
1583 eap_send_nak(esp
, id
, EAPT_MD5CHAP
);
1586 if (esp
->es_client
.ea_skey
!= NULL
) {
1588 * ID number should not change here. Warn
1589 * if it does (but otherwise ignore).
1591 if (id
!= esp
->es_client
.ea_id
) {
1592 warn("EAP: ID changed from %d to %d "
1593 "in SRP Subtype 2 rexmit",
1594 esp
->es_client
.ea_id
, id
);
1597 if (get_srp_secret(esp
->es_unit
,
1598 esp
->es_client
.ea_name
,
1599 esp
->es_client
.ea_peer
, secret
, 0) == 0) {
1601 * Can't work with this peer because
1602 * the secret is missing. Just give
1605 eap_send_nak(esp
, id
, EAPT_MD5CHAP
);
1610 t_clientpasswd(tc
, secret
);
1611 BZERO(secret
, sizeof (secret
));
1612 esp
->es_client
.ea_skey
=
1613 t_clientgetkey(tc
, &Bval
);
1614 if (esp
->es_client
.ea_skey
== NULL
) {
1615 /* Server is rogue; stop now */
1616 error("EAP: SRP server is rogue");
1617 goto client_failure
;
1620 eap_srpval_response(esp
, id
, SRPVAL_EBIT
,
1621 t_clientresponse(tc
));
1624 case EAPSRP_SVALIDATOR
:
1625 tc
= (struct t_client
*)esp
->es_client
.ea_session
;
1626 if (tc
== NULL
|| esp
->es_client
.ea_skey
== NULL
) {
1627 warn("EAP: peer sent Subtype 3 without 1/2");
1628 eap_send_nak(esp
, id
, EAPT_MD5CHAP
);
1632 * If we're already open, then this ought to be a
1633 * duplicate. Otherwise, check that the server is
1634 * who we think it is.
1636 if (esp
->es_client
.ea_state
== eapOpen
) {
1637 if (id
!= esp
->es_client
.ea_id
) {
1638 warn("EAP: ID changed from %d to %d "
1639 "in SRP Subtype 3 rexmit",
1640 esp
->es_client
.ea_id
, id
);
1643 len
-= sizeof (u_int32_t
) + SHA_DIGESTSIZE
;
1644 if (len
< 0 || t_clientverify(tc
, inp
+
1645 sizeof (u_int32_t
)) != 0) {
1646 error("EAP: SRP server verification "
1648 goto client_failure
;
1650 GETLONG(esp
->es_client
.ea_keyflags
, inp
);
1651 /* Save pseudonym if user wants it. */
1652 if (len
> 0 && esp
->es_usepseudo
) {
1653 INCPTR(SHA_DIGESTSIZE
, inp
);
1654 write_pseudonym(esp
, inp
, len
, id
);
1658 * We've verified our peer. We're now mostly done,
1659 * except for waiting on the regular EAP Success
1662 eap_srp_response(esp
, id
, EAPSRP_ACK
, NULL
, 0);
1665 case EAPSRP_LWRECHALLENGE
:
1667 warn("EAP: malformed Lightweight rechallenge");
1672 SHA1Update(&ctxt
, vals
, 1);
1673 SHA1Update(&ctxt
, esp
->es_client
.ea_skey
,
1675 SHA1Update(&ctxt
, inp
, len
);
1676 SHA1Update(&ctxt
, esp
->es_client
.ea_name
,
1677 esp
->es_client
.ea_namelen
);
1678 SHA1Final(dig
, &ctxt
);
1679 eap_srp_response(esp
, id
, EAPSRP_LWRECHALLENGE
, dig
,
1684 error("EAP: unknown SRP Subtype %d", vallen
);
1685 eap_send_nak(esp
, id
, EAPT_MD5CHAP
);
1689 #endif /* USE_SRP */
1692 info("EAP: unknown authentication type %d; Naking", typenum
);
1693 eap_send_nak(esp
, id
, EAPT_SRP
);
1697 if (esp
->es_client
.ea_timeout
> 0) {
1698 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
1699 TIMEOUT(eap_client_timeout
, (void *)esp
,
1700 esp
->es_client
.ea_timeout
);
1706 esp
->es_client
.ea_state
= eapBadAuth
;
1707 if (esp
->es_client
.ea_timeout
> 0) {
1708 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
1710 esp
->es_client
.ea_session
= NULL
;
1712 auth_withpeer_fail(esp
->es_unit
, PPP_EAP
);
1713 #endif /* USE_SRP */
1717 * eap_response - Receive EAP Response message (server mode).
1720 eap_response(esp
, inp
, id
, len
)
1729 char secret
[MAXSECRETLEN
];
1730 char rhostname
[256];
1732 u_char hash
[MD5_SIGNATURE_SIZE
];
1734 struct t_server
*ts
;
1737 u_char dig
[SHA_DIGESTSIZE
];
1738 #endif /* USE_SRP */
1740 if (esp
->es_server
.ea_id
!= id
) {
1741 dbglog("EAP: discarding Response %d; expected ID %d", id
,
1742 esp
->es_server
.ea_id
);
1746 esp
->es_server
.ea_responses
++;
1749 error("EAP: empty Response message discarded");
1753 GETCHAR(typenum
, inp
);
1758 if (esp
->es_server
.ea_state
!= eapIdentify
) {
1759 dbglog("EAP discarding unwanted Identify \"%.q\"", len
,
1763 info("EAP: unauthenticated peer name \"%.*q\"", len
, inp
);
1764 if (esp
->es_server
.ea_peer
!= NULL
&&
1765 esp
->es_server
.ea_peer
!= remote_name
)
1766 free(esp
->es_server
.ea_peer
);
1767 esp
->es_server
.ea_peer
= malloc(len
+ 1);
1768 if (esp
->es_server
.ea_peer
== NULL
) {
1769 esp
->es_server
.ea_peerlen
= 0;
1770 eap_figure_next_state(esp
, 1);
1773 BCOPY(inp
, esp
->es_server
.ea_peer
, len
);
1774 esp
->es_server
.ea_peer
[len
] = '\0';
1775 esp
->es_server
.ea_peerlen
= len
;
1776 eap_figure_next_state(esp
, 0);
1779 case EAPT_NOTIFICATION
:
1780 dbglog("EAP unexpected Notification; response discarded");
1785 info("EAP: Nak Response with no suggested protocol");
1786 eap_figure_next_state(esp
, 1);
1790 GETCHAR(vallen
, inp
);
1793 if (!explicit_remote
&& esp
->es_server
.ea_state
== eapIdentify
){
1794 /* Peer cannot Nak Identify Request */
1795 eap_figure_next_state(esp
, 1);
1801 /* Run through SRP validator selection again. */
1802 esp
->es_server
.ea_state
= eapIdentify
;
1803 eap_figure_next_state(esp
, 0);
1807 esp
->es_server
.ea_state
= eapMD5Chall
;
1811 dbglog("EAP: peer requesting unknown Type %d", vallen
);
1812 switch (esp
->es_server
.ea_state
) {
1816 esp
->es_server
.ea_state
= eapMD5Chall
;
1820 esp
->es_server
.ea_state
= eapIdentify
;
1821 eap_figure_next_state(esp
, 0);
1831 if (esp
->es_server
.ea_state
!= eapMD5Chall
) {
1832 error("EAP: unexpected MD5-Response");
1833 eap_figure_next_state(esp
, 1);
1837 error("EAP: received MD5-Response with no data");
1838 eap_figure_next_state(esp
, 1);
1841 GETCHAR(vallen
, inp
);
1843 if (vallen
!= 16 || vallen
> len
) {
1844 error("EAP: MD5-Response with bad length %d", vallen
);
1845 eap_figure_next_state(esp
, 1);
1849 /* Not so likely to happen. */
1850 if (vallen
>= len
+ sizeof (rhostname
)) {
1851 dbglog("EAP: trimming really long peer name down");
1852 BCOPY(inp
+ vallen
, rhostname
, sizeof (rhostname
) - 1);
1853 rhostname
[sizeof (rhostname
) - 1] = '\0';
1855 BCOPY(inp
+ vallen
, rhostname
, len
- vallen
);
1856 rhostname
[len
- vallen
] = '\0';
1859 /* In case the remote doesn't give us his name. */
1860 if (explicit_remote
||
1861 (remote_name
[0] != '\0' && vallen
== len
))
1862 strlcpy(rhostname
, remote_name
, sizeof (rhostname
));
1865 * Get the secret for authenticating the specified
1868 if (!get_secret(esp
->es_unit
, rhostname
,
1869 esp
->es_server
.ea_name
, secret
, &secret_len
, 1)) {
1870 dbglog("EAP: no MD5 secret for auth of %q", rhostname
);
1871 eap_send_failure(esp
);
1874 MD5_Init(&mdContext
);
1875 MD5_Update(&mdContext
, &esp
->es_server
.ea_id
, 1);
1876 MD5_Update(&mdContext
, secret
, secret_len
);
1877 BZERO(secret
, sizeof (secret
));
1878 MD5_Update(&mdContext
, esp
->es_challenge
, esp
->es_challen
);
1879 MD5_Final(hash
, &mdContext
);
1880 if (BCMP(hash
, inp
, MD5_SIGNATURE_SIZE
) != 0) {
1881 eap_send_failure(esp
);
1884 esp
->es_server
.ea_type
= EAPT_MD5CHAP
;
1885 eap_send_success(esp
);
1886 eap_figure_next_state(esp
, 0);
1887 if (esp
->es_rechallenge
!= 0)
1888 TIMEOUT(eap_rechallenge
, esp
, esp
->es_rechallenge
);
1894 error("EAP: empty SRP Response");
1895 eap_figure_next_state(esp
, 1);
1898 GETCHAR(typenum
, inp
);
1902 if (esp
->es_server
.ea_state
!= eapSRP1
) {
1903 error("EAP: unexpected SRP Subtype 1 Response");
1904 eap_figure_next_state(esp
, 1);
1909 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
1911 esp
->es_server
.ea_skey
= t_servergetkey(ts
, &A
);
1912 if (esp
->es_server
.ea_skey
== NULL
) {
1913 /* Client's A value is bogus; terminate now */
1914 error("EAP: bogus A value from client");
1915 eap_send_failure(esp
);
1917 eap_figure_next_state(esp
, 0);
1921 case EAPSRP_CVALIDATOR
:
1922 if (esp
->es_server
.ea_state
!= eapSRP2
) {
1923 error("EAP: unexpected SRP Subtype 2 Response");
1924 eap_figure_next_state(esp
, 1);
1927 if (len
< sizeof (u_int32_t
) + SHA_DIGESTSIZE
) {
1928 error("EAP: M1 length %d < %d", len
,
1929 sizeof (u_int32_t
) + SHA_DIGESTSIZE
);
1930 eap_figure_next_state(esp
, 1);
1933 GETLONG(esp
->es_server
.ea_keyflags
, inp
);
1934 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
1936 if (t_serververify(ts
, inp
)) {
1937 info("EAP: unable to validate client identity");
1938 eap_send_failure(esp
);
1941 eap_figure_next_state(esp
, 0);
1945 if (esp
->es_server
.ea_state
!= eapSRP3
) {
1946 error("EAP: unexpected SRP Subtype 3 Response");
1947 eap_send_failure(esp
);
1950 esp
->es_server
.ea_type
= EAPT_SRP
;
1951 eap_send_success(esp
);
1952 eap_figure_next_state(esp
, 0);
1953 if (esp
->es_rechallenge
!= 0)
1954 TIMEOUT(eap_rechallenge
, esp
,
1955 esp
->es_rechallenge
);
1956 if (esp
->es_lwrechallenge
!= 0)
1957 TIMEOUT(srp_lwrechallenge
, esp
,
1958 esp
->es_lwrechallenge
);
1961 case EAPSRP_LWRECHALLENGE
:
1962 if (esp
->es_server
.ea_state
!= eapSRP4
) {
1963 info("EAP: unexpected SRP Subtype 4 Response");
1966 if (len
!= SHA_DIGESTSIZE
) {
1967 error("EAP: bad Lightweight rechallenge "
1973 SHA1Update(&ctxt
, &vallen
, 1);
1974 SHA1Update(&ctxt
, esp
->es_server
.ea_skey
,
1976 SHA1Update(&ctxt
, esp
->es_challenge
, esp
->es_challen
);
1977 SHA1Update(&ctxt
, esp
->es_server
.ea_peer
,
1978 esp
->es_server
.ea_peerlen
);
1979 SHA1Final(dig
, &ctxt
);
1980 if (BCMP(dig
, inp
, SHA_DIGESTSIZE
) != 0) {
1981 error("EAP: failed Lightweight rechallenge");
1982 eap_send_failure(esp
);
1985 esp
->es_server
.ea_state
= eapOpen
;
1986 if (esp
->es_lwrechallenge
!= 0)
1987 TIMEOUT(srp_lwrechallenge
, esp
,
1988 esp
->es_lwrechallenge
);
1992 #endif /* USE_SRP */
1995 /* This can't happen. */
1996 error("EAP: unknown Response type %d; ignored", typenum
);
2000 if (esp
->es_server
.ea_timeout
> 0) {
2001 UNTIMEOUT(eap_server_timeout
, (void *)esp
);
2004 if (esp
->es_server
.ea_state
!= eapBadAuth
&&
2005 esp
->es_server
.ea_state
!= eapOpen
) {
2006 esp
->es_server
.ea_id
++;
2007 eap_send_request(esp
);
2012 * eap_success - Receive EAP Success message (client mode).
2015 eap_success(esp
, inp
, id
, len
)
2021 if (esp
->es_client
.ea_state
!= eapOpen
&& !eap_client_active(esp
)) {
2022 dbglog("EAP unexpected success message in state %s (%d)",
2023 eap_state_name(esp
->es_client
.ea_state
),
2024 esp
->es_client
.ea_state
);
2028 if (esp
->es_client
.ea_timeout
> 0) {
2029 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
2033 /* This is odd. The spec doesn't allow for this. */
2037 esp
->es_client
.ea_state
= eapOpen
;
2038 auth_withpeer_success(esp
->es_unit
, PPP_EAP
, 0);
2042 * eap_failure - Receive EAP Failure message (client mode).
2045 eap_failure(esp
, inp
, id
, len
)
2051 if (!eap_client_active(esp
)) {
2052 dbglog("EAP unexpected failure message in state %s (%d)",
2053 eap_state_name(esp
->es_client
.ea_state
),
2054 esp
->es_client
.ea_state
);
2057 if (esp
->es_client
.ea_timeout
> 0) {
2058 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
2062 /* This is odd. The spec doesn't allow for this. */
2066 esp
->es_client
.ea_state
= eapBadAuth
;
2068 error("EAP: peer reports authentication failure");
2069 auth_withpeer_fail(esp
->es_unit
, PPP_EAP
);
2073 * eap_input - Handle received EAP message.
2076 eap_input(unit
, inp
, inlen
)
2081 eap_state
*esp
= &eap_states
[unit
];
2086 * Parse header (code, id and length). If packet too short,
2089 if (inlen
< EAP_HEADERLEN
) {
2090 error("EAP: packet too short: %d < %d", inlen
, EAP_HEADERLEN
);
2096 if (len
< EAP_HEADERLEN
|| len
> inlen
) {
2097 error("EAP: packet has illegal length field %d (%d..%d)", len
,
2098 EAP_HEADERLEN
, inlen
);
2101 len
-= EAP_HEADERLEN
;
2103 /* Dispatch based on message code */
2106 eap_request(esp
, inp
, id
, len
);
2110 eap_response(esp
, inp
, id
, len
);
2114 eap_success(esp
, inp
, id
, len
);
2118 eap_failure(esp
, inp
, id
, len
);
2121 default: /* XXX Need code reject */
2122 /* Note: it's not legal to send EAP Nak here. */
2123 warn("EAP: unknown code %d received", code
);
2129 * eap_printpkt - print the contents of an EAP packet.
2131 static char *eap_codenames
[] = {
2132 "Request", "Response", "Success", "Failure"
2135 static char *eap_typenames
[] = {
2136 "Identity", "Notification", "Nak", "MD5-Challenge",
2137 "OTP", "Generic-Token", NULL
, NULL
,
2138 "RSA", "DSS", "KEA", "KEA-Validate",
2139 "TLS", "Defender", "Windows 2000", "Arcot",
2140 "Cisco", "Nokia", "SRP"
2144 eap_printpkt(inp
, inlen
, printer
, arg
)
2147 void (*printer
) __P((void *, char *, ...));
2150 int code
, id
, len
, rtype
, vallen
;
2154 if (inlen
< EAP_HEADERLEN
)
2160 if (len
< EAP_HEADERLEN
|| len
> inlen
)
2163 if (code
>= 1 && code
<= sizeof(eap_codenames
) / sizeof(char *))
2164 printer(arg
, " %s", eap_codenames
[code
-1]);
2166 printer(arg
, " code=0x%x", code
);
2167 printer(arg
, " id=0x%x", id
);
2168 len
-= EAP_HEADERLEN
;
2172 printer(arg
, " <missing type>");
2175 GETCHAR(rtype
, inp
);
2178 rtype
<= sizeof (eap_typenames
) / sizeof (char *))
2179 printer(arg
, " %s", eap_typenames
[rtype
-1]);
2181 printer(arg
, " type=0x%x", rtype
);
2184 case EAPT_NOTIFICATION
:
2186 printer(arg
, " <Message ");
2187 print_string((char *)inp
, len
, printer
, arg
);
2192 printer(arg
, " <No message>");
2199 GETCHAR(vallen
, inp
);
2203 printer(arg
, " <Value%.*B>", vallen
, inp
);
2204 INCPTR(vallen
, inp
);
2207 printer(arg
, " <Name ");
2208 print_string((char *)inp
, len
, printer
, arg
);
2213 printer(arg
, " <No name>");
2220 GETCHAR(vallen
, inp
);
2222 printer(arg
, "-%d", vallen
);
2224 case EAPSRP_CHALLENGE
:
2225 GETCHAR(vallen
, inp
);
2230 printer(arg
, " <Name ");
2231 print_string((char *)inp
, vallen
, printer
,
2235 printer(arg
, " <No name>");
2237 INCPTR(vallen
, inp
);
2239 GETCHAR(vallen
, inp
);
2243 printer(arg
, " <s%.*B>", vallen
, inp
);
2244 INCPTR(vallen
, inp
);
2246 GETCHAR(vallen
, inp
);
2251 printer(arg
, " <Default g=2>");
2253 printer(arg
, " <g%.*B>", vallen
, inp
);
2255 INCPTR(vallen
, inp
);
2258 printer(arg
, " <Default N>");
2260 printer(arg
, " <N%.*B>", len
, inp
);
2267 printer(arg
, " <B%.*B>", len
, inp
);
2272 case EAPSRP_SVALIDATOR
:
2273 if (len
< sizeof (u_int32_t
))
2276 len
-= sizeof (u_int32_t
);
2277 if (uval
& SRPVAL_EBIT
) {
2279 uval
&= ~SRPVAL_EBIT
;
2282 printer(arg
, " f<%X>", uval
);
2284 if ((vallen
= len
) > SHA_DIGESTSIZE
)
2285 vallen
= SHA_DIGESTSIZE
;
2286 printer(arg
, " <M2%.*B%s>", len
, inp
,
2287 len
< SHA_DIGESTSIZE
? "?" : "");
2288 INCPTR(vallen
, inp
);
2291 printer(arg
, " <PN%.*B>", len
, inp
);
2297 case EAPSRP_LWRECHALLENGE
:
2298 printer(arg
, " <Challenge%.*B>", len
, inp
);
2310 GETCHAR(rtype
, inp
);
2313 rtype
<= sizeof (eap_typenames
) / sizeof (char *))
2314 printer(arg
, " %s", eap_typenames
[rtype
-1]);
2316 printer(arg
, " type=0x%x", rtype
);
2320 printer(arg
, " <Name ");
2321 print_string((char *)inp
, len
, printer
, arg
);
2330 printer(arg
, " <missing hint>");
2333 GETCHAR(rtype
, inp
);
2335 printer(arg
, " <Suggested-type %02X", rtype
);
2337 rtype
< sizeof (eap_typenames
) / sizeof (char *))
2338 printer(arg
, " (%s)", eap_typenames
[rtype
-1]);
2344 printer(arg
, " <missing length>");
2347 GETCHAR(vallen
, inp
);
2351 printer(arg
, " <Value%.*B>", vallen
, inp
);
2352 INCPTR(vallen
, inp
);
2355 printer(arg
, " <Name ");
2356 print_string((char *)inp
, len
, printer
, arg
);
2361 printer(arg
, " <No name>");
2368 GETCHAR(vallen
, inp
);
2370 printer(arg
, "-%d", vallen
);
2373 printer(arg
, " <A%.*B>", len
, inp
);
2378 case EAPSRP_CVALIDATOR
:
2379 if (len
< sizeof (u_int32_t
))
2382 len
-= sizeof (u_int32_t
);
2383 if (uval
& SRPVAL_EBIT
) {
2385 uval
&= ~SRPVAL_EBIT
;
2388 printer(arg
, " f<%X>", uval
);
2390 printer(arg
, " <M1%.*B%s>", len
, inp
,
2391 len
== SHA_DIGESTSIZE
? "" : "?");
2399 case EAPSRP_LWRECHALLENGE
:
2400 printer(arg
, " <Response%.*B%s>", len
, inp
,
2401 len
== SHA_DIGESTSIZE
? "" : "?");
2402 if ((vallen
= len
) > SHA_DIGESTSIZE
)
2403 vallen
= SHA_DIGESTSIZE
;
2404 INCPTR(vallen
, inp
);
2412 case EAP_SUCCESS
: /* No payload expected for these! */
2417 printer(arg
, " <truncated>");
2422 printer(arg
, "%8B...", inp
);
2424 printer(arg
, "%.*B", len
, inp
);
2427 return (inp
- pstart
);