1 /*
2 * eap.c rfc2284 & rfc2869 implementation
3 *
4 * Version: $Id: f0452b43f4f887e9872363cfa6df53c25359b207 $
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 * Copyright 2000-2003,2006 The FreeRADIUS server project
21 * Copyright 2001 hereUare Communications, Inc. <raghud@hereuare.com>
22 * Copyright 2003 Alan DeKok <aland@freeradius.org>
23 */
24 /*
25 * EAP PACKET FORMAT
26 * --- ------ ------
27 * 0 1 2 3
28 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
29 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30 * | Code | Identifier | Length |
31 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 * | Data ...
33 * +-+-+-+-+
34 *
35 *
36 * EAP Request and Response Packet Format
37 * --- ------- --- -------- ------ ------
38 * 0 1 2 3
39 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * | Code | Identifier | Length |
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * | Type | Type-Data ...
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
45 *
46 *
47 * EAP Success and Failure Packet Format
48 * --- ------- --- ------- ------ ------
49 * 0 1 2 3
50 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
51 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 * | Code | Identifier | Length |
53 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 *
55 */
56
57 #include <freeradius-devel/modpriv.h>
58
59 RCSID("$Id: f0452b43f4f887e9872363cfa6df53c25359b207 $")
60
61 #include "rlm_eap.h"
62 #include <ctype.h>
63
64 static char const *eap_codes[] = {
65 "", /* 0 is invalid */
66 "Request",
67 "Response",
68 "Success",
69 "Failure"
70 };
71
_eap_module_free(eap_module_t * inst)72 static int _eap_module_free(eap_module_t *inst)
73 {
74 /*
75 * We have to check inst->type as it's only allocated
76 * if we loaded the eap method.
77 */
78 if (inst->type && inst->type->detach) (inst->type->detach)(inst->instance);
79
80 #ifndef NDEBUG
81 /*
82 * Don't dlclose() modules if we're doing memory
83 * debugging. This removes the symbols needed by
84 * valgrind.
85 */
86 if (!main_config.debug_memory)
87 #endif
88 if (inst->handle) dlclose(inst->handle);
89
90 return 0;
91 }
92
93 /** Load required EAP sub-modules (methods)
94 *
95 */
eap_module_instantiate(rlm_eap_t * inst,eap_module_t ** m_inst,eap_type_t num,CONF_SECTION * cs)96 int eap_module_instantiate(rlm_eap_t *inst, eap_module_t **m_inst, eap_type_t num, CONF_SECTION *cs)
97 {
98 eap_module_t *method;
99 char *mod_name, *p;
100
101 /* Make room for the EAP-Type */
102 *m_inst = method = talloc_zero(cs, eap_module_t);
103 if (!inst) return -1;
104
105 talloc_set_destructor(method, _eap_module_free);
106
107 /* fill in the structure */
108 method->cs = cs;
109 method->name = eap_type2name(num);
110
111 /*
112 * The name of the module were trying to load
113 */
114 mod_name = talloc_typed_asprintf(method, "rlm_eap_%s", method->name);
115
116 /*
117 * dlopen is case sensitive
118 */
119 p = mod_name;
120 while (*p) {
121 *p = tolower(*p);
122 p++;
123 }
124
125 /*
126 * Link the loaded EAP-Type
127 */
128 method->handle = fr_dlopenext(mod_name);
129 if (!method->handle) {
130 ERROR("rlm_eap (%s): Failed to link %s: %s", inst->xlat_name, mod_name, fr_strerror());
131
132 return -1;
133 }
134
135 method->type = dlsym(method->handle, mod_name);
136 if (!method->type) {
137 ERROR("rlm_eap (%s): Failed linking to structure in %s: %s", inst->xlat_name,
138 method->name, dlerror());
139
140 return -1;
141 }
142
143 cf_log_module(cs, "Linked to sub-module %s", mod_name);
144
145 /*
146 * Call the attach num in the EAP num module
147 */
148 if ((method->type->instantiate) && ((method->type->instantiate)(method->cs, &(method->instance)) < 0)) {
149 ERROR("rlm_eap (%s): Failed to initialise %s", inst->xlat_name, mod_name);
150
151 if (method->instance) {
152 (void) talloc_steal(method, method->instance);
153 }
154
155 return -1;
156 }
157
158 if (method->instance) {
159 (void) talloc_steal(method, method->instance);
160 }
161
162 return 0;
163 }
164
165 /*
166 * Call the appropriate handle with the right eap_method.
167 */
eap_module_call(eap_module_t * module,eap_handler_t * handler)168 static int eap_module_call(eap_module_t *module, eap_handler_t *handler)
169 {
170 int rcode = 1;
171 REQUEST *request = handler->request;
172
173 char const *caller = request->module;
174
175 rad_assert(module != NULL);
176
177 RDEBUG2("Calling submodule %s to process data", module->type->name);
178
179 request->module = module->type->name;
180
181 switch (handler->stage) {
182 case INITIATE:
183 if (!module->type->session_init(module->instance, handler)) {
184 rcode = 0;
185 }
186
187 break;
188
189 case PROCESS:
190 /*
191 * The called function updates the EAP reply packet.
192 */
193 if (!module->type->process ||
194 !module->type->process(module->instance, handler)) {
195 rcode = 0;
196 }
197
198 break;
199
200 default:
201 /* Should never enter here */
202 RDEBUG("Internal sanity check failed on EAP");
203 rcode = 0;
204 break;
205 }
206
207 request->module = caller;
208 return rcode;
209 }
210
211 /** Process NAK data from EAP peer
212 *
213 */
eap_process_nak(rlm_eap_t * inst,REQUEST * request,eap_type_t type,eap_type_data_t * nak)214 static eap_type_t eap_process_nak(rlm_eap_t *inst, REQUEST *request,
215 eap_type_t type,
216 eap_type_data_t *nak)
217 {
218 unsigned int i;
219 VALUE_PAIR *vp;
220 eap_type_t method = PW_EAP_INVALID;
221
222 /*
223 * The NAK data is the preferred EAP type(s) of
224 * the client.
225 *
226 * RFC 3748 says to list one or more proposed
227 * alternative types, one per octet, or to use
228 * 0 for no alternative.
229 */
230 if (!nak->data) {
231 REDEBUG("Peer sent empty (invalid) NAK. "
232 "Can't select method to continue with");
233
234 return PW_EAP_INVALID;
235 }
236
237 /*
238 * Pick one type out of the one they asked for,
239 * as they may have asked for many.
240 */
241 vp = fr_pair_find_by_num(request->config, PW_EAP_TYPE, 0, TAG_ANY);
242 for (i = 0; i < nak->length; i++) {
243 /*
244 * Type 0 is valid, and means there are no
245 * common choices.
246 */
247 if (nak->data[i] == 0) {
248 RDEBUG("Peer NAK'd indicating it is not willing to "
249 "continue ");
250
251 return PW_EAP_INVALID;
252 }
253
254 /*
255 * It is invalid to request identity,
256 * notification & nak in nak.
257 */
258 if (nak->data[i] < PW_EAP_MD5) {
259 REDEBUG("Peer NAK'd asking for bad "
260 "type %s (%d)",
261 eap_type2name(nak->data[i]),
262 nak->data[i]);
263
264 return PW_EAP_INVALID;
265 }
266
267 if ((nak->data[i] >= PW_EAP_MAX_TYPES) ||
268 !inst->methods[nak->data[i]]) {
269 RDEBUG2("Peer NAK'd asking for "
270 "unsupported EAP type %s (%d), skipping...",
271 eap_type2name(nak->data[i]),
272 nak->data[i]);
273
274 continue;
275 }
276
277 /*
278 * Prevent a firestorm if the client is confused.
279 */
280 if (type == nak->data[i]) {
281 RDEBUG2("Peer NAK'd our request for "
282 "%s (%d) with a request for "
283 "%s (%d), skipping...",
284 eap_type2name(nak->data[i]),
285 nak->data[i],
286 eap_type2name(nak->data[i]),
287 nak->data[i]);
288
289 RWARN("!!! We requested to use an EAP type as normal.");
290 RWARN("!!! The supplicant rejected that, and requested to use the same EAP type.");
291 RWARN("!!! i.e. the supplicant said 'I don't like X, please use X instead.");
292 RWARN("!!! The supplicant software is broken and does not work properly.");
293 RWARN("!!! Please upgrade it to software that works.");
294
295 continue;
296 }
297
298 /*
299 * Enforce per-user configuration of EAP
300 * types.
301 */
302 if (vp && (vp->vp_integer != nak->data[i])) {
303 RDEBUG2("Peer wants %s (%d), while we "
304 "require %s (%d), skipping",
305 eap_type2name(nak->data[i]),
306 nak->data[i],
307 eap_type2name(vp->vp_integer),
308 vp->vp_integer);
309
310 continue;
311 }
312
313 RDEBUG("Found mutually acceptable type %s (%d)",
314 eap_type2name(nak->data[i]), nak->data[i]);
315
316 method = nak->data[i];
317
318 break;
319 }
320
321 if (method == PW_EAP_INVALID) {
322 REDEBUG("No mutually acceptable types found");
323 }
324
325 return method;
326 }
327
328 /** Select the correct callback based on a response
329 *
330 * Based on the EAP response from the supplicant, call the appropriate
331 * method callback.
332 *
333 * Default to the configured EAP-Type for all Unsupported EAP-Types.
334 *
335 * @param inst Configuration data for this instance of rlm_eap.
336 * @param handler State data that persists over multiple rounds of EAP.
337 * @return a status code.
338 */
eap_method_select(rlm_eap_t * inst,eap_handler_t * handler)339 eap_rcode_t eap_method_select(rlm_eap_t *inst, eap_handler_t *handler)
340 {
341 eap_type_data_t *type = &handler->eap_ds->response->type;
342 REQUEST *request = handler->request;
343
344 eap_type_t next = inst->default_method;
345 VALUE_PAIR *vp;
346
347 /*
348 * Don't trust anyone.
349 */
350 if ((type->num == 0) || (type->num >= PW_EAP_MAX_TYPES)) {
351 REDEBUG("Peer sent EAP method number %d, which is outside known range", type->num);
352
353 return EAP_INVALID;
354 }
355
356 /*
357 * Multiple levels of TLS nesting are invalid. But if
358 * the parent has a home_server defined, then this
359 * request is being processed through a virtual
360 * server... so that's OK.
361 *
362 * i.e. we're inside an EAP tunnel, which means we have a
363 * parent. If the outer session exists, and doesn't have
364 * a home server, then it's multiple layers of tunneling.
365 */
366 if (handler->request->parent &&
367 handler->request->parent->parent &&
368 !handler->request->parent->parent->home_server) {
369 RERROR("Multiple levels of TLS nesting are invalid");
370
371 return EAP_INVALID;
372 }
373
374 RDEBUG2("Peer sent packet with method EAP %s (%d)", eap_type2name(type->num), type->num);
375 /*
376 * Figure out what to do.
377 */
378 switch (type->num) {
379 case PW_EAP_IDENTITY:
380 /*
381 * Allow per-user configuration of EAP types.
382 */
383 vp = fr_pair_find_by_num(handler->request->config, PW_EAP_TYPE, 0,
384 TAG_ANY);
385 if (vp) next = vp->vp_integer;
386
387 /*
388 * Ensure it's valid.
389 */
390 if ((next < PW_EAP_MD5) ||
391 (next >= PW_EAP_MAX_TYPES) ||
392 (!inst->methods[next])) {
393 REDEBUG2("Tried to start unsupported EAP type %s (%d)",
394 eap_type2name(next), next);
395
396 return EAP_INVALID;
397 }
398
399 do_initiate:
400 /*
401 * If any of these fail, we messed badly somewhere
402 */
403 rad_assert(next >= PW_EAP_MD5);
404 rad_assert(next < PW_EAP_MAX_TYPES);
405 rad_assert(inst->methods[next]);
406
407 handler->stage = INITIATE;
408 handler->type = next;
409
410 if (eap_module_call(inst->methods[next], handler) == 0) {
411 REDEBUG2("Failed starting EAP %s (%d) session. EAP sub-module failed",
412 eap_type2name(next), next);
413
414 return EAP_INVALID;
415 }
416 break;
417
418 case PW_EAP_NAK:
419 /*
420 * Delete old data, if necessary.
421 */
422 if (handler->opaque && handler->free_opaque) {
423 handler->free_opaque(handler->opaque);
424 handler->free_opaque = NULL;
425 handler->opaque = NULL;
426 }
427
428 /*
429 * We got a NAK after the peer started doing a
430 * particular EAP type. That's rude, tell the
431 * peer to go away.
432 */
433 if (handler->started) return EAP_INVALID;
434
435 next = eap_process_nak(inst, handler->request,
436 handler->type, type);
437
438 /*
439 * We probably want to return 'fail' here...
440 */
441 if (!next) {
442 return EAP_INVALID;
443 }
444
445 goto do_initiate;
446
447 /*
448 * Key off of the configured sub-modules.
449 */
450 default:
451 /*
452 * We haven't configured it, it doesn't exist.
453 */
454 if (!inst->methods[type->num]) {
455 REDEBUG2("Client asked for unsupported EAP type %s (%d)",
456 eap_type2name(type->num),
457 type->num);
458
459 return EAP_INVALID;
460 }
461
462 rad_assert(handler->stage == PROCESS);
463 handler->type = type->num;
464 if (eap_module_call(inst->methods[type->num],
465 handler) == 0) {
466 REDEBUG2("Failed continuing EAP %s (%d) session. EAP sub-module failed",
467 eap_type2name(type->num),
468 type->num);
469
470 return EAP_INVALID;
471 }
472 handler->started = true;
473 break;
474 }
475
476 return EAP_OK;
477 }
478
479
480 /*
481 * compose EAP reply packet in EAP-Message attr of RADIUS.
482 *
483 * Set the RADIUS reply codes based on EAP request codes. Append
484 * any additonal VPs to RADIUS reply
485 */
eap_compose(eap_handler_t * handler)486 rlm_rcode_t eap_compose(eap_handler_t *handler)
487 {
488 VALUE_PAIR *vp;
489 eap_packet_raw_t *eap_packet;
490 REQUEST *request;
491 EAP_DS *eap_ds;
492 eap_packet_t *reply;
493 int rcode;
494
495 #ifndef NDEBUG
496 handler = talloc_get_type_abort(handler, eap_handler_t);
497 request = talloc_get_type_abort(handler->request, REQUEST);
498 eap_ds = talloc_get_type_abort(handler->eap_ds, EAP_DS);
499 reply = talloc_get_type_abort(eap_ds->request, eap_packet_t);
500 #else
501 request = handler->request;
502 eap_ds = handler->eap_ds;
503 reply = eap_ds->request;
504 #endif
505
506 /*
507 * The Id for the EAP packet to the NAS wasn't set.
508 * Do so now.
509 */
510 if (!eap_ds->set_request_id) {
511 /*
512 * Id serves to suppport request/response
513 * retransmission in the EAP layer and as such
514 * must be different for 'adjacent' packets
515 * except in case of success/failure-replies.
516 *
517 * RFC2716 (EAP-TLS) requires this to be
518 * incremented, RFC2284 only makes the above-
519 * mentioned restriction.
520 */
521 reply->id = handler->eap_ds->response->id;
522
523 switch (reply->code) {
524 /*
525 * The Id is a simple "ack" for success
526 * and failure.
527 *
528 * RFC 3748 section 4.2 says
529 *
530 * ... The Identifier field MUST match
531 * the Identifier field of the Response
532 * packet that it is sent in response
533 * to.
534 */
535 case PW_EAP_SUCCESS:
536 case PW_EAP_FAILURE:
537 break;
538
539 /*
540 * We've sent a response to their
541 * request, the Id is incremented.
542 */
543 default:
544 ++reply->id;
545 }
546 }
547
548 /*
549 * For Request & Response packets, set the EAP sub-type,
550 * if the EAP sub-module didn't already set it.
551 *
552 * This allows the TLS module to be "morphic", and means
553 * that the TTLS and PEAP modules can call it to do most
554 * of their dirty work.
555 */
556 if (((eap_ds->request->code == PW_EAP_REQUEST) ||
557 (eap_ds->request->code == PW_EAP_RESPONSE)) &&
558 (eap_ds->request->type.num == 0)) {
559 rad_assert(handler->type >= PW_EAP_MD5);
560 rad_assert(handler->type < PW_EAP_MAX_TYPES);
561
562 eap_ds->request->type.num = handler->type;
563 }
564
565 if (eap_wireformat(reply) == EAP_INVALID) {
566 return RLM_MODULE_INVALID;
567 }
568 eap_packet = (eap_packet_raw_t *)reply->packet;
569
570 vp = radius_pair_create(request->reply, &request->reply->vps, PW_EAP_MESSAGE, 0);
571 if (!vp) return RLM_MODULE_INVALID;
572
573 vp->vp_length = eap_packet->length[0] * 256 + eap_packet->length[1];
574 vp->vp_octets = talloc_steal(vp, reply->packet);
575 reply->packet = NULL;
576
577 /*
578 * EAP-Message is always associated with
579 * Message-Authenticator but not vice-versa.
580 *
581 * Don't add a Message-Authenticator if it's already
582 * there.
583 */
584 vp = fr_pair_find_by_num(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
585 if (!vp) {
586 vp = fr_pair_afrom_num(request->reply, PW_MESSAGE_AUTHENTICATOR, 0);
587 vp->vp_length = AUTH_VECTOR_LEN;
588 vp->vp_octets = talloc_zero_array(vp, uint8_t, vp->vp_length);
589 fr_pair_add(&(request->reply->vps), vp);
590 }
591
592 /* Set request reply code, but only if it's not already set. */
593 rcode = RLM_MODULE_OK;
594 if (!request->reply->code) switch (reply->code) {
595 case PW_EAP_RESPONSE:
596 request->reply->code = PW_CODE_ACCESS_REJECT;
597 rcode = RLM_MODULE_REJECT;
598 break;
599 case PW_EAP_SUCCESS:
600 request->reply->code = PW_CODE_ACCESS_ACCEPT;
601 rcode = RLM_MODULE_OK;
602 break;
603 case PW_EAP_FAILURE:
604 request->reply->code = PW_CODE_ACCESS_REJECT;
605 rcode = RLM_MODULE_REJECT;
606 break;
607 case PW_EAP_REQUEST:
608 request->reply->code = PW_CODE_ACCESS_CHALLENGE;
609 rcode = RLM_MODULE_HANDLED;
610 break;
611 default:
612 /*
613 * When we're pulling MS-CHAPv2 out of EAP-MS-CHAPv2,
614 * we do so WITHOUT setting a reply code, as the
615 * request is being proxied.
616 */
617 if (request->options & RAD_REQUEST_OPTION_PROXY_EAP) {
618 return RLM_MODULE_HANDLED;
619 }
620
621 /* Should never enter here */
622 REDEBUG("Reply code %d is unknown, rejecting the request", reply->code);
623 request->reply->code = PW_CODE_ACCESS_REJECT;
624 reply->code = PW_EAP_FAILURE;
625 rcode = RLM_MODULE_REJECT;
626 break;
627 }
628
629 RDEBUG2("Sending EAP %s (code %i) ID %d length %i",
630 eap_codes[eap_packet->code], eap_packet->code, reply->id,
631 eap_packet->length[0] * 256 + eap_packet->length[1]);
632
633 return rcode;
634 }
635
636 /*
637 * Radius criteria, EAP-Message is invalid without Message-Authenticator
638 * For EAP_START, send Access-Challenge with EAP Identity request.
639 */
eap_start(rlm_eap_t * inst,REQUEST * request)640 int eap_start(rlm_eap_t *inst, REQUEST *request)
641 {
642 VALUE_PAIR *vp, *proxy;
643 VALUE_PAIR *eap_msg;
644
645 eap_msg = fr_pair_find_by_num(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
646 if (!eap_msg) {
647 RDEBUG2("No EAP-Message, not doing EAP");
648 return EAP_NOOP;
649 }
650
651 /*
652 * Look for EAP-Type = None (FreeRADIUS specific attribute)
653 * this allows you to NOT do EAP for some users.
654 */
655 vp = fr_pair_find_by_num(request->packet->vps, PW_EAP_TYPE, 0, TAG_ANY);
656 if (vp && vp->vp_integer == 0) {
657 RDEBUG2("Found EAP-Message, but EAP-Type = None, so we're not doing EAP");
658 return EAP_NOOP;
659 }
660
661 /*
662 * http://www.freeradius.org/rfc/rfc2869.html#EAP-Message
663 *
664 * Checks for Message-Authenticator are handled by rad_recv().
665 */
666
667 /*
668 * Check for a Proxy-To-Realm. Don't get excited over LOCAL
669 * realms (sigh).
670 */
671 proxy = fr_pair_find_by_num(request->config, PW_PROXY_TO_REALM, 0, TAG_ANY);
672 if (proxy) {
673 REALM *realm;
674
675 /*
676 * If it's a LOCAL realm, then we're not proxying
677 * to it.
678 */
679 realm = realm_find(proxy->vp_strvalue);
680 if (!realm || (realm && (!realm->auth_pool))) {
681 proxy = NULL;
682 }
683 }
684
685 /*
686 * Check the length before de-referencing the contents.
687 *
688 * Lengths of zero are required by the RFC for EAP-Start,
689 * but we've never seen them in practice.
690 *
691 * Lengths of two are what we see in practice as
692 * EAP-Starts.
693 */
694 if ((eap_msg->vp_length == 0) || (eap_msg->vp_length == 2)) {
695 uint8_t *p;
696
697 /*
698 * It's a valid EAP-Start, but the request
699 * was marked as being proxied. So we don't
700 * do EAP, as the home server will do it.
701 */
702 if (proxy) {
703 do_proxy:
704 RDEBUG2("Request is supposed to be proxied to "
705 "Realm %s. Not doing EAP.", proxy->vp_strvalue);
706 return EAP_NOOP;
707 }
708
709 RDEBUG2("Got EAP_START message");
710 vp = fr_pair_afrom_num(request->reply, PW_EAP_MESSAGE, 0);
711 if (!vp) return EAP_FAIL;
712 fr_pair_add(&request->reply->vps, vp);
713
714 /*
715 * Manually create an EAP Identity request
716 */
717 vp->vp_length = 5;
718 vp->vp_octets = p = talloc_array(vp, uint8_t, vp->vp_length);
719
720 p[0] = PW_EAP_REQUEST;
721 p[1] = 0; /* ID */
722 p[2] = 0;
723 p[3] = 5; /* length */
724 p[4] = PW_EAP_IDENTITY;
725
726 request->reply->code = PW_CODE_ACCESS_CHALLENGE;
727 return EAP_FOUND;
728 } /* end of handling EAP-Start */
729
730 /*
731 * The EAP packet header is 4 bytes, plus one byte of
732 * EAP sub-type. Short packets are discarded, unless
733 * we're proxying.
734 */
735 if (eap_msg->vp_length < (EAP_HEADER_LEN + 1)) {
736 if (proxy) goto do_proxy;
737
738 RDEBUG2("Ignoring EAP-Message which is too short to be meaningful");
739 return EAP_FAIL;
740 }
741
742 /*
743 * Create an EAP-Type containing the EAP-type
744 * from the packet.
745 */
746 vp = fr_pair_afrom_num(request->packet, PW_EAP_TYPE, 0);
747 if (vp) {
748 vp->vp_integer = eap_msg->vp_octets[4];
749 fr_pair_add(&(request->packet->vps), vp);
750 }
751
752 /*
753 * If the request was marked to be proxied, do it now.
754 * This is done after checking for a valid length
755 * (which may not be good), and after adding the EAP-Type
756 * attribute. This lets other modules selectively cancel
757 * proxying based on EAP-Type.
758 */
759 if (proxy) goto do_proxy;
760
761 /*
762 * From now on, we're supposed to be handling the
763 * EAP packet. We better understand it...
764 */
765
766 /*
767 * We're allowed only a few codes. Request, Response,
768 * Success, or Failure.
769 */
770 if ((eap_msg->vp_octets[0] == 0) ||
771 (eap_msg->vp_octets[0] >= PW_EAP_MAX_CODES)) {
772 RDEBUG2("Peer sent EAP packet with unknown code %i", eap_msg->vp_octets[0]);
773 } else {
774 RDEBUG2("Peer sent EAP %s (code %i) ID %d length %zu",
775 eap_codes[eap_msg->vp_octets[0]],
776 eap_msg->vp_octets[0],
777 eap_msg->vp_octets[1],
778 eap_msg->vp_length);
779 }
780
781 /*
782 * We handle request and responses. The only other defined
783 * codes are success and fail. The client SHOULD NOT be
784 * sending success/fail packets to us, as it doesn't make
785 * sense.
786 */
787 if ((eap_msg->vp_octets[0] != PW_EAP_REQUEST) &&
788 (eap_msg->vp_octets[0] != PW_EAP_RESPONSE)) {
789 RDEBUG2("Ignoring EAP packet which we don't know how to handle");
790 return EAP_FAIL;
791 }
792
793 /*
794 * We've been told to ignore unknown EAP types, AND it's
795 * an unknown type. Return "NOOP", which will cause the
796 * mod_authorize() to return NOOP.
797 *
798 * EAP-Identity, Notification, and NAK are all handled
799 * internally, so they never have handlers.
800 */
801 if ((eap_msg->vp_octets[4] >= PW_EAP_MD5) &&
802 inst->ignore_unknown_types &&
803 ((eap_msg->vp_octets[4] == 0) ||
804 (eap_msg->vp_octets[4] >= PW_EAP_MAX_TYPES) ||
805 (!inst->methods[eap_msg->vp_octets[4]]))) {
806 RDEBUG2("Ignoring Unknown EAP type");
807 return EAP_NOOP;
808 }
809
810 /*
811 * They're NAKing the EAP type we wanted to use, and
812 * asking for one which we don't support.
813 *
814 * NAK is code + id + length1 + length + NAK
815 * + requested EAP type(s).
816 *
817 * We know at this point that we can't handle the
818 * request. We could either return an EAP-Fail here, but
819 * it's not too critical.
820 *
821 * By returning "noop", we can ensure that authorize()
822 * returns NOOP, and another module may choose to proxy
823 * the request.
824 */
825 if ((eap_msg->vp_octets[4] == PW_EAP_NAK) &&
826 (eap_msg->vp_length >= (EAP_HEADER_LEN + 2)) &&
827 inst->ignore_unknown_types &&
828 ((eap_msg->vp_octets[5] == 0) ||
829 (eap_msg->vp_octets[5] >= PW_EAP_MAX_TYPES) ||
830 (!inst->methods[eap_msg->vp_octets[5]]))) {
831 RDEBUG2("Ignoring NAK with request for unknown EAP type");
832 return EAP_NOOP;
833 }
834
835 if ((eap_msg->vp_octets[4] == PW_EAP_TTLS) ||
836 (eap_msg->vp_octets[4] == PW_EAP_PEAP)) {
837 RDEBUG2("Continuing tunnel setup");
838 return EAP_OK;
839 }
840 /*
841 * We return ok in response to EAP identity
842 * This means we can write:
843 *
844 * eap {
845 * ok = return
846 * }
847 * ldap
848 * sql
849 *
850 * ...in the inner-tunnel, to avoid expensive and unnecessary SQL/LDAP lookups
851 */
852 if (eap_msg->vp_octets[4] == PW_EAP_IDENTITY) {
853 RDEBUG2("EAP-Identity reply, returning 'ok' so we can short-circuit the rest of authorize");
854 return EAP_OK;
855 }
856
857 /*
858 * Later EAP messages are longer than the 'start'
859 * message, so if everything is OK, this function returns
860 * 'no start found', so that the rest of the EAP code can
861 * use the State attribute to match this EAP-Message to
862 * an ongoing conversation.
863 */
864 RDEBUG2("No EAP Start, assuming it's an on-going EAP conversation");
865
866 return EAP_NOTFOUND;
867 }
868
869 /*
870 * compose EAP FAILURE packet in EAP-Message
871 */
eap_fail(eap_handler_t * handler)872 void eap_fail(eap_handler_t *handler)
873 {
874 /*
875 * Delete any previous replies.
876 */
877 fr_pair_delete_by_num(&handler->request->reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
878 fr_pair_delete_by_num(&handler->request->reply->vps, PW_STATE, 0, TAG_ANY);
879
880 talloc_free(handler->eap_ds->request);
881 handler->eap_ds->request = talloc_zero(handler->eap_ds, eap_packet_t);
882 handler->eap_ds->request->code = PW_EAP_FAILURE;
883 handler->finished = true;
884 eap_compose(handler);
885 }
886
887 /*
888 * compose EAP SUCCESS packet in EAP-Message
889 */
eap_success(eap_handler_t * handler)890 void eap_success(eap_handler_t *handler)
891 {
892 handler->eap_ds->request->code = PW_EAP_SUCCESS;
893 handler->finished = true;
894 eap_compose(handler);
895 }
896
897 /*
898 * Basic EAP packet verfications & validations
899 */
eap_validation(REQUEST * request,eap_packet_raw_t ** eap_packet_p)900 static int eap_validation(REQUEST *request, eap_packet_raw_t **eap_packet_p)
901 {
902 uint16_t len;
903 eap_packet_raw_t *eap_packet = *eap_packet_p;
904
905 memcpy(&len, eap_packet->length, sizeof(uint16_t));
906 len = ntohs(len);
907
908 /*
909 * High level EAP packet checks
910 */
911 if (len <= EAP_HEADER_LEN) {
912 RAUTH("EAP packet is too small: Ignoring it.");
913 return EAP_INVALID;
914 }
915
916 if (eap_packet->code == PW_EAP_REQUEST) {
917 VALUE_PAIR *vp;
918 RAUTH("Unexpected EAP-Request. NAKing it.");
919
920 vp = pair_make_reply("EAP-Message", "123456", T_OP_SET);
921 if (vp) {
922 uint8_t buffer[6];
923
924 buffer[0] = PW_EAP_RESPONSE;
925 buffer[1] = eap_packet->id;
926 buffer[2] = 0;
927 buffer[3] = 6;
928 buffer[4] = PW_EAP_NAK;
929 buffer[5] = 0; /* no overlapping EAP types */
930
931 fr_pair_value_memcpy(vp, buffer, 6);
932 }
933
934 /*
935 * Ensure that the Access-Reject has a Message-Authenticator
936 */
937 vp = fr_pair_find_by_num(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
938 if (!vp) {
939 vp = fr_pair_afrom_num(request->reply, PW_MESSAGE_AUTHENTICATOR, 0);
940 vp->vp_length = AUTH_VECTOR_LEN;
941 vp->vp_octets = talloc_zero_array(vp, uint8_t, vp->vp_length);
942 fr_pair_add(&(request->reply->vps), vp);
943 }
944 request->reply->code = PW_CODE_ACCESS_REJECT;
945
946 return EAP_INVALID;
947 }
948
949 /*
950 * We only allow responses from the peer. The peer
951 * CANNOT ask us to authenticate outselves.
952 */
953 if (eap_packet->code != PW_EAP_RESPONSE) {
954 RAUTH("Unexpected packet code %02x: Ignoring it.", eap_packet->code);
955 return EAP_INVALID;
956 }
957
958 if ((eap_packet->data[0] <= 0) ||
959 (eap_packet->data[0] >= PW_EAP_MAX_TYPES)) {
960 /*
961 * Handle expanded types by smashing them to
962 * normal types.
963 */
964 if (eap_packet->data[0] == PW_EAP_EXPANDED_TYPE) {
965 uint8_t *p, *q;
966
967 if (len <= (EAP_HEADER_LEN + 1 + 3 + 4)) {
968 RAUTH("Expanded EAP type is too short: ignoring the packet");
969 return EAP_INVALID;
970 }
971
972 if ((eap_packet->data[1] != 0) ||
973 (eap_packet->data[2] != 0) ||
974 (eap_packet->data[3] != 0)) {
975 RAUTH("Expanded EAP type has unknown Vendor-ID: ignoring the packet");
976 return EAP_INVALID;
977 }
978
979 if ((eap_packet->data[4] != 0) ||
980 (eap_packet->data[5] != 0) ||
981 (eap_packet->data[6] != 0)) {
982 RAUTH("Expanded EAP type has unknown Vendor-Type: ignoring the packet");
983 return EAP_INVALID;
984 }
985
986 if ((eap_packet->data[7] == 0) ||
987 (eap_packet->data[7] >= PW_EAP_MAX_TYPES)) {
988 RAUTH("Unsupported Expanded EAP type %s (%u): ignoring the packet",
989 eap_type2name(eap_packet->data[7]), eap_packet->data[7]);
990 return EAP_INVALID;
991 }
992
993 if (eap_packet->data[7] == PW_EAP_NAK) {
994 RAUTH("Unsupported Expanded EAP-NAK: ignoring the packet");
995 return EAP_INVALID;
996 }
997
998 /*
999 * Re-write the EAP packet to NOT have the expanded type.
1000 */
1001 q = (uint8_t *) eap_packet;
1002 memmove(q + EAP_HEADER_LEN, q + EAP_HEADER_LEN + 7, len - 7 - EAP_HEADER_LEN);
1003
1004 p = talloc_realloc(talloc_parent(eap_packet), eap_packet, uint8_t, len - 7);
1005 if (!p) {
1006 RAUTH("Unsupported EAP type %s (%u): ignoring the packet",
1007 eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
1008 return EAP_INVALID;
1009 }
1010
1011 len -= 7;
1012 p[2] = (len >> 8) & 0xff;
1013 p[3] = len & 0xff;
1014
1015 *eap_packet_p = (eap_packet_raw_t *) p;
1016 RWARN("Converting Expanded EAP to normal EAP.");
1017 RWARN("Unnecessary use of Expanded EAP types is not recommended.");
1018
1019 return EAP_VALID;
1020 }
1021
1022 RAUTH("Unsupported EAP type %s (%u): ignoring the packet",
1023 eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
1024 return EAP_INVALID;
1025 }
1026
1027 /* we don't expect notification, but we send it */
1028 if (eap_packet->data[0] == PW_EAP_NOTIFICATION) {
1029 RAUTH("Got NOTIFICATION, "
1030 "Ignoring the packet");
1031 return EAP_INVALID;
1032 }
1033
1034 return EAP_VALID;
1035 }
1036
1037
1038 /*
1039 * Get the user Identity only from EAP-Identity packets
1040 */
eap_identity(REQUEST * request,eap_handler_t * handler,eap_packet_raw_t * eap_packet)1041 static char *eap_identity(REQUEST *request, eap_handler_t *handler, eap_packet_raw_t *eap_packet)
1042 {
1043 int size;
1044 uint16_t len;
1045 char *identity;
1046
1047 if ((!eap_packet) ||
1048 (eap_packet->code != PW_EAP_RESPONSE) ||
1049 (eap_packet->data[0] != PW_EAP_IDENTITY)) {
1050 return NULL;
1051 }
1052
1053 memcpy(&len, eap_packet->length, sizeof(uint16_t));
1054 len = ntohs(len);
1055
1056 if ((len <= 5) || (eap_packet->data[1] == 0x00)) {
1057 REDEBUG("EAP-Identity Unknown");
1058 return NULL;
1059 }
1060
1061 if (len > 1024) {
1062 REDEBUG("EAP-Identity too long");
1063 return NULL;
1064 }
1065
1066 size = len - 5;
1067 identity = talloc_array(handler, char, size + 1);
1068 memcpy(identity, &eap_packet->data[1], size);
1069 identity[size] = '\0';
1070
1071 return identity;
1072 }
1073
1074
1075 /*
1076 * Create our Request-Response data structure with the eap packet
1077 */
eap_buildds(eap_handler_t * handler,eap_packet_raw_t ** eap_packet_p)1078 static EAP_DS *eap_buildds(eap_handler_t *handler,
1079 eap_packet_raw_t **eap_packet_p)
1080 {
1081 EAP_DS *eap_ds = NULL;
1082 eap_packet_raw_t *eap_packet = *eap_packet_p;
1083 int typelen;
1084 uint16_t len;
1085
1086 if ((eap_ds = eap_ds_alloc(handler)) == NULL) {
1087 return NULL;
1088 }
1089
1090 eap_ds->response->packet = (uint8_t *) eap_packet;
1091 (void) talloc_steal(eap_ds, eap_packet);
1092 eap_ds->response->code = eap_packet->code;
1093 eap_ds->response->id = eap_packet->id;
1094 eap_ds->response->type.num = eap_packet->data[0];
1095
1096 memcpy(&len, eap_packet->length, sizeof(uint16_t));
1097 len = ntohs(len);
1098 eap_ds->response->length = len;
1099
1100 /*
1101 * We've eaten the eap packet into the eap_ds.
1102 */
1103 *eap_packet_p = NULL;
1104
1105 /*
1106 * First 5 bytes in eap, are code + id + length(2) + type.
1107 *
1108 * The rest is type-specific data. We skip type while
1109 * getting typedata from data.
1110 */
1111 typelen = len - 5/*code + id + length + type */;
1112 if (typelen > 0) {
1113 /*
1114 * Since the packet contains the complete
1115 * eap_packet, typedata will be a ptr in packet
1116 * to its typedata
1117 */
1118 eap_ds->response->type.data = eap_ds->response->packet + 5/*code+id+length+type*/;
1119 eap_ds->response->type.length = typelen;
1120 } else {
1121 eap_ds->response->type.length = 0;
1122 eap_ds->response->type.data = NULL;
1123 }
1124
1125 return eap_ds;
1126 }
1127
1128
1129 /*
1130 * If identity response then create a fresh handler & fill the identity
1131 * else handler MUST be in our list, get that.
1132 * This handler creation cannot fail
1133 *
1134 * username contains REQUEST->username which might have been stripped.
1135 * identity contains the one sent in EAP-Identity response
1136 */
eap_handler(rlm_eap_t * inst,eap_packet_raw_t ** eap_packet_p,REQUEST * request)1137 eap_handler_t *eap_handler(rlm_eap_t *inst, eap_packet_raw_t **eap_packet_p,
1138 REQUEST *request)
1139 {
1140 eap_handler_t *handler = NULL;
1141 eap_packet_raw_t *eap_packet;
1142 VALUE_PAIR *vp;
1143
1144 /*
1145 * Ensure it's a valid EAP-Request, or EAP-Response.
1146 */
1147 if (eap_validation(request, eap_packet_p) == EAP_INVALID) {
1148 error:
1149 talloc_free(*eap_packet_p);
1150 *eap_packet_p = NULL;
1151 return NULL;
1152 }
1153
1154 eap_packet = *eap_packet_p;
1155
1156 /*
1157 * eap_handler_t MUST be found in the list if it is not
1158 * EAP-Identity response
1159 */
1160 if (eap_packet->data[0] != PW_EAP_IDENTITY) {
1161 handler = eaplist_find(inst, request, eap_packet);
1162 if (!handler) {
1163 /* Either send EAP_Identity or EAP-Fail */
1164 RDEBUG("Either EAP-request timed out OR EAP-response to an unknown EAP-request");
1165 goto error;
1166 }
1167
1168 /*
1169 * Even more paranoia. Without this, some weird
1170 * clients could do crazy things.
1171 *
1172 * It's ok to send EAP sub-type NAK in response
1173 * to a request for a particular type, but it's NOT
1174 * OK to blindly return data for another type.
1175 */
1176 if ((eap_packet->data[0] != PW_EAP_NAK) &&
1177 (eap_packet->data[0] != handler->type)) {
1178 RERROR("Response appears to match a previous request, but the EAP type is wrong");
1179 RERROR("We expected EAP type %s, but received type %s",
1180 eap_type2name(handler->type),
1181 eap_type2name(eap_packet->data[0]));
1182 RERROR("Your Supplicant or NAS is probably broken");
1183 goto error;
1184 }
1185
1186 vp = fr_pair_find_by_num(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
1187 if (!vp) {
1188 /*
1189 * NAS did not set the User-Name
1190 * attribute, so we set it here and
1191 * prepend it to the beginning of the
1192 * request vps so that autz's work
1193 * correctly
1194 */
1195 RDEBUG2("Broken NAS did not set User-Name, setting from EAP Identity");
1196 vp = fr_pair_make(request->packet, &request->packet->vps, "User-Name", handler->identity, T_OP_EQ);
1197 if (!vp) {
1198 goto error;
1199 }
1200 } else {
1201 /*
1202 * A little more paranoia. If the NAS
1203 * *did* set the User-Name, and it doesn't
1204 * match the identity, (i.e. If they
1205 * change their User-Name part way through
1206 * the EAP transaction), then reject the
1207 * request as the NAS is doing something
1208 * funny.
1209 */
1210 if (strncmp(handler->identity, vp->vp_strvalue,
1211 MAX_STRING_LEN) != 0) {
1212 RDEBUG("Identity does not match User-Name. Authentication failed");
1213 goto error;
1214 }
1215 }
1216 } else { /* packet was EAP identity */
1217 handler = eap_handler_alloc(inst);
1218 if (!handler) {
1219 goto error;
1220 }
1221
1222 /*
1223 * All fields in the handler are set to zero.
1224 */
1225 handler->identity = eap_identity(request, handler, eap_packet);
1226 if (!handler->identity) {
1227 RDEBUG("Identity Unknown, authentication failed");
1228 error2:
1229 talloc_free(handler);
1230 goto error;
1231 }
1232
1233 vp = fr_pair_find_by_num(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
1234 if (!vp) {
1235 /*
1236 * NAS did not set the User-Name
1237 * attribute, so we set it here and
1238 * prepend it to the beginning of the
1239 * request vps so that autz's work
1240 * correctly
1241 */
1242 RWDEBUG2("NAS did not set User-Name. Setting it locally from EAP Identity");
1243 vp = fr_pair_make(request->packet, &request->packet->vps, "User-Name", handler->identity, T_OP_EQ);
1244 if (!vp) {
1245 goto error2;
1246 }
1247 } else {
1248 /*
1249 * Paranoia. If the NAS *did* set the
1250 * User-Name, and it doesn't match the
1251 * identity, the NAS is doing something
1252 * funny, so reject the request.
1253 */
1254 if (strncmp(handler->identity, vp->vp_strvalue,
1255 MAX_STRING_LEN) != 0) {
1256 RDEBUG("Identity does not match User-Name, setting from EAP Identity");
1257 goto error2;
1258 }
1259 }
1260 }
1261
1262 handler->eap_ds = eap_buildds(handler, eap_packet_p);
1263 if (!handler->eap_ds) {
1264 goto error2;
1265 }
1266
1267 handler->timestamp = request->timestamp;
1268 handler->request = request;
1269 return handler;
1270 }
1271