1 /* $NetBSD: eap.c,v 1.1.1.1 2005/02/20 10:28:42 cube Exp $ */
4 * eap.c - Extensible Authentication Protocol for PPP (RFC 2284)
6 * Copyright (c) 2001 by Sun Microsystems, Inc.
9 * Non-exclusive rights to redistribute, modify, translate, and use
10 * this software in source and binary forms, in whole or in part, is
11 * hereby granted, provided that the above copyright notice is
12 * duplicated in any source form, and that neither the name of the
13 * copyright holder nor the author is used to endorse or promote
14 * products derived from this software.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 * Original version by James Carlson
22 * This implementation of EAP supports MD5-Challenge and SRP-SHA1
23 * authentication styles. Note that support of MD5-Challenge is a
24 * requirement of RFC 2284, and that it's essentially just a
25 * reimplementation of regular RFC 1994 CHAP using EAP messages.
27 * As an authenticator ("server"), there are multiple phases for each
28 * style. In the first phase of each style, the unauthenticated peer
29 * name is queried using the EAP Identity request type. If the
30 * "remotename" option is used, then this phase is skipped, because
31 * the peer's name is presumed to be known.
33 * For MD5-Challenge, there are two phases, and the second phase
34 * consists of sending the challenge itself and handling the
35 * associated response.
37 * For SRP-SHA1, there are four phases. The second sends 's', 'N',
38 * and 'g'. The reply contains 'A'. The third sends 'B', and the
39 * reply contains 'M1'. The forth sends the 'M2' value.
41 * As an authenticatee ("client"), there's just a single phase --
42 * responding to the queries generated by the peer. EAP is an
43 * authenticator-driven protocol.
45 * Based on draft-ietf-pppext-eap-srp-03.txt.
48 #include <sys/cdefs.h>
51 #define RCSID "Id: eap.c,v 1.4 2004/11/09 22:39:25 paulus Exp"
53 __RCSID("$NetBSD: eap.c,v 1.1.1.1 2005/02/20 10:28:42 cube Exp $");
66 #include <sys/types.h>
74 #include "pathnames.h"
84 #ifndef SHA_DIGESTSIZE
85 #define SHA_DIGESTSIZE 20
89 static const char rcsid
[] = RCSID
;
92 eap_state eap_states
[NUM_PPP
]; /* EAP state; one for each unit */
94 static char *pn_secret
= NULL
; /* Pseudonym generating secret */
98 * Command-line options.
100 static option_t eap_option_list
[] = {
101 { "eap-restart", o_int
, &eap_states
[0].es_server
.ea_timeout
,
102 "Set retransmit timeout for EAP Requests (server)" },
103 { "eap-max-sreq", o_int
, &eap_states
[0].es_server
.ea_maxrequests
,
104 "Set max number of EAP Requests sent (server)" },
105 { "eap-timeout", o_int
, &eap_states
[0].es_client
.ea_timeout
,
106 "Set time limit for peer EAP authentication" },
107 { "eap-max-rreq", o_int
, &eap_states
[0].es_client
.ea_maxrequests
,
108 "Set max number of EAP Requests allows (client)" },
109 { "eap-interval", o_int
, &eap_states
[0].es_rechallenge
,
110 "Set interval for EAP rechallenge" },
112 { "srp-interval", o_int
, &eap_states
[0].es_lwrechallenge
,
113 "Set interval for SRP lightweight rechallenge" },
114 { "srp-pn-secret", o_string
, &pn_secret
,
115 "Long term pseudonym generation secret" },
116 { "srp-use-pseudonym", o_bool
, &eap_states
[0].es_usepseudo
,
117 "Use pseudonym if offered one by server", 1 },
123 * Protocol entry points.
125 static void eap_init
__P((int unit
));
126 static void eap_input
__P((int unit
, u_char
*inp
, int inlen
));
127 static void eap_protrej
__P((int unit
));
128 static void eap_lowerup
__P((int unit
));
129 static void eap_lowerdown
__P((int unit
));
130 static int eap_printpkt
__P((u_char
*inp
, int inlen
,
131 void (*)(void *arg
, char *fmt
, ...), void *arg
));
133 struct protent eap_protent
= {
134 PPP_EAP
, /* protocol number */
135 eap_init
, /* initialization procedure */
136 eap_input
, /* process a received packet */
137 eap_protrej
, /* process a received protocol-reject */
138 eap_lowerup
, /* lower layer has gone up */
139 eap_lowerdown
, /* lower layer has gone down */
140 NULL
, /* open the protocol */
141 NULL
, /* close the protocol */
142 eap_printpkt
, /* print a packet in readable form */
143 NULL
, /* process a received data packet */
144 1, /* protocol enabled */
145 "EAP", /* text name of protocol */
146 NULL
, /* text name of corresponding data protocol */
147 eap_option_list
, /* list of command-line options */
148 NULL
, /* check requested options; assign defaults */
149 NULL
, /* configure interface for demand-dial */
150 NULL
/* say whether to bring up link for this pkt */
154 * A well-known 2048 bit modulus.
156 static const u_char wkmodulus
[] = {
157 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
158 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
159 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
160 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
161 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
162 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
163 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
164 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
165 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
166 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
167 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
168 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
169 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
170 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
171 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
172 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
173 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
174 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
175 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
176 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
177 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
178 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
179 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
180 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
181 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
182 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
183 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
184 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
185 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
186 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
187 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
188 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
191 /* Local forward declarations. */
192 static void eap_server_timeout
__P((void *arg
));
193 static const char *eap_state_name
__P((enum eap_state_code
));
194 static void eap_client_timeout
__P((void *arg
));
195 static void eap_send_failure
__P((eap_state
*));
196 static void eap_send_success
__P((eap_state
*));
197 static void eap_figure_next_state
__P((eap_state
*, int));
198 static void eap_send_request
__P((eap_state
*));
199 static void eap_rechallenge
__P((void *));
200 static void srp_lwrechallenge
__P((void *));
201 static void eap_send_response
__P((eap_state
*, u_char
, u_char
, u_char
*, int));
202 static void eap_chap_response
__P((eap_state
*, u_char
, u_char
*, char *, int));
203 static void eap_send_nak
__P((eap_state
*,u_char
,u_char
));
204 static void eap_request
__P((eap_state
*, u_char
*, int, int));
205 static void eap_response
__P((eap_state
*, u_char
*, int, int));
206 static void eap_success
__P((eap_state
*, u_char
*, int, int));
207 static void eap_failure
__P((eap_state
*, u_char
*, int, int));
210 * Convert EAP state code to printable string for debug.
214 enum eap_state_code esc
;
216 static const char *state_names
[] = { EAP_STATES
};
218 return (state_names
[(int)esc
]);
222 * eap_init - Initialize state for an EAP user. This is currently
223 * called once by main() during start-up.
229 eap_state
*esp
= &eap_states
[unit
];
231 BZERO(esp
, sizeof (*esp
));
233 esp
->es_server
.ea_timeout
= EAP_DEFTIMEOUT
;
234 esp
->es_server
.ea_maxrequests
= EAP_DEFTRANSMITS
;
235 esp
->es_server
.ea_id
= (u_char
)(drand48() * 0x100);
236 esp
->es_client
.ea_timeout
= EAP_DEFREQTIME
;
237 esp
->es_client
.ea_maxrequests
= EAP_DEFALLOWREQ
;
241 * eap_client_timeout - Give up waiting for the peer to send any
245 eap_client_timeout(arg
)
248 eap_state
*esp
= (eap_state
*) arg
;
250 if (!eap_client_active(esp
))
253 error("EAP: timeout waiting for Request from peer");
254 auth_withpeer_fail(esp
->es_unit
, PPP_EAP
);
255 esp
->es_client
.ea_state
= eapBadAuth
;
259 * eap_authwithpeer - Authenticate to our peer (behave as client).
261 * Start client state and wait for requests. This is called only
265 eap_authwithpeer(unit
, localname
)
269 eap_state
*esp
= &eap_states
[unit
];
271 /* Save the peer name we're given */
272 esp
->es_client
.ea_name
= localname
;
273 esp
->es_client
.ea_namelen
= strlen(localname
);
275 esp
->es_client
.ea_state
= eapListen
;
278 * Start a timer so that if the other end just goes
279 * silent, we don't sit here waiting forever.
281 if (esp
->es_client
.ea_timeout
> 0)
282 TIMEOUT(eap_client_timeout
, (void *)esp
,
283 esp
->es_client
.ea_timeout
);
287 * Format a standard EAP Failure message and send it to the peer.
291 eap_send_failure(esp
)
296 outp
= outpacket_buf
;
298 MAKEHEADER(outp
, PPP_EAP
);
300 PUTCHAR(EAP_FAILURE
, outp
);
301 esp
->es_server
.ea_id
++;
302 PUTCHAR(esp
->es_server
.ea_id
, outp
);
303 PUTSHORT(EAP_HEADERLEN
, outp
);
305 output(esp
->es_unit
, outpacket_buf
, EAP_HEADERLEN
+ PPP_HDRLEN
);
307 esp
->es_server
.ea_state
= eapBadAuth
;
308 auth_peer_fail(esp
->es_unit
, PPP_EAP
);
312 * Format a standard EAP Success message and send it to the peer.
316 eap_send_success(esp
)
321 outp
= outpacket_buf
;
323 MAKEHEADER(outp
, PPP_EAP
);
325 PUTCHAR(EAP_SUCCESS
, outp
);
326 esp
->es_server
.ea_id
++;
327 PUTCHAR(esp
->es_server
.ea_id
, outp
);
328 PUTSHORT(EAP_HEADERLEN
, outp
);
330 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ EAP_HEADERLEN
);
332 auth_peer_success(esp
->es_unit
, PPP_EAP
, 0,
333 esp
->es_server
.ea_peer
, esp
->es_server
.ea_peerlen
);
338 * Set DES key according to pseudonym-generating secret and current
342 pncrypt_setkey(int timeoffs
)
347 u_char dig
[SHA_DIGESTSIZE
];
350 if (pn_secret
== NULL
)
352 reftime
= time(NULL
) + timeoffs
;
353 tp
= localtime(&reftime
);
355 SHA1Update(&ctxt
, pn_secret
, strlen(pn_secret
));
356 strftime(tbuf
, sizeof (tbuf
), "%Y%m%d", tp
);
357 SHA1Update(&ctxt
, tbuf
, strlen(tbuf
));
358 SHA1Final(dig
, &ctxt
);
359 return (DesSetkey(dig
));
362 static char base64
[] =
363 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
371 b64enc(bs
, inp
, inlen
, outp
)
380 bs
->bs_bits
= (bs
->bs_bits
<< 8) | *inp
++;
383 if (bs
->bs_offs
>= 24) {
384 *outp
++ = base64
[(bs
->bs_bits
>> 18) & 0x3F];
385 *outp
++ = base64
[(bs
->bs_bits
>> 12) & 0x3F];
386 *outp
++ = base64
[(bs
->bs_bits
>> 6) & 0x3F];
387 *outp
++ = base64
[bs
->bs_bits
& 0x3F];
403 if (bs
->bs_offs
== 8) {
404 *outp
++ = base64
[(bs
->bs_bits
>> 2) & 0x3F];
405 *outp
++ = base64
[(bs
->bs_bits
<< 4) & 0x3F];
407 } else if (bs
->bs_offs
== 16) {
408 *outp
++ = base64
[(bs
->bs_bits
>> 10) & 0x3F];
409 *outp
++ = base64
[(bs
->bs_bits
>> 4) & 0x3F];
410 *outp
++ = base64
[(bs
->bs_bits
<< 2) & 0x3F];
419 b64dec(bs
, inp
, inlen
, outp
)
429 if ((cp
= strchr(base64
, *inp
++)) == NULL
)
431 bs
->bs_bits
= (bs
->bs_bits
<< 6) | (cp
- base64
);
434 if (bs
->bs_offs
>= 8) {
435 *outp
++ = bs
->bs_bits
>> (bs
->bs_offs
- 8);
445 * Assume that current waiting server state is complete and figure
446 * next state to use based on available authentication data. 'status'
447 * indicates if there was an error in handling the last query. It is
448 * 0 for success and non-zero for failure.
451 eap_figure_next_state(esp
, status
)
456 unsigned char secbuf
[MAXWORDLEN
], clear
[8], *sp
, *dp
;
458 struct t_confent
*tce
, mytce
;
461 int id
, i
, plen
, toffs
;
466 esp
->es_server
.ea_timeout
= esp
->es_savedtime
;
467 switch (esp
->es_server
.ea_state
) {
473 /* Discard any previous session. */
474 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
477 esp
->es_server
.ea_session
= NULL
;
478 esp
->es_server
.ea_skey
= NULL
;
482 esp
->es_server
.ea_state
= eapBadAuth
;
486 /* If we've got a pseudonym, try to decode to real name. */
487 if (esp
->es_server
.ea_peerlen
> SRP_PSEUDO_LEN
&&
488 strncmp(esp
->es_server
.ea_peer
, SRP_PSEUDO_ID
,
489 SRP_PSEUDO_LEN
) == 0 &&
490 (esp
->es_server
.ea_peerlen
- SRP_PSEUDO_LEN
) * 3 / 4 <
492 BZERO(&bs
, sizeof (bs
));
494 esp
->es_server
.ea_peer
+ SRP_PSEUDO_LEN
,
495 esp
->es_server
.ea_peerlen
- SRP_PSEUDO_LEN
,
498 for (i
= 0; i
< 5; i
++) {
499 pncrypt_setkey(toffs
);
501 if (!DesDecrypt(secbuf
, clear
)) {
502 dbglog("no DES here; cannot decode "
506 id
= *(unsigned char *)clear
;
507 if (id
+ 1 <= plen
&& id
+ 9 > plen
)
510 if (plen
% 8 == 0 && i
< 5) {
512 * Note that this is always shorter than the
513 * original stored string, so there's no need
516 if ((i
= plen
= *(unsigned char *)clear
) > 7)
518 esp
->es_server
.ea_peerlen
= plen
;
519 dp
= (unsigned char *)esp
->es_server
.ea_peer
;
520 BCOPY(clear
+ 1, dp
, i
);
525 (void) DesDecrypt(sp
, dp
);
530 esp
->es_server
.ea_peer
[
531 esp
->es_server
.ea_peerlen
] = '\0';
532 dbglog("decoded pseudonym to \"%.*q\"",
533 esp
->es_server
.ea_peerlen
,
534 esp
->es_server
.ea_peer
);
536 dbglog("failed to decode real name");
537 /* Stay in eapIdentfy state; requery */
541 /* Look up user in secrets database. */
542 if (get_srp_secret(esp
->es_unit
, esp
->es_server
.ea_peer
,
543 esp
->es_server
.ea_name
, (char *)secbuf
, 1) != 0) {
544 /* Set up default in case SRP entry is bad */
545 esp
->es_server
.ea_state
= eapMD5Chall
;
546 /* Get t_confent based on index in srp-secrets */
547 id
= strtol((char *)secbuf
, &cp
, 10);
548 if (*cp
++ != ':' || id
< 0)
552 mytce
.modulus
.data
= (u_char
*)wkmodulus
;
553 mytce
.modulus
.len
= sizeof (wkmodulus
);
554 mytce
.generator
.data
= (u_char
*)"\002";
555 mytce
.generator
.len
= 1;
557 } else if ((tce
= gettcid(id
)) != NULL
) {
559 * Client will have to verify this modulus/
560 * generator combination, and that will take
561 * a while. Lengthen the timeout here.
563 if (esp
->es_server
.ea_timeout
> 0 &&
564 esp
->es_server
.ea_timeout
< 30)
565 esp
->es_server
.ea_timeout
= 30;
569 if ((cp2
= strchr(cp
, ':')) == NULL
)
572 tpw
.pebuf
.name
= esp
->es_server
.ea_peer
;
573 tpw
.pebuf
.password
.len
= t_fromb64((char *)tpw
.pwbuf
,
575 tpw
.pebuf
.password
.data
= tpw
.pwbuf
;
576 tpw
.pebuf
.salt
.len
= t_fromb64((char *)tpw
.saltbuf
,
578 tpw
.pebuf
.salt
.data
= tpw
.saltbuf
;
579 if ((ts
= t_serveropenraw(&tpw
.pebuf
, tce
)) == NULL
)
581 esp
->es_server
.ea_session
= (void *)ts
;
582 esp
->es_server
.ea_state
= eapSRP1
;
583 vals
[0] = esp
->es_server
.ea_id
+ 1;
585 t_serveraddexdata(ts
, vals
, 2);
586 /* Generate B; must call before t_servergetkey() */
591 esp
->es_server
.ea_state
= eapMD5Chall
;
596 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
597 if (ts
!= NULL
&& status
!= 0) {
599 esp
->es_server
.ea_session
= NULL
;
600 esp
->es_server
.ea_skey
= NULL
;
604 esp
->es_server
.ea_state
= eapMD5Chall
;
605 } else if (status
!= 0 || esp
->es_server
.ea_session
== NULL
) {
606 esp
->es_server
.ea_state
= eapBadAuth
;
608 esp
->es_server
.ea_state
= eapSRP2
;
614 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
615 if (ts
!= NULL
&& status
!= 0) {
617 esp
->es_server
.ea_session
= NULL
;
618 esp
->es_server
.ea_skey
= NULL
;
621 if (status
!= 0 || esp
->es_server
.ea_session
== NULL
) {
622 esp
->es_server
.ea_state
= eapBadAuth
;
624 esp
->es_server
.ea_state
= eapSRP3
;
631 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
632 if (ts
!= NULL
&& status
!= 0) {
634 esp
->es_server
.ea_session
= NULL
;
635 esp
->es_server
.ea_skey
= NULL
;
638 if (status
!= 0 || esp
->es_server
.ea_session
== NULL
) {
639 esp
->es_server
.ea_state
= eapBadAuth
;
641 esp
->es_server
.ea_state
= eapOpen
;
647 esp
->es_server
.ea_state
= eapBadAuth
;
649 esp
->es_server
.ea_state
= eapOpen
;
654 esp
->es_server
.ea_state
= eapBadAuth
;
657 if (esp
->es_server
.ea_state
== eapBadAuth
)
658 eap_send_failure(esp
);
662 * Format an EAP Request message and send it to the peer. Message
663 * type depends on current state. (Server operation)
666 eap_send_request(esp
)
677 u_char clear
[8], cipher
[8], dig
[SHA_DIGESTSIZE
], *optr
, *cp
;
683 /* Handle both initial auth and restart */
684 if (esp
->es_server
.ea_state
< eapIdentify
&&
685 esp
->es_server
.ea_state
!= eapInitial
) {
686 esp
->es_server
.ea_state
= eapIdentify
;
687 if (explicit_remote
) {
689 * If we already know the peer's
690 * unauthenticated name, then there's no
691 * reason to ask. Go to next state instead.
693 esp
->es_server
.ea_peer
= remote_name
;
694 esp
->es_server
.ea_peerlen
= strlen(remote_name
);
695 eap_figure_next_state(esp
, 0);
699 if (esp
->es_server
.ea_maxrequests
> 0 &&
700 esp
->es_server
.ea_requests
>= esp
->es_server
.ea_maxrequests
) {
701 if (esp
->es_server
.ea_responses
> 0)
702 error("EAP: too many Requests sent");
704 error("EAP: no response to Requests");
705 eap_send_failure(esp
);
709 outp
= outpacket_buf
;
711 MAKEHEADER(outp
, PPP_EAP
);
713 PUTCHAR(EAP_REQUEST
, outp
);
714 PUTCHAR(esp
->es_server
.ea_id
, outp
);
718 switch (esp
->es_server
.ea_state
) {
720 PUTCHAR(EAPT_IDENTITY
, outp
);
722 challen
= strlen(str
);
723 BCOPY(str
, outp
, challen
);
724 INCPTR(challen
, outp
);
728 PUTCHAR(EAPT_MD5CHAP
, outp
);
730 * pick a random challenge length between
731 * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
733 challen
= (drand48() *
734 (MAX_CHALLENGE_LENGTH
- MIN_CHALLENGE_LENGTH
)) +
735 MIN_CHALLENGE_LENGTH
;
736 PUTCHAR(challen
, outp
);
737 esp
->es_challen
= challen
;
738 ptr
= esp
->es_challenge
;
739 while (--challen
>= 0)
740 *ptr
++ = (u_char
) (drand48() * 0x100);
741 BCOPY(esp
->es_challenge
, outp
, esp
->es_challen
);
742 INCPTR(esp
->es_challen
, outp
);
743 BCOPY(esp
->es_server
.ea_name
, outp
, esp
->es_server
.ea_namelen
);
744 INCPTR(esp
->es_server
.ea_namelen
, outp
);
749 PUTCHAR(EAPT_SRP
, outp
);
750 PUTCHAR(EAPSRP_CHALLENGE
, outp
);
752 PUTCHAR(esp
->es_server
.ea_namelen
, outp
);
753 BCOPY(esp
->es_server
.ea_name
, outp
, esp
->es_server
.ea_namelen
);
754 INCPTR(esp
->es_server
.ea_namelen
, outp
);
756 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
758 PUTCHAR(ts
->s
.len
, outp
);
759 BCOPY(ts
->s
.data
, outp
, ts
->s
.len
);
760 INCPTR(ts
->s
.len
, outp
);
762 if (ts
->g
.len
== 1 && ts
->g
.data
[0] == 2) {
765 PUTCHAR(ts
->g
.len
, outp
);
766 BCOPY(ts
->g
.data
, outp
, ts
->g
.len
);
767 INCPTR(ts
->g
.len
, outp
);
770 if (ts
->n
.len
!= sizeof (wkmodulus
) ||
771 BCMP(ts
->n
.data
, wkmodulus
, sizeof (wkmodulus
)) != 0) {
772 BCOPY(ts
->n
.data
, outp
, ts
->n
.len
);
773 INCPTR(ts
->n
.len
, outp
);
778 PUTCHAR(EAPT_SRP
, outp
);
779 PUTCHAR(EAPSRP_SKEY
, outp
);
781 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
783 BCOPY(ts
->B
.data
, outp
, ts
->B
.len
);
784 INCPTR(ts
->B
.len
, outp
);
788 PUTCHAR(EAPT_SRP
, outp
);
789 PUTCHAR(EAPSRP_SVALIDATOR
, outp
);
790 PUTLONG(SRPVAL_EBIT
, outp
);
791 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
793 BCOPY(t_serverresponse(ts
), outp
, SHA_DIGESTSIZE
);
794 INCPTR(SHA_DIGESTSIZE
, outp
);
796 if (pncrypt_setkey(0)) {
797 /* Generate pseudonym */
799 cp
= (unsigned char *)esp
->es_server
.ea_peer
;
800 if ((j
= i
= esp
->es_server
.ea_peerlen
) > 7)
803 BCOPY(cp
, clear
+ 1, j
);
806 if (!DesEncrypt(clear
, cipher
)) {
807 dbglog("no DES here; not generating pseudonym");
810 BZERO(&b64
, sizeof (b64
));
811 outp
++; /* space for pseudonym length */
812 outp
+= b64enc(&b64
, cipher
, 8, outp
);
814 (void) DesEncrypt(cp
, cipher
);
815 outp
+= b64enc(&b64
, cipher
, 8, outp
);
823 *cp
++ = drand48() * 0x100;
826 (void) DesEncrypt(clear
, cipher
);
827 outp
+= b64enc(&b64
, cipher
, 8, outp
);
829 outp
+= b64flush(&b64
, outp
);
831 /* Set length and pad out to next 20 octet boundary */
836 while (i
< SHA_DIGESTSIZE
) {
837 *outp
++ = drand48() * 0x100;
842 /* Obscure the pseudonym with SHA1 hash */
844 SHA1Update(&ctxt
, &esp
->es_server
.ea_id
, 1);
845 SHA1Update(&ctxt
, esp
->es_server
.ea_skey
,
847 SHA1Update(&ctxt
, esp
->es_server
.ea_peer
,
848 esp
->es_server
.ea_peerlen
);
849 while (optr
< outp
) {
850 SHA1Final(dig
, &ctxt
);
852 while (cp
< dig
+ SHA_DIGESTSIZE
)
855 SHA1Update(&ctxt
, &esp
->es_server
.ea_id
, 1);
856 SHA1Update(&ctxt
, esp
->es_server
.ea_skey
,
858 SHA1Update(&ctxt
, optr
- SHA_DIGESTSIZE
,
865 PUTCHAR(EAPT_SRP
, outp
);
866 PUTCHAR(EAPSRP_LWRECHALLENGE
, outp
);
867 challen
= MIN_CHALLENGE_LENGTH
+
868 ((MAX_CHALLENGE_LENGTH
- MIN_CHALLENGE_LENGTH
) * drand48());
869 esp
->es_challen
= challen
;
870 ptr
= esp
->es_challenge
;
871 while (--challen
>= 0)
872 *ptr
++ = drand48() * 0x100;
873 BCOPY(esp
->es_challenge
, outp
, esp
->es_challen
);
874 INCPTR(esp
->es_challen
, outp
);
882 outlen
= (outp
- outpacket_buf
) - PPP_HDRLEN
;
883 PUTSHORT(outlen
, lenloc
);
885 output(esp
->es_unit
, outpacket_buf
, outlen
+ PPP_HDRLEN
);
887 esp
->es_server
.ea_requests
++;
889 if (esp
->es_server
.ea_timeout
> 0)
890 TIMEOUT(eap_server_timeout
, esp
, esp
->es_server
.ea_timeout
);
894 * eap_authpeer - Authenticate our peer (behave as server).
896 * Start server state and send first request. This is called only
900 eap_authpeer(unit
, localname
)
904 eap_state
*esp
= &eap_states
[unit
];
906 /* Save the name we're given. */
907 esp
->es_server
.ea_name
= localname
;
908 esp
->es_server
.ea_namelen
= strlen(localname
);
910 esp
->es_savedtime
= esp
->es_server
.ea_timeout
;
912 /* Lower layer up yet? */
913 if (esp
->es_server
.ea_state
== eapInitial
||
914 esp
->es_server
.ea_state
== eapPending
) {
915 esp
->es_server
.ea_state
= eapPending
;
919 esp
->es_server
.ea_state
= eapPending
;
921 /* ID number not updated here intentionally; hashed into M1 */
922 eap_send_request(esp
);
926 * eap_server_timeout - Retransmission timer for sending Requests
930 eap_server_timeout(arg
)
933 eap_state
*esp
= (eap_state
*) arg
;
935 if (!eap_server_active(esp
))
938 /* EAP ID number must not change on timeout. */
939 eap_send_request(esp
);
943 * When it's time to send rechallenge the peer, this timeout is
944 * called. Once the rechallenge is successful, the response handler
945 * will restart the timer. If it fails, then the link is dropped.
951 eap_state
*esp
= (eap_state
*)arg
;
953 if (esp
->es_server
.ea_state
!= eapOpen
&&
954 esp
->es_server
.ea_state
!= eapSRP4
)
957 esp
->es_server
.ea_requests
= 0;
958 esp
->es_server
.ea_state
= eapIdentify
;
959 eap_figure_next_state(esp
, 0);
960 esp
->es_server
.ea_id
++;
961 eap_send_request(esp
);
965 srp_lwrechallenge(arg
)
968 eap_state
*esp
= (eap_state
*)arg
;
970 if (esp
->es_server
.ea_state
!= eapOpen
||
971 esp
->es_server
.ea_type
!= EAPT_SRP
)
974 esp
->es_server
.ea_requests
= 0;
975 esp
->es_server
.ea_state
= eapSRP4
;
976 esp
->es_server
.ea_id
++;
977 eap_send_request(esp
);
981 * eap_lowerup - The lower layer is now up.
983 * This is called before either eap_authpeer or eap_authwithpeer. See
984 * link_established() in auth.c. All that's necessary here is to
985 * return to closed state so that those two routines will do the right
992 eap_state
*esp
= &eap_states
[unit
];
994 /* Discard any (possibly authenticated) peer name. */
995 if (esp
->es_server
.ea_peer
!= NULL
&&
996 esp
->es_server
.ea_peer
!= remote_name
)
997 free(esp
->es_server
.ea_peer
);
998 esp
->es_server
.ea_peer
= NULL
;
999 if (esp
->es_client
.ea_peer
!= NULL
)
1000 free(esp
->es_client
.ea_peer
);
1001 esp
->es_client
.ea_peer
= NULL
;
1003 esp
->es_client
.ea_state
= eapClosed
;
1004 esp
->es_server
.ea_state
= eapClosed
;
1008 * eap_lowerdown - The lower layer is now down.
1010 * Cancel all timeouts and return to initial state.
1016 eap_state
*esp
= &eap_states
[unit
];
1018 if (eap_client_active(esp
) && esp
->es_client
.ea_timeout
> 0) {
1019 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
1021 if (eap_server_active(esp
)) {
1022 if (esp
->es_server
.ea_timeout
> 0) {
1023 UNTIMEOUT(eap_server_timeout
, (void *)esp
);
1026 if ((esp
->es_server
.ea_state
== eapOpen
||
1027 esp
->es_server
.ea_state
== eapSRP4
) &&
1028 esp
->es_rechallenge
> 0) {
1029 UNTIMEOUT(eap_rechallenge
, (void *)esp
);
1031 if (esp
->es_server
.ea_state
== eapOpen
&&
1032 esp
->es_lwrechallenge
> 0) {
1033 UNTIMEOUT(srp_lwrechallenge
, (void *)esp
);
1037 esp
->es_client
.ea_state
= esp
->es_server
.ea_state
= eapInitial
;
1038 esp
->es_client
.ea_requests
= esp
->es_server
.ea_requests
= 0;
1042 * eap_protrej - Peer doesn't speak this protocol.
1044 * This shouldn't happen. If it does, it represents authentication
1051 eap_state
*esp
= &eap_states
[unit
];
1053 if (eap_client_active(esp
)) {
1054 error("EAP authentication failed due to Protocol-Reject");
1055 auth_withpeer_fail(unit
, PPP_EAP
);
1057 if (eap_server_active(esp
)) {
1058 error("EAP authentication of peer failed on Protocol-Reject");
1059 auth_peer_fail(unit
, PPP_EAP
);
1061 eap_lowerdown(unit
);
1065 * Format and send a regular EAP Response message.
1068 eap_send_response(esp
, id
, typenum
, str
, lenstr
)
1078 outp
= outpacket_buf
;
1080 MAKEHEADER(outp
, PPP_EAP
);
1082 PUTCHAR(EAP_RESPONSE
, outp
);
1084 esp
->es_client
.ea_id
= id
;
1085 msglen
= EAP_HEADERLEN
+ sizeof (u_char
) + lenstr
;
1086 PUTSHORT(msglen
, outp
);
1087 PUTCHAR(typenum
, outp
);
1089 BCOPY(str
, outp
, lenstr
);
1092 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ msglen
);
1096 * Format and send an MD5-Challenge EAP Response message.
1099 eap_chap_response(esp
, id
, hash
, name
, namelen
)
1109 outp
= outpacket_buf
;
1111 MAKEHEADER(outp
, PPP_EAP
);
1113 PUTCHAR(EAP_RESPONSE
, outp
);
1115 esp
->es_client
.ea_id
= id
;
1116 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
) + MD5_SIGNATURE_SIZE
+
1118 PUTSHORT(msglen
, outp
);
1119 PUTCHAR(EAPT_MD5CHAP
, outp
);
1120 PUTCHAR(MD5_SIGNATURE_SIZE
, outp
);
1121 BCOPY(hash
, outp
, MD5_SIGNATURE_SIZE
);
1122 INCPTR(MD5_SIGNATURE_SIZE
, outp
);
1124 BCOPY(name
, outp
, namelen
);
1127 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ msglen
);
1132 * Format and send a SRP EAP Response message.
1135 eap_srp_response(esp
, id
, subtypenum
, str
, lenstr
)
1145 outp
= outpacket_buf
;
1147 MAKEHEADER(outp
, PPP_EAP
);
1149 PUTCHAR(EAP_RESPONSE
, outp
);
1151 esp
->es_client
.ea_id
= id
;
1152 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
) + lenstr
;
1153 PUTSHORT(msglen
, outp
);
1154 PUTCHAR(EAPT_SRP
, outp
);
1155 PUTCHAR(subtypenum
, outp
);
1157 BCOPY(str
, outp
, lenstr
);
1160 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ msglen
);
1164 * Format and send a SRP EAP Client Validator Response message.
1167 eap_srpval_response(esp
, id
, flags
, str
)
1176 outp
= outpacket_buf
;
1178 MAKEHEADER(outp
, PPP_EAP
);
1180 PUTCHAR(EAP_RESPONSE
, outp
);
1182 esp
->es_client
.ea_id
= id
;
1183 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
) + sizeof (u_int32_t
) +
1185 PUTSHORT(msglen
, outp
);
1186 PUTCHAR(EAPT_SRP
, outp
);
1187 PUTCHAR(EAPSRP_CVALIDATOR
, outp
);
1188 PUTLONG(flags
, outp
);
1189 BCOPY(str
, outp
, SHA_DIGESTSIZE
);
1191 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ msglen
);
1193 #endif /* USE_SRP */
1196 eap_send_nak(esp
, id
, type
)
1204 outp
= outpacket_buf
;
1206 MAKEHEADER(outp
, PPP_EAP
);
1208 PUTCHAR(EAP_RESPONSE
, outp
);
1210 esp
->es_client
.ea_id
= id
;
1211 msglen
= EAP_HEADERLEN
+ 2 * sizeof (u_char
);
1212 PUTSHORT(msglen
, outp
);
1213 PUTCHAR(EAPT_NAK
, outp
);
1214 PUTCHAR(type
, outp
);
1216 output(esp
->es_unit
, outpacket_buf
, PPP_HDRLEN
+ msglen
);
1223 char *user
, *path
, *file
;
1226 static bool pnlogged
= 0;
1228 pw
= getpwuid(getuid());
1229 if (pw
== NULL
|| (user
= pw
->pw_dir
) == NULL
|| user
[0] == 0) {
1233 file
= _PATH_PSEUDONYM
;
1234 pl
= strlen(user
) + strlen(file
) + 2;
1238 (void) slprintf(path
, pl
, "%s/%s", user
, file
);
1240 dbglog("pseudonym file: %s", path
);
1247 open_pn_file(modebits
)
1253 if ((path
= name_of_pn_file()) == NULL
)
1255 fd
= open(path
, modebits
, S_IRUSR
| S_IWUSR
);
1267 if ((path
= name_of_pn_file()) != NULL
) {
1268 (void) unlink(path
);
1274 write_pseudonym(esp
, inp
, len
, id
)
1280 u_char
*datp
, *digp
;
1282 u_char dig
[SHA_DIGESTSIZE
];
1283 int dsize
, fd
, olen
= len
;
1286 * Do the decoding by working backwards. This eliminates the need
1287 * to save the decoded output in a separate buffer.
1291 if ((dsize
= len
% SHA_DIGESTSIZE
) == 0)
1292 dsize
= SHA_DIGESTSIZE
;
1296 SHA1Update(&ctxt
, &val
, 1);
1297 SHA1Update(&ctxt
, esp
->es_client
.ea_skey
, SESSION_KEY_LEN
);
1299 SHA1Update(&ctxt
, datp
, SHA_DIGESTSIZE
);
1301 SHA1Update(&ctxt
, esp
->es_client
.ea_name
,
1302 esp
->es_client
.ea_namelen
);
1304 SHA1Final(dig
, &ctxt
);
1305 for (digp
= dig
; digp
< dig
+ SHA_DIGESTSIZE
; digp
++)
1309 /* Now check that the result is sane */
1310 if (olen
<= 0 || *inp
+ 1 > olen
) {
1311 dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen
, inp
);
1316 fd
= open_pn_file(O_WRONLY
| O_CREAT
| O_TRUNC
);
1318 dbglog("EAP: error saving pseudonym: %m");
1321 len
= write(fd
, inp
+ 1, *inp
);
1322 if (close(fd
) != -1 && len
== *inp
) {
1323 dbglog("EAP: saved pseudonym");
1324 esp
->es_usedpseudo
= 0;
1326 dbglog("EAP: failed to save pseudonym");
1330 #endif /* USE_SRP */
1333 * eap_request - Receive EAP Request message (client mode).
1336 eap_request(esp
, inp
, id
, len
)
1345 char secret
[MAXWORDLEN
];
1346 char rhostname
[256];
1348 u_char hash
[MD5_SIGNATURE_SIZE
];
1350 struct t_client
*tc
;
1351 struct t_num sval
, gval
, Nval
, *Ap
, Bval
;
1354 u_char dig
[SHA_DIGESTSIZE
];
1356 #endif /* USE_SRP */
1359 * Note: we update es_client.ea_id *only if* a Response
1360 * message is being generated. Otherwise, we leave it the
1361 * same for duplicate detection purposes.
1364 esp
->es_client
.ea_requests
++;
1365 if (esp
->es_client
.ea_maxrequests
!= 0 &&
1366 esp
->es_client
.ea_requests
> esp
->es_client
.ea_maxrequests
) {
1367 info("EAP: received too many Request messages");
1368 if (esp
->es_client
.ea_timeout
> 0) {
1369 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
1371 auth_withpeer_fail(esp
->es_unit
, PPP_EAP
);
1376 error("EAP: empty Request message discarded");
1380 GETCHAR(typenum
, inp
);
1386 info("EAP: Identity prompt \"%.*q\"", len
, inp
);
1388 if (esp
->es_usepseudo
&&
1389 (esp
->es_usedpseudo
== 0 ||
1390 (esp
->es_usedpseudo
== 1 &&
1391 id
== esp
->es_client
.ea_id
))) {
1392 esp
->es_usedpseudo
= 1;
1393 /* Try to get a pseudonym */
1394 if ((fd
= open_pn_file(O_RDONLY
)) >= 0) {
1395 strcpy(rhostname
, SRP_PSEUDO_ID
);
1396 len
= read(fd
, rhostname
+ SRP_PSEUDO_LEN
,
1397 sizeof (rhostname
) - SRP_PSEUDO_LEN
);
1398 /* XXX NAI unsupported */
1400 eap_send_response(esp
, id
, typenum
,
1401 rhostname
, len
+ SRP_PSEUDO_LEN
);
1408 /* Stop using pseudonym now. */
1409 if (esp
->es_usepseudo
&& esp
->es_usedpseudo
!= 2) {
1411 esp
->es_usedpseudo
= 2;
1413 #endif /* USE_SRP */
1414 eap_send_response(esp
, id
, typenum
, esp
->es_client
.ea_name
,
1415 esp
->es_client
.ea_namelen
);
1418 case EAPT_NOTIFICATION
:
1420 info("EAP: Notification \"%.*q\"", len
, inp
);
1421 eap_send_response(esp
, id
, typenum
, NULL
, 0);
1426 * Avoid the temptation to send Response Nak in reply
1427 * to Request Nak here. It can only lead to trouble.
1429 warn("EAP: unexpected Nak in Request; ignored");
1430 /* Return because we're waiting for something real. */
1435 error("EAP: received MD5-Challenge with no data");
1436 /* Bogus request; wait for something real. */
1439 GETCHAR(vallen
, inp
);
1441 if (vallen
< 8 || vallen
> len
) {
1442 error("EAP: MD5-Challenge with bad length %d (8..%d)",
1444 /* Try something better. */
1445 eap_send_nak(esp
, id
, EAPT_SRP
);
1449 /* Not so likely to happen. */
1450 if (vallen
>= len
+ sizeof (rhostname
)) {
1451 dbglog("EAP: trimming really long peer name down");
1452 BCOPY(inp
+ vallen
, rhostname
, sizeof (rhostname
) - 1);
1453 rhostname
[sizeof (rhostname
) - 1] = '\0';
1455 BCOPY(inp
+ vallen
, rhostname
, len
- vallen
);
1456 rhostname
[len
- vallen
] = '\0';
1459 /* In case the remote doesn't give us his name. */
1460 if (explicit_remote
||
1461 (remote_name
[0] != '\0' && vallen
== len
))
1462 strlcpy(rhostname
, remote_name
, sizeof (rhostname
));
1465 * Get the secret for authenticating ourselves with
1466 * the specified host.
1468 if (!get_secret(esp
->es_unit
, esp
->es_client
.ea_name
,
1469 rhostname
, secret
, &secret_len
, 0)) {
1470 dbglog("EAP: no MD5 secret for auth to %q", rhostname
);
1471 eap_send_nak(esp
, id
, EAPT_SRP
);
1474 MD5Init(&mdContext
);
1476 MD5Update(&mdContext
, &typenum
, 1);
1477 MD5Update(&mdContext
, secret
, secret_len
);
1478 BZERO(secret
, sizeof (secret
));
1479 MD5Update(&mdContext
, inp
, vallen
);
1480 MD5Final(hash
, &mdContext
);
1481 eap_chap_response(esp
, id
, hash
, esp
->es_client
.ea_name
,
1482 esp
->es_client
.ea_namelen
);
1488 error("EAP: received empty SRP Request");
1489 /* Bogus request; wait for something real. */
1494 GETCHAR(vallen
, inp
);
1497 case EAPSRP_CHALLENGE
:
1499 if (esp
->es_client
.ea_session
!= NULL
) {
1500 tc
= (struct t_client
*)esp
->es_client
.
1503 * If this is a new challenge, then start
1504 * over with a new client session context.
1505 * Otherwise, just resend last response.
1507 if (id
!= esp
->es_client
.ea_id
) {
1509 esp
->es_client
.ea_session
= NULL
;
1513 /* No session key just yet */
1514 esp
->es_client
.ea_skey
= NULL
;
1516 GETCHAR(vallen
, inp
);
1518 if (vallen
>= len
) {
1519 error("EAP: badly-formed SRP Challenge"
1521 /* Ignore badly-formed messages */
1524 BCOPY(inp
, rhostname
, vallen
);
1525 rhostname
[vallen
] = '\0';
1526 INCPTR(vallen
, inp
);
1530 * In case the remote doesn't give us his name,
1531 * use configured name.
1533 if (explicit_remote
||
1534 (remote_name
[0] != '\0' && vallen
== 0)) {
1535 strlcpy(rhostname
, remote_name
,
1536 sizeof (rhostname
));
1539 if (esp
->es_client
.ea_peer
!= NULL
)
1540 free(esp
->es_client
.ea_peer
);
1541 esp
->es_client
.ea_peer
= strdup(rhostname
);
1542 esp
->es_client
.ea_peerlen
= strlen(rhostname
);
1544 GETCHAR(vallen
, inp
);
1546 if (vallen
>= len
) {
1547 error("EAP: badly-formed SRP Challenge"
1549 /* Ignore badly-formed messages */
1554 INCPTR(vallen
, inp
);
1557 GETCHAR(vallen
, inp
);
1560 error("EAP: badly-formed SRP Challenge"
1562 /* Ignore badly-formed messages */
1565 /* If no generator present, then use value 2 */
1567 gval
.data
= (u_char
*)"\002";
1573 INCPTR(vallen
, inp
);
1577 * If no modulus present, then use well-known
1581 Nval
.data
= (u_char
*)wkmodulus
;
1582 Nval
.len
= sizeof (wkmodulus
);
1587 tc
= t_clientopen(esp
->es_client
.ea_name
,
1588 &Nval
, &gval
, &sval
);
1590 eap_send_nak(esp
, id
, EAPT_MD5CHAP
);
1593 esp
->es_client
.ea_session
= (void *)tc
;
1595 /* Add Challenge ID & type to verifier */
1598 t_clientaddexdata(tc
, vals
, 2);
1600 Ap
= t_clientgenexp(tc
);
1601 eap_srp_response(esp
, id
, EAPSRP_CKEY
, Ap
->data
,
1606 tc
= (struct t_client
*)esp
->es_client
.ea_session
;
1608 warn("EAP: peer sent Subtype 2 without 1");
1609 eap_send_nak(esp
, id
, EAPT_MD5CHAP
);
1612 if (esp
->es_client
.ea_skey
!= NULL
) {
1614 * ID number should not change here. Warn
1615 * if it does (but otherwise ignore).
1617 if (id
!= esp
->es_client
.ea_id
) {
1618 warn("EAP: ID changed from %d to %d "
1619 "in SRP Subtype 2 rexmit",
1620 esp
->es_client
.ea_id
, id
);
1623 if (get_srp_secret(esp
->es_unit
,
1624 esp
->es_client
.ea_name
,
1625 esp
->es_client
.ea_peer
, secret
, 0) == 0) {
1627 * Can't work with this peer because
1628 * the secret is missing. Just give
1631 eap_send_nak(esp
, id
, EAPT_MD5CHAP
);
1636 t_clientpasswd(tc
, secret
);
1637 BZERO(secret
, sizeof (secret
));
1638 esp
->es_client
.ea_skey
=
1639 t_clientgetkey(tc
, &Bval
);
1640 if (esp
->es_client
.ea_skey
== NULL
) {
1641 /* Server is rogue; stop now */
1642 error("EAP: SRP server is rogue");
1643 goto client_failure
;
1646 eap_srpval_response(esp
, id
, SRPVAL_EBIT
,
1647 t_clientresponse(tc
));
1650 case EAPSRP_SVALIDATOR
:
1651 tc
= (struct t_client
*)esp
->es_client
.ea_session
;
1652 if (tc
== NULL
|| esp
->es_client
.ea_skey
== NULL
) {
1653 warn("EAP: peer sent Subtype 3 without 1/2");
1654 eap_send_nak(esp
, id
, EAPT_MD5CHAP
);
1658 * If we're already open, then this ought to be a
1659 * duplicate. Otherwise, check that the server is
1660 * who we think it is.
1662 if (esp
->es_client
.ea_state
== eapOpen
) {
1663 if (id
!= esp
->es_client
.ea_id
) {
1664 warn("EAP: ID changed from %d to %d "
1665 "in SRP Subtype 3 rexmit",
1666 esp
->es_client
.ea_id
, id
);
1669 len
-= sizeof (u_int32_t
) + SHA_DIGESTSIZE
;
1670 if (len
< 0 || t_clientverify(tc
, inp
+
1671 sizeof (u_int32_t
)) != 0) {
1672 error("EAP: SRP server verification "
1674 goto client_failure
;
1676 GETLONG(esp
->es_client
.ea_keyflags
, inp
);
1677 /* Save pseudonym if user wants it. */
1678 if (len
> 0 && esp
->es_usepseudo
) {
1679 INCPTR(SHA_DIGESTSIZE
, inp
);
1680 write_pseudonym(esp
, inp
, len
, id
);
1684 * We've verified our peer. We're now mostly done,
1685 * except for waiting on the regular EAP Success
1688 eap_srp_response(esp
, id
, EAPSRP_ACK
, NULL
, 0);
1691 case EAPSRP_LWRECHALLENGE
:
1693 warn("EAP: malformed Lightweight rechallenge");
1698 SHA1Update(&ctxt
, vals
, 1);
1699 SHA1Update(&ctxt
, esp
->es_client
.ea_skey
,
1701 SHA1Update(&ctxt
, inp
, len
);
1702 SHA1Update(&ctxt
, esp
->es_client
.ea_name
,
1703 esp
->es_client
.ea_namelen
);
1704 SHA1Final(dig
, &ctxt
);
1705 eap_srp_response(esp
, id
, EAPSRP_LWRECHALLENGE
, dig
,
1710 error("EAP: unknown SRP Subtype %d", vallen
);
1711 eap_send_nak(esp
, id
, EAPT_MD5CHAP
);
1715 #endif /* USE_SRP */
1718 info("EAP: unknown authentication type %d; Naking", typenum
);
1719 eap_send_nak(esp
, id
, EAPT_SRP
);
1723 if (esp
->es_client
.ea_timeout
> 0) {
1724 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
1725 TIMEOUT(eap_client_timeout
, (void *)esp
,
1726 esp
->es_client
.ea_timeout
);
1732 esp
->es_client
.ea_state
= eapBadAuth
;
1733 if (esp
->es_client
.ea_timeout
> 0) {
1734 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
1736 esp
->es_client
.ea_session
= NULL
;
1738 auth_withpeer_fail(esp
->es_unit
, PPP_EAP
);
1739 #endif /* USE_SRP */
1743 * eap_response - Receive EAP Response message (server mode).
1746 eap_response(esp
, inp
, id
, len
)
1755 char secret
[MAXSECRETLEN
];
1756 char rhostname
[256];
1758 u_char hash
[MD5_SIGNATURE_SIZE
];
1760 struct t_server
*ts
;
1763 u_char dig
[SHA_DIGESTSIZE
];
1764 #endif /* USE_SRP */
1766 if (esp
->es_server
.ea_id
!= id
) {
1767 dbglog("EAP: discarding Response %d; expected ID %d", id
,
1768 esp
->es_server
.ea_id
);
1772 esp
->es_server
.ea_responses
++;
1775 error("EAP: empty Response message discarded");
1779 GETCHAR(typenum
, inp
);
1784 if (esp
->es_server
.ea_state
!= eapIdentify
) {
1785 dbglog("EAP discarding unwanted Identify \"%.q\"", len
,
1789 info("EAP: unauthenticated peer name \"%.*q\"", len
, inp
);
1790 if (esp
->es_server
.ea_peer
!= NULL
&&
1791 esp
->es_server
.ea_peer
!= remote_name
)
1792 free(esp
->es_server
.ea_peer
);
1793 esp
->es_server
.ea_peer
= malloc(len
+ 1);
1794 if (esp
->es_server
.ea_peer
== NULL
) {
1795 esp
->es_server
.ea_peerlen
= 0;
1796 eap_figure_next_state(esp
, 1);
1799 BCOPY(inp
, esp
->es_server
.ea_peer
, len
);
1800 esp
->es_server
.ea_peer
[len
] = '\0';
1801 esp
->es_server
.ea_peerlen
= len
;
1802 eap_figure_next_state(esp
, 0);
1805 case EAPT_NOTIFICATION
:
1806 dbglog("EAP unexpected Notification; response discarded");
1811 info("EAP: Nak Response with no suggested protocol");
1812 eap_figure_next_state(esp
, 1);
1816 GETCHAR(vallen
, inp
);
1819 if (!explicit_remote
&& esp
->es_server
.ea_state
== eapIdentify
){
1820 /* Peer cannot Nak Identify Request */
1821 eap_figure_next_state(esp
, 1);
1827 /* Run through SRP validator selection again. */
1828 esp
->es_server
.ea_state
= eapIdentify
;
1829 eap_figure_next_state(esp
, 0);
1833 esp
->es_server
.ea_state
= eapMD5Chall
;
1837 dbglog("EAP: peer requesting unknown Type %d", vallen
);
1838 switch (esp
->es_server
.ea_state
) {
1842 esp
->es_server
.ea_state
= eapMD5Chall
;
1846 esp
->es_server
.ea_state
= eapIdentify
;
1847 eap_figure_next_state(esp
, 0);
1857 if (esp
->es_server
.ea_state
!= eapMD5Chall
) {
1858 error("EAP: unexpected MD5-Response");
1859 eap_figure_next_state(esp
, 1);
1863 error("EAP: received MD5-Response with no data");
1864 eap_figure_next_state(esp
, 1);
1867 GETCHAR(vallen
, inp
);
1869 if (vallen
!= 16 || vallen
> len
) {
1870 error("EAP: MD5-Response with bad length %d", vallen
);
1871 eap_figure_next_state(esp
, 1);
1875 /* Not so likely to happen. */
1876 if (vallen
>= len
+ sizeof (rhostname
)) {
1877 dbglog("EAP: trimming really long peer name down");
1878 BCOPY(inp
+ vallen
, rhostname
, sizeof (rhostname
) - 1);
1879 rhostname
[sizeof (rhostname
) - 1] = '\0';
1881 BCOPY(inp
+ vallen
, rhostname
, len
- vallen
);
1882 rhostname
[len
- vallen
] = '\0';
1885 /* In case the remote doesn't give us his name. */
1886 if (explicit_remote
||
1887 (remote_name
[0] != '\0' && vallen
== len
))
1888 strlcpy(rhostname
, remote_name
, sizeof (rhostname
));
1891 * Get the secret for authenticating the specified
1894 if (!get_secret(esp
->es_unit
, rhostname
,
1895 esp
->es_server
.ea_name
, secret
, &secret_len
, 1)) {
1896 dbglog("EAP: no MD5 secret for auth of %q", rhostname
);
1897 eap_send_failure(esp
);
1900 MD5Init(&mdContext
);
1901 MD5Update(&mdContext
, &esp
->es_server
.ea_id
, 1);
1902 MD5Update(&mdContext
, secret
, secret_len
);
1903 BZERO(secret
, sizeof (secret
));
1904 MD5Update(&mdContext
, esp
->es_challenge
, esp
->es_challen
);
1905 MD5Final(hash
, &mdContext
);
1906 if (BCMP(hash
, inp
, MD5_SIGNATURE_SIZE
) != 0) {
1907 eap_send_failure(esp
);
1910 esp
->es_server
.ea_type
= EAPT_MD5CHAP
;
1911 eap_send_success(esp
);
1912 eap_figure_next_state(esp
, 0);
1913 if (esp
->es_rechallenge
!= 0)
1914 TIMEOUT(eap_rechallenge
, esp
, esp
->es_rechallenge
);
1920 error("EAP: empty SRP Response");
1921 eap_figure_next_state(esp
, 1);
1924 GETCHAR(typenum
, inp
);
1928 if (esp
->es_server
.ea_state
!= eapSRP1
) {
1929 error("EAP: unexpected SRP Subtype 1 Response");
1930 eap_figure_next_state(esp
, 1);
1935 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
1937 esp
->es_server
.ea_skey
= t_servergetkey(ts
, &A
);
1938 if (esp
->es_server
.ea_skey
== NULL
) {
1939 /* Client's A value is bogus; terminate now */
1940 error("EAP: bogus A value from client");
1941 eap_send_failure(esp
);
1943 eap_figure_next_state(esp
, 0);
1947 case EAPSRP_CVALIDATOR
:
1948 if (esp
->es_server
.ea_state
!= eapSRP2
) {
1949 error("EAP: unexpected SRP Subtype 2 Response");
1950 eap_figure_next_state(esp
, 1);
1953 if (len
< sizeof (u_int32_t
) + SHA_DIGESTSIZE
) {
1954 error("EAP: M1 length %d < %d", len
,
1955 sizeof (u_int32_t
) + SHA_DIGESTSIZE
);
1956 eap_figure_next_state(esp
, 1);
1959 GETLONG(esp
->es_server
.ea_keyflags
, inp
);
1960 ts
= (struct t_server
*)esp
->es_server
.ea_session
;
1962 if (t_serververify(ts
, inp
)) {
1963 info("EAP: unable to validate client identity");
1964 eap_send_failure(esp
);
1967 eap_figure_next_state(esp
, 0);
1971 if (esp
->es_server
.ea_state
!= eapSRP3
) {
1972 error("EAP: unexpected SRP Subtype 3 Response");
1973 eap_send_failure(esp
);
1976 esp
->es_server
.ea_type
= EAPT_SRP
;
1977 eap_send_success(esp
);
1978 eap_figure_next_state(esp
, 0);
1979 if (esp
->es_rechallenge
!= 0)
1980 TIMEOUT(eap_rechallenge
, esp
,
1981 esp
->es_rechallenge
);
1982 if (esp
->es_lwrechallenge
!= 0)
1983 TIMEOUT(srp_lwrechallenge
, esp
,
1984 esp
->es_lwrechallenge
);
1987 case EAPSRP_LWRECHALLENGE
:
1988 if (esp
->es_server
.ea_state
!= eapSRP4
) {
1989 info("EAP: unexpected SRP Subtype 4 Response");
1992 if (len
!= SHA_DIGESTSIZE
) {
1993 error("EAP: bad Lightweight rechallenge "
1999 SHA1Update(&ctxt
, &vallen
, 1);
2000 SHA1Update(&ctxt
, esp
->es_server
.ea_skey
,
2002 SHA1Update(&ctxt
, esp
->es_challenge
, esp
->es_challen
);
2003 SHA1Update(&ctxt
, esp
->es_server
.ea_peer
,
2004 esp
->es_server
.ea_peerlen
);
2005 SHA1Final(dig
, &ctxt
);
2006 if (BCMP(dig
, inp
, SHA_DIGESTSIZE
) != 0) {
2007 error("EAP: failed Lightweight rechallenge");
2008 eap_send_failure(esp
);
2011 esp
->es_server
.ea_state
= eapOpen
;
2012 if (esp
->es_lwrechallenge
!= 0)
2013 TIMEOUT(srp_lwrechallenge
, esp
,
2014 esp
->es_lwrechallenge
);
2018 #endif /* USE_SRP */
2021 /* This can't happen. */
2022 error("EAP: unknown Response type %d; ignored", typenum
);
2026 if (esp
->es_server
.ea_timeout
> 0) {
2027 UNTIMEOUT(eap_server_timeout
, (void *)esp
);
2030 if (esp
->es_server
.ea_state
!= eapBadAuth
&&
2031 esp
->es_server
.ea_state
!= eapOpen
) {
2032 esp
->es_server
.ea_id
++;
2033 eap_send_request(esp
);
2038 * eap_success - Receive EAP Success message (client mode).
2041 eap_success(esp
, inp
, id
, len
)
2047 if (esp
->es_client
.ea_state
!= eapOpen
&& !eap_client_active(esp
)) {
2048 dbglog("EAP unexpected success message in state %s (%d)",
2049 eap_state_name(esp
->es_client
.ea_state
),
2050 esp
->es_client
.ea_state
);
2054 if (esp
->es_client
.ea_timeout
> 0) {
2055 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
2059 /* This is odd. The spec doesn't allow for this. */
2063 esp
->es_client
.ea_state
= eapOpen
;
2064 auth_withpeer_success(esp
->es_unit
, PPP_EAP
, 0);
2068 * eap_failure - Receive EAP Failure message (client mode).
2071 eap_failure(esp
, inp
, id
, len
)
2077 if (!eap_client_active(esp
)) {
2078 dbglog("EAP unexpected failure message in state %s (%d)",
2079 eap_state_name(esp
->es_client
.ea_state
),
2080 esp
->es_client
.ea_state
);
2083 if (esp
->es_client
.ea_timeout
> 0) {
2084 UNTIMEOUT(eap_client_timeout
, (void *)esp
);
2088 /* This is odd. The spec doesn't allow for this. */
2092 esp
->es_client
.ea_state
= eapBadAuth
;
2094 error("EAP: peer reports authentication failure");
2095 auth_withpeer_fail(esp
->es_unit
, PPP_EAP
);
2099 * eap_input - Handle received EAP message.
2102 eap_input(unit
, inp
, inlen
)
2107 eap_state
*esp
= &eap_states
[unit
];
2112 * Parse header (code, id and length). If packet too short,
2115 if (inlen
< EAP_HEADERLEN
) {
2116 error("EAP: packet too short: %d < %d", inlen
, EAP_HEADERLEN
);
2122 if (len
< EAP_HEADERLEN
|| len
> inlen
) {
2123 error("EAP: packet has illegal length field %d (%d..%d)", len
,
2124 EAP_HEADERLEN
, inlen
);
2127 len
-= EAP_HEADERLEN
;
2129 /* Dispatch based on message code */
2132 eap_request(esp
, inp
, id
, len
);
2136 eap_response(esp
, inp
, id
, len
);
2140 eap_success(esp
, inp
, id
, len
);
2144 eap_failure(esp
, inp
, id
, len
);
2147 default: /* XXX Need code reject */
2148 /* Note: it's not legal to send EAP Nak here. */
2149 warn("EAP: unknown code %d received", code
);
2155 * eap_printpkt - print the contents of an EAP packet.
2157 static char *eap_codenames
[] = {
2158 "Request", "Response", "Success", "Failure"
2161 static char *eap_typenames
[] = {
2162 "Identity", "Notification", "Nak", "MD5-Challenge",
2163 "OTP", "Generic-Token", NULL
, NULL
,
2164 "RSA", "DSS", "KEA", "KEA-Validate",
2165 "TLS", "Defender", "Windows 2000", "Arcot",
2166 "Cisco", "Nokia", "SRP"
2170 eap_printpkt(inp
, inlen
, printer
, arg
)
2173 void (*printer
) __P((void *, char *, ...));
2176 int code
, id
, len
, rtype
, vallen
;
2180 if (inlen
< EAP_HEADERLEN
)
2186 if (len
< EAP_HEADERLEN
|| len
> inlen
)
2189 if (code
>= 1 && code
<= sizeof(eap_codenames
) / sizeof(char *))
2190 printer(arg
, " %s", eap_codenames
[code
-1]);
2192 printer(arg
, " code=0x%x", code
);
2193 printer(arg
, " id=0x%x", id
);
2194 len
-= EAP_HEADERLEN
;
2198 printer(arg
, " <missing type>");
2201 GETCHAR(rtype
, inp
);
2204 rtype
<= sizeof (eap_typenames
) / sizeof (char *))
2205 printer(arg
, " %s", eap_typenames
[rtype
-1]);
2207 printer(arg
, " type=0x%x", rtype
);
2210 case EAPT_NOTIFICATION
:
2212 printer(arg
, " <Message ");
2213 print_string((char *)inp
, len
, printer
, arg
);
2218 printer(arg
, " <No message>");
2225 GETCHAR(vallen
, inp
);
2229 printer(arg
, " <Value%.*B>", vallen
, inp
);
2230 INCPTR(vallen
, inp
);
2233 printer(arg
, " <Name ");
2234 print_string((char *)inp
, len
, printer
, arg
);
2239 printer(arg
, " <No name>");
2246 GETCHAR(vallen
, inp
);
2248 printer(arg
, "-%d", vallen
);
2250 case EAPSRP_CHALLENGE
:
2251 GETCHAR(vallen
, inp
);
2256 printer(arg
, " <Name ");
2257 print_string((char *)inp
, vallen
, printer
,
2261 printer(arg
, " <No name>");
2263 INCPTR(vallen
, inp
);
2265 GETCHAR(vallen
, inp
);
2269 printer(arg
, " <s%.*B>", vallen
, inp
);
2270 INCPTR(vallen
, inp
);
2272 GETCHAR(vallen
, inp
);
2277 printer(arg
, " <Default g=2>");
2279 printer(arg
, " <g%.*B>", vallen
, inp
);
2281 INCPTR(vallen
, inp
);
2284 printer(arg
, " <Default N>");
2286 printer(arg
, " <N%.*B>", len
, inp
);
2293 printer(arg
, " <B%.*B>", len
, inp
);
2298 case EAPSRP_SVALIDATOR
:
2299 if (len
< sizeof (u_int32_t
))
2302 len
-= sizeof (u_int32_t
);
2303 if (uval
& SRPVAL_EBIT
) {
2305 uval
&= ~SRPVAL_EBIT
;
2308 printer(arg
, " f<%X>", uval
);
2310 if ((vallen
= len
) > SHA_DIGESTSIZE
)
2311 vallen
= SHA_DIGESTSIZE
;
2312 printer(arg
, " <M2%.*B%s>", len
, inp
,
2313 len
< SHA_DIGESTSIZE
? "?" : "");
2314 INCPTR(vallen
, inp
);
2317 printer(arg
, " <PN%.*B>", len
, inp
);
2323 case EAPSRP_LWRECHALLENGE
:
2324 printer(arg
, " <Challenge%.*B>", len
, inp
);
2336 GETCHAR(rtype
, inp
);
2339 rtype
<= sizeof (eap_typenames
) / sizeof (char *))
2340 printer(arg
, " %s", eap_typenames
[rtype
-1]);
2342 printer(arg
, " type=0x%x", rtype
);
2346 printer(arg
, " <Name ");
2347 print_string((char *)inp
, len
, printer
, arg
);
2356 printer(arg
, " <missing hint>");
2359 GETCHAR(rtype
, inp
);
2361 printer(arg
, " <Suggested-type %02X", rtype
);
2363 rtype
< sizeof (eap_typenames
) / sizeof (char *))
2364 printer(arg
, " (%s)", eap_typenames
[rtype
-1]);
2370 printer(arg
, " <missing length>");
2373 GETCHAR(vallen
, inp
);
2377 printer(arg
, " <Value%.*B>", vallen
, inp
);
2378 INCPTR(vallen
, inp
);
2381 printer(arg
, " <Name ");
2382 print_string((char *)inp
, len
, printer
, arg
);
2387 printer(arg
, " <No name>");
2394 GETCHAR(vallen
, inp
);
2396 printer(arg
, "-%d", vallen
);
2399 printer(arg
, " <A%.*B>", len
, inp
);
2404 case EAPSRP_CVALIDATOR
:
2405 if (len
< sizeof (u_int32_t
))
2408 len
-= sizeof (u_int32_t
);
2409 if (uval
& SRPVAL_EBIT
) {
2411 uval
&= ~SRPVAL_EBIT
;
2414 printer(arg
, " f<%X>", uval
);
2416 printer(arg
, " <M1%.*B%s>", len
, inp
,
2417 len
== SHA_DIGESTSIZE
? "" : "?");
2425 case EAPSRP_LWRECHALLENGE
:
2426 printer(arg
, " <Response%.*B%s>", len
, inp
,
2427 len
== SHA_DIGESTSIZE
? "" : "?");
2428 if ((vallen
= len
) > SHA_DIGESTSIZE
)
2429 vallen
= SHA_DIGESTSIZE
;
2430 INCPTR(vallen
, inp
);
2438 case EAP_SUCCESS
: /* No payload expected for these! */
2443 printer(arg
, " <truncated>");
2448 printer(arg
, "%8B...", inp
);
2450 printer(arg
, "%.*B", len
, inp
);
2453 return (inp
- pstart
);