eap.c revision 1.1.1.5 1 1.1 christos /*
2 1.1 christos * eap.c - Extensible Authentication Protocol for PPP (RFC 2284)
3 1.1 christos *
4 1.1 christos * Copyright (c) 2001 by Sun Microsystems, Inc.
5 1.1 christos * All rights reserved.
6 1.1 christos *
7 1.1 christos * Non-exclusive rights to redistribute, modify, translate, and use
8 1.1 christos * this software in source and binary forms, in whole or in part, is
9 1.1 christos * hereby granted, provided that the above copyright notice is
10 1.1 christos * duplicated in any source form, and that neither the name of the
11 1.1 christos * copyright holder nor the author is used to endorse or promote
12 1.1 christos * products derived from this software.
13 1.1 christos *
14 1.1 christos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 1.1 christos * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 1.1 christos * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 1.1 christos *
18 1.1 christos * Original version by James Carlson
19 1.1 christos *
20 1.1 christos * This implementation of EAP supports MD5-Challenge and SRP-SHA1
21 1.1 christos * authentication styles. Note that support of MD5-Challenge is a
22 1.1 christos * requirement of RFC 2284, and that it's essentially just a
23 1.1 christos * reimplementation of regular RFC 1994 CHAP using EAP messages.
24 1.1 christos *
25 1.1 christos * As an authenticator ("server"), there are multiple phases for each
26 1.1 christos * style. In the first phase of each style, the unauthenticated peer
27 1.1 christos * name is queried using the EAP Identity request type. If the
28 1.1 christos * "remotename" option is used, then this phase is skipped, because
29 1.1 christos * the peer's name is presumed to be known.
30 1.1 christos *
31 1.1 christos * For MD5-Challenge, there are two phases, and the second phase
32 1.1 christos * consists of sending the challenge itself and handling the
33 1.1 christos * associated response.
34 1.1 christos *
35 1.1 christos * For SRP-SHA1, there are four phases. The second sends 's', 'N',
36 1.1 christos * and 'g'. The reply contains 'A'. The third sends 'B', and the
37 1.1 christos * reply contains 'M1'. The forth sends the 'M2' value.
38 1.1 christos *
39 1.1 christos * As an authenticatee ("client"), there's just a single phase --
40 1.1 christos * responding to the queries generated by the peer. EAP is an
41 1.1 christos * authenticator-driven protocol.
42 1.1 christos *
43 1.1 christos * Based on draft-ietf-pppext-eap-srp-03.txt.
44 1.1 christos */
45 1.1 christos
46 1.1 christos /*
47 1.1.1.4 christos * Modification by Beniamino Galvani, Mar 2005
48 1.1.1.4 christos * Implemented EAP-TLS authentication
49 1.1 christos */
50 1.1 christos
51 1.1.1.5 christos #ifdef HAVE_CONFIG_H
52 1.1.1.5 christos #include "config.h"
53 1.1.1.5 christos #endif
54 1.1.1.5 christos
55 1.1 christos #include <stdio.h>
56 1.1 christos #include <stdlib.h>
57 1.1 christos #include <string.h>
58 1.1 christos #include <unistd.h>
59 1.1 christos #include <pwd.h>
60 1.1 christos #include <sys/types.h>
61 1.1 christos #include <sys/stat.h>
62 1.1 christos #include <fcntl.h>
63 1.1 christos #include <assert.h>
64 1.1 christos #include <errno.h>
65 1.1 christos
66 1.1.1.5 christos #include "pppd-private.h"
67 1.1.1.5 christos #include "options.h"
68 1.1 christos #include "pathnames.h"
69 1.1.1.5 christos #include "crypto.h"
70 1.1.1.5 christos #include "crypto_ms.h"
71 1.1 christos #include "eap.h"
72 1.1.1.5 christos #ifdef PPP_WITH_PEAP
73 1.1.1.5 christos #include "peap.h"
74 1.1.1.5 christos #endif /* PPP_WITH_PEAP */
75 1.1.1.5 christos
76 1.1.1.5 christos #ifdef PPP_WITH_SRP
77 1.1.1.5 christos #ifdef HAVE_TIME_H
78 1.1.1.5 christos #include <time.h>
79 1.1.1.4 christos #endif
80 1.1 christos #include <t_pwd.h>
81 1.1 christos #include <t_server.h>
82 1.1 christos #include <t_client.h>
83 1.1.1.5 christos #endif /* PPP_WITH_SRP */
84 1.1 christos
85 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
86 1.1.1.4 christos #include "eap-tls.h"
87 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
88 1.1.1.5 christos
89 1.1.1.5 christos #ifdef PPP_WITH_CHAPMS
90 1.1.1.5 christos #include "chap.h"
91 1.1.1.4 christos #include "chap_ms.h"
92 1.1.1.5 christos
93 1.1.1.5 christos extern int chapms_strip_domain;
94 1.1.1.5 christos #endif /* PPP_WITH_CHAPMS */
95 1.1 christos
96 1.1 christos eap_state eap_states[NUM_PPP]; /* EAP state; one for each unit */
97 1.1.1.5 christos #ifdef PPP_WITH_SRP
98 1.1 christos static char *pn_secret = NULL; /* Pseudonym generating secret */
99 1.1 christos #endif
100 1.1 christos
101 1.1 christos /*
102 1.1 christos * Command-line options.
103 1.1 christos */
104 1.1.1.5 christos static struct option eap_option_list[] = {
105 1.1 christos { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,
106 1.1 christos "Set retransmit timeout for EAP Requests (server)" },
107 1.1 christos { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,
108 1.1 christos "Set max number of EAP Requests sent (server)" },
109 1.1 christos { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,
110 1.1 christos "Set time limit for peer EAP authentication" },
111 1.1 christos { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,
112 1.1 christos "Set max number of EAP Requests allows (client)" },
113 1.1 christos { "eap-interval", o_int, &eap_states[0].es_rechallenge,
114 1.1 christos "Set interval for EAP rechallenge" },
115 1.1.1.5 christos #ifdef PPP_WITH_SRP
116 1.1 christos { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,
117 1.1 christos "Set interval for SRP lightweight rechallenge" },
118 1.1 christos { "srp-pn-secret", o_string, &pn_secret,
119 1.1 christos "Long term pseudonym generation secret" },
120 1.1 christos { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,
121 1.1 christos "Use pseudonym if offered one by server", 1 },
122 1.1 christos #endif
123 1.1 christos { NULL }
124 1.1 christos };
125 1.1 christos
126 1.1 christos /*
127 1.1 christos * Protocol entry points.
128 1.1 christos */
129 1.1.1.4 christos static void eap_init (int unit);
130 1.1.1.4 christos static void eap_input (int unit, u_char *inp, int inlen);
131 1.1.1.4 christos static void eap_protrej (int unit);
132 1.1.1.4 christos static void eap_lowerup (int unit);
133 1.1.1.4 christos static void eap_lowerdown (int unit);
134 1.1.1.4 christos static int eap_printpkt (u_char *inp, int inlen,
135 1.1.1.4 christos void (*)(void *arg, char *fmt, ...), void *arg);
136 1.1 christos
137 1.1 christos struct protent eap_protent = {
138 1.1 christos PPP_EAP, /* protocol number */
139 1.1 christos eap_init, /* initialization procedure */
140 1.1 christos eap_input, /* process a received packet */
141 1.1 christos eap_protrej, /* process a received protocol-reject */
142 1.1 christos eap_lowerup, /* lower layer has gone up */
143 1.1 christos eap_lowerdown, /* lower layer has gone down */
144 1.1 christos NULL, /* open the protocol */
145 1.1 christos NULL, /* close the protocol */
146 1.1 christos eap_printpkt, /* print a packet in readable form */
147 1.1 christos NULL, /* process a received data packet */
148 1.1 christos 1, /* protocol enabled */
149 1.1 christos "EAP", /* text name of protocol */
150 1.1 christos NULL, /* text name of corresponding data protocol */
151 1.1 christos eap_option_list, /* list of command-line options */
152 1.1 christos NULL, /* check requested options; assign defaults */
153 1.1 christos NULL, /* configure interface for demand-dial */
154 1.1 christos NULL /* say whether to bring up link for this pkt */
155 1.1 christos };
156 1.1 christos
157 1.1.1.5 christos #ifdef PPP_WITH_SRP
158 1.1 christos /*
159 1.1 christos * A well-known 2048 bit modulus.
160 1.1 christos */
161 1.1 christos static const u_char wkmodulus[] = {
162 1.1 christos 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,
163 1.1 christos 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,
164 1.1 christos 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,
165 1.1 christos 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,
166 1.1 christos 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,
167 1.1 christos 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,
168 1.1 christos 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,
169 1.1 christos 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,
170 1.1 christos 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,
171 1.1 christos 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,
172 1.1 christos 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,
173 1.1 christos 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,
174 1.1 christos 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,
175 1.1 christos 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,
176 1.1 christos 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,
177 1.1 christos 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,
178 1.1 christos 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,
179 1.1 christos 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,
180 1.1 christos 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,
181 1.1 christos 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,
182 1.1 christos 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,
183 1.1 christos 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,
184 1.1 christos 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,
185 1.1 christos 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,
186 1.1 christos 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,
187 1.1 christos 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,
188 1.1 christos 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,
189 1.1 christos 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,
190 1.1 christos 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,
191 1.1 christos 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,
192 1.1 christos 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,
193 1.1 christos 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73
194 1.1 christos };
195 1.1.1.5 christos #endif /* PPP_WITH_SRP */
196 1.1 christos
197 1.1 christos /* Local forward declarations. */
198 1.1.1.4 christos static void eap_server_timeout (void *arg);
199 1.1 christos
200 1.1 christos /*
201 1.1 christos * Convert EAP state code to printable string for debug.
202 1.1 christos */
203 1.1 christos static const char *
204 1.1.1.4 christos eap_state_name(enum eap_state_code esc)
205 1.1 christos {
206 1.1 christos static const char *state_names[] = { EAP_STATES };
207 1.1 christos
208 1.1 christos return (state_names[(int)esc]);
209 1.1 christos }
210 1.1 christos
211 1.1 christos /*
212 1.1 christos * eap_init - Initialize state for an EAP user. This is currently
213 1.1 christos * called once by main() during start-up.
214 1.1 christos */
215 1.1 christos static void
216 1.1.1.4 christos eap_init(int unit)
217 1.1 christos {
218 1.1 christos eap_state *esp = &eap_states[unit];
219 1.1 christos
220 1.1 christos BZERO(esp, sizeof (*esp));
221 1.1 christos esp->es_unit = unit;
222 1.1 christos esp->es_server.ea_timeout = EAP_DEFTIMEOUT;
223 1.1 christos esp->es_server.ea_maxrequests = EAP_DEFTRANSMITS;
224 1.1 christos esp->es_server.ea_id = (u_char)(drand48() * 0x100);
225 1.1 christos esp->es_client.ea_timeout = EAP_DEFREQTIME;
226 1.1 christos esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
227 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
228 1.1.1.4 christos esp->es_client.ea_using_eaptls = 0;
229 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
230 1.1.1.5 christos #ifdef PPP_WITH_CHAPMS
231 1.1.1.5 christos esp->es_client.digest = chap_find_digest(CHAP_MICROSOFT_V2);
232 1.1.1.5 christos esp->es_server.digest = chap_find_digest(CHAP_MICROSOFT_V2);
233 1.1.1.4 christos #endif
234 1.1 christos }
235 1.1 christos
236 1.1 christos /*
237 1.1 christos * eap_client_timeout - Give up waiting for the peer to send any
238 1.1 christos * Request messages.
239 1.1 christos */
240 1.1 christos static void
241 1.1.1.4 christos eap_client_timeout(void *arg)
242 1.1 christos {
243 1.1 christos eap_state *esp = (eap_state *) arg;
244 1.1 christos
245 1.1 christos if (!eap_client_active(esp))
246 1.1 christos return;
247 1.1 christos
248 1.1 christos error("EAP: timeout waiting for Request from peer");
249 1.1 christos auth_withpeer_fail(esp->es_unit, PPP_EAP);
250 1.1 christos esp->es_client.ea_state = eapBadAuth;
251 1.1 christos }
252 1.1 christos
253 1.1 christos /*
254 1.1 christos * eap_authwithpeer - Authenticate to our peer (behave as client).
255 1.1 christos *
256 1.1 christos * Start client state and wait for requests. This is called only
257 1.1 christos * after eap_lowerup.
258 1.1 christos */
259 1.1 christos void
260 1.1.1.4 christos eap_authwithpeer(int unit, char *localname)
261 1.1 christos {
262 1.1 christos eap_state *esp = &eap_states[unit];
263 1.1 christos
264 1.1 christos /* Save the peer name we're given */
265 1.1 christos esp->es_client.ea_name = localname;
266 1.1 christos esp->es_client.ea_namelen = strlen(localname);
267 1.1 christos
268 1.1 christos esp->es_client.ea_state = eapListen;
269 1.1 christos
270 1.1 christos /*
271 1.1 christos * Start a timer so that if the other end just goes
272 1.1 christos * silent, we don't sit here waiting forever.
273 1.1 christos */
274 1.1 christos if (esp->es_client.ea_timeout > 0)
275 1.1 christos TIMEOUT(eap_client_timeout, (void *)esp,
276 1.1 christos esp->es_client.ea_timeout);
277 1.1 christos }
278 1.1 christos
279 1.1 christos /*
280 1.1 christos * Format a standard EAP Failure message and send it to the peer.
281 1.1 christos * (Server operation)
282 1.1 christos */
283 1.1 christos static void
284 1.1.1.4 christos eap_send_failure(eap_state *esp)
285 1.1 christos {
286 1.1 christos u_char *outp;
287 1.1 christos
288 1.1 christos outp = outpacket_buf;
289 1.1 christos
290 1.1 christos MAKEHEADER(outp, PPP_EAP);
291 1.1 christos
292 1.1 christos PUTCHAR(EAP_FAILURE, outp);
293 1.1 christos esp->es_server.ea_id++;
294 1.1 christos PUTCHAR(esp->es_server.ea_id, outp);
295 1.1 christos PUTSHORT(EAP_HEADERLEN, outp);
296 1.1 christos
297 1.1 christos output(esp->es_unit, outpacket_buf, EAP_HEADERLEN + PPP_HDRLEN);
298 1.1 christos
299 1.1 christos esp->es_server.ea_state = eapBadAuth;
300 1.1 christos auth_peer_fail(esp->es_unit, PPP_EAP);
301 1.1 christos }
302 1.1 christos
303 1.1 christos /*
304 1.1 christos * Format a standard EAP Success message and send it to the peer.
305 1.1 christos * (Server operation)
306 1.1 christos */
307 1.1 christos static void
308 1.1.1.4 christos eap_send_success(eap_state *esp)
309 1.1 christos {
310 1.1 christos u_char *outp;
311 1.1 christos
312 1.1 christos outp = outpacket_buf;
313 1.1 christos
314 1.1 christos MAKEHEADER(outp, PPP_EAP);
315 1.1 christos
316 1.1 christos PUTCHAR(EAP_SUCCESS, outp);
317 1.1 christos esp->es_server.ea_id++;
318 1.1 christos PUTCHAR(esp->es_server.ea_id, outp);
319 1.1 christos PUTSHORT(EAP_HEADERLEN, outp);
320 1.1 christos
321 1.1 christos output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);
322 1.1 christos
323 1.1 christos auth_peer_success(esp->es_unit, PPP_EAP, 0,
324 1.1 christos esp->es_server.ea_peer, esp->es_server.ea_peerlen);
325 1.1 christos }
326 1.1 christos
327 1.1.1.5 christos #ifdef PPP_WITH_SRP
328 1.1 christos /*
329 1.1 christos * Set DES key according to pseudonym-generating secret and current
330 1.1 christos * date.
331 1.1 christos */
332 1.1 christos static bool
333 1.1.1.5 christos pncrypt_getkey(int timeoffs, unsigned char *key, int keylen)
334 1.1 christos {
335 1.1 christos struct tm *tp;
336 1.1 christos char tbuf[9];
337 1.1.1.5 christos PPP_MD_CTX *ctxt;
338 1.1 christos time_t reftime;
339 1.1 christos
340 1.1 christos if (pn_secret == NULL)
341 1.1 christos return (0);
342 1.1 christos reftime = time(NULL) + timeoffs;
343 1.1 christos tp = localtime(&reftime);
344 1.1.1.5 christos
345 1.1.1.5 christos ctxt = PPP_MD_CTX_new();
346 1.1.1.5 christos if (ctxt) {
347 1.1.1.5 christos
348 1.1.1.5 christos strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp);
349 1.1.1.5 christos
350 1.1.1.5 christos PPP_DigestInit(ctxt, PPP_sha1());
351 1.1.1.5 christos PPP_DigestUpdate(ctxt, pn_secret, strlen(pn_secret));
352 1.1.1.5 christos PPP_DigestUpdate(ctxt, tbuf, strlen(tbuf));
353 1.1.1.5 christos PPP_DigestFinal(ctxt, key, &keylen);
354 1.1.1.5 christos
355 1.1.1.5 christos PPP_MD_CTX_free(ctxt);
356 1.1.1.5 christos return 1;
357 1.1.1.5 christos }
358 1.1.1.5 christos
359 1.1.1.5 christos return (0);
360 1.1 christos }
361 1.1 christos
362 1.1 christos static char base64[] =
363 1.1 christos "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
364 1.1 christos
365 1.1 christos struct b64state {
366 1.1 christos u_int32_t bs_bits;
367 1.1 christos int bs_offs;
368 1.1 christos };
369 1.1 christos
370 1.1 christos static int
371 1.1.1.4 christos b64enc(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
372 1.1 christos {
373 1.1 christos int outlen = 0;
374 1.1 christos
375 1.1 christos while (inlen > 0) {
376 1.1 christos bs->bs_bits = (bs->bs_bits << 8) | *inp++;
377 1.1 christos inlen--;
378 1.1 christos bs->bs_offs += 8;
379 1.1 christos if (bs->bs_offs >= 24) {
380 1.1 christos *outp++ = base64[(bs->bs_bits >> 18) & 0x3F];
381 1.1 christos *outp++ = base64[(bs->bs_bits >> 12) & 0x3F];
382 1.1 christos *outp++ = base64[(bs->bs_bits >> 6) & 0x3F];
383 1.1 christos *outp++ = base64[bs->bs_bits & 0x3F];
384 1.1 christos outlen += 4;
385 1.1 christos bs->bs_offs = 0;
386 1.1 christos bs->bs_bits = 0;
387 1.1 christos }
388 1.1 christos }
389 1.1 christos return (outlen);
390 1.1 christos }
391 1.1 christos
392 1.1 christos static int
393 1.1.1.4 christos b64flush(struct b64state *bs, u_char *outp)
394 1.1 christos {
395 1.1 christos int outlen = 0;
396 1.1 christos
397 1.1 christos if (bs->bs_offs == 8) {
398 1.1 christos *outp++ = base64[(bs->bs_bits >> 2) & 0x3F];
399 1.1 christos *outp++ = base64[(bs->bs_bits << 4) & 0x3F];
400 1.1 christos outlen = 2;
401 1.1 christos } else if (bs->bs_offs == 16) {
402 1.1 christos *outp++ = base64[(bs->bs_bits >> 10) & 0x3F];
403 1.1 christos *outp++ = base64[(bs->bs_bits >> 4) & 0x3F];
404 1.1 christos *outp++ = base64[(bs->bs_bits << 2) & 0x3F];
405 1.1 christos outlen = 3;
406 1.1 christos }
407 1.1 christos bs->bs_offs = 0;
408 1.1 christos bs->bs_bits = 0;
409 1.1 christos return (outlen);
410 1.1 christos }
411 1.1 christos
412 1.1 christos static int
413 1.1.1.4 christos b64dec(struct b64state *bs, u_char *inp, int inlen, u_char *outp)
414 1.1 christos {
415 1.1 christos int outlen = 0;
416 1.1 christos char *cp;
417 1.1 christos
418 1.1 christos while (inlen > 0) {
419 1.1 christos if ((cp = strchr(base64, *inp++)) == NULL)
420 1.1 christos break;
421 1.1 christos bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);
422 1.1 christos inlen--;
423 1.1 christos bs->bs_offs += 6;
424 1.1 christos if (bs->bs_offs >= 8) {
425 1.1 christos *outp++ = bs->bs_bits >> (bs->bs_offs - 8);
426 1.1 christos outlen++;
427 1.1 christos bs->bs_offs -= 8;
428 1.1 christos }
429 1.1 christos }
430 1.1 christos return (outlen);
431 1.1 christos }
432 1.1.1.5 christos #endif /* PPP_WITH_SRP */
433 1.1 christos
434 1.1 christos /*
435 1.1 christos * Assume that current waiting server state is complete and figure
436 1.1 christos * next state to use based on available authentication data. 'status'
437 1.1 christos * indicates if there was an error in handling the last query. It is
438 1.1 christos * 0 for success and non-zero for failure.
439 1.1 christos */
440 1.1 christos static void
441 1.1.1.4 christos eap_figure_next_state(eap_state *esp, int status)
442 1.1 christos {
443 1.1.1.5 christos #ifdef PPP_WITH_SRP
444 1.1.1.5 christos unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp, key[SHA_DIGEST_LENGTH];
445 1.1 christos struct t_pw tpw;
446 1.1 christos struct t_confent *tce, mytce;
447 1.1 christos char *cp, *cp2;
448 1.1 christos struct t_server *ts;
449 1.1.1.5 christos int id, i, plen, clen, toffs, keylen;
450 1.1 christos u_char vals[2];
451 1.1 christos struct b64state bs;
452 1.1.1.5 christos #endif /* PPP_WITH_SRP */
453 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
454 1.1.1.4 christos struct eaptls_session *ets;
455 1.1.1.4 christos int secret_len;
456 1.1.1.4 christos char secret[MAXWORDLEN];
457 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
458 1.1 christos
459 1.1 christos esp->es_server.ea_timeout = esp->es_savedtime;
460 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
461 1.1.1.4 christos esp->es_server.ea_prev_state = esp->es_server.ea_state;
462 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
463 1.1 christos switch (esp->es_server.ea_state) {
464 1.1 christos case eapBadAuth:
465 1.1 christos return;
466 1.1 christos
467 1.1 christos case eapIdentify:
468 1.1.1.5 christos #ifdef PPP_WITH_SRP
469 1.1 christos /* Discard any previous session. */
470 1.1 christos ts = (struct t_server *)esp->es_server.ea_session;
471 1.1 christos if (ts != NULL) {
472 1.1 christos t_serverclose(ts);
473 1.1 christos esp->es_server.ea_session = NULL;
474 1.1 christos esp->es_server.ea_skey = NULL;
475 1.1 christos }
476 1.1.1.5 christos #endif /* PPP_WITH_SRP */
477 1.1 christos if (status != 0) {
478 1.1 christos esp->es_server.ea_state = eapBadAuth;
479 1.1 christos break;
480 1.1 christos }
481 1.1.1.5 christos #ifdef PPP_WITH_SRP
482 1.1 christos /* If we've got a pseudonym, try to decode to real name. */
483 1.1 christos if (esp->es_server.ea_peerlen > SRP_PSEUDO_LEN &&
484 1.1 christos strncmp(esp->es_server.ea_peer, SRP_PSEUDO_ID,
485 1.1 christos SRP_PSEUDO_LEN) == 0 &&
486 1.1 christos (esp->es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 <
487 1.1 christos sizeof (secbuf)) {
488 1.1 christos BZERO(&bs, sizeof (bs));
489 1.1 christos plen = b64dec(&bs,
490 1.1 christos esp->es_server.ea_peer + SRP_PSEUDO_LEN,
491 1.1 christos esp->es_server.ea_peerlen - SRP_PSEUDO_LEN,
492 1.1 christos secbuf);
493 1.1 christos toffs = 0;
494 1.1 christos for (i = 0; i < 5; i++) {
495 1.1.1.5 christos pncrypt_getkey(toffs, key, keylen);
496 1.1 christos toffs -= 86400;
497 1.1.1.5 christos
498 1.1.1.5 christos if (!DesDecrypt(secbuf, key, clear)) {
499 1.1 christos dbglog("no DES here; cannot decode "
500 1.1.1.5 christos "pseudonym");
501 1.1 christos return;
502 1.1 christos }
503 1.1 christos id = *(unsigned char *)clear;
504 1.1 christos if (id + 1 <= plen && id + 9 > plen)
505 1.1 christos break;
506 1.1 christos }
507 1.1 christos if (plen % 8 == 0 && i < 5) {
508 1.1 christos /*
509 1.1 christos * Note that this is always shorter than the
510 1.1 christos * original stored string, so there's no need
511 1.1 christos * to realloc.
512 1.1 christos */
513 1.1 christos if ((i = plen = *(unsigned char *)clear) > 7)
514 1.1 christos i = 7;
515 1.1 christos esp->es_server.ea_peerlen = plen;
516 1.1 christos dp = (unsigned char *)esp->es_server.ea_peer;
517 1.1 christos BCOPY(clear + 1, dp, i);
518 1.1 christos plen -= i;
519 1.1 christos dp += i;
520 1.1 christos sp = secbuf + 8;
521 1.1 christos while (plen > 0) {
522 1.1.1.5 christos DesDecrypt(sp, key, dp);
523 1.1 christos sp += 8;
524 1.1 christos dp += 8;
525 1.1 christos plen -= 8;
526 1.1 christos }
527 1.1 christos esp->es_server.ea_peer[
528 1.1 christos esp->es_server.ea_peerlen] = '\0';
529 1.1 christos dbglog("decoded pseudonym to \"%.*q\"",
530 1.1 christos esp->es_server.ea_peerlen,
531 1.1 christos esp->es_server.ea_peer);
532 1.1 christos } else {
533 1.1 christos dbglog("failed to decode real name");
534 1.1 christos /* Stay in eapIdentfy state; requery */
535 1.1 christos break;
536 1.1 christos }
537 1.1 christos }
538 1.1 christos /* Look up user in secrets database. */
539 1.1 christos if (get_srp_secret(esp->es_unit, esp->es_server.ea_peer,
540 1.1 christos esp->es_server.ea_name, (char *)secbuf, 1) != 0) {
541 1.1 christos /* Set up default in case SRP entry is bad */
542 1.1 christos esp->es_server.ea_state = eapMD5Chall;
543 1.1 christos /* Get t_confent based on index in srp-secrets */
544 1.1 christos id = strtol((char *)secbuf, &cp, 10);
545 1.1 christos if (*cp++ != ':' || id < 0)
546 1.1 christos break;
547 1.1 christos if (id == 0) {
548 1.1 christos mytce.index = 0;
549 1.1 christos mytce.modulus.data = (u_char *)wkmodulus;
550 1.1 christos mytce.modulus.len = sizeof (wkmodulus);
551 1.1 christos mytce.generator.data = (u_char *)"\002";
552 1.1 christos mytce.generator.len = 1;
553 1.1 christos tce = &mytce;
554 1.1 christos } else if ((tce = gettcid(id)) != NULL) {
555 1.1 christos /*
556 1.1 christos * Client will have to verify this modulus/
557 1.1 christos * generator combination, and that will take
558 1.1 christos * a while. Lengthen the timeout here.
559 1.1 christos */
560 1.1 christos if (esp->es_server.ea_timeout > 0 &&
561 1.1 christos esp->es_server.ea_timeout < 30)
562 1.1 christos esp->es_server.ea_timeout = 30;
563 1.1 christos } else {
564 1.1 christos break;
565 1.1 christos }
566 1.1 christos if ((cp2 = strchr(cp, ':')) == NULL)
567 1.1 christos break;
568 1.1 christos *cp2++ = '\0';
569 1.1 christos tpw.pebuf.name = esp->es_server.ea_peer;
570 1.1 christos tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,
571 1.1 christos cp);
572 1.1.1.5 christos tpw.pebuf.password.data = (char*) tpw.pwbuf;
573 1.1 christos tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,
574 1.1 christos cp2);
575 1.1 christos tpw.pebuf.salt.data = tpw.saltbuf;
576 1.1 christos if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)
577 1.1 christos break;
578 1.1 christos esp->es_server.ea_session = (void *)ts;
579 1.1 christos esp->es_server.ea_state = eapSRP1;
580 1.1 christos vals[0] = esp->es_server.ea_id + 1;
581 1.1 christos vals[1] = EAPT_SRP;
582 1.1 christos t_serveraddexdata(ts, vals, 2);
583 1.1 christos /* Generate B; must call before t_servergetkey() */
584 1.1 christos t_servergenexp(ts);
585 1.1 christos break;
586 1.1 christos }
587 1.1.1.5 christos #endif /* PPP_WITH_SRP */
588 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
589 1.1.1.4 christos if (!get_secret(esp->es_unit, esp->es_server.ea_peer,
590 1.1.1.4 christos esp->es_server.ea_name, secret, &secret_len, 1)) {
591 1.1.1.4 christos
592 1.1.1.4 christos esp->es_server.ea_state = eapTlsStart;
593 1.1.1.4 christos break;
594 1.1.1.4 christos }
595 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
596 1.1.1.4 christos
597 1.1 christos esp->es_server.ea_state = eapMD5Chall;
598 1.1 christos break;
599 1.1 christos
600 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
601 1.1.1.4 christos case eapTlsStart:
602 1.1.1.4 christos /* Initialize ssl session */
603 1.1.1.4 christos if(!eaptls_init_ssl_server(esp)) {
604 1.1.1.4 christos esp->es_server.ea_state = eapBadAuth;
605 1.1.1.4 christos break;
606 1.1.1.4 christos }
607 1.1.1.4 christos
608 1.1.1.4 christos esp->es_server.ea_state = eapTlsRecv;
609 1.1.1.4 christos break;
610 1.1.1.4 christos
611 1.1.1.4 christos case eapTlsRecv:
612 1.1.1.4 christos ets = (struct eaptls_session *) esp->es_server.ea_session;
613 1.1.1.4 christos
614 1.1.1.4 christos if(ets->alert_sent) {
615 1.1.1.4 christos esp->es_server.ea_state = eapTlsSendAlert;
616 1.1.1.4 christos break;
617 1.1.1.4 christos }
618 1.1.1.4 christos
619 1.1.1.4 christos if (status) {
620 1.1.1.4 christos esp->es_server.ea_state = eapBadAuth;
621 1.1.1.4 christos break;
622 1.1.1.4 christos }
623 1.1.1.4 christos ets = (struct eaptls_session *) esp->es_server.ea_session;
624 1.1.1.4 christos
625 1.1.1.4 christos if(ets->frag)
626 1.1.1.4 christos esp->es_server.ea_state = eapTlsSendAck;
627 1.1.1.4 christos else
628 1.1.1.4 christos esp->es_server.ea_state = eapTlsSend;
629 1.1.1.4 christos break;
630 1.1.1.4 christos
631 1.1.1.4 christos case eapTlsSend:
632 1.1.1.4 christos ets = (struct eaptls_session *) esp->es_server.ea_session;
633 1.1.1.4 christos
634 1.1.1.4 christos if(ets->frag)
635 1.1.1.4 christos esp->es_server.ea_state = eapTlsRecvAck;
636 1.1.1.4 christos else
637 1.1.1.4 christos if(SSL_is_init_finished(ets->ssl))
638 1.1.1.4 christos esp->es_server.ea_state = eapTlsRecvClient;
639 1.1.1.4 christos else
640 1.1.1.4 christos /* JJK Add "TLS empty record" message here ??? */
641 1.1.1.4 christos esp->es_server.ea_state = eapTlsRecv;
642 1.1.1.4 christos break;
643 1.1.1.4 christos
644 1.1.1.4 christos case eapTlsSendAck:
645 1.1.1.4 christos esp->es_server.ea_state = eapTlsRecv;
646 1.1.1.4 christos break;
647 1.1.1.4 christos
648 1.1.1.4 christos case eapTlsRecvAck:
649 1.1.1.4 christos if (status)
650 1.1.1.4 christos {
651 1.1.1.4 christos esp->es_server.ea_state = eapBadAuth;
652 1.1.1.4 christos break;
653 1.1.1.4 christos }
654 1.1.1.4 christos
655 1.1.1.4 christos esp->es_server.ea_state = eapTlsSend;
656 1.1.1.4 christos break;
657 1.1.1.4 christos
658 1.1.1.4 christos case eapTlsSendAlert:
659 1.1.1.4 christos esp->es_server.ea_state = eapTlsRecvAlertAck;
660 1.1.1.4 christos break;
661 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
662 1.1.1.4 christos
663 1.1 christos case eapSRP1:
664 1.1.1.5 christos #ifdef PPP_WITH_SRP
665 1.1 christos ts = (struct t_server *)esp->es_server.ea_session;
666 1.1 christos if (ts != NULL && status != 0) {
667 1.1 christos t_serverclose(ts);
668 1.1 christos esp->es_server.ea_session = NULL;
669 1.1 christos esp->es_server.ea_skey = NULL;
670 1.1 christos }
671 1.1.1.5 christos #endif /* PPP_WITH_SRP */
672 1.1 christos if (status == 1) {
673 1.1 christos esp->es_server.ea_state = eapMD5Chall;
674 1.1 christos } else if (status != 0 || esp->es_server.ea_session == NULL) {
675 1.1 christos esp->es_server.ea_state = eapBadAuth;
676 1.1 christos } else {
677 1.1 christos esp->es_server.ea_state = eapSRP2;
678 1.1 christos }
679 1.1 christos break;
680 1.1 christos
681 1.1 christos case eapSRP2:
682 1.1.1.5 christos #ifdef PPP_WITH_SRP
683 1.1 christos ts = (struct t_server *)esp->es_server.ea_session;
684 1.1 christos if (ts != NULL && status != 0) {
685 1.1 christos t_serverclose(ts);
686 1.1 christos esp->es_server.ea_session = NULL;
687 1.1 christos esp->es_server.ea_skey = NULL;
688 1.1 christos }
689 1.1.1.5 christos #endif /* PPP_WITH_SRP */
690 1.1 christos if (status != 0 || esp->es_server.ea_session == NULL) {
691 1.1 christos esp->es_server.ea_state = eapBadAuth;
692 1.1 christos } else {
693 1.1 christos esp->es_server.ea_state = eapSRP3;
694 1.1 christos }
695 1.1 christos break;
696 1.1 christos
697 1.1 christos case eapSRP3:
698 1.1 christos case eapSRP4:
699 1.1.1.5 christos #ifdef PPP_WITH_SRP
700 1.1 christos ts = (struct t_server *)esp->es_server.ea_session;
701 1.1 christos if (ts != NULL && status != 0) {
702 1.1 christos t_serverclose(ts);
703 1.1 christos esp->es_server.ea_session = NULL;
704 1.1 christos esp->es_server.ea_skey = NULL;
705 1.1 christos }
706 1.1.1.5 christos #endif /* PPP_WITH_SRP */
707 1.1 christos if (status != 0 || esp->es_server.ea_session == NULL) {
708 1.1 christos esp->es_server.ea_state = eapBadAuth;
709 1.1 christos } else {
710 1.1 christos esp->es_server.ea_state = eapOpen;
711 1.1 christos }
712 1.1 christos break;
713 1.1 christos
714 1.1.1.5 christos #ifdef PPP_WITH_CHAPMS
715 1.1.1.4 christos case eapMSCHAPv2Chall:
716 1.1.1.4 christos #endif
717 1.1 christos case eapMD5Chall:
718 1.1 christos if (status != 0) {
719 1.1 christos esp->es_server.ea_state = eapBadAuth;
720 1.1 christos } else {
721 1.1 christos esp->es_server.ea_state = eapOpen;
722 1.1 christos }
723 1.1 christos break;
724 1.1 christos
725 1.1 christos default:
726 1.1 christos esp->es_server.ea_state = eapBadAuth;
727 1.1 christos break;
728 1.1 christos }
729 1.1 christos if (esp->es_server.ea_state == eapBadAuth)
730 1.1 christos eap_send_failure(esp);
731 1.1.1.4 christos
732 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
733 1.1.1.4 christos dbglog("EAP id=0x%2x '%s' -> '%s'", esp->es_server.ea_id, eap_state_name(esp->es_server.ea_prev_state), eap_state_name(esp->es_server.ea_state));
734 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
735 1.1.1.4 christos }
736 1.1.1.4 christos
737 1.1.1.5 christos #if PPP_WITH_CHAPMS
738 1.1.1.4 christos /*
739 1.1.1.4 christos * eap_chap_verify_response - check whether the peer's response matches
740 1.1.1.4 christos * what we think it should be. Returns 1 if it does (authentication
741 1.1.1.4 christos * succeeded), or 0 if it doesn't.
742 1.1.1.4 christos */
743 1.1.1.4 christos static int
744 1.1.1.4 christos eap_chap_verify_response(char *name, char *ourname, int id,
745 1.1.1.4 christos struct chap_digest_type *digest,
746 1.1.1.4 christos unsigned char *challenge, unsigned char *response,
747 1.1.1.4 christos char *message, int message_space)
748 1.1.1.4 christos {
749 1.1.1.4 christos int ok;
750 1.1.1.4 christos unsigned char secret[MAXSECRETLEN];
751 1.1.1.4 christos int secret_len;
752 1.1.1.4 christos
753 1.1.1.4 christos /* Get the secret that the peer is supposed to know */
754 1.1.1.4 christos if (!get_secret(0, name, ourname, (char *)secret, &secret_len, 1)) {
755 1.1.1.4 christos error("No CHAP secret found for authenticating %q", name);
756 1.1.1.4 christos return 0;
757 1.1.1.4 christos }
758 1.1.1.4 christos
759 1.1.1.4 christos ok = digest->verify_response(id, name, secret, secret_len, challenge,
760 1.1.1.4 christos response, message, message_space);
761 1.1.1.4 christos memset(secret, 0, sizeof(secret));
762 1.1.1.4 christos
763 1.1.1.4 christos return ok;
764 1.1 christos }
765 1.1 christos
766 1.1 christos /*
767 1.1.1.4 christos * Format and send an CHAPV2-Success/Failure EAP Request message.
768 1.1.1.4 christos */
769 1.1.1.4 christos static void
770 1.1.1.4 christos eap_chapms2_send_request(eap_state *esp, u_char id,
771 1.1.1.4 christos u_char opcode, u_char chapid,
772 1.1.1.4 christos char *message, int message_len)
773 1.1.1.4 christos {
774 1.1.1.4 christos u_char *outp;
775 1.1.1.4 christos int msglen;
776 1.1.1.4 christos
777 1.1.1.4 christos outp = outpacket_buf;
778 1.1.1.4 christos
779 1.1.1.4 christos MAKEHEADER(outp, PPP_EAP);
780 1.1.1.4 christos
781 1.1.1.4 christos msglen = EAP_HEADERLEN + 5 * sizeof (u_char);
782 1.1.1.4 christos msglen += message_len;
783 1.1.1.4 christos
784 1.1.1.4 christos PUTCHAR(EAP_REQUEST, outp);
785 1.1.1.4 christos PUTCHAR(id, outp);
786 1.1.1.4 christos PUTSHORT(msglen, outp);
787 1.1.1.4 christos PUTCHAR(EAPT_MSCHAPV2, outp);
788 1.1.1.4 christos PUTCHAR(opcode, outp);
789 1.1.1.4 christos PUTCHAR(chapid, outp);
790 1.1.1.4 christos /* MS len */
791 1.1.1.4 christos PUTSHORT(msglen - 5, outp);
792 1.1.1.4 christos BCOPY(message, outp, message_len);
793 1.1.1.4 christos
794 1.1.1.4 christos output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
795 1.1.1.4 christos
796 1.1.1.4 christos if (opcode == CHAP_SUCCESS) {
797 1.1.1.4 christos auth_peer_success(esp->es_unit, PPP_EAP, 0,
798 1.1.1.4 christos esp->es_server.ea_peer, esp->es_server.ea_peerlen);
799 1.1.1.4 christos }
800 1.1.1.4 christos else {
801 1.1.1.4 christos esp->es_server.ea_state = eapBadAuth;
802 1.1.1.4 christos auth_peer_fail(esp->es_unit, PPP_EAP);
803 1.1.1.4 christos }
804 1.1.1.4 christos }
805 1.1.1.5 christos #endif /* PPP_WITH_CHAPMS */
806 1.1.1.4 christos
807 1.1.1.4 christos /*
808 1.1 christos * Format an EAP Request message and send it to the peer. Message
809 1.1 christos * type depends on current state. (Server operation)
810 1.1 christos */
811 1.1 christos static void
812 1.1.1.4 christos eap_send_request(eap_state *esp)
813 1.1 christos {
814 1.1 christos u_char *outp;
815 1.1 christos u_char *lenloc;
816 1.1 christos u_char *ptr;
817 1.1 christos int outlen;
818 1.1 christos int challen;
819 1.1 christos char *str;
820 1.1.1.5 christos #ifdef PPP_WITH_SRP
821 1.1 christos struct t_server *ts;
822 1.1.1.5 christos u_char clear[8], cipher[8], dig[SHA_DIGEST_LENGTH], *optr, *cp, key[SHA_DIGEST_LENGTH];
823 1.1.1.5 christos int i, j, diglen, clen, keylen = sizeof(key);
824 1.1 christos struct b64state b64;
825 1.1.1.5 christos PPP_MD_CTX *ctxt;
826 1.1.1.5 christos #endif /* PPP_WITH_SRP */
827 1.1 christos
828 1.1 christos /* Handle both initial auth and restart */
829 1.1 christos if (esp->es_server.ea_state < eapIdentify &&
830 1.1 christos esp->es_server.ea_state != eapInitial) {
831 1.1 christos esp->es_server.ea_state = eapIdentify;
832 1.1 christos if (explicit_remote) {
833 1.1 christos /*
834 1.1 christos * If we already know the peer's
835 1.1 christos * unauthenticated name, then there's no
836 1.1 christos * reason to ask. Go to next state instead.
837 1.1 christos */
838 1.1 christos esp->es_server.ea_peer = remote_name;
839 1.1 christos esp->es_server.ea_peerlen = strlen(remote_name);
840 1.1 christos eap_figure_next_state(esp, 0);
841 1.1 christos }
842 1.1 christos }
843 1.1 christos
844 1.1 christos if (esp->es_server.ea_maxrequests > 0 &&
845 1.1 christos esp->es_server.ea_requests >= esp->es_server.ea_maxrequests) {
846 1.1 christos if (esp->es_server.ea_responses > 0)
847 1.1 christos error("EAP: too many Requests sent");
848 1.1 christos else
849 1.1 christos error("EAP: no response to Requests");
850 1.1 christos eap_send_failure(esp);
851 1.1 christos return;
852 1.1 christos }
853 1.1 christos
854 1.1 christos outp = outpacket_buf;
855 1.1 christos
856 1.1 christos MAKEHEADER(outp, PPP_EAP);
857 1.1 christos
858 1.1 christos PUTCHAR(EAP_REQUEST, outp);
859 1.1 christos PUTCHAR(esp->es_server.ea_id, outp);
860 1.1 christos lenloc = outp;
861 1.1 christos INCPTR(2, outp);
862 1.1 christos
863 1.1 christos switch (esp->es_server.ea_state) {
864 1.1 christos case eapIdentify:
865 1.1 christos PUTCHAR(EAPT_IDENTITY, outp);
866 1.1 christos str = "Name";
867 1.1 christos challen = strlen(str);
868 1.1 christos BCOPY(str, outp, challen);
869 1.1 christos INCPTR(challen, outp);
870 1.1 christos break;
871 1.1 christos
872 1.1 christos case eapMD5Chall:
873 1.1 christos PUTCHAR(EAPT_MD5CHAP, outp);
874 1.1 christos /*
875 1.1 christos * pick a random challenge length between
876 1.1 christos * MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH
877 1.1 christos */
878 1.1 christos challen = (drand48() *
879 1.1 christos (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
880 1.1 christos MIN_CHALLENGE_LENGTH;
881 1.1 christos PUTCHAR(challen, outp);
882 1.1 christos esp->es_challen = challen;
883 1.1 christos ptr = esp->es_challenge;
884 1.1 christos while (--challen >= 0)
885 1.1 christos *ptr++ = (u_char) (drand48() * 0x100);
886 1.1 christos BCOPY(esp->es_challenge, outp, esp->es_challen);
887 1.1 christos INCPTR(esp->es_challen, outp);
888 1.1 christos BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
889 1.1 christos INCPTR(esp->es_server.ea_namelen, outp);
890 1.1 christos break;
891 1.1 christos
892 1.1.1.5 christos #ifdef PPP_WITH_CHAPMS
893 1.1.1.4 christos case eapMSCHAPv2Chall:
894 1.1.1.5 christos esp->es_server.digest->generate_challenge(esp->es_challenge);
895 1.1.1.5 christos challen = esp->es_challenge[0];
896 1.1.1.4 christos esp->es_challen = challen;
897 1.1.1.4 christos
898 1.1.1.4 christos PUTCHAR(EAPT_MSCHAPV2, outp);
899 1.1.1.4 christos PUTCHAR(CHAP_CHALLENGE, outp);
900 1.1.1.4 christos PUTCHAR(esp->es_server.ea_id, outp);
901 1.1.1.4 christos /* MS len */
902 1.1.1.4 christos PUTSHORT(5 + challen +
903 1.1.1.4 christos esp->es_server.ea_namelen,
904 1.1.1.4 christos outp);
905 1.1.1.4 christos /* challen + challenge */
906 1.1.1.4 christos BCOPY(esp->es_challenge, outp, challen+1);
907 1.1.1.4 christos INCPTR(challen+1, outp);
908 1.1.1.4 christos BCOPY(esp->es_server.ea_name,
909 1.1.1.4 christos outp,
910 1.1.1.4 christos esp->es_server.ea_namelen);
911 1.1.1.4 christos INCPTR(esp->es_server.ea_namelen, outp);
912 1.1.1.4 christos break;
913 1.1.1.5 christos #endif /* PPP_WITH_CHAPMS */
914 1.1.1.4 christos
915 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
916 1.1.1.4 christos case eapTlsStart:
917 1.1.1.4 christos PUTCHAR(EAPT_TLS, outp);
918 1.1.1.4 christos PUTCHAR(EAP_TLS_FLAGS_START, outp);
919 1.1.1.4 christos eap_figure_next_state(esp, 0);
920 1.1.1.4 christos break;
921 1.1.1.4 christos
922 1.1.1.4 christos case eapTlsSend:
923 1.1.1.4 christos eaptls_send(esp->es_server.ea_session, &outp);
924 1.1.1.4 christos eap_figure_next_state(esp, 0);
925 1.1.1.4 christos break;
926 1.1.1.4 christos
927 1.1.1.4 christos case eapTlsSendAck:
928 1.1.1.4 christos PUTCHAR(EAPT_TLS, outp);
929 1.1.1.4 christos PUTCHAR(0, outp);
930 1.1.1.4 christos eap_figure_next_state(esp, 0);
931 1.1.1.4 christos break;
932 1.1.1.4 christos
933 1.1.1.4 christos case eapTlsSendAlert:
934 1.1.1.4 christos eaptls_send(esp->es_server.ea_session, &outp);
935 1.1.1.4 christos eap_figure_next_state(esp, 0);
936 1.1.1.4 christos break;
937 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
938 1.1.1.4 christos
939 1.1.1.5 christos #ifdef PPP_WITH_SRP
940 1.1 christos case eapSRP1:
941 1.1 christos PUTCHAR(EAPT_SRP, outp);
942 1.1 christos PUTCHAR(EAPSRP_CHALLENGE, outp);
943 1.1 christos
944 1.1 christos PUTCHAR(esp->es_server.ea_namelen, outp);
945 1.1 christos BCOPY(esp->es_server.ea_name, outp, esp->es_server.ea_namelen);
946 1.1 christos INCPTR(esp->es_server.ea_namelen, outp);
947 1.1 christos
948 1.1 christos ts = (struct t_server *)esp->es_server.ea_session;
949 1.1 christos assert(ts != NULL);
950 1.1 christos PUTCHAR(ts->s.len, outp);
951 1.1 christos BCOPY(ts->s.data, outp, ts->s.len);
952 1.1 christos INCPTR(ts->s.len, outp);
953 1.1 christos
954 1.1 christos if (ts->g.len == 1 && ts->g.data[0] == 2) {
955 1.1 christos PUTCHAR(0, outp);
956 1.1 christos } else {
957 1.1 christos PUTCHAR(ts->g.len, outp);
958 1.1 christos BCOPY(ts->g.data, outp, ts->g.len);
959 1.1 christos INCPTR(ts->g.len, outp);
960 1.1 christos }
961 1.1 christos
962 1.1 christos if (ts->n.len != sizeof (wkmodulus) ||
963 1.1 christos BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) {
964 1.1 christos BCOPY(ts->n.data, outp, ts->n.len);
965 1.1 christos INCPTR(ts->n.len, outp);
966 1.1 christos }
967 1.1 christos break;
968 1.1 christos
969 1.1 christos case eapSRP2:
970 1.1 christos PUTCHAR(EAPT_SRP, outp);
971 1.1 christos PUTCHAR(EAPSRP_SKEY, outp);
972 1.1 christos
973 1.1 christos ts = (struct t_server *)esp->es_server.ea_session;
974 1.1 christos assert(ts != NULL);
975 1.1 christos BCOPY(ts->B.data, outp, ts->B.len);
976 1.1 christos INCPTR(ts->B.len, outp);
977 1.1 christos break;
978 1.1 christos
979 1.1 christos case eapSRP3:
980 1.1 christos PUTCHAR(EAPT_SRP, outp);
981 1.1 christos PUTCHAR(EAPSRP_SVALIDATOR, outp);
982 1.1 christos PUTLONG(SRPVAL_EBIT, outp);
983 1.1 christos ts = (struct t_server *)esp->es_server.ea_session;
984 1.1 christos assert(ts != NULL);
985 1.1.1.5 christos BCOPY(t_serverresponse(ts), outp, SHA_DIGEST_LENGTH);
986 1.1.1.5 christos INCPTR(SHA_DIGEST_LENGTH, outp);
987 1.1 christos
988 1.1.1.5 christos if (pncrypt_getkey(0, key, keylen)) {
989 1.1 christos /* Generate pseudonym */
990 1.1 christos optr = outp;
991 1.1 christos cp = (unsigned char *)esp->es_server.ea_peer;
992 1.1 christos if ((j = i = esp->es_server.ea_peerlen) > 7)
993 1.1 christos j = 7;
994 1.1 christos clear[0] = i;
995 1.1 christos BCOPY(cp, clear + 1, j);
996 1.1 christos i -= j;
997 1.1 christos cp += j;
998 1.1.1.5 christos
999 1.1.1.5 christos if (!DesEncrypt(clear, key, cipher)) {
1000 1.1 christos dbglog("no DES here; not generating pseudonym");
1001 1.1 christos break;
1002 1.1.1.5 christos }
1003 1.1.1.5 christos
1004 1.1 christos BZERO(&b64, sizeof (b64));
1005 1.1 christos outp++; /* space for pseudonym length */
1006 1.1 christos outp += b64enc(&b64, cipher, 8, outp);
1007 1.1 christos while (i >= 8) {
1008 1.1.1.5 christos DesEncrypt(cp, key, cipher);
1009 1.1 christos outp += b64enc(&b64, cipher, 8, outp);
1010 1.1 christos cp += 8;
1011 1.1 christos i -= 8;
1012 1.1 christos }
1013 1.1 christos if (i > 0) {
1014 1.1 christos BCOPY(cp, clear, i);
1015 1.1 christos cp += i;
1016 1.1 christos while (i < 8) {
1017 1.1 christos *cp++ = drand48() * 0x100;
1018 1.1 christos i++;
1019 1.1 christos }
1020 1.1.1.5 christos
1021 1.1.1.5 christos DesEncrypt(clear, key, cipher);
1022 1.1 christos outp += b64enc(&b64, cipher, 8, outp);
1023 1.1 christos }
1024 1.1 christos outp += b64flush(&b64, outp);
1025 1.1 christos
1026 1.1 christos /* Set length and pad out to next 20 octet boundary */
1027 1.1 christos i = outp - optr - 1;
1028 1.1 christos *optr = i;
1029 1.1.1.5 christos i %= SHA_DIGEST_LENGTH;
1030 1.1 christos if (i != 0) {
1031 1.1.1.5 christos while (i < SHA_DIGEST_LENGTH) {
1032 1.1 christos *outp++ = drand48() * 0x100;
1033 1.1 christos i++;
1034 1.1 christos }
1035 1.1 christos }
1036 1.1 christos
1037 1.1 christos /* Obscure the pseudonym with SHA1 hash */
1038 1.1.1.5 christos ctxt = PPP_MD_CTX_new();
1039 1.1.1.5 christos if (ctxt) {
1040 1.1.1.5 christos
1041 1.1.1.5 christos PPP_DigestInit(ctxt, PPP_sha1());
1042 1.1.1.5 christos PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1);
1043 1.1.1.5 christos PPP_DigestUpdate(ctxt, &esp->es_server.ea_skey,
1044 1.1.1.5 christos SESSION_KEY_LEN);
1045 1.1.1.5 christos PPP_DigestUpdate(ctxt, esp->es_server.ea_peer,
1046 1.1.1.5 christos esp->es_server.ea_peerlen);
1047 1.1.1.5 christos while (optr < outp) {
1048 1.1.1.5 christos diglen = SHA_DIGEST_LENGTH;
1049 1.1.1.5 christos PPP_DigestFinal(ctxt, dig, &diglen);
1050 1.1.1.5 christos cp = dig;
1051 1.1.1.5 christos while (cp < dig + SHA_DIGEST_LENGTH)
1052 1.1.1.5 christos *optr++ ^= *cp++;
1053 1.1.1.5 christos
1054 1.1.1.5 christos PPP_DigestInit(ctxt, PPP_sha1());
1055 1.1.1.5 christos PPP_DigestUpdate(ctxt, &esp->es_server.ea_id, 1);
1056 1.1.1.5 christos PPP_DigestUpdate(ctxt, esp->es_server.ea_skey,
1057 1.1.1.5 christos SESSION_KEY_LEN);
1058 1.1.1.5 christos PPP_DigestUpdate(ctxt, optr - SHA_DIGEST_LENGTH,
1059 1.1.1.5 christos SHA_DIGEST_LENGTH);
1060 1.1.1.5 christos }
1061 1.1.1.5 christos
1062 1.1.1.5 christos PPP_MD_CTX_free(ctxt);
1063 1.1 christos }
1064 1.1 christos }
1065 1.1 christos break;
1066 1.1 christos
1067 1.1 christos case eapSRP4:
1068 1.1 christos PUTCHAR(EAPT_SRP, outp);
1069 1.1 christos PUTCHAR(EAPSRP_LWRECHALLENGE, outp);
1070 1.1 christos challen = MIN_CHALLENGE_LENGTH +
1071 1.1 christos ((MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH) * drand48());
1072 1.1 christos esp->es_challen = challen;
1073 1.1 christos ptr = esp->es_challenge;
1074 1.1 christos while (--challen >= 0)
1075 1.1 christos *ptr++ = drand48() * 0x100;
1076 1.1 christos BCOPY(esp->es_challenge, outp, esp->es_challen);
1077 1.1 christos INCPTR(esp->es_challen, outp);
1078 1.1 christos break;
1079 1.1.1.5 christos #endif /* PPP_WITH_SRP */
1080 1.1 christos
1081 1.1 christos default:
1082 1.1 christos return;
1083 1.1 christos }
1084 1.1 christos
1085 1.1 christos outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1086 1.1 christos PUTSHORT(outlen, lenloc);
1087 1.1 christos
1088 1.1 christos output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
1089 1.1 christos
1090 1.1 christos esp->es_server.ea_requests++;
1091 1.1 christos
1092 1.1 christos if (esp->es_server.ea_timeout > 0)
1093 1.1 christos TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
1094 1.1 christos }
1095 1.1 christos
1096 1.1 christos /*
1097 1.1 christos * eap_authpeer - Authenticate our peer (behave as server).
1098 1.1 christos *
1099 1.1 christos * Start server state and send first request. This is called only
1100 1.1 christos * after eap_lowerup.
1101 1.1 christos */
1102 1.1 christos void
1103 1.1.1.4 christos eap_authpeer(int unit, char *localname)
1104 1.1 christos {
1105 1.1 christos eap_state *esp = &eap_states[unit];
1106 1.1 christos
1107 1.1 christos /* Save the name we're given. */
1108 1.1 christos esp->es_server.ea_name = localname;
1109 1.1 christos esp->es_server.ea_namelen = strlen(localname);
1110 1.1 christos
1111 1.1 christos esp->es_savedtime = esp->es_server.ea_timeout;
1112 1.1 christos
1113 1.1 christos /* Lower layer up yet? */
1114 1.1 christos if (esp->es_server.ea_state == eapInitial ||
1115 1.1 christos esp->es_server.ea_state == eapPending) {
1116 1.1 christos esp->es_server.ea_state = eapPending;
1117 1.1 christos return;
1118 1.1 christos }
1119 1.1 christos
1120 1.1 christos esp->es_server.ea_state = eapPending;
1121 1.1 christos
1122 1.1 christos /* ID number not updated here intentionally; hashed into M1 */
1123 1.1 christos eap_send_request(esp);
1124 1.1 christos }
1125 1.1 christos
1126 1.1 christos /*
1127 1.1 christos * eap_server_timeout - Retransmission timer for sending Requests
1128 1.1 christos * expired.
1129 1.1 christos */
1130 1.1 christos static void
1131 1.1.1.4 christos eap_server_timeout(void *arg)
1132 1.1 christos {
1133 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
1134 1.1.1.4 christos u_char *outp;
1135 1.1.1.4 christos u_char *lenloc;
1136 1.1.1.4 christos int outlen;
1137 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
1138 1.1.1.4 christos
1139 1.1 christos eap_state *esp = (eap_state *) arg;
1140 1.1 christos
1141 1.1 christos if (!eap_server_active(esp))
1142 1.1 christos return;
1143 1.1 christos
1144 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
1145 1.1.1.4 christos switch(esp->es_server.ea_prev_state) {
1146 1.1.1.4 christos
1147 1.1.1.4 christos /*
1148 1.1.1.4 christos * In eap-tls the state changes after a request, so we return to
1149 1.1.1.4 christos * previous state ...
1150 1.1.1.4 christos */
1151 1.1.1.4 christos case(eapTlsStart):
1152 1.1.1.4 christos case(eapTlsSendAck):
1153 1.1.1.4 christos esp->es_server.ea_state = esp->es_server.ea_prev_state;
1154 1.1.1.4 christos break;
1155 1.1.1.4 christos
1156 1.1.1.4 christos /*
1157 1.1.1.4 christos * ... or resend the stored data
1158 1.1.1.4 christos */
1159 1.1.1.4 christos case(eapTlsSend):
1160 1.1.1.4 christos case(eapTlsSendAlert):
1161 1.1.1.4 christos outp = outpacket_buf;
1162 1.1.1.4 christos MAKEHEADER(outp, PPP_EAP);
1163 1.1.1.4 christos PUTCHAR(EAP_REQUEST, outp);
1164 1.1.1.4 christos PUTCHAR(esp->es_server.ea_id, outp);
1165 1.1.1.4 christos lenloc = outp;
1166 1.1.1.4 christos INCPTR(2, outp);
1167 1.1.1.4 christos
1168 1.1.1.4 christos eaptls_retransmit(esp->es_server.ea_session, &outp);
1169 1.1.1.4 christos
1170 1.1.1.4 christos outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1171 1.1.1.4 christos PUTSHORT(outlen, lenloc);
1172 1.1.1.4 christos output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
1173 1.1.1.4 christos esp->es_server.ea_requests++;
1174 1.1.1.4 christos
1175 1.1.1.4 christos if (esp->es_server.ea_timeout > 0)
1176 1.1.1.4 christos TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
1177 1.1.1.4 christos
1178 1.1.1.4 christos return;
1179 1.1.1.4 christos default:
1180 1.1.1.4 christos break;
1181 1.1.1.4 christos }
1182 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
1183 1.1.1.4 christos
1184 1.1 christos /* EAP ID number must not change on timeout. */
1185 1.1 christos eap_send_request(esp);
1186 1.1 christos }
1187 1.1 christos
1188 1.1 christos /*
1189 1.1 christos * When it's time to send rechallenge the peer, this timeout is
1190 1.1 christos * called. Once the rechallenge is successful, the response handler
1191 1.1 christos * will restart the timer. If it fails, then the link is dropped.
1192 1.1 christos */
1193 1.1 christos static void
1194 1.1.1.4 christos eap_rechallenge(void *arg)
1195 1.1 christos {
1196 1.1 christos eap_state *esp = (eap_state *)arg;
1197 1.1 christos
1198 1.1 christos if (esp->es_server.ea_state != eapOpen &&
1199 1.1 christos esp->es_server.ea_state != eapSRP4)
1200 1.1 christos return;
1201 1.1 christos
1202 1.1 christos esp->es_server.ea_requests = 0;
1203 1.1 christos esp->es_server.ea_state = eapIdentify;
1204 1.1 christos eap_figure_next_state(esp, 0);
1205 1.1 christos esp->es_server.ea_id++;
1206 1.1 christos eap_send_request(esp);
1207 1.1 christos }
1208 1.1 christos
1209 1.1 christos static void
1210 1.1.1.4 christos srp_lwrechallenge(void *arg)
1211 1.1 christos {
1212 1.1 christos eap_state *esp = (eap_state *)arg;
1213 1.1 christos
1214 1.1 christos if (esp->es_server.ea_state != eapOpen ||
1215 1.1 christos esp->es_server.ea_type != EAPT_SRP)
1216 1.1 christos return;
1217 1.1 christos
1218 1.1 christos esp->es_server.ea_requests = 0;
1219 1.1 christos esp->es_server.ea_state = eapSRP4;
1220 1.1 christos esp->es_server.ea_id++;
1221 1.1 christos eap_send_request(esp);
1222 1.1 christos }
1223 1.1 christos
1224 1.1 christos /*
1225 1.1 christos * eap_lowerup - The lower layer is now up.
1226 1.1 christos *
1227 1.1 christos * This is called before either eap_authpeer or eap_authwithpeer. See
1228 1.1 christos * link_established() in auth.c. All that's necessary here is to
1229 1.1 christos * return to closed state so that those two routines will do the right
1230 1.1 christos * thing.
1231 1.1 christos */
1232 1.1 christos static void
1233 1.1.1.4 christos eap_lowerup(int unit)
1234 1.1 christos {
1235 1.1 christos eap_state *esp = &eap_states[unit];
1236 1.1 christos
1237 1.1 christos /* Discard any (possibly authenticated) peer name. */
1238 1.1 christos if (esp->es_server.ea_peer != NULL &&
1239 1.1 christos esp->es_server.ea_peer != remote_name)
1240 1.1 christos free(esp->es_server.ea_peer);
1241 1.1 christos esp->es_server.ea_peer = NULL;
1242 1.1 christos if (esp->es_client.ea_peer != NULL)
1243 1.1 christos free(esp->es_client.ea_peer);
1244 1.1 christos esp->es_client.ea_peer = NULL;
1245 1.1 christos
1246 1.1 christos esp->es_client.ea_state = eapClosed;
1247 1.1 christos esp->es_server.ea_state = eapClosed;
1248 1.1 christos }
1249 1.1 christos
1250 1.1 christos /*
1251 1.1 christos * eap_lowerdown - The lower layer is now down.
1252 1.1 christos *
1253 1.1 christos * Cancel all timeouts and return to initial state.
1254 1.1 christos */
1255 1.1 christos static void
1256 1.1.1.4 christos eap_lowerdown(int unit)
1257 1.1 christos {
1258 1.1 christos eap_state *esp = &eap_states[unit];
1259 1.1 christos
1260 1.1 christos if (eap_client_active(esp) && esp->es_client.ea_timeout > 0) {
1261 1.1 christos UNTIMEOUT(eap_client_timeout, (void *)esp);
1262 1.1 christos }
1263 1.1 christos if (eap_server_active(esp)) {
1264 1.1 christos if (esp->es_server.ea_timeout > 0) {
1265 1.1 christos UNTIMEOUT(eap_server_timeout, (void *)esp);
1266 1.1 christos }
1267 1.1 christos } else {
1268 1.1 christos if ((esp->es_server.ea_state == eapOpen ||
1269 1.1 christos esp->es_server.ea_state == eapSRP4) &&
1270 1.1 christos esp->es_rechallenge > 0) {
1271 1.1 christos UNTIMEOUT(eap_rechallenge, (void *)esp);
1272 1.1 christos }
1273 1.1 christos if (esp->es_server.ea_state == eapOpen &&
1274 1.1 christos esp->es_lwrechallenge > 0) {
1275 1.1 christos UNTIMEOUT(srp_lwrechallenge, (void *)esp);
1276 1.1 christos }
1277 1.1 christos }
1278 1.1 christos
1279 1.1 christos esp->es_client.ea_state = esp->es_server.ea_state = eapInitial;
1280 1.1 christos esp->es_client.ea_requests = esp->es_server.ea_requests = 0;
1281 1.1 christos }
1282 1.1 christos
1283 1.1 christos /*
1284 1.1 christos * eap_protrej - Peer doesn't speak this protocol.
1285 1.1 christos *
1286 1.1 christos * This shouldn't happen. If it does, it represents authentication
1287 1.1 christos * failure.
1288 1.1 christos */
1289 1.1 christos static void
1290 1.1.1.4 christos eap_protrej(int unit)
1291 1.1 christos {
1292 1.1 christos eap_state *esp = &eap_states[unit];
1293 1.1 christos
1294 1.1 christos if (eap_client_active(esp)) {
1295 1.1 christos error("EAP authentication failed due to Protocol-Reject");
1296 1.1 christos auth_withpeer_fail(unit, PPP_EAP);
1297 1.1 christos }
1298 1.1 christos if (eap_server_active(esp)) {
1299 1.1 christos error("EAP authentication of peer failed on Protocol-Reject");
1300 1.1 christos auth_peer_fail(unit, PPP_EAP);
1301 1.1 christos }
1302 1.1 christos eap_lowerdown(unit);
1303 1.1 christos }
1304 1.1 christos
1305 1.1 christos /*
1306 1.1 christos * Format and send a regular EAP Response message.
1307 1.1 christos */
1308 1.1 christos static void
1309 1.1.1.4 christos eap_send_response(eap_state *esp, u_char id, u_char typenum,
1310 1.1.1.4 christos u_char *str, int lenstr)
1311 1.1 christos {
1312 1.1 christos u_char *outp;
1313 1.1 christos int msglen;
1314 1.1 christos
1315 1.1 christos outp = outpacket_buf;
1316 1.1 christos
1317 1.1 christos MAKEHEADER(outp, PPP_EAP);
1318 1.1 christos
1319 1.1 christos PUTCHAR(EAP_RESPONSE, outp);
1320 1.1 christos PUTCHAR(id, outp);
1321 1.1 christos esp->es_client.ea_id = id;
1322 1.1 christos msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr;
1323 1.1 christos PUTSHORT(msglen, outp);
1324 1.1 christos PUTCHAR(typenum, outp);
1325 1.1 christos if (lenstr > 0) {
1326 1.1 christos BCOPY(str, outp, lenstr);
1327 1.1 christos }
1328 1.1 christos
1329 1.1 christos output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1330 1.1 christos }
1331 1.1 christos
1332 1.1 christos /*
1333 1.1 christos * Format and send an MD5-Challenge EAP Response message.
1334 1.1 christos */
1335 1.1 christos static void
1336 1.1.1.4 christos eap_chap_response(eap_state *esp, u_char id, u_char *hash,
1337 1.1.1.4 christos char *name, int namelen)
1338 1.1 christos {
1339 1.1 christos u_char *outp;
1340 1.1 christos int msglen;
1341 1.1 christos
1342 1.1 christos outp = outpacket_buf;
1343 1.1.1.5 christos
1344 1.1 christos MAKEHEADER(outp, PPP_EAP);
1345 1.1 christos
1346 1.1 christos PUTCHAR(EAP_RESPONSE, outp);
1347 1.1 christos PUTCHAR(id, outp);
1348 1.1 christos esp->es_client.ea_id = id;
1349 1.1.1.5 christos msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_DIGEST_LENGTH +
1350 1.1 christos namelen;
1351 1.1 christos PUTSHORT(msglen, outp);
1352 1.1 christos PUTCHAR(EAPT_MD5CHAP, outp);
1353 1.1.1.5 christos PUTCHAR(MD5_DIGEST_LENGTH, outp);
1354 1.1.1.5 christos BCOPY(hash, outp, MD5_DIGEST_LENGTH);
1355 1.1.1.5 christos INCPTR(MD5_DIGEST_LENGTH, outp);
1356 1.1 christos if (namelen > 0) {
1357 1.1 christos BCOPY(name, outp, namelen);
1358 1.1 christos }
1359 1.1 christos
1360 1.1 christos output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1361 1.1 christos }
1362 1.1 christos
1363 1.1.1.5 christos #ifdef PPP_WITH_SRP
1364 1.1 christos /*
1365 1.1 christos * Format and send a SRP EAP Response message.
1366 1.1 christos */
1367 1.1 christos static void
1368 1.1.1.4 christos eap_srp_response(eap_state *esp, u_char id, u_char subtypenum,
1369 1.1.1.4 christos u_char *str, int lenstr)
1370 1.1 christos {
1371 1.1 christos u_char *outp;
1372 1.1 christos int msglen;
1373 1.1 christos
1374 1.1 christos outp = outpacket_buf;
1375 1.1 christos
1376 1.1 christos MAKEHEADER(outp, PPP_EAP);
1377 1.1 christos
1378 1.1 christos PUTCHAR(EAP_RESPONSE, outp);
1379 1.1 christos PUTCHAR(id, outp);
1380 1.1 christos esp->es_client.ea_id = id;
1381 1.1 christos msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr;
1382 1.1 christos PUTSHORT(msglen, outp);
1383 1.1 christos PUTCHAR(EAPT_SRP, outp);
1384 1.1 christos PUTCHAR(subtypenum, outp);
1385 1.1 christos if (lenstr > 0) {
1386 1.1 christos BCOPY(str, outp, lenstr);
1387 1.1 christos }
1388 1.1 christos
1389 1.1 christos output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1390 1.1 christos }
1391 1.1 christos
1392 1.1 christos /*
1393 1.1 christos * Format and send a SRP EAP Client Validator Response message.
1394 1.1 christos */
1395 1.1 christos static void
1396 1.1.1.4 christos eap_srpval_response(eap_state *esp, u_char id, u_int32_t flags, u_char *str)
1397 1.1 christos {
1398 1.1 christos u_char *outp;
1399 1.1 christos int msglen;
1400 1.1 christos
1401 1.1 christos outp = outpacket_buf;
1402 1.1 christos
1403 1.1 christos MAKEHEADER(outp, PPP_EAP);
1404 1.1 christos
1405 1.1 christos PUTCHAR(EAP_RESPONSE, outp);
1406 1.1 christos PUTCHAR(id, outp);
1407 1.1 christos esp->es_client.ea_id = id;
1408 1.1 christos msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u_int32_t) +
1409 1.1.1.5 christos SHA_DIGEST_LENGTH;
1410 1.1 christos PUTSHORT(msglen, outp);
1411 1.1 christos PUTCHAR(EAPT_SRP, outp);
1412 1.1 christos PUTCHAR(EAPSRP_CVALIDATOR, outp);
1413 1.1 christos PUTLONG(flags, outp);
1414 1.1.1.5 christos BCOPY(str, outp, SHA_DIGEST_LENGTH);
1415 1.1 christos
1416 1.1 christos output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1417 1.1 christos }
1418 1.1.1.5 christos #endif /* PPP_WITH_SRP */
1419 1.1 christos
1420 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
1421 1.1.1.4 christos /*
1422 1.1.1.4 christos * Send an EAP-TLS response message with tls data
1423 1.1.1.4 christos */
1424 1.1.1.4 christos static void
1425 1.1.1.4 christos eap_tls_response(eap_state *esp, u_char id)
1426 1.1.1.4 christos {
1427 1.1.1.4 christos u_char *outp;
1428 1.1.1.4 christos int outlen;
1429 1.1.1.4 christos u_char *lenloc;
1430 1.1.1.4 christos
1431 1.1.1.4 christos outp = outpacket_buf;
1432 1.1.1.4 christos
1433 1.1.1.4 christos MAKEHEADER(outp, PPP_EAP);
1434 1.1.1.4 christos
1435 1.1.1.4 christos PUTCHAR(EAP_RESPONSE, outp);
1436 1.1.1.4 christos PUTCHAR(id, outp);
1437 1.1.1.4 christos
1438 1.1.1.4 christos lenloc = outp;
1439 1.1.1.4 christos INCPTR(2, outp);
1440 1.1.1.4 christos
1441 1.1.1.4 christos /*
1442 1.1.1.4 christos If the id in the request is unchanged, we must retransmit
1443 1.1.1.4 christos the old data
1444 1.1.1.4 christos */
1445 1.1.1.4 christos if(id == esp->es_client.ea_id)
1446 1.1.1.4 christos eaptls_retransmit(esp->es_client.ea_session, &outp);
1447 1.1.1.4 christos else
1448 1.1.1.4 christos eaptls_send(esp->es_client.ea_session, &outp);
1449 1.1.1.4 christos
1450 1.1.1.4 christos outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1451 1.1.1.4 christos PUTSHORT(outlen, lenloc);
1452 1.1.1.4 christos
1453 1.1.1.4 christos output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1454 1.1.1.4 christos
1455 1.1.1.4 christos esp->es_client.ea_id = id;
1456 1.1.1.4 christos }
1457 1.1.1.4 christos
1458 1.1.1.4 christos /*
1459 1.1.1.4 christos * Send an EAP-TLS ack
1460 1.1.1.4 christos */
1461 1.1.1.4 christos static void
1462 1.1.1.4 christos eap_tls_sendack(eap_state *esp, u_char id)
1463 1.1.1.4 christos {
1464 1.1.1.4 christos u_char *outp;
1465 1.1.1.4 christos int outlen;
1466 1.1.1.4 christos u_char *lenloc;
1467 1.1.1.4 christos
1468 1.1.1.4 christos outp = outpacket_buf;
1469 1.1.1.4 christos
1470 1.1.1.4 christos MAKEHEADER(outp, PPP_EAP);
1471 1.1.1.4 christos
1472 1.1.1.4 christos PUTCHAR(EAP_RESPONSE, outp);
1473 1.1.1.4 christos PUTCHAR(id, outp);
1474 1.1.1.4 christos esp->es_client.ea_id = id;
1475 1.1.1.4 christos
1476 1.1.1.4 christos lenloc = outp;
1477 1.1.1.4 christos INCPTR(2, outp);
1478 1.1.1.4 christos
1479 1.1.1.4 christos PUTCHAR(EAPT_TLS, outp);
1480 1.1.1.4 christos PUTCHAR(0, outp);
1481 1.1.1.4 christos
1482 1.1.1.4 christos outlen = (outp - outpacket_buf) - PPP_HDRLEN;
1483 1.1.1.4 christos PUTSHORT(outlen, lenloc);
1484 1.1.1.4 christos
1485 1.1.1.4 christos output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
1486 1.1.1.4 christos }
1487 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
1488 1.1.1.4 christos
1489 1.1 christos static void
1490 1.1.1.4 christos eap_send_nak(eap_state *esp, u_char id, u_char type)
1491 1.1 christos {
1492 1.1 christos u_char *outp;
1493 1.1 christos int msglen;
1494 1.1 christos
1495 1.1 christos outp = outpacket_buf;
1496 1.1 christos
1497 1.1 christos MAKEHEADER(outp, PPP_EAP);
1498 1.1 christos
1499 1.1 christos PUTCHAR(EAP_RESPONSE, outp);
1500 1.1 christos PUTCHAR(id, outp);
1501 1.1 christos esp->es_client.ea_id = id;
1502 1.1 christos msglen = EAP_HEADERLEN + 2 * sizeof (u_char);
1503 1.1 christos PUTSHORT(msglen, outp);
1504 1.1 christos PUTCHAR(EAPT_NAK, outp);
1505 1.1 christos PUTCHAR(type, outp);
1506 1.1 christos
1507 1.1 christos output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1508 1.1 christos }
1509 1.1 christos
1510 1.1.1.5 christos #ifdef PPP_WITH_SRP
1511 1.1 christos static char *
1512 1.1.1.4 christos name_of_pn_file(void)
1513 1.1 christos {
1514 1.1 christos char *user, *path, *file;
1515 1.1 christos struct passwd *pw;
1516 1.1 christos size_t pl;
1517 1.1 christos static bool pnlogged = 0;
1518 1.1 christos
1519 1.1 christos pw = getpwuid(getuid());
1520 1.1 christos if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) {
1521 1.1 christos errno = EINVAL;
1522 1.1 christos return (NULL);
1523 1.1 christos }
1524 1.1.1.5 christos file = PPP_PATH_PSEUDONYM;
1525 1.1 christos pl = strlen(user) + strlen(file) + 2;
1526 1.1 christos path = malloc(pl);
1527 1.1 christos if (path == NULL)
1528 1.1 christos return (NULL);
1529 1.1 christos (void) slprintf(path, pl, "%s/%s", user, file);
1530 1.1 christos if (!pnlogged) {
1531 1.1 christos dbglog("pseudonym file: %s", path);
1532 1.1 christos pnlogged = 1;
1533 1.1 christos }
1534 1.1 christos return (path);
1535 1.1 christos }
1536 1.1 christos
1537 1.1 christos static int
1538 1.1.1.4 christos open_pn_file(mode_t modebits)
1539 1.1 christos {
1540 1.1 christos char *path;
1541 1.1 christos int fd, err;
1542 1.1 christos
1543 1.1 christos if ((path = name_of_pn_file()) == NULL)
1544 1.1 christos return (-1);
1545 1.1 christos fd = open(path, modebits, S_IRUSR | S_IWUSR);
1546 1.1 christos err = errno;
1547 1.1 christos free(path);
1548 1.1 christos errno = err;
1549 1.1 christos return (fd);
1550 1.1 christos }
1551 1.1 christos
1552 1.1 christos static void
1553 1.1.1.4 christos remove_pn_file(void)
1554 1.1 christos {
1555 1.1 christos char *path;
1556 1.1 christos
1557 1.1 christos if ((path = name_of_pn_file()) != NULL) {
1558 1.1 christos (void) unlink(path);
1559 1.1 christos (void) free(path);
1560 1.1 christos }
1561 1.1 christos }
1562 1.1 christos
1563 1.1 christos static void
1564 1.1.1.4 christos write_pseudonym(eap_state *esp, u_char *inp, int len, int id)
1565 1.1 christos {
1566 1.1 christos u_char val;
1567 1.1 christos u_char *datp, *digp;
1568 1.1.1.5 christos PPP_MD_CTX *ctxt;
1569 1.1.1.5 christos u_char dig[SHA_DIGEST_LENGTH];
1570 1.1.1.5 christos int dsize, fd, olen = len, diglen = sizeof(dig);
1571 1.1 christos
1572 1.1 christos /*
1573 1.1 christos * Do the decoding by working backwards. This eliminates the need
1574 1.1 christos * to save the decoded output in a separate buffer.
1575 1.1 christos */
1576 1.1 christos val = id;
1577 1.1 christos while (len > 0) {
1578 1.1.1.5 christos if ((dsize = len % SHA_DIGEST_LENGTH) == 0)
1579 1.1.1.5 christos dsize = SHA_DIGEST_LENGTH;
1580 1.1 christos len -= dsize;
1581 1.1 christos datp = inp + len;
1582 1.1.1.5 christos ctxt = PPP_MD_CTX_new();
1583 1.1.1.5 christos if (ctxt) {
1584 1.1.1.5 christos
1585 1.1.1.5 christos PPP_DigestInit(ctxt, PPP_sha1());
1586 1.1.1.5 christos PPP_DigestUpdate(ctxt, &val, 1);
1587 1.1.1.5 christos PPP_DigestUpdate(ctxt, esp->es_client.ea_skey,
1588 1.1.1.5 christos SESSION_KEY_LEN);
1589 1.1.1.5 christos if (len > 0) {
1590 1.1.1.5 christos PPP_DigestUpdate(ctxt, datp, SHA_DIGEST_LENGTH);
1591 1.1.1.5 christos } else {
1592 1.1.1.5 christos PPP_DigestUpdate(ctxt, esp->es_client.ea_name,
1593 1.1.1.5 christos esp->es_client.ea_namelen);
1594 1.1.1.5 christos }
1595 1.1.1.5 christos PPP_DigestFinal(ctxt, dig, &diglen);
1596 1.1.1.5 christos
1597 1.1.1.5 christos for (digp = dig; digp < dig + SHA_DIGEST_LENGTH; digp++)
1598 1.1.1.5 christos *datp++ ^= *digp;
1599 1.1.1.5 christos
1600 1.1.1.5 christos PPP_MD_CTX_free(ctxt);
1601 1.1 christos }
1602 1.1 christos }
1603 1.1 christos
1604 1.1 christos /* Now check that the result is sane */
1605 1.1 christos if (olen <= 0 || *inp + 1 > olen) {
1606 1.1 christos dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp);
1607 1.1 christos return;
1608 1.1 christos }
1609 1.1 christos
1610 1.1 christos /* Save it away */
1611 1.1 christos fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);
1612 1.1 christos if (fd < 0) {
1613 1.1 christos dbglog("EAP: error saving pseudonym: %m");
1614 1.1 christos return;
1615 1.1 christos }
1616 1.1 christos len = write(fd, inp + 1, *inp);
1617 1.1 christos if (close(fd) != -1 && len == *inp) {
1618 1.1 christos dbglog("EAP: saved pseudonym");
1619 1.1 christos esp->es_usedpseudo = 0;
1620 1.1 christos } else {
1621 1.1 christos dbglog("EAP: failed to save pseudonym");
1622 1.1 christos remove_pn_file();
1623 1.1 christos }
1624 1.1 christos }
1625 1.1.1.5 christos #endif /* PPP_WITH_SRP */
1626 1.1 christos
1627 1.1.1.5 christos #if PPP_WITH_CHAPMS
1628 1.1.1.4 christos /*
1629 1.1.1.4 christos * Format and send an CHAPV2-Challenge EAP Response message.
1630 1.1.1.4 christos */
1631 1.1.1.4 christos static void
1632 1.1.1.4 christos eap_chapv2_response(eap_state *esp, u_char id, u_char chapid, u_char *response, char *user, int user_len)
1633 1.1.1.4 christos {
1634 1.1.1.4 christos u_char *outp;
1635 1.1.1.4 christos int msglen;
1636 1.1.1.4 christos
1637 1.1.1.4 christos outp = outpacket_buf;
1638 1.1.1.4 christos
1639 1.1.1.4 christos MAKEHEADER(outp, PPP_EAP);
1640 1.1.1.4 christos
1641 1.1.1.4 christos PUTCHAR(EAP_RESPONSE, outp);
1642 1.1.1.4 christos PUTCHAR(id, outp);
1643 1.1.1.4 christos esp->es_client.ea_id = id;
1644 1.1.1.4 christos msglen = EAP_HEADERLEN + 6 * sizeof (u_char) + MS_CHAP2_RESPONSE_LEN + user_len;
1645 1.1.1.4 christos PUTSHORT(msglen, outp);
1646 1.1.1.4 christos PUTCHAR(EAPT_MSCHAPV2, outp);
1647 1.1.1.4 christos PUTCHAR(CHAP_RESPONSE, outp);
1648 1.1.1.4 christos PUTCHAR(chapid, outp);
1649 1.1.1.4 christos PUTCHAR(0, outp);
1650 1.1.1.4 christos /* len */
1651 1.1.1.4 christos PUTCHAR(5 + user_len + MS_CHAP2_RESPONSE_LEN, outp);
1652 1.1.1.4 christos BCOPY(response, outp, MS_CHAP2_RESPONSE_LEN+1); // VLEN + VALUE
1653 1.1.1.4 christos INCPTR(MS_CHAP2_RESPONSE_LEN+1, outp);
1654 1.1.1.4 christos BCOPY(user, outp, user_len);
1655 1.1.1.4 christos
1656 1.1.1.4 christos output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
1657 1.1.1.4 christos }
1658 1.1.1.4 christos #endif
1659 1.1.1.4 christos
1660 1.1 christos /*
1661 1.1 christos * eap_request - Receive EAP Request message (client mode).
1662 1.1 christos */
1663 1.1 christos static void
1664 1.1.1.4 christos eap_request(eap_state *esp, u_char *inp, int id, int len)
1665 1.1 christos {
1666 1.1 christos u_char typenum;
1667 1.1 christos u_char vallen;
1668 1.1 christos int secret_len;
1669 1.1 christos char secret[MAXWORDLEN];
1670 1.1 christos char rhostname[256];
1671 1.1.1.5 christos PPP_MD_CTX *mdctx;
1672 1.1.1.5 christos u_char hash[MD5_DIGEST_LENGTH];
1673 1.1.1.5 christos int hashlen = MD5_DIGEST_LENGTH;
1674 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
1675 1.1.1.4 christos u_char flags;
1676 1.1.1.4 christos struct eaptls_session *ets = esp->es_client.ea_session;
1677 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
1678 1.1.1.4 christos
1679 1.1.1.5 christos #ifdef PPP_WITH_SRP
1680 1.1 christos struct t_client *tc;
1681 1.1 christos struct t_num sval, gval, Nval, *Ap, Bval;
1682 1.1 christos u_char vals[2];
1683 1.1.1.5 christos PPP_MD_CTX *ctxt;
1684 1.1.1.5 christos u_char dig[SHA_DIGEST_LENGTH];
1685 1.1.1.5 christos int diglen = sizeof(dig);
1686 1.1 christos int fd;
1687 1.1.1.5 christos #endif /* PPP_WITH_SRP */
1688 1.1 christos
1689 1.1 christos /*
1690 1.1.1.4 christos * Ignore requests if we're not open
1691 1.1.1.4 christos */
1692 1.1.1.4 christos if (esp->es_client.ea_state <= eapClosed)
1693 1.1.1.4 christos return;
1694 1.1.1.4 christos
1695 1.1.1.4 christos /*
1696 1.1 christos * Note: we update es_client.ea_id *only if* a Response
1697 1.1 christos * message is being generated. Otherwise, we leave it the
1698 1.1 christos * same for duplicate detection purposes.
1699 1.1 christos */
1700 1.1 christos
1701 1.1 christos esp->es_client.ea_requests++;
1702 1.1 christos if (esp->es_client.ea_maxrequests != 0 &&
1703 1.1 christos esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {
1704 1.1 christos info("EAP: received too many Request messages");
1705 1.1 christos if (esp->es_client.ea_timeout > 0) {
1706 1.1 christos UNTIMEOUT(eap_client_timeout, (void *)esp);
1707 1.1 christos }
1708 1.1 christos auth_withpeer_fail(esp->es_unit, PPP_EAP);
1709 1.1 christos return;
1710 1.1 christos }
1711 1.1 christos
1712 1.1 christos if (len <= 0) {
1713 1.1 christos error("EAP: empty Request message discarded");
1714 1.1 christos return;
1715 1.1 christos }
1716 1.1 christos
1717 1.1 christos GETCHAR(typenum, inp);
1718 1.1 christos len--;
1719 1.1 christos
1720 1.1 christos switch (typenum) {
1721 1.1 christos case EAPT_IDENTITY:
1722 1.1 christos if (len > 0)
1723 1.1 christos info("EAP: Identity prompt \"%.*q\"", len, inp);
1724 1.1.1.5 christos #ifdef PPP_WITH_SRP
1725 1.1 christos if (esp->es_usepseudo &&
1726 1.1 christos (esp->es_usedpseudo == 0 ||
1727 1.1 christos (esp->es_usedpseudo == 1 &&
1728 1.1 christos id == esp->es_client.ea_id))) {
1729 1.1 christos esp->es_usedpseudo = 1;
1730 1.1 christos /* Try to get a pseudonym */
1731 1.1 christos if ((fd = open_pn_file(O_RDONLY)) >= 0) {
1732 1.1 christos strcpy(rhostname, SRP_PSEUDO_ID);
1733 1.1 christos len = read(fd, rhostname + SRP_PSEUDO_LEN,
1734 1.1 christos sizeof (rhostname) - SRP_PSEUDO_LEN);
1735 1.1 christos /* XXX NAI unsupported */
1736 1.1 christos if (len > 0) {
1737 1.1 christos eap_send_response(esp, id, typenum,
1738 1.1 christos rhostname, len + SRP_PSEUDO_LEN);
1739 1.1 christos }
1740 1.1 christos (void) close(fd);
1741 1.1 christos if (len > 0)
1742 1.1 christos break;
1743 1.1 christos }
1744 1.1 christos }
1745 1.1 christos /* Stop using pseudonym now. */
1746 1.1 christos if (esp->es_usepseudo && esp->es_usedpseudo != 2) {
1747 1.1 christos remove_pn_file();
1748 1.1 christos esp->es_usedpseudo = 2;
1749 1.1 christos }
1750 1.1.1.5 christos #endif /* PPP_WITH_SRP */
1751 1.1.1.4 christos eap_send_response(esp, id, typenum, (u_char *)esp->es_client.ea_name,
1752 1.1 christos esp->es_client.ea_namelen);
1753 1.1 christos break;
1754 1.1 christos
1755 1.1 christos case EAPT_NOTIFICATION:
1756 1.1 christos if (len > 0)
1757 1.1 christos info("EAP: Notification \"%.*q\"", len, inp);
1758 1.1 christos eap_send_response(esp, id, typenum, NULL, 0);
1759 1.1 christos break;
1760 1.1 christos
1761 1.1 christos case EAPT_NAK:
1762 1.1 christos /*
1763 1.1 christos * Avoid the temptation to send Response Nak in reply
1764 1.1 christos * to Request Nak here. It can only lead to trouble.
1765 1.1 christos */
1766 1.1 christos warn("EAP: unexpected Nak in Request; ignored");
1767 1.1 christos /* Return because we're waiting for something real. */
1768 1.1 christos return;
1769 1.1 christos
1770 1.1 christos case EAPT_MD5CHAP:
1771 1.1 christos if (len < 1) {
1772 1.1 christos error("EAP: received MD5-Challenge with no data");
1773 1.1 christos /* Bogus request; wait for something real. */
1774 1.1 christos return;
1775 1.1 christos }
1776 1.1 christos GETCHAR(vallen, inp);
1777 1.1 christos len--;
1778 1.1 christos if (vallen < 8 || vallen > len) {
1779 1.1 christos error("EAP: MD5-Challenge with bad length %d (8..%d)",
1780 1.1 christos vallen, len);
1781 1.1 christos /* Try something better. */
1782 1.1 christos eap_send_nak(esp, id, EAPT_SRP);
1783 1.1 christos break;
1784 1.1 christos }
1785 1.1 christos
1786 1.1 christos /* Not so likely to happen. */
1787 1.1.1.4 christos if (len - vallen >= sizeof (rhostname)) {
1788 1.1 christos dbglog("EAP: trimming really long peer name down");
1789 1.1 christos BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
1790 1.1 christos rhostname[sizeof (rhostname) - 1] = '\0';
1791 1.1 christos } else {
1792 1.1 christos BCOPY(inp + vallen, rhostname, len - vallen);
1793 1.1 christos rhostname[len - vallen] = '\0';
1794 1.1 christos }
1795 1.1 christos
1796 1.1 christos /* In case the remote doesn't give us his name. */
1797 1.1 christos if (explicit_remote ||
1798 1.1 christos (remote_name[0] != '\0' && vallen == len))
1799 1.1 christos strlcpy(rhostname, remote_name, sizeof (rhostname));
1800 1.1 christos
1801 1.1 christos /*
1802 1.1 christos * Get the secret for authenticating ourselves with
1803 1.1 christos * the specified host.
1804 1.1 christos */
1805 1.1 christos if (!get_secret(esp->es_unit, esp->es_client.ea_name,
1806 1.1 christos rhostname, secret, &secret_len, 0)) {
1807 1.1 christos dbglog("EAP: no MD5 secret for auth to %q", rhostname);
1808 1.1 christos eap_send_nak(esp, id, EAPT_SRP);
1809 1.1 christos break;
1810 1.1 christos }
1811 1.1.1.5 christos
1812 1.1.1.5 christos mdctx = PPP_MD_CTX_new();
1813 1.1.1.5 christos if (mdctx != NULL) {
1814 1.1.1.5 christos if (PPP_DigestInit(mdctx, PPP_md5())) {
1815 1.1.1.5 christos typenum = id;
1816 1.1.1.5 christos if (PPP_DigestUpdate(mdctx, &typenum, 1)) {
1817 1.1.1.5 christos if (PPP_DigestUpdate(mdctx, secret, secret_len)) {
1818 1.1.1.5 christos BZERO(secret, sizeof(secret));
1819 1.1.1.5 christos if (PPP_DigestUpdate(mdctx, inp, vallen)) {
1820 1.1.1.5 christos if (PPP_DigestFinal(mdctx, hash, &hashlen)) {
1821 1.1.1.5 christos eap_chap_response(esp, id, hash, esp->es_client.ea_name,
1822 1.1.1.5 christos esp->es_client.ea_namelen);
1823 1.1.1.5 christos PPP_MD_CTX_free(mdctx);
1824 1.1.1.5 christos break;
1825 1.1.1.5 christos }
1826 1.1.1.5 christos }
1827 1.1.1.5 christos }
1828 1.1.1.5 christos }
1829 1.1.1.5 christos }
1830 1.1.1.5 christos PPP_MD_CTX_free(mdctx);
1831 1.1.1.5 christos }
1832 1.1.1.5 christos dbglog("EAP: Invalid MD5 checksum");
1833 1.1.1.5 christos eap_send_nak(esp, id, EAPT_SRP);
1834 1.1 christos break;
1835 1.1 christos
1836 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
1837 1.1.1.4 christos case EAPT_TLS:
1838 1.1.1.4 christos
1839 1.1.1.4 christos switch(esp->es_client.ea_state) {
1840 1.1.1.4 christos
1841 1.1.1.4 christos case eapListen:
1842 1.1.1.4 christos
1843 1.1.1.4 christos if (len < 1) {
1844 1.1.1.4 christos error("EAP: received EAP-TLS Listen packet with no data");
1845 1.1.1.4 christos /* Bogus request; wait for something real. */
1846 1.1.1.4 christos return;
1847 1.1.1.4 christos }
1848 1.1.1.4 christos GETCHAR(flags, inp);
1849 1.1.1.4 christos if(flags & EAP_TLS_FLAGS_START){
1850 1.1.1.4 christos
1851 1.1.1.4 christos esp->es_client.ea_using_eaptls = 1;
1852 1.1.1.4 christos
1853 1.1.1.4 christos if (explicit_remote){
1854 1.1.1.4 christos esp->es_client.ea_peer = strdup(remote_name);
1855 1.1.1.4 christos esp->es_client.ea_peerlen = strlen(remote_name);
1856 1.1.1.4 christos } else
1857 1.1.1.4 christos esp->es_client.ea_peer = NULL;
1858 1.1.1.4 christos
1859 1.1.1.4 christos /* Init ssl session */
1860 1.1.1.4 christos if(!eaptls_init_ssl_client(esp)) {
1861 1.1.1.4 christos dbglog("cannot init ssl");
1862 1.1.1.4 christos eap_send_nak(esp, id, EAPT_MSCHAPV2);
1863 1.1.1.4 christos esp->es_client.ea_using_eaptls = 0;
1864 1.1.1.4 christos break;
1865 1.1.1.4 christos }
1866 1.1.1.4 christos
1867 1.1.1.4 christos ets = esp->es_client.ea_session;
1868 1.1.1.4 christos eap_tls_response(esp, id);
1869 1.1.1.4 christos esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1870 1.1.1.4 christos break;
1871 1.1.1.4 christos }
1872 1.1.1.4 christos
1873 1.1.1.4 christos /* The server has sent a bad start packet. */
1874 1.1.1.4 christos eap_send_nak(esp, id, EAPT_MSCHAPV2);
1875 1.1.1.4 christos break;
1876 1.1.1.4 christos
1877 1.1.1.4 christos case eapTlsRecvAck:
1878 1.1.1.4 christos eap_tls_response(esp, id);
1879 1.1.1.4 christos esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1880 1.1.1.4 christos break;
1881 1.1.1.4 christos
1882 1.1.1.4 christos case eapTlsRecv:
1883 1.1.1.4 christos if (len < 1) {
1884 1.1.1.4 christos error("EAP: discarding EAP-TLS Receive packet with no data");
1885 1.1.1.4 christos /* Bogus request; wait for something real. */
1886 1.1.1.4 christos return;
1887 1.1.1.4 christos }
1888 1.1.1.4 christos eaptls_receive(ets, inp, len);
1889 1.1.1.4 christos
1890 1.1.1.4 christos if(ets->frag) {
1891 1.1.1.4 christos eap_tls_sendack(esp, id);
1892 1.1.1.4 christos esp->es_client.ea_state = eapTlsRecv;
1893 1.1.1.4 christos break;
1894 1.1.1.4 christos }
1895 1.1.1.4 christos
1896 1.1.1.4 christos if(ets->alert_recv) {
1897 1.1.1.4 christos eap_tls_sendack(esp, id);
1898 1.1.1.4 christos esp->es_client.ea_state = eapTlsRecvFailure;
1899 1.1.1.4 christos break;
1900 1.1.1.4 christos }
1901 1.1.1.4 christos
1902 1.1.1.4 christos /* Check if TLS handshake is finished */
1903 1.1.1.4 christos if(eaptls_is_init_finished(ets)) {
1904 1.1.1.5 christos #ifdef PPP_WITH_MPPE
1905 1.1.1.4 christos eaptls_gen_mppe_keys(ets, 1);
1906 1.1.1.4 christos #endif
1907 1.1.1.4 christos eaptls_free_session(ets);
1908 1.1.1.4 christos eap_tls_sendack(esp, id);
1909 1.1.1.4 christos esp->es_client.ea_state = eapTlsRecvSuccess;
1910 1.1.1.4 christos break;
1911 1.1.1.4 christos }
1912 1.1.1.4 christos
1913 1.1.1.4 christos eap_tls_response(esp,id);
1914 1.1.1.4 christos esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : eapTlsRecv);
1915 1.1.1.4 christos break;
1916 1.1.1.4 christos
1917 1.1.1.4 christos default:
1918 1.1.1.4 christos eap_send_nak(esp, id, EAPT_MSCHAPV2);
1919 1.1.1.4 christos esp->es_client.ea_using_eaptls = 0;
1920 1.1.1.4 christos break;
1921 1.1.1.4 christos }
1922 1.1.1.4 christos
1923 1.1.1.4 christos break;
1924 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
1925 1.1.1.4 christos
1926 1.1.1.5 christos #ifdef PPP_WITH_SRP
1927 1.1 christos case EAPT_SRP:
1928 1.1 christos if (len < 1) {
1929 1.1 christos error("EAP: received empty SRP Request");
1930 1.1 christos /* Bogus request; wait for something real. */
1931 1.1 christos return;
1932 1.1 christos }
1933 1.1 christos
1934 1.1 christos /* Get subtype */
1935 1.1 christos GETCHAR(vallen, inp);
1936 1.1 christos len--;
1937 1.1 christos switch (vallen) {
1938 1.1 christos case EAPSRP_CHALLENGE:
1939 1.1 christos tc = NULL;
1940 1.1 christos if (esp->es_client.ea_session != NULL) {
1941 1.1 christos tc = (struct t_client *)esp->es_client.
1942 1.1 christos ea_session;
1943 1.1 christos /*
1944 1.1 christos * If this is a new challenge, then start
1945 1.1 christos * over with a new client session context.
1946 1.1 christos * Otherwise, just resend last response.
1947 1.1 christos */
1948 1.1 christos if (id != esp->es_client.ea_id) {
1949 1.1 christos t_clientclose(tc);
1950 1.1 christos esp->es_client.ea_session = NULL;
1951 1.1 christos tc = NULL;
1952 1.1 christos }
1953 1.1 christos }
1954 1.1 christos /* No session key just yet */
1955 1.1 christos esp->es_client.ea_skey = NULL;
1956 1.1 christos if (tc == NULL) {
1957 1.1 christos GETCHAR(vallen, inp);
1958 1.1 christos len--;
1959 1.1 christos if (vallen >= len) {
1960 1.1 christos error("EAP: badly-formed SRP Challenge"
1961 1.1 christos " (name)");
1962 1.1 christos /* Ignore badly-formed messages */
1963 1.1 christos return;
1964 1.1 christos }
1965 1.1 christos BCOPY(inp, rhostname, vallen);
1966 1.1 christos rhostname[vallen] = '\0';
1967 1.1 christos INCPTR(vallen, inp);
1968 1.1 christos len -= vallen;
1969 1.1 christos
1970 1.1 christos /*
1971 1.1 christos * In case the remote doesn't give us his name,
1972 1.1 christos * use configured name.
1973 1.1 christos */
1974 1.1 christos if (explicit_remote ||
1975 1.1 christos (remote_name[0] != '\0' && vallen == 0)) {
1976 1.1 christos strlcpy(rhostname, remote_name,
1977 1.1 christos sizeof (rhostname));
1978 1.1 christos }
1979 1.1 christos
1980 1.1 christos if (esp->es_client.ea_peer != NULL)
1981 1.1 christos free(esp->es_client.ea_peer);
1982 1.1 christos esp->es_client.ea_peer = strdup(rhostname);
1983 1.1 christos esp->es_client.ea_peerlen = strlen(rhostname);
1984 1.1 christos
1985 1.1 christos GETCHAR(vallen, inp);
1986 1.1 christos len--;
1987 1.1 christos if (vallen >= len) {
1988 1.1 christos error("EAP: badly-formed SRP Challenge"
1989 1.1 christos " (s)");
1990 1.1 christos /* Ignore badly-formed messages */
1991 1.1 christos return;
1992 1.1 christos }
1993 1.1 christos sval.data = inp;
1994 1.1 christos sval.len = vallen;
1995 1.1 christos INCPTR(vallen, inp);
1996 1.1 christos len -= vallen;
1997 1.1 christos
1998 1.1 christos GETCHAR(vallen, inp);
1999 1.1 christos len--;
2000 1.1 christos if (vallen > len) {
2001 1.1 christos error("EAP: badly-formed SRP Challenge"
2002 1.1 christos " (g)");
2003 1.1 christos /* Ignore badly-formed messages */
2004 1.1 christos return;
2005 1.1 christos }
2006 1.1 christos /* If no generator present, then use value 2 */
2007 1.1 christos if (vallen == 0) {
2008 1.1 christos gval.data = (u_char *)"\002";
2009 1.1 christos gval.len = 1;
2010 1.1 christos } else {
2011 1.1 christos gval.data = inp;
2012 1.1 christos gval.len = vallen;
2013 1.1 christos }
2014 1.1 christos INCPTR(vallen, inp);
2015 1.1 christos len -= vallen;
2016 1.1 christos
2017 1.1 christos /*
2018 1.1 christos * If no modulus present, then use well-known
2019 1.1 christos * value.
2020 1.1 christos */
2021 1.1 christos if (len == 0) {
2022 1.1 christos Nval.data = (u_char *)wkmodulus;
2023 1.1 christos Nval.len = sizeof (wkmodulus);
2024 1.1 christos } else {
2025 1.1 christos Nval.data = inp;
2026 1.1 christos Nval.len = len;
2027 1.1 christos }
2028 1.1 christos tc = t_clientopen(esp->es_client.ea_name,
2029 1.1 christos &Nval, &gval, &sval);
2030 1.1 christos if (tc == NULL) {
2031 1.1 christos eap_send_nak(esp, id, EAPT_MD5CHAP);
2032 1.1 christos break;
2033 1.1 christos }
2034 1.1 christos esp->es_client.ea_session = (void *)tc;
2035 1.1 christos
2036 1.1 christos /* Add Challenge ID & type to verifier */
2037 1.1 christos vals[0] = id;
2038 1.1 christos vals[1] = EAPT_SRP;
2039 1.1 christos t_clientaddexdata(tc, vals, 2);
2040 1.1 christos }
2041 1.1 christos Ap = t_clientgenexp(tc);
2042 1.1 christos eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,
2043 1.1 christos Ap->len);
2044 1.1 christos break;
2045 1.1 christos
2046 1.1 christos case EAPSRP_SKEY:
2047 1.1 christos tc = (struct t_client *)esp->es_client.ea_session;
2048 1.1 christos if (tc == NULL) {
2049 1.1 christos warn("EAP: peer sent Subtype 2 without 1");
2050 1.1 christos eap_send_nak(esp, id, EAPT_MD5CHAP);
2051 1.1 christos break;
2052 1.1 christos }
2053 1.1 christos if (esp->es_client.ea_skey != NULL) {
2054 1.1 christos /*
2055 1.1 christos * ID number should not change here. Warn
2056 1.1 christos * if it does (but otherwise ignore).
2057 1.1 christos */
2058 1.1 christos if (id != esp->es_client.ea_id) {
2059 1.1 christos warn("EAP: ID changed from %d to %d "
2060 1.1 christos "in SRP Subtype 2 rexmit",
2061 1.1 christos esp->es_client.ea_id, id);
2062 1.1 christos }
2063 1.1 christos } else {
2064 1.1 christos if (get_srp_secret(esp->es_unit,
2065 1.1 christos esp->es_client.ea_name,
2066 1.1 christos esp->es_client.ea_peer, secret, 0) == 0) {
2067 1.1 christos /*
2068 1.1 christos * Can't work with this peer because
2069 1.1 christos * the secret is missing. Just give
2070 1.1 christos * up.
2071 1.1 christos */
2072 1.1 christos eap_send_nak(esp, id, EAPT_MD5CHAP);
2073 1.1 christos break;
2074 1.1 christos }
2075 1.1 christos Bval.data = inp;
2076 1.1 christos Bval.len = len;
2077 1.1 christos t_clientpasswd(tc, secret);
2078 1.1 christos BZERO(secret, sizeof (secret));
2079 1.1 christos esp->es_client.ea_skey =
2080 1.1 christos t_clientgetkey(tc, &Bval);
2081 1.1 christos if (esp->es_client.ea_skey == NULL) {
2082 1.1 christos /* Server is rogue; stop now */
2083 1.1 christos error("EAP: SRP server is rogue");
2084 1.1 christos goto client_failure;
2085 1.1 christos }
2086 1.1 christos }
2087 1.1 christos eap_srpval_response(esp, id, SRPVAL_EBIT,
2088 1.1 christos t_clientresponse(tc));
2089 1.1 christos break;
2090 1.1 christos
2091 1.1 christos case EAPSRP_SVALIDATOR:
2092 1.1 christos tc = (struct t_client *)esp->es_client.ea_session;
2093 1.1 christos if (tc == NULL || esp->es_client.ea_skey == NULL) {
2094 1.1 christos warn("EAP: peer sent Subtype 3 without 1/2");
2095 1.1 christos eap_send_nak(esp, id, EAPT_MD5CHAP);
2096 1.1 christos break;
2097 1.1 christos }
2098 1.1 christos /*
2099 1.1 christos * If we're already open, then this ought to be a
2100 1.1 christos * duplicate. Otherwise, check that the server is
2101 1.1 christos * who we think it is.
2102 1.1 christos */
2103 1.1 christos if (esp->es_client.ea_state == eapOpen) {
2104 1.1 christos if (id != esp->es_client.ea_id) {
2105 1.1 christos warn("EAP: ID changed from %d to %d "
2106 1.1 christos "in SRP Subtype 3 rexmit",
2107 1.1 christos esp->es_client.ea_id, id);
2108 1.1 christos }
2109 1.1 christos } else {
2110 1.1.1.5 christos len -= sizeof (u_int32_t) + SHA_DIGEST_LENGTH;
2111 1.1 christos if (len < 0 || t_clientverify(tc, inp +
2112 1.1 christos sizeof (u_int32_t)) != 0) {
2113 1.1 christos error("EAP: SRP server verification "
2114 1.1 christos "failed");
2115 1.1 christos goto client_failure;
2116 1.1 christos }
2117 1.1 christos GETLONG(esp->es_client.ea_keyflags, inp);
2118 1.1 christos /* Save pseudonym if user wants it. */
2119 1.1 christos if (len > 0 && esp->es_usepseudo) {
2120 1.1.1.5 christos INCPTR(SHA_DIGEST_LENGTH, inp);
2121 1.1 christos write_pseudonym(esp, inp, len, id);
2122 1.1 christos }
2123 1.1 christos }
2124 1.1 christos /*
2125 1.1 christos * We've verified our peer. We're now mostly done,
2126 1.1 christos * except for waiting on the regular EAP Success
2127 1.1 christos * message.
2128 1.1 christos */
2129 1.1 christos eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);
2130 1.1 christos break;
2131 1.1 christos
2132 1.1 christos case EAPSRP_LWRECHALLENGE:
2133 1.1 christos if (len < 4) {
2134 1.1 christos warn("EAP: malformed Lightweight rechallenge");
2135 1.1 christos return;
2136 1.1 christos }
2137 1.1.1.5 christos ctxt = PPP_MD_CTX_new();
2138 1.1.1.5 christos if (ctxt) {
2139 1.1.1.5 christos
2140 1.1.1.5 christos vals[0] = id;
2141 1.1.1.5 christos PPP_DigestInit(ctxt, PPP_sha1());
2142 1.1.1.5 christos PPP_DigestUpdate(ctxt, vals, 1);
2143 1.1.1.5 christos PPP_DigestUpdate(ctxt, esp->es_client.ea_skey,
2144 1.1.1.5 christos SESSION_KEY_LEN);
2145 1.1.1.5 christos PPP_DigestUpdate(ctxt, inp, len);
2146 1.1.1.5 christos PPP_DigestUpdate(ctxt, esp->es_client.ea_name,
2147 1.1.1.5 christos esp->es_client.ea_namelen);
2148 1.1.1.5 christos PPP_DigestFinal(ctxt, dig, &diglen);
2149 1.1.1.5 christos
2150 1.1.1.5 christos PPP_MD_CTX_free(ctxt);
2151 1.1.1.5 christos
2152 1.1.1.5 christos eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,
2153 1.1.1.5 christos SHA_DIGEST_LENGTH);
2154 1.1.1.5 christos }
2155 1.1 christos break;
2156 1.1 christos
2157 1.1 christos default:
2158 1.1 christos error("EAP: unknown SRP Subtype %d", vallen);
2159 1.1 christos eap_send_nak(esp, id, EAPT_MD5CHAP);
2160 1.1 christos break;
2161 1.1 christos }
2162 1.1 christos break;
2163 1.1.1.5 christos #endif /* PPP_WITH_SRP */
2164 1.1.1.5 christos
2165 1.1.1.5 christos #ifdef PPP_WITH_CHAPMS
2166 1.1.1.4 christos case EAPT_MSCHAPV2:
2167 1.1.1.4 christos if (len < 4) {
2168 1.1.1.4 christos error("EAP: received invalid MSCHAPv2 packet, too short");
2169 1.1.1.4 christos return;
2170 1.1.1.4 christos }
2171 1.1.1.4 christos unsigned char opcode;
2172 1.1.1.4 christos GETCHAR(opcode, inp);
2173 1.1.1.4 christos unsigned char chapid; /* Chapv2-ID */
2174 1.1.1.4 christos GETCHAR(chapid, inp);
2175 1.1.1.4 christos short mssize;
2176 1.1.1.4 christos GETSHORT(mssize, inp);
2177 1.1.1.4 christos
2178 1.1.1.4 christos /* Validate the mssize field */
2179 1.1.1.4 christos if (len != mssize) {
2180 1.1.1.4 christos error("EAP: received invalid MSCHAPv2 packet, invalid length");
2181 1.1.1.4 christos return;
2182 1.1.1.4 christos }
2183 1.1.1.4 christos len -= 4;
2184 1.1.1.4 christos
2185 1.1.1.4 christos /* If MSCHAPv2 digest was not found, NAK the packet */
2186 1.1.1.4 christos if (!esp->es_client.digest) {
2187 1.1.1.4 christos error("EAP MSCHAPv2 not supported");
2188 1.1.1.4 christos eap_send_nak(esp, id, EAPT_SRP);
2189 1.1.1.4 christos return;
2190 1.1.1.4 christos }
2191 1.1.1.4 christos
2192 1.1.1.4 christos switch (opcode) {
2193 1.1.1.4 christos case CHAP_CHALLENGE: {
2194 1.1.1.4 christos
2195 1.1.1.4 christos /* make_response() expects: VLEN + VALUE */
2196 1.1.1.4 christos u_char *challenge = inp;
2197 1.1.1.4 christos
2198 1.1.1.4 christos unsigned char vsize;
2199 1.1.1.4 christos GETCHAR(vsize, inp);
2200 1.1.1.4 christos len -= 1;
2201 1.1.1.4 christos
2202 1.1.1.4 christos /* Validate the VALUE field */
2203 1.1.1.4 christos if (vsize != MS_CHAP2_PEER_CHAL_LEN || len < MS_CHAP2_PEER_CHAL_LEN) {
2204 1.1.1.4 christos error("EAP: received invalid MSCHAPv2 packet, invalid value-length: %d", vsize);
2205 1.1.1.4 christos return;
2206 1.1.1.4 christos }
2207 1.1.1.4 christos
2208 1.1.1.4 christos /* Increment past the VALUE field */
2209 1.1.1.4 christos INCPTR(MS_CHAP2_PEER_CHAL_LEN, inp);
2210 1.1.1.4 christos len -= MS_CHAP2_PEER_CHAL_LEN;
2211 1.1.1.4 christos
2212 1.1.1.4 christos /* Extract the hostname */
2213 1.1.1.4 christos rhostname[0] = '\0';
2214 1.1.1.4 christos if (len > 0) {
2215 1.1.1.4 christos if (len >= sizeof (rhostname)) {
2216 1.1.1.4 christos dbglog("EAP: trimming really long peer name down");
2217 1.1.1.4 christos len = sizeof(rhostname) - 1;
2218 1.1.1.4 christos }
2219 1.1.1.4 christos BCOPY(inp, rhostname, len);
2220 1.1.1.4 christos rhostname[len] = '\0';
2221 1.1.1.4 christos }
2222 1.1.1.4 christos
2223 1.1.1.4 christos /* In case the remote doesn't give us his name. */
2224 1.1.1.4 christos if (explicit_remote || (remote_name[0] != '\0' && len == 0))
2225 1.1.1.4 christos strlcpy(rhostname, remote_name, sizeof(rhostname));
2226 1.1.1.4 christos
2227 1.1.1.4 christos /* Get the secret for authenticating ourselves with the specified host. */
2228 1.1.1.4 christos if (!get_secret(esp->es_unit, esp->es_client.ea_name,
2229 1.1.1.4 christos rhostname, secret, &secret_len, 0)) {
2230 1.1.1.4 christos dbglog("EAP: no CHAP secret for auth to %q", rhostname);
2231 1.1.1.4 christos eap_send_nak(esp, id, EAPT_SRP);
2232 1.1.1.4 christos break;
2233 1.1.1.4 christos }
2234 1.1.1.5 christos esp->es_client.ea_namelen = strlen(esp->es_client.ea_name);
2235 1.1.1.4 christos
2236 1.1.1.4 christos /* Create the MSCHAPv2 response (and add to cache) */
2237 1.1.1.4 christos unsigned char response[MS_CHAP2_RESPONSE_LEN+1]; // VLEN + VALUE
2238 1.1.1.4 christos esp->es_client.digest->make_response(response, chapid, esp->es_client.ea_name,
2239 1.1.1.4 christos challenge, secret, secret_len, NULL);
2240 1.1.1.4 christos
2241 1.1.1.4 christos eap_chapv2_response(esp, id, chapid, response, esp->es_client.ea_name, esp->es_client.ea_namelen);
2242 1.1.1.4 christos break;
2243 1.1.1.4 christos }
2244 1.1.1.4 christos case CHAP_SUCCESS: {
2245 1.1.1.4 christos
2246 1.1.1.4 christos /* Check response for mutual authentication */
2247 1.1.1.4 christos u_char status = CHAP_FAILURE;
2248 1.1.1.4 christos if (esp->es_client.digest->check_success(chapid, inp, len) == 1) {
2249 1.1.1.4 christos info("Chap authentication succeeded! %.*v", len, inp);
2250 1.1.1.4 christos status = CHAP_SUCCESS;
2251 1.1.1.4 christos }
2252 1.1.1.4 christos eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
2253 1.1.1.4 christos break;
2254 1.1.1.4 christos }
2255 1.1.1.4 christos case CHAP_FAILURE: {
2256 1.1.1.4 christos
2257 1.1.1.4 christos /* Process the failure string, and log appropriate information */
2258 1.1.1.4 christos esp->es_client.digest->handle_failure(inp, len);
2259 1.1.1.4 christos
2260 1.1.1.4 christos u_char status = CHAP_FAILURE;
2261 1.1.1.4 christos eap_send_response(esp, id, EAPT_MSCHAPV2, &status, sizeof(status));
2262 1.1.1.4 christos goto client_failure; /* force termination */
2263 1.1.1.4 christos }
2264 1.1.1.4 christos default:
2265 1.1.1.4 christos
2266 1.1.1.4 christos error("EAP: received invalid MSCHAPv2 packet, invalid or unsupported opcode: %d", opcode);
2267 1.1.1.4 christos eap_send_nak(esp, id, EAPT_SRP);
2268 1.1.1.4 christos }
2269 1.1.1.4 christos
2270 1.1.1.4 christos break;
2271 1.1.1.5 christos #endif /* PPP_WITH_CHAPMS */
2272 1.1.1.5 christos #ifdef PPP_WITH_PEAP
2273 1.1.1.5 christos case EAPT_PEAP:
2274 1.1.1.5 christos
2275 1.1.1.5 christos /* Initialize the PEAP context (if not already initialized) */
2276 1.1.1.5 christos if (!esp->ea_peap) {
2277 1.1.1.5 christos rhostname[0] = '\0';
2278 1.1.1.5 christos if (explicit_remote || (remote_name[0] != '\0')) {
2279 1.1.1.5 christos strlcpy(rhostname, remote_name, sizeof (rhostname));
2280 1.1.1.5 christos }
2281 1.1.1.5 christos if (peap_init(&esp->ea_peap, rhostname)) {
2282 1.1.1.5 christos eap_send_nak(esp, id, EAPT_TLS);
2283 1.1.1.5 christos break;
2284 1.1.1.5 christos }
2285 1.1.1.5 christos }
2286 1.1.1.5 christos
2287 1.1.1.5 christos /* Process the PEAP packet */
2288 1.1.1.5 christos if (peap_process(esp, id, inp, len)) {
2289 1.1.1.5 christos eap_send_nak(esp, id, EAPT_TLS);
2290 1.1.1.5 christos }
2291 1.1.1.5 christos
2292 1.1.1.5 christos break;
2293 1.1.1.5 christos #endif // PPP_WITH_PEAP
2294 1.1 christos
2295 1.1 christos default:
2296 1.1 christos info("EAP: unknown authentication type %d; Naking", typenum);
2297 1.1 christos eap_send_nak(esp, id, EAPT_SRP);
2298 1.1 christos break;
2299 1.1 christos }
2300 1.1 christos
2301 1.1 christos if (esp->es_client.ea_timeout > 0) {
2302 1.1 christos UNTIMEOUT(eap_client_timeout, (void *)esp);
2303 1.1 christos TIMEOUT(eap_client_timeout, (void *)esp,
2304 1.1 christos esp->es_client.ea_timeout);
2305 1.1 christos }
2306 1.1 christos return;
2307 1.1 christos
2308 1.1 christos client_failure:
2309 1.1 christos esp->es_client.ea_state = eapBadAuth;
2310 1.1 christos if (esp->es_client.ea_timeout > 0) {
2311 1.1 christos UNTIMEOUT(eap_client_timeout, (void *)esp);
2312 1.1 christos }
2313 1.1 christos esp->es_client.ea_session = NULL;
2314 1.1.1.5 christos #ifdef PPP_WITH_SRP
2315 1.1 christos t_clientclose(tc);
2316 1.1 christos auth_withpeer_fail(esp->es_unit, PPP_EAP);
2317 1.1.1.5 christos #endif /* PPP_WITH_SRP */
2318 1.1 christos }
2319 1.1 christos
2320 1.1 christos /*
2321 1.1 christos * eap_response - Receive EAP Response message (server mode).
2322 1.1 christos */
2323 1.1 christos static void
2324 1.1.1.4 christos eap_response(eap_state *esp, u_char *inp, int id, int len)
2325 1.1 christos {
2326 1.1 christos u_char typenum;
2327 1.1 christos u_char vallen;
2328 1.1 christos int secret_len;
2329 1.1 christos char secret[MAXSECRETLEN];
2330 1.1 christos char rhostname[256];
2331 1.1.1.5 christos PPP_MD_CTX *mdctx;
2332 1.1.1.5 christos u_char hash[MD5_DIGEST_LENGTH];
2333 1.1.1.5 christos int hashlen = MD5_DIGEST_LENGTH;
2334 1.1.1.5 christos #ifdef PPP_WITH_SRP
2335 1.1 christos struct t_server *ts;
2336 1.1 christos struct t_num A;
2337 1.1.1.5 christos PPP_MD_CTX *ctxt;
2338 1.1.1.5 christos u_char dig[SHA_DIGEST_LENGTH];
2339 1.1.1.5 christos int diglen = sizeof(dig);
2340 1.1.1.5 christos #endif /* PPP_WITH_SRP */
2341 1.1 christos
2342 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
2343 1.1.1.4 christos struct eaptls_session *ets;
2344 1.1.1.4 christos u_char flags;
2345 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
2346 1.1.1.5 christos #ifdef PPP_WITH_CHAPMS
2347 1.1.1.4 christos u_char opcode;
2348 1.1.1.5 christos chap_verify_hook_fn *chap_verifier;
2349 1.1.1.4 christos char response_message[256];
2350 1.1.1.5 christos #endif /* PPP_WITH_CHAPMS */
2351 1.1.1.4 christos
2352 1.1.1.4 christos /*
2353 1.1.1.4 christos * Ignore responses if we're not open
2354 1.1.1.4 christos */
2355 1.1.1.4 christos if (esp->es_server.ea_state <= eapClosed)
2356 1.1.1.4 christos return;
2357 1.1.1.4 christos
2358 1.1 christos if (esp->es_server.ea_id != id) {
2359 1.1 christos dbglog("EAP: discarding Response %d; expected ID %d", id,
2360 1.1 christos esp->es_server.ea_id);
2361 1.1 christos return;
2362 1.1 christos }
2363 1.1 christos
2364 1.1 christos esp->es_server.ea_responses++;
2365 1.1 christos
2366 1.1 christos if (len <= 0) {
2367 1.1 christos error("EAP: empty Response message discarded");
2368 1.1 christos return;
2369 1.1 christos }
2370 1.1 christos
2371 1.1 christos GETCHAR(typenum, inp);
2372 1.1 christos len--;
2373 1.1 christos
2374 1.1 christos switch (typenum) {
2375 1.1 christos case EAPT_IDENTITY:
2376 1.1 christos if (esp->es_server.ea_state != eapIdentify) {
2377 1.1 christos dbglog("EAP discarding unwanted Identify \"%.q\"", len,
2378 1.1 christos inp);
2379 1.1 christos break;
2380 1.1 christos }
2381 1.1 christos info("EAP: unauthenticated peer name \"%.*q\"", len, inp);
2382 1.1 christos if (esp->es_server.ea_peer != NULL &&
2383 1.1 christos esp->es_server.ea_peer != remote_name)
2384 1.1 christos free(esp->es_server.ea_peer);
2385 1.1 christos esp->es_server.ea_peer = malloc(len + 1);
2386 1.1 christos if (esp->es_server.ea_peer == NULL) {
2387 1.1 christos esp->es_server.ea_peerlen = 0;
2388 1.1 christos eap_figure_next_state(esp, 1);
2389 1.1 christos break;
2390 1.1 christos }
2391 1.1 christos BCOPY(inp, esp->es_server.ea_peer, len);
2392 1.1 christos esp->es_server.ea_peer[len] = '\0';
2393 1.1 christos esp->es_server.ea_peerlen = len;
2394 1.1 christos eap_figure_next_state(esp, 0);
2395 1.1 christos break;
2396 1.1 christos
2397 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
2398 1.1.1.4 christos case EAPT_TLS:
2399 1.1.1.4 christos switch(esp->es_server.ea_state) {
2400 1.1.1.4 christos
2401 1.1.1.4 christos case eapTlsRecv:
2402 1.1.1.4 christos
2403 1.1.1.4 christos ets = (struct eaptls_session *) esp->es_server.ea_session;
2404 1.1.1.4 christos
2405 1.1.1.4 christos eap_figure_next_state(esp,
2406 1.1.1.4 christos eaptls_receive(esp->es_server.ea_session, inp, len));
2407 1.1.1.4 christos
2408 1.1.1.4 christos if(ets->alert_recv) {
2409 1.1.1.4 christos eap_send_failure(esp);
2410 1.1.1.4 christos break;
2411 1.1.1.4 christos }
2412 1.1.1.4 christos break;
2413 1.1.1.4 christos
2414 1.1.1.4 christos case eapTlsRecvAck:
2415 1.1.1.4 christos if(len > 1) {
2416 1.1.1.4 christos dbglog("EAP-TLS ACK with extra data");
2417 1.1.1.4 christos }
2418 1.1.1.4 christos eap_figure_next_state(esp, 0);
2419 1.1.1.4 christos break;
2420 1.1.1.4 christos
2421 1.1.1.4 christos case eapTlsRecvClient:
2422 1.1.1.4 christos /* Receive authentication response from client */
2423 1.1.1.4 christos if (len > 0) {
2424 1.1.1.4 christos GETCHAR(flags, inp);
2425 1.1.1.4 christos
2426 1.1.1.4 christos if(len == 1 && !flags) { /* Ack = ok */
2427 1.1.1.5 christos #ifdef PPP_WITH_MPPE
2428 1.1.1.4 christos eaptls_gen_mppe_keys( esp->es_server.ea_session, 0 );
2429 1.1.1.4 christos #endif
2430 1.1.1.4 christos eap_send_success(esp);
2431 1.1.1.4 christos }
2432 1.1.1.4 christos else { /* failure */
2433 1.1.1.4 christos warn("Server authentication failed");
2434 1.1.1.4 christos eap_send_failure(esp);
2435 1.1.1.4 christos }
2436 1.1.1.4 christos }
2437 1.1.1.4 christos else
2438 1.1.1.4 christos warn("Bogus EAP-TLS packet received from client");
2439 1.1.1.4 christos
2440 1.1.1.4 christos eaptls_free_session(esp->es_server.ea_session);
2441 1.1.1.4 christos
2442 1.1.1.4 christos break;
2443 1.1.1.4 christos
2444 1.1.1.4 christos case eapTlsRecvAlertAck:
2445 1.1.1.4 christos eap_send_failure(esp);
2446 1.1.1.4 christos break;
2447 1.1.1.4 christos
2448 1.1.1.4 christos default:
2449 1.1.1.4 christos eap_figure_next_state(esp, 1);
2450 1.1.1.4 christos break;
2451 1.1.1.4 christos }
2452 1.1.1.4 christos break;
2453 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
2454 1.1.1.4 christos
2455 1.1 christos case EAPT_NOTIFICATION:
2456 1.1 christos dbglog("EAP unexpected Notification; response discarded");
2457 1.1 christos break;
2458 1.1 christos
2459 1.1 christos case EAPT_NAK:
2460 1.1 christos if (len < 1) {
2461 1.1 christos info("EAP: Nak Response with no suggested protocol");
2462 1.1 christos eap_figure_next_state(esp, 1);
2463 1.1 christos break;
2464 1.1 christos }
2465 1.1 christos
2466 1.1 christos GETCHAR(vallen, inp);
2467 1.1 christos len--;
2468 1.1 christos
2469 1.1 christos if (!explicit_remote && esp->es_server.ea_state == eapIdentify){
2470 1.1 christos /* Peer cannot Nak Identify Request */
2471 1.1 christos eap_figure_next_state(esp, 1);
2472 1.1 christos break;
2473 1.1 christos }
2474 1.1 christos
2475 1.1 christos switch (vallen) {
2476 1.1 christos case EAPT_SRP:
2477 1.1 christos /* Run through SRP validator selection again. */
2478 1.1 christos esp->es_server.ea_state = eapIdentify;
2479 1.1 christos eap_figure_next_state(esp, 0);
2480 1.1 christos break;
2481 1.1 christos
2482 1.1 christos case EAPT_MD5CHAP:
2483 1.1 christos esp->es_server.ea_state = eapMD5Chall;
2484 1.1 christos break;
2485 1.1 christos
2486 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
2487 1.1.1.4 christos /* Send EAP-TLS start packet */
2488 1.1.1.4 christos case EAPT_TLS:
2489 1.1.1.4 christos esp->es_server.ea_state = eapTlsStart;
2490 1.1.1.4 christos break;
2491 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
2492 1.1.1.4 christos
2493 1.1.1.5 christos #ifdef PPP_WITH_CHAPMS
2494 1.1.1.4 christos case EAPT_MSCHAPV2:
2495 1.1.1.4 christos info("EAP: peer proposes MSCHAPv2");
2496 1.1.1.5 christos /* If MSCHAPv2 digest was not found, NAK the packet */
2497 1.1.1.5 christos if (!esp->es_server.digest) {
2498 1.1.1.5 christos error("EAP MSCHAPv2 not supported");
2499 1.1.1.5 christos eap_send_nak(esp, id, EAPT_SRP);
2500 1.1.1.5 christos break;
2501 1.1.1.5 christos }
2502 1.1.1.4 christos esp->es_server.ea_state = eapMSCHAPv2Chall;
2503 1.1.1.4 christos break;
2504 1.1.1.5 christos #endif /* PPP_WITH_CHAPMS */
2505 1.1.1.4 christos
2506 1.1 christos default:
2507 1.1 christos dbglog("EAP: peer requesting unknown Type %d", vallen);
2508 1.1 christos switch (esp->es_server.ea_state) {
2509 1.1 christos case eapSRP1:
2510 1.1 christos case eapSRP2:
2511 1.1 christos case eapSRP3:
2512 1.1 christos esp->es_server.ea_state = eapMD5Chall;
2513 1.1 christos break;
2514 1.1 christos case eapMD5Chall:
2515 1.1 christos case eapSRP4:
2516 1.1 christos esp->es_server.ea_state = eapIdentify;
2517 1.1 christos eap_figure_next_state(esp, 0);
2518 1.1 christos break;
2519 1.1 christos default:
2520 1.1 christos break;
2521 1.1 christos }
2522 1.1 christos break;
2523 1.1 christos }
2524 1.1 christos break;
2525 1.1 christos
2526 1.1 christos case EAPT_MD5CHAP:
2527 1.1 christos if (esp->es_server.ea_state != eapMD5Chall) {
2528 1.1 christos error("EAP: unexpected MD5-Response");
2529 1.1 christos eap_figure_next_state(esp, 1);
2530 1.1 christos break;
2531 1.1 christos }
2532 1.1 christos if (len < 1) {
2533 1.1 christos error("EAP: received MD5-Response with no data");
2534 1.1 christos eap_figure_next_state(esp, 1);
2535 1.1 christos break;
2536 1.1 christos }
2537 1.1 christos GETCHAR(vallen, inp);
2538 1.1 christos len--;
2539 1.1 christos if (vallen != 16 || vallen > len) {
2540 1.1 christos error("EAP: MD5-Response with bad length %d", vallen);
2541 1.1 christos eap_figure_next_state(esp, 1);
2542 1.1 christos break;
2543 1.1 christos }
2544 1.1 christos
2545 1.1 christos /* Not so likely to happen. */
2546 1.1.1.4 christos if (len - vallen >= sizeof (rhostname)) {
2547 1.1 christos dbglog("EAP: trimming really long peer name down");
2548 1.1 christos BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2549 1.1 christos rhostname[sizeof (rhostname) - 1] = '\0';
2550 1.1 christos } else {
2551 1.1 christos BCOPY(inp + vallen, rhostname, len - vallen);
2552 1.1 christos rhostname[len - vallen] = '\0';
2553 1.1 christos }
2554 1.1 christos
2555 1.1 christos /* In case the remote doesn't give us his name. */
2556 1.1 christos if (explicit_remote ||
2557 1.1 christos (remote_name[0] != '\0' && vallen == len))
2558 1.1 christos strlcpy(rhostname, remote_name, sizeof (rhostname));
2559 1.1 christos
2560 1.1 christos /*
2561 1.1 christos * Get the secret for authenticating the specified
2562 1.1 christos * host.
2563 1.1 christos */
2564 1.1 christos if (!get_secret(esp->es_unit, rhostname,
2565 1.1 christos esp->es_server.ea_name, secret, &secret_len, 1)) {
2566 1.1 christos dbglog("EAP: no MD5 secret for auth of %q", rhostname);
2567 1.1 christos eap_send_failure(esp);
2568 1.1 christos break;
2569 1.1 christos }
2570 1.1.1.5 christos
2571 1.1.1.5 christos mdctx = PPP_MD_CTX_new();
2572 1.1.1.5 christos if (mdctx != NULL) {
2573 1.1.1.5 christos
2574 1.1.1.5 christos if (PPP_DigestInit(mdctx, PPP_md5())) {
2575 1.1.1.5 christos
2576 1.1.1.5 christos if (PPP_DigestUpdate(mdctx, &esp->es_server.ea_id, 1)) {
2577 1.1.1.5 christos
2578 1.1.1.5 christos if (PPP_DigestUpdate(mdctx, &secret, secret_len)) {
2579 1.1.1.5 christos
2580 1.1.1.5 christos BZERO(secret, sizeof(secret));
2581 1.1.1.5 christos if (PPP_DigestUpdate(mdctx, esp->es_challenge, esp->es_challen)) {
2582 1.1.1.5 christos
2583 1.1.1.5 christos if (PPP_DigestFinal(mdctx, hash, &hashlen)) {
2584 1.1.1.5 christos
2585 1.1.1.5 christos if (BCMP(hash, inp, MD5_DIGEST_LENGTH) == 0) {
2586 1.1.1.5 christos esp->es_server.ea_type = EAPT_MD5CHAP;
2587 1.1.1.5 christos eap_send_success(esp);
2588 1.1.1.5 christos eap_figure_next_state(esp, 0);
2589 1.1.1.5 christos
2590 1.1.1.5 christos if (esp->es_rechallenge != 0) {
2591 1.1.1.5 christos TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2592 1.1.1.5 christos }
2593 1.1.1.5 christos PPP_MD_CTX_free(mdctx);
2594 1.1.1.5 christos break;
2595 1.1.1.5 christos }
2596 1.1.1.5 christos }
2597 1.1.1.5 christos }
2598 1.1.1.5 christos }
2599 1.1.1.5 christos }
2600 1.1.1.5 christos }
2601 1.1.1.5 christos
2602 1.1.1.5 christos PPP_MD_CTX_free(mdctx);
2603 1.1 christos }
2604 1.1.1.5 christos
2605 1.1.1.5 christos eap_send_failure(esp);
2606 1.1 christos break;
2607 1.1 christos
2608 1.1.1.5 christos #ifdef PPP_WITH_CHAPMS
2609 1.1.1.4 christos case EAPT_MSCHAPV2:
2610 1.1.1.4 christos if (len < 1) {
2611 1.1.1.4 christos error("EAP: received MSCHAPv2 with no data");
2612 1.1.1.4 christos eap_figure_next_state(esp, 1);
2613 1.1.1.4 christos break;
2614 1.1.1.4 christos }
2615 1.1.1.4 christos GETCHAR(opcode, inp);
2616 1.1.1.4 christos len--;
2617 1.1.1.4 christos
2618 1.1.1.4 christos switch (opcode) {
2619 1.1.1.4 christos case CHAP_RESPONSE:
2620 1.1.1.4 christos if (esp->es_server.ea_state != eapMSCHAPv2Chall) {
2621 1.1.1.4 christos error("EAP: unexpected MSCHAPv2-Response");
2622 1.1.1.4 christos eap_figure_next_state(esp, 1);
2623 1.1.1.4 christos break;
2624 1.1.1.4 christos }
2625 1.1.1.4 christos /* skip MS ID + len */
2626 1.1.1.4 christos INCPTR(3, inp);
2627 1.1.1.4 christos GETCHAR(vallen, inp);
2628 1.1.1.4 christos len -= 4;
2629 1.1.1.4 christos
2630 1.1.1.4 christos if (vallen != MS_CHAP2_RESPONSE_LEN || vallen > len) {
2631 1.1.1.4 christos error("EAP: Invalid MSCHAPv2-Response "
2632 1.1.1.4 christos "length %d", vallen);
2633 1.1.1.4 christos eap_figure_next_state(esp, 1);
2634 1.1.1.4 christos break;
2635 1.1.1.4 christos }
2636 1.1.1.4 christos
2637 1.1.1.4 christos /* Not so likely to happen. */
2638 1.1.1.4 christos if (len - vallen >= sizeof (rhostname)) {
2639 1.1.1.4 christos dbglog("EAP: trimming really long peer name down");
2640 1.1.1.4 christos BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
2641 1.1.1.4 christos rhostname[sizeof (rhostname) - 1] = '\0';
2642 1.1.1.4 christos } else {
2643 1.1.1.4 christos BCOPY(inp + vallen, rhostname, len - vallen);
2644 1.1.1.4 christos rhostname[len - vallen] = '\0';
2645 1.1.1.4 christos }
2646 1.1.1.4 christos
2647 1.1.1.4 christos /* In case the remote doesn't give us his name. */
2648 1.1.1.4 christos if (explicit_remote ||
2649 1.1.1.4 christos (remote_name[0] != '\0' && vallen == len))
2650 1.1.1.4 christos strlcpy(rhostname, remote_name, sizeof (rhostname));
2651 1.1.1.4 christos
2652 1.1.1.5 christos /* strip the MS domain name */
2653 1.1.1.5 christos if (chapms_strip_domain && strrchr(rhostname, '\\')) {
2654 1.1.1.5 christos char tmp[MAXNAMELEN+1];
2655 1.1.1.5 christos
2656 1.1.1.5 christos strcpy(tmp, strrchr(rhostname, '\\') + 1);
2657 1.1.1.5 christos strlcpy(rhostname, tmp, sizeof(rhostname));
2658 1.1.1.5 christos }
2659 1.1.1.5 christos
2660 1.1.1.4 christos if (chap_verify_hook)
2661 1.1.1.4 christos chap_verifier = chap_verify_hook;
2662 1.1.1.4 christos else
2663 1.1.1.4 christos chap_verifier = eap_chap_verify_response;
2664 1.1.1.4 christos
2665 1.1.1.4 christos esp->es_server.ea_id += 1;
2666 1.1.1.4 christos if ((*chap_verifier)(rhostname,
2667 1.1.1.4 christos esp->es_server.ea_name,
2668 1.1.1.4 christos id,
2669 1.1.1.5 christos esp->es_server.digest,
2670 1.1.1.4 christos esp->es_challenge,
2671 1.1.1.4 christos inp - 1,
2672 1.1.1.4 christos response_message,
2673 1.1.1.4 christos sizeof(response_message)))
2674 1.1.1.4 christos {
2675 1.1.1.4 christos info("EAP: MSCHAPv2 success for peer %q",
2676 1.1.1.4 christos rhostname);
2677 1.1.1.4 christos esp->es_server.ea_type = EAPT_MSCHAPV2;
2678 1.1.1.4 christos eap_chapms2_send_request(esp,
2679 1.1.1.4 christos esp->es_server.ea_id,
2680 1.1.1.4 christos CHAP_SUCCESS,
2681 1.1.1.4 christos esp->es_server.ea_id,
2682 1.1.1.4 christos response_message,
2683 1.1.1.4 christos strlen(response_message));
2684 1.1.1.4 christos eap_figure_next_state(esp, 0);
2685 1.1.1.4 christos if (esp->es_rechallenge != 0)
2686 1.1.1.4 christos TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
2687 1.1.1.4 christos }
2688 1.1.1.4 christos else {
2689 1.1.1.4 christos warn("EAP: MSCHAPv2 failure for peer %q",
2690 1.1.1.4 christos rhostname);
2691 1.1.1.4 christos eap_chapms2_send_request(esp,
2692 1.1.1.4 christos esp->es_server.ea_id,
2693 1.1.1.4 christos CHAP_FAILURE,
2694 1.1.1.4 christos esp->es_server.ea_id,
2695 1.1.1.4 christos response_message,
2696 1.1.1.4 christos strlen(response_message));
2697 1.1.1.4 christos }
2698 1.1.1.4 christos break;
2699 1.1.1.4 christos case CHAP_SUCCESS:
2700 1.1.1.4 christos info("EAP: MSCHAPv2 success confirmed");
2701 1.1.1.4 christos break;
2702 1.1.1.4 christos case CHAP_FAILURE:
2703 1.1.1.4 christos info("EAP: MSCHAPv2 failure confirmed");
2704 1.1.1.4 christos break;
2705 1.1.1.4 christos default:
2706 1.1.1.4 christos error("EAP: Unhandled MSCHAPv2 opcode %d", opcode);
2707 1.1.1.4 christos eap_send_nak(esp, id, EAPT_SRP);
2708 1.1.1.4 christos }
2709 1.1.1.4 christos
2710 1.1.1.4 christos break;
2711 1.1.1.5 christos #endif /* PPP_WITH_CHAPMS */
2712 1.1.1.4 christos
2713 1.1.1.5 christos #ifdef PPP_WITH_SRP
2714 1.1 christos case EAPT_SRP:
2715 1.1 christos if (len < 1) {
2716 1.1 christos error("EAP: empty SRP Response");
2717 1.1 christos eap_figure_next_state(esp, 1);
2718 1.1 christos break;
2719 1.1 christos }
2720 1.1 christos GETCHAR(typenum, inp);
2721 1.1 christos len--;
2722 1.1 christos switch (typenum) {
2723 1.1 christos case EAPSRP_CKEY:
2724 1.1 christos if (esp->es_server.ea_state != eapSRP1) {
2725 1.1 christos error("EAP: unexpected SRP Subtype 1 Response");
2726 1.1 christos eap_figure_next_state(esp, 1);
2727 1.1 christos break;
2728 1.1 christos }
2729 1.1 christos A.data = inp;
2730 1.1 christos A.len = len;
2731 1.1 christos ts = (struct t_server *)esp->es_server.ea_session;
2732 1.1 christos assert(ts != NULL);
2733 1.1 christos esp->es_server.ea_skey = t_servergetkey(ts, &A);
2734 1.1 christos if (esp->es_server.ea_skey == NULL) {
2735 1.1 christos /* Client's A value is bogus; terminate now */
2736 1.1 christos error("EAP: bogus A value from client");
2737 1.1 christos eap_send_failure(esp);
2738 1.1 christos } else {
2739 1.1 christos eap_figure_next_state(esp, 0);
2740 1.1 christos }
2741 1.1 christos break;
2742 1.1 christos
2743 1.1 christos case EAPSRP_CVALIDATOR:
2744 1.1 christos if (esp->es_server.ea_state != eapSRP2) {
2745 1.1 christos error("EAP: unexpected SRP Subtype 2 Response");
2746 1.1 christos eap_figure_next_state(esp, 1);
2747 1.1 christos break;
2748 1.1 christos }
2749 1.1.1.5 christos if (len < sizeof (u_int32_t) + SHA_DIGEST_LENGTH) {
2750 1.1 christos error("EAP: M1 length %d < %d", len,
2751 1.1.1.5 christos sizeof (u_int32_t) + SHA_DIGEST_LENGTH);
2752 1.1 christos eap_figure_next_state(esp, 1);
2753 1.1 christos break;
2754 1.1 christos }
2755 1.1 christos GETLONG(esp->es_server.ea_keyflags, inp);
2756 1.1 christos ts = (struct t_server *)esp->es_server.ea_session;
2757 1.1 christos assert(ts != NULL);
2758 1.1 christos if (t_serververify(ts, inp)) {
2759 1.1 christos info("EAP: unable to validate client identity");
2760 1.1 christos eap_send_failure(esp);
2761 1.1 christos break;
2762 1.1 christos }
2763 1.1 christos eap_figure_next_state(esp, 0);
2764 1.1 christos break;
2765 1.1 christos
2766 1.1 christos case EAPSRP_ACK:
2767 1.1 christos if (esp->es_server.ea_state != eapSRP3) {
2768 1.1 christos error("EAP: unexpected SRP Subtype 3 Response");
2769 1.1 christos eap_send_failure(esp);
2770 1.1 christos break;
2771 1.1 christos }
2772 1.1 christos esp->es_server.ea_type = EAPT_SRP;
2773 1.1 christos eap_send_success(esp);
2774 1.1 christos eap_figure_next_state(esp, 0);
2775 1.1 christos if (esp->es_rechallenge != 0)
2776 1.1 christos TIMEOUT(eap_rechallenge, esp,
2777 1.1 christos esp->es_rechallenge);
2778 1.1 christos if (esp->es_lwrechallenge != 0)
2779 1.1 christos TIMEOUT(srp_lwrechallenge, esp,
2780 1.1 christos esp->es_lwrechallenge);
2781 1.1 christos break;
2782 1.1 christos
2783 1.1 christos case EAPSRP_LWRECHALLENGE:
2784 1.1 christos if (esp->es_server.ea_state != eapSRP4) {
2785 1.1 christos info("EAP: unexpected SRP Subtype 4 Response");
2786 1.1 christos return;
2787 1.1 christos }
2788 1.1.1.5 christos if (len != SHA_DIGEST_LENGTH) {
2789 1.1 christos error("EAP: bad Lightweight rechallenge "
2790 1.1 christos "response");
2791 1.1 christos return;
2792 1.1 christos }
2793 1.1.1.5 christos ctxt = PPP_MD_CTX_new();
2794 1.1.1.5 christos if (ctxt) {
2795 1.1.1.5 christos vallen = id;
2796 1.1.1.5 christos
2797 1.1.1.5 christos PPP_DigestInit(ctxt, PPP_sha1());
2798 1.1.1.5 christos PPP_DigestUpdate(ctxt, &vallen, 1);
2799 1.1.1.5 christos PPP_DigestUpdate(ctxt, esp->es_server.ea_skey,
2800 1.1.1.5 christos SESSION_KEY_LEN);
2801 1.1.1.5 christos PPP_DigestUpdate(ctxt, esp->es_challenge, esp->es_challen);
2802 1.1.1.5 christos PPP_DigestUpdate(ctxt, esp->es_server.ea_peer,
2803 1.1.1.5 christos esp->es_server.ea_peerlen);
2804 1.1.1.5 christos PPP_DigestFinal(ctxt, dig, &diglen);
2805 1.1.1.5 christos
2806 1.1.1.5 christos PPP_MD_CTX_free(ctxt);
2807 1.1.1.5 christos
2808 1.1.1.5 christos if (BCMP(dig, inp, SHA_DIGEST_LENGTH) != 0) {
2809 1.1.1.5 christos error("EAP: failed Lightweight rechallenge");
2810 1.1.1.5 christos eap_send_failure(esp);
2811 1.1.1.5 christos break;
2812 1.1.1.5 christos }
2813 1.1.1.5 christos
2814 1.1.1.5 christos esp->es_server.ea_state = eapOpen;
2815 1.1.1.5 christos if (esp->es_lwrechallenge != 0)
2816 1.1.1.5 christos TIMEOUT(srp_lwrechallenge, esp,
2817 1.1.1.5 christos esp->es_lwrechallenge);
2818 1.1 christos }
2819 1.1 christos break;
2820 1.1 christos }
2821 1.1 christos break;
2822 1.1.1.5 christos #endif /* PPP_WITH_SRP */
2823 1.1 christos
2824 1.1 christos default:
2825 1.1 christos /* This can't happen. */
2826 1.1 christos error("EAP: unknown Response type %d; ignored", typenum);
2827 1.1 christos return;
2828 1.1 christos }
2829 1.1 christos
2830 1.1 christos if (esp->es_server.ea_timeout > 0) {
2831 1.1 christos UNTIMEOUT(eap_server_timeout, (void *)esp);
2832 1.1 christos }
2833 1.1 christos
2834 1.1 christos if (esp->es_server.ea_state != eapBadAuth &&
2835 1.1 christos esp->es_server.ea_state != eapOpen) {
2836 1.1 christos esp->es_server.ea_id++;
2837 1.1 christos eap_send_request(esp);
2838 1.1 christos }
2839 1.1 christos }
2840 1.1 christos
2841 1.1 christos /*
2842 1.1 christos * eap_success - Receive EAP Success message (client mode).
2843 1.1 christos */
2844 1.1 christos static void
2845 1.1.1.4 christos eap_success(eap_state *esp, u_char *inp, int id, int len)
2846 1.1 christos {
2847 1.1.1.4 christos if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
2848 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
2849 1.1.1.4 christos && esp->es_client.ea_state != eapTlsRecvSuccess
2850 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
2851 1.1.1.4 christos ) {
2852 1.1 christos dbglog("EAP unexpected success message in state %s (%d)",
2853 1.1 christos eap_state_name(esp->es_client.ea_state),
2854 1.1 christos esp->es_client.ea_state);
2855 1.1 christos return;
2856 1.1 christos }
2857 1.1 christos
2858 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
2859 1.1.1.4 christos if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state !=
2860 1.1.1.4 christos eapTlsRecvSuccess) {
2861 1.1.1.4 christos dbglog("EAP-TLS unexpected success message in state %s (%d)",
2862 1.1.1.4 christos eap_state_name(esp->es_client.ea_state),
2863 1.1.1.4 christos esp->es_client.ea_state);
2864 1.1.1.4 christos return;
2865 1.1.1.4 christos }
2866 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
2867 1.1.1.4 christos
2868 1.1 christos if (esp->es_client.ea_timeout > 0) {
2869 1.1 christos UNTIMEOUT(eap_client_timeout, (void *)esp);
2870 1.1 christos }
2871 1.1 christos
2872 1.1 christos if (len > 0) {
2873 1.1 christos /* This is odd. The spec doesn't allow for this. */
2874 1.1 christos PRINTMSG(inp, len);
2875 1.1 christos }
2876 1.1 christos
2877 1.1.1.5 christos #ifdef PPP_WITH_PEAP
2878 1.1.1.5 christos peap_finish(&esp->ea_peap);
2879 1.1.1.5 christos #endif
2880 1.1.1.5 christos
2881 1.1 christos esp->es_client.ea_state = eapOpen;
2882 1.1 christos auth_withpeer_success(esp->es_unit, PPP_EAP, 0);
2883 1.1 christos }
2884 1.1 christos
2885 1.1 christos /*
2886 1.1 christos * eap_failure - Receive EAP Failure message (client mode).
2887 1.1 christos */
2888 1.1 christos static void
2889 1.1.1.4 christos eap_failure(eap_state *esp, u_char *inp, int id, int len)
2890 1.1 christos {
2891 1.1.1.4 christos /*
2892 1.1.1.4 christos * Ignore failure messages if we're not open
2893 1.1.1.4 christos */
2894 1.1.1.4 christos if (esp->es_client.ea_state <= eapClosed)
2895 1.1.1.4 christos return;
2896 1.1.1.4 christos
2897 1.1 christos if (!eap_client_active(esp)) {
2898 1.1 christos dbglog("EAP unexpected failure message in state %s (%d)",
2899 1.1 christos eap_state_name(esp->es_client.ea_state),
2900 1.1 christos esp->es_client.ea_state);
2901 1.1 christos }
2902 1.1 christos
2903 1.1 christos if (esp->es_client.ea_timeout > 0) {
2904 1.1 christos UNTIMEOUT(eap_client_timeout, (void *)esp);
2905 1.1 christos }
2906 1.1 christos
2907 1.1 christos if (len > 0) {
2908 1.1 christos /* This is odd. The spec doesn't allow for this. */
2909 1.1 christos PRINTMSG(inp, len);
2910 1.1 christos }
2911 1.1 christos
2912 1.1 christos esp->es_client.ea_state = eapBadAuth;
2913 1.1 christos
2914 1.1 christos error("EAP: peer reports authentication failure");
2915 1.1.1.5 christos
2916 1.1.1.5 christos #ifdef PPP_WITH_PEAP
2917 1.1.1.5 christos peap_finish(&esp->ea_peap);
2918 1.1.1.5 christos #endif
2919 1.1.1.5 christos
2920 1.1 christos auth_withpeer_fail(esp->es_unit, PPP_EAP);
2921 1.1 christos }
2922 1.1 christos
2923 1.1 christos /*
2924 1.1 christos * eap_input - Handle received EAP message.
2925 1.1 christos */
2926 1.1 christos static void
2927 1.1.1.4 christos eap_input(int unit, u_char *inp, int inlen)
2928 1.1 christos {
2929 1.1 christos eap_state *esp = &eap_states[unit];
2930 1.1 christos u_char code, id;
2931 1.1 christos int len;
2932 1.1 christos
2933 1.1 christos /*
2934 1.1 christos * Parse header (code, id and length). If packet too short,
2935 1.1 christos * drop it.
2936 1.1 christos */
2937 1.1 christos if (inlen < EAP_HEADERLEN) {
2938 1.1 christos error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN);
2939 1.1 christos return;
2940 1.1 christos }
2941 1.1 christos GETCHAR(code, inp);
2942 1.1 christos GETCHAR(id, inp);
2943 1.1 christos GETSHORT(len, inp);
2944 1.1 christos if (len < EAP_HEADERLEN || len > inlen) {
2945 1.1 christos error("EAP: packet has illegal length field %d (%d..%d)", len,
2946 1.1 christos EAP_HEADERLEN, inlen);
2947 1.1 christos return;
2948 1.1 christos }
2949 1.1 christos len -= EAP_HEADERLEN;
2950 1.1 christos
2951 1.1 christos /* Dispatch based on message code */
2952 1.1 christos switch (code) {
2953 1.1 christos case EAP_REQUEST:
2954 1.1 christos eap_request(esp, inp, id, len);
2955 1.1 christos break;
2956 1.1 christos
2957 1.1 christos case EAP_RESPONSE:
2958 1.1 christos eap_response(esp, inp, id, len);
2959 1.1 christos break;
2960 1.1 christos
2961 1.1 christos case EAP_SUCCESS:
2962 1.1 christos eap_success(esp, inp, id, len);
2963 1.1 christos break;
2964 1.1 christos
2965 1.1 christos case EAP_FAILURE:
2966 1.1 christos eap_failure(esp, inp, id, len);
2967 1.1 christos break;
2968 1.1 christos
2969 1.1 christos default: /* XXX Need code reject */
2970 1.1 christos /* Note: it's not legal to send EAP Nak here. */
2971 1.1 christos warn("EAP: unknown code %d received", code);
2972 1.1 christos break;
2973 1.1 christos }
2974 1.1 christos }
2975 1.1 christos
2976 1.1 christos /*
2977 1.1 christos * eap_printpkt - print the contents of an EAP packet.
2978 1.1 christos */
2979 1.1 christos static char *eap_codenames[] = {
2980 1.1 christos "Request", "Response", "Success", "Failure"
2981 1.1 christos };
2982 1.1 christos
2983 1.1 christos static char *eap_typenames[] = {
2984 1.1 christos "Identity", "Notification", "Nak", "MD5-Challenge",
2985 1.1 christos "OTP", "Generic-Token", NULL, NULL,
2986 1.1 christos "RSA", "DSS", "KEA", "KEA-Validate",
2987 1.1 christos "TLS", "Defender", "Windows 2000", "Arcot",
2988 1.1.1.4 christos "Cisco", "Nokia", "SRP", NULL,
2989 1.1.1.4 christos "TTLS", "RAS", "AKA", "3COM", "PEAP",
2990 1.1.1.4 christos "MSCHAPv2"
2991 1.1 christos };
2992 1.1 christos
2993 1.1 christos static int
2994 1.1.1.4 christos eap_printpkt(u_char *inp, int inlen,
2995 1.1.1.4 christos void (*printer) (void *, char *, ...), void *arg)
2996 1.1 christos {
2997 1.1 christos int code, id, len, rtype, vallen;
2998 1.1 christos u_char *pstart;
2999 1.1 christos u_int32_t uval;
3000 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
3001 1.1.1.4 christos u_char flags;
3002 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
3003 1.1.1.5 christos #ifdef PPP_WITH_CHAPMS
3004 1.1.1.4 christos u_char opcode;
3005 1.1.1.5 christos #endif /* PPP_WITH_CHAPMS */
3006 1.1 christos
3007 1.1 christos if (inlen < EAP_HEADERLEN)
3008 1.1 christos return (0);
3009 1.1 christos pstart = inp;
3010 1.1 christos GETCHAR(code, inp);
3011 1.1 christos GETCHAR(id, inp);
3012 1.1 christos GETSHORT(len, inp);
3013 1.1 christos if (len < EAP_HEADERLEN || len > inlen)
3014 1.1 christos return (0);
3015 1.1 christos
3016 1.1 christos if (code >= 1 && code <= sizeof(eap_codenames) / sizeof(char *))
3017 1.1 christos printer(arg, " %s", eap_codenames[code-1]);
3018 1.1 christos else
3019 1.1 christos printer(arg, " code=0x%x", code);
3020 1.1 christos printer(arg, " id=0x%x", id);
3021 1.1 christos len -= EAP_HEADERLEN;
3022 1.1 christos switch (code) {
3023 1.1 christos case EAP_REQUEST:
3024 1.1 christos if (len < 1) {
3025 1.1 christos printer(arg, " <missing type>");
3026 1.1 christos break;
3027 1.1 christos }
3028 1.1 christos GETCHAR(rtype, inp);
3029 1.1 christos len--;
3030 1.1 christos if (rtype >= 1 &&
3031 1.1 christos rtype <= sizeof (eap_typenames) / sizeof (char *))
3032 1.1 christos printer(arg, " %s", eap_typenames[rtype-1]);
3033 1.1 christos else
3034 1.1 christos printer(arg, " type=0x%x", rtype);
3035 1.1 christos switch (rtype) {
3036 1.1 christos case EAPT_IDENTITY:
3037 1.1 christos case EAPT_NOTIFICATION:
3038 1.1 christos if (len > 0) {
3039 1.1 christos printer(arg, " <Message ");
3040 1.1 christos print_string((char *)inp, len, printer, arg);
3041 1.1 christos printer(arg, ">");
3042 1.1 christos INCPTR(len, inp);
3043 1.1 christos len = 0;
3044 1.1 christos } else {
3045 1.1 christos printer(arg, " <No message>");
3046 1.1 christos }
3047 1.1 christos break;
3048 1.1 christos
3049 1.1 christos case EAPT_MD5CHAP:
3050 1.1 christos if (len <= 0)
3051 1.1 christos break;
3052 1.1 christos GETCHAR(vallen, inp);
3053 1.1 christos len--;
3054 1.1 christos if (vallen > len)
3055 1.1 christos goto truncated;
3056 1.1 christos printer(arg, " <Value%.*B>", vallen, inp);
3057 1.1 christos INCPTR(vallen, inp);
3058 1.1 christos len -= vallen;
3059 1.1 christos if (len > 0) {
3060 1.1 christos printer(arg, " <Name ");
3061 1.1 christos print_string((char *)inp, len, printer, arg);
3062 1.1 christos printer(arg, ">");
3063 1.1 christos INCPTR(len, inp);
3064 1.1 christos len = 0;
3065 1.1 christos } else {
3066 1.1 christos printer(arg, " <No name>");
3067 1.1 christos }
3068 1.1 christos break;
3069 1.1 christos
3070 1.1.1.5 christos #ifdef PPP_WITH_CHAPMS
3071 1.1.1.4 christos case EAPT_MSCHAPV2:
3072 1.1.1.4 christos if (len <= 0)
3073 1.1.1.4 christos break;
3074 1.1.1.4 christos GETCHAR(opcode, inp);
3075 1.1.1.4 christos len--;
3076 1.1.1.4 christos switch (opcode) {
3077 1.1.1.4 christos case CHAP_CHALLENGE:
3078 1.1.1.4 christos INCPTR(3, inp);
3079 1.1.1.4 christos len -= 3;
3080 1.1.1.4 christos GETCHAR(vallen, inp);
3081 1.1.1.4 christos len--;
3082 1.1.1.4 christos if (vallen > len)
3083 1.1.1.4 christos goto truncated;
3084 1.1.1.4 christos len -= vallen;
3085 1.1.1.4 christos printer(arg, " Challenge <");
3086 1.1.1.4 christos for (; vallen > 0; --vallen) {
3087 1.1.1.4 christos u_char val;
3088 1.1.1.4 christos GETCHAR(val, inp);
3089 1.1.1.4 christos printer(arg, "%.2x", val);
3090 1.1.1.4 christos }
3091 1.1.1.4 christos printer(arg, ">");
3092 1.1.1.4 christos if (len > 0) {
3093 1.1.1.4 christos printer(arg, ", <Name ");
3094 1.1.1.4 christos print_string((char *)inp, len, printer, arg);
3095 1.1.1.4 christos printer(arg, ">");
3096 1.1.1.4 christos INCPTR(len, inp);
3097 1.1.1.4 christos len = 0;
3098 1.1.1.4 christos } else {
3099 1.1.1.4 christos printer(arg, ", <No name>");
3100 1.1.1.4 christos }
3101 1.1.1.4 christos break;
3102 1.1.1.4 christos case CHAP_SUCCESS:
3103 1.1.1.4 christos INCPTR(3, inp);
3104 1.1.1.4 christos len -= 3;
3105 1.1.1.4 christos printer(arg, " Success <Message ");
3106 1.1.1.4 christos print_string((char *)inp, len, printer, arg);
3107 1.1.1.4 christos printer(arg, ">");
3108 1.1.1.4 christos break;
3109 1.1.1.4 christos case CHAP_FAILURE:
3110 1.1.1.4 christos INCPTR(3, inp);
3111 1.1.1.4 christos len -= 3;
3112 1.1.1.4 christos printer(arg, " Failure <Message ");
3113 1.1.1.4 christos print_string((char *)inp, len, printer, arg);
3114 1.1.1.4 christos printer(arg, ">");
3115 1.1.1.4 christos break;
3116 1.1.1.4 christos default:
3117 1.1.1.4 christos INCPTR(3, inp);
3118 1.1.1.4 christos len -= 3;
3119 1.1.1.4 christos printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
3120 1.1.1.4 christos break;
3121 1.1.1.4 christos }
3122 1.1.1.4 christos break;
3123 1.1.1.5 christos #endif /* PPP_WITH_CHAPMS */
3124 1.1.1.4 christos
3125 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
3126 1.1.1.4 christos case EAPT_TLS:
3127 1.1.1.4 christos if (len < 1)
3128 1.1.1.4 christos break;
3129 1.1.1.4 christos GETCHAR(flags, inp);
3130 1.1.1.4 christos len--;
3131 1.1.1.4 christos
3132 1.1.1.4 christos if(flags == 0 && len == 0){
3133 1.1.1.4 christos printer(arg, " Ack");
3134 1.1.1.4 christos break;
3135 1.1.1.4 christos }
3136 1.1.1.4 christos
3137 1.1.1.4 christos printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
3138 1.1.1.4 christos printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
3139 1.1.1.4 christos printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
3140 1.1.1.4 christos break;
3141 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
3142 1.1.1.4 christos
3143 1.1.1.5 christos #ifdef PPP_WITH_SRP
3144 1.1 christos case EAPT_SRP:
3145 1.1 christos if (len < 3)
3146 1.1 christos goto truncated;
3147 1.1 christos GETCHAR(vallen, inp);
3148 1.1 christos len--;
3149 1.1 christos printer(arg, "-%d", vallen);
3150 1.1 christos switch (vallen) {
3151 1.1 christos case EAPSRP_CHALLENGE:
3152 1.1 christos GETCHAR(vallen, inp);
3153 1.1 christos len--;
3154 1.1 christos if (vallen >= len)
3155 1.1 christos goto truncated;
3156 1.1 christos if (vallen > 0) {
3157 1.1 christos printer(arg, " <Name ");
3158 1.1 christos print_string((char *)inp, vallen, printer,
3159 1.1 christos arg);
3160 1.1 christos printer(arg, ">");
3161 1.1 christos } else {
3162 1.1 christos printer(arg, " <No name>");
3163 1.1 christos }
3164 1.1 christos INCPTR(vallen, inp);
3165 1.1 christos len -= vallen;
3166 1.1 christos GETCHAR(vallen, inp);
3167 1.1 christos len--;
3168 1.1 christos if (vallen >= len)
3169 1.1 christos goto truncated;
3170 1.1 christos printer(arg, " <s%.*B>", vallen, inp);
3171 1.1 christos INCPTR(vallen, inp);
3172 1.1 christos len -= vallen;
3173 1.1 christos GETCHAR(vallen, inp);
3174 1.1 christos len--;
3175 1.1 christos if (vallen > len)
3176 1.1 christos goto truncated;
3177 1.1 christos if (vallen == 0) {
3178 1.1 christos printer(arg, " <Default g=2>");
3179 1.1 christos } else {
3180 1.1 christos printer(arg, " <g%.*B>", vallen, inp);
3181 1.1 christos }
3182 1.1 christos INCPTR(vallen, inp);
3183 1.1 christos len -= vallen;
3184 1.1 christos if (len == 0) {
3185 1.1 christos printer(arg, " <Default N>");
3186 1.1 christos } else {
3187 1.1 christos printer(arg, " <N%.*B>", len, inp);
3188 1.1 christos INCPTR(len, inp);
3189 1.1 christos len = 0;
3190 1.1 christos }
3191 1.1 christos break;
3192 1.1 christos
3193 1.1 christos case EAPSRP_SKEY:
3194 1.1 christos printer(arg, " <B%.*B>", len, inp);
3195 1.1 christos INCPTR(len, inp);
3196 1.1 christos len = 0;
3197 1.1 christos break;
3198 1.1 christos
3199 1.1 christos case EAPSRP_SVALIDATOR:
3200 1.1 christos if (len < sizeof (u_int32_t))
3201 1.1 christos break;
3202 1.1 christos GETLONG(uval, inp);
3203 1.1 christos len -= sizeof (u_int32_t);
3204 1.1 christos if (uval & SRPVAL_EBIT) {
3205 1.1 christos printer(arg, " E");
3206 1.1 christos uval &= ~SRPVAL_EBIT;
3207 1.1 christos }
3208 1.1 christos if (uval != 0) {
3209 1.1 christos printer(arg, " f<%X>", uval);
3210 1.1 christos }
3211 1.1.1.5 christos if ((vallen = len) > SHA_DIGEST_LENGTH)
3212 1.1.1.5 christos vallen = SHA_DIGEST_LENGTH;
3213 1.1 christos printer(arg, " <M2%.*B%s>", len, inp,
3214 1.1.1.5 christos len < SHA_DIGEST_LENGTH ? "?" : "");
3215 1.1 christos INCPTR(vallen, inp);
3216 1.1 christos len -= vallen;
3217 1.1 christos if (len > 0) {
3218 1.1 christos printer(arg, " <PN%.*B>", len, inp);
3219 1.1 christos INCPTR(len, inp);
3220 1.1 christos len = 0;
3221 1.1 christos }
3222 1.1 christos break;
3223 1.1 christos
3224 1.1 christos case EAPSRP_LWRECHALLENGE:
3225 1.1 christos printer(arg, " <Challenge%.*B>", len, inp);
3226 1.1 christos INCPTR(len, inp);
3227 1.1 christos len = 0;
3228 1.1 christos break;
3229 1.1 christos }
3230 1.1 christos break;
3231 1.1.1.5 christos #endif /* PPP_WITH_SRP */
3232 1.1 christos }
3233 1.1 christos break;
3234 1.1 christos
3235 1.1 christos case EAP_RESPONSE:
3236 1.1 christos if (len < 1)
3237 1.1 christos break;
3238 1.1 christos GETCHAR(rtype, inp);
3239 1.1 christos len--;
3240 1.1 christos if (rtype >= 1 &&
3241 1.1 christos rtype <= sizeof (eap_typenames) / sizeof (char *))
3242 1.1 christos printer(arg, " %s", eap_typenames[rtype-1]);
3243 1.1 christos else
3244 1.1 christos printer(arg, " type=0x%x", rtype);
3245 1.1 christos switch (rtype) {
3246 1.1 christos case EAPT_IDENTITY:
3247 1.1 christos if (len > 0) {
3248 1.1 christos printer(arg, " <Name ");
3249 1.1 christos print_string((char *)inp, len, printer, arg);
3250 1.1 christos printer(arg, ">");
3251 1.1 christos INCPTR(len, inp);
3252 1.1 christos len = 0;
3253 1.1 christos }
3254 1.1 christos break;
3255 1.1 christos
3256 1.1.1.5 christos #ifdef PPP_WITH_EAPTLS
3257 1.1.1.4 christos case EAPT_TLS:
3258 1.1.1.4 christos if (len < 1)
3259 1.1.1.4 christos break;
3260 1.1.1.4 christos GETCHAR(flags, inp);
3261 1.1.1.4 christos len--;
3262 1.1.1.4 christos
3263 1.1.1.4 christos if(flags == 0 && len == 0){
3264 1.1.1.4 christos printer(arg, " Ack");
3265 1.1.1.4 christos break;
3266 1.1.1.4 christos }
3267 1.1.1.4 christos
3268 1.1.1.4 christos printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
3269 1.1.1.4 christos printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
3270 1.1.1.4 christos printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
3271 1.1.1.4 christos
3272 1.1.1.4 christos break;
3273 1.1.1.5 christos #endif /* PPP_WITH_EAPTLS */
3274 1.1.1.4 christos
3275 1.1 christos case EAPT_NAK:
3276 1.1 christos if (len <= 0) {
3277 1.1 christos printer(arg, " <missing hint>");
3278 1.1 christos break;
3279 1.1 christos }
3280 1.1 christos GETCHAR(rtype, inp);
3281 1.1 christos len--;
3282 1.1 christos printer(arg, " <Suggested-type %02X", rtype);
3283 1.1 christos if (rtype >= 1 &&
3284 1.1.1.4 christos rtype <= sizeof (eap_typenames) / sizeof (char *))
3285 1.1 christos printer(arg, " (%s)", eap_typenames[rtype-1]);
3286 1.1 christos printer(arg, ">");
3287 1.1 christos break;
3288 1.1 christos
3289 1.1 christos case EAPT_MD5CHAP:
3290 1.1 christos if (len <= 0) {
3291 1.1 christos printer(arg, " <missing length>");
3292 1.1 christos break;
3293 1.1 christos }
3294 1.1 christos GETCHAR(vallen, inp);
3295 1.1 christos len--;
3296 1.1 christos if (vallen > len)
3297 1.1 christos goto truncated;
3298 1.1 christos printer(arg, " <Value%.*B>", vallen, inp);
3299 1.1 christos INCPTR(vallen, inp);
3300 1.1 christos len -= vallen;
3301 1.1 christos if (len > 0) {
3302 1.1 christos printer(arg, " <Name ");
3303 1.1 christos print_string((char *)inp, len, printer, arg);
3304 1.1 christos printer(arg, ">");
3305 1.1 christos INCPTR(len, inp);
3306 1.1 christos len = 0;
3307 1.1 christos } else {
3308 1.1 christos printer(arg, " <No name>");
3309 1.1 christos }
3310 1.1 christos break;
3311 1.1 christos
3312 1.1.1.5 christos #ifdef PPP_WITH_CHAPMS
3313 1.1.1.4 christos case EAPT_MSCHAPV2:
3314 1.1.1.4 christos if (len <= 0)
3315 1.1.1.4 christos break;
3316 1.1.1.4 christos GETCHAR(opcode, inp);
3317 1.1.1.4 christos len--;
3318 1.1.1.4 christos switch (opcode) {
3319 1.1.1.4 christos case CHAP_RESPONSE:
3320 1.1.1.4 christos INCPTR(3, inp);
3321 1.1.1.4 christos len -= 3;
3322 1.1.1.4 christos GETCHAR(vallen, inp);
3323 1.1.1.4 christos len--;
3324 1.1.1.4 christos if (vallen > len)
3325 1.1.1.4 christos goto truncated;
3326 1.1.1.4 christos len -= vallen;
3327 1.1.1.4 christos printer(arg, " Response <");
3328 1.1.1.4 christos for (; vallen > 0; --vallen) {
3329 1.1.1.4 christos u_char val;
3330 1.1.1.4 christos GETCHAR(val, inp);
3331 1.1.1.4 christos printer(arg, "%.2x", val);
3332 1.1.1.4 christos }
3333 1.1.1.4 christos printer(arg, ">");
3334 1.1.1.4 christos if (len > 0) {
3335 1.1.1.4 christos printer(arg, ", <Name ");
3336 1.1.1.4 christos print_string((char *)inp, len, printer, arg);
3337 1.1.1.4 christos printer(arg, ">");
3338 1.1.1.4 christos INCPTR(len, inp);
3339 1.1.1.4 christos len = 0;
3340 1.1.1.4 christos } else {
3341 1.1.1.4 christos printer(arg, ", <No name>");
3342 1.1.1.4 christos }
3343 1.1.1.4 christos break;
3344 1.1.1.4 christos case CHAP_SUCCESS:
3345 1.1.1.4 christos printer(arg, " Success");
3346 1.1.1.4 christos break;
3347 1.1.1.4 christos case CHAP_FAILURE:
3348 1.1.1.4 christos printer(arg, " Failure");
3349 1.1.1.4 christos break;
3350 1.1.1.4 christos default:
3351 1.1.1.4 christos printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
3352 1.1.1.4 christos break;
3353 1.1.1.4 christos }
3354 1.1.1.4 christos break;
3355 1.1.1.5 christos #endif /* PPP_WITH_CHAPMS */
3356 1.1.1.4 christos
3357 1.1.1.5 christos #ifdef PPP_WITH_SRP
3358 1.1 christos case EAPT_SRP:
3359 1.1 christos if (len < 1)
3360 1.1 christos goto truncated;
3361 1.1 christos GETCHAR(vallen, inp);
3362 1.1 christos len--;
3363 1.1 christos printer(arg, "-%d", vallen);
3364 1.1 christos switch (vallen) {
3365 1.1 christos case EAPSRP_CKEY:
3366 1.1 christos printer(arg, " <A%.*B>", len, inp);
3367 1.1 christos INCPTR(len, inp);
3368 1.1 christos len = 0;
3369 1.1 christos break;
3370 1.1 christos
3371 1.1 christos case EAPSRP_CVALIDATOR:
3372 1.1 christos if (len < sizeof (u_int32_t))
3373 1.1 christos break;
3374 1.1 christos GETLONG(uval, inp);
3375 1.1 christos len -= sizeof (u_int32_t);
3376 1.1 christos if (uval & SRPVAL_EBIT) {
3377 1.1 christos printer(arg, " E");
3378 1.1 christos uval &= ~SRPVAL_EBIT;
3379 1.1 christos }
3380 1.1 christos if (uval != 0) {
3381 1.1 christos printer(arg, " f<%X>", uval);
3382 1.1 christos }
3383 1.1 christos printer(arg, " <M1%.*B%s>", len, inp,
3384 1.1.1.5 christos len == SHA_DIGEST_LENGTH ? "" : "?");
3385 1.1 christos INCPTR(len, inp);
3386 1.1 christos len = 0;
3387 1.1 christos break;
3388 1.1 christos
3389 1.1 christos case EAPSRP_ACK:
3390 1.1 christos break;
3391 1.1 christos
3392 1.1 christos case EAPSRP_LWRECHALLENGE:
3393 1.1 christos printer(arg, " <Response%.*B%s>", len, inp,
3394 1.1.1.5 christos len == SHA_DIGEST_LENGTH ? "" : "?");
3395 1.1.1.5 christos if ((vallen = len) > SHA_DIGEST_LENGTH)
3396 1.1.1.5 christos vallen = SHA_DIGEST_LENGTH;
3397 1.1 christos INCPTR(vallen, inp);
3398 1.1 christos len -= vallen;
3399 1.1 christos break;
3400 1.1 christos }
3401 1.1 christos break;
3402 1.1.1.5 christos #endif /* PPP_WITH_SRP */
3403 1.1 christos }
3404 1.1 christos break;
3405 1.1 christos
3406 1.1 christos case EAP_SUCCESS: /* No payload expected for these! */
3407 1.1 christos case EAP_FAILURE:
3408 1.1 christos break;
3409 1.1 christos
3410 1.1 christos truncated:
3411 1.1 christos printer(arg, " <truncated>");
3412 1.1 christos break;
3413 1.1 christos }
3414 1.1 christos
3415 1.1 christos if (len > 8)
3416 1.1 christos printer(arg, "%8B...", inp);
3417 1.1 christos else if (len > 0)
3418 1.1 christos printer(arg, "%.*B", len, inp);
3419 1.1 christos INCPTR(len, inp);
3420 1.1 christos
3421 1.1 christos return (inp - pstart);
3422 1.1 christos }
3423