2 * eap.c rfc2284 & rfc2869 implementation
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.
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.
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
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>
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 * EAP Request and Response Packet Format
37 * --- ------- --- -------- ------ ------
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
47 * EAP Success and Failure Packet Format
48 * --- ------- --- ------- ------ ------
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 #include <freeradius-devel/modpriv.h>
64 static char const *eap_codes[] = {
65 "", /* 0 is invalid */
72 static int _eap_module_free(eap_module_t *inst)
75 * We have to check inst->type as it's only allocated
76 * if we loaded the eap method.
78 if (inst->type && inst->type->detach) (inst->type->detach)(inst->instance);
82 * Don't dlclose() modules if we're doing memory
83 * debugging. This removes the symbols needed by
86 if (!main_config.debug_memory)
88 if (inst->handle) dlclose(inst->handle);
93 /** Load required EAP sub-modules (methods)
96 int eap_module_instantiate(rlm_eap_t *inst, eap_module_t **m_inst, eap_type_t num, CONF_SECTION *cs)
101 /* Make room for the EAP-Type */
102 *m_inst = method = talloc_zero(cs, eap_module_t);
103 if (!inst) return -1;
105 talloc_set_destructor(method, _eap_module_free);
107 /* fill in the structure */
109 method->name = eap_type2name(num);
112 * The name of the module were trying to load
114 mod_name = talloc_typed_asprintf(method, "rlm_eap_%s", method->name);
117 * dlopen is case sensitive
126 * Link the loaded EAP-Type
128 method->handle = lt_dlopenext(mod_name);
129 if (!method->handle) {
130 ERROR("rlm_eap (%s): Failed to link %s: %s", inst->xlat_name, mod_name, fr_strerror());
135 method->type = dlsym(method->handle, mod_name);
137 ERROR("rlm_eap (%s): Failed linking to structure in %s: %s", inst->xlat_name,
138 method->name, dlerror());
143 cf_log_module(cs, "Linked to sub-module %s", mod_name);
146 * Call the attach num in the EAP num module
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);
151 if (method->instance) {
152 (void) talloc_steal(method, method->instance);
158 if (method->instance) {
159 (void) talloc_steal(method, method->instance);
166 * Call the appropriate handle with the right eap_method.
168 static int eap_module_call(eap_module_t *module, eap_handler_t *handler)
171 REQUEST *request = handler->request;
173 char const *caller = request->module;
175 rad_assert(module != NULL);
177 RDEBUG2("Calling submodule %s to process data", module->type->name);
179 request->module = module->type->name;
181 switch (handler->stage) {
183 if (!module->type->session_init(module->instance, handler)) {
191 * The called function updates the EAP reply packet.
193 if (!module->type->process ||
194 !module->type->process(module->instance, handler)) {
201 /* Should never enter here */
202 RDEBUG("Internal sanity check failed on EAP");
207 request->module = caller;
211 /** Process NAK data from EAP peer
214 static eap_type_t eap_process_nak(rlm_eap_t *inst, REQUEST *request,
216 eap_type_data_t *nak)
220 eap_type_t method = PW_EAP_INVALID;
223 * The NAK data is the preferred EAP type(s) of
226 * RFC 3748 says to list one or more proposed
227 * alternative types, one per octet, or to use
228 * 0 for no alternative.
231 REDEBUG("Peer sent empty (invalid) NAK. "
232 "Can't select method to continue with");
234 return PW_EAP_INVALID;
238 * Pick one type out of the one they asked for,
239 * as they may have asked for many.
241 vp = fr_pair_find_by_num(request->config, PW_EAP_TYPE, 0, TAG_ANY);
242 for (i = 0; i < nak->length; i++) {
244 * Type 0 is valid, and means there are no
247 if (nak->data[i] == 0) {
248 RDEBUG("Peer NAK'd indicating it is not willing to "
251 return PW_EAP_INVALID;
255 * It is invalid to request identity,
256 * notification & nak in nak.
258 if (nak->data[i] < PW_EAP_MD5) {
259 REDEBUG("Peer NAK'd asking for bad "
261 eap_type2name(nak->data[i]),
264 return PW_EAP_INVALID;
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]),
278 * Prevent a firestorm if the client is confused.
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]),
286 eap_type2name(nak->data[i]),
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.");
299 * Enforce per-user configuration of EAP
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]),
307 eap_type2name(vp->vp_integer),
313 RDEBUG("Found mutually acceptable type %s (%d)",
314 eap_type2name(nak->data[i]), nak->data[i]);
316 method = nak->data[i];
321 if (method == PW_EAP_INVALID) {
322 REDEBUG("No mutually acceptable types found");
328 /** Select the correct callback based on a response
330 * Based on the EAP response from the supplicant, call the appropriate
333 * Default to the configured EAP-Type for all Unsupported EAP-Types.
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.
339 eap_rcode_t eap_method_select(rlm_eap_t *inst, eap_handler_t *handler)
341 eap_type_data_t *type = &handler->eap_ds->response->type;
342 REQUEST *request = handler->request;
344 eap_type_t next = inst->default_method;
348 * Don't trust anyone.
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);
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.
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.
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");
374 RDEBUG2("Peer sent packet with method EAP %s (%d)", eap_type2name(type->num), type->num);
376 * Figure out what to do.
379 case PW_EAP_IDENTITY:
381 * Allow per-user configuration of EAP types.
383 vp = fr_pair_find_by_num(handler->request->config, PW_EAP_TYPE, 0,
385 if (vp) next = vp->vp_integer;
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);
401 * If any of these fail, we messed badly somewhere
403 rad_assert(next >= PW_EAP_MD5);
404 rad_assert(next < PW_EAP_MAX_TYPES);
405 rad_assert(inst->methods[next]);
407 handler->stage = INITIATE;
408 handler->type = next;
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);
420 * Delete old data, if necessary.
422 if (handler->opaque && handler->free_opaque) {
423 handler->free_opaque(handler->opaque);
424 handler->free_opaque = NULL;
425 handler->opaque = NULL;
428 next = eap_process_nak(inst, handler->request,
429 handler->type, type);
432 * We probably want to return 'fail' here...
441 * Key off of the configured sub-modules.
445 * We haven't configured it, it doesn't exit.
447 if (!inst->methods[type->num]) {
448 REDEBUG2("Client asked for unsupported EAP type %s (%d)",
449 eap_type2name(type->num),
455 rad_assert(handler->stage == PROCESS);
456 handler->type = type->num;
457 if (eap_module_call(inst->methods[type->num],
459 REDEBUG2("Failed continuing EAP %s (%d) session. EAP sub-module failed",
460 eap_type2name(type->num),
473 * compose EAP reply packet in EAP-Message attr of RADIUS.
475 * Set the RADIUS reply codes based on EAP request codes. Append
476 * any additonal VPs to RADIUS reply
478 rlm_rcode_t eap_compose(eap_handler_t *handler)
481 eap_packet_raw_t *eap_packet;
488 handler = talloc_get_type_abort(handler, eap_handler_t);
489 request = talloc_get_type_abort(handler->request, REQUEST);
490 eap_ds = talloc_get_type_abort(handler->eap_ds, EAP_DS);
491 reply = talloc_get_type_abort(eap_ds->request, eap_packet_t);
493 request = handler->request;
494 eap_ds = handler->eap_ds;
495 reply = eap_ds->request;
499 * The Id for the EAP packet to the NAS wasn't set.
502 * LEAP requires the Id to be incremented on EAP-Success
503 * in Stage 4, so that we can carry on the conversation
504 * where the client asks us to authenticate ourselves
507 if (!eap_ds->set_request_id) {
509 * Id serves to suppport request/response
510 * retransmission in the EAP layer and as such
511 * must be different for 'adjacent' packets
512 * except in case of success/failure-replies.
514 * RFC2716 (EAP-TLS) requires this to be
515 * incremented, RFC2284 only makes the above-
516 * mentioned restriction.
518 reply->id = handler->eap_ds->response->id;
520 switch (reply->code) {
522 * The Id is a simple "ack" for success
525 * RFC 3748 section 4.2 says
527 * ... The Identifier field MUST match
528 * the Identifier field of the Response
529 * packet that it is sent in response
537 * We've sent a response to their
538 * request, the Id is incremented.
546 * For Request & Response packets, set the EAP sub-type,
547 * if the EAP sub-module didn't already set it.
549 * This allows the TLS module to be "morphic", and means
550 * that the TTLS and PEAP modules can call it to do most
551 * of their dirty work.
553 if (((eap_ds->request->code == PW_EAP_REQUEST) ||
554 (eap_ds->request->code == PW_EAP_RESPONSE)) &&
555 (eap_ds->request->type.num == 0)) {
556 rad_assert(handler->type >= PW_EAP_MD5);
557 rad_assert(handler->type < PW_EAP_MAX_TYPES);
559 eap_ds->request->type.num = handler->type;
562 if (eap_wireformat(reply) == EAP_INVALID) {
563 return RLM_MODULE_INVALID;
565 eap_packet = (eap_packet_raw_t *)reply->packet;
567 vp = radius_pair_create(request->reply, &request->reply->vps, PW_EAP_MESSAGE, 0);
568 if (!vp) return RLM_MODULE_INVALID;
570 vp->vp_length = eap_packet->length[0] * 256 + eap_packet->length[1];
571 vp->vp_octets = talloc_steal(vp, reply->packet);
572 reply->packet = NULL;
575 * EAP-Message is always associated with
576 * Message-Authenticator but not vice-versa.
578 * Don't add a Message-Authenticator if it's already
581 vp = fr_pair_find_by_num(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY);
583 vp = fr_pair_afrom_num(request->reply, PW_MESSAGE_AUTHENTICATOR, 0);
584 vp->vp_length = AUTH_VECTOR_LEN;
585 vp->vp_octets = talloc_zero_array(vp, uint8_t, vp->vp_length);
586 fr_pair_add(&(request->reply->vps), vp);
589 /* Set request reply code, but only if it's not already set. */
590 rcode = RLM_MODULE_OK;
591 if (!request->reply->code) switch (reply->code) {
592 case PW_EAP_RESPONSE:
593 request->reply->code = PW_CODE_ACCESS_ACCEPT;
594 rcode = RLM_MODULE_HANDLED; /* leap weirdness */
597 request->reply->code = PW_CODE_ACCESS_ACCEPT;
598 rcode = RLM_MODULE_OK;
601 request->reply->code = PW_CODE_ACCESS_REJECT;
602 rcode = RLM_MODULE_REJECT;
605 request->reply->code = PW_CODE_ACCESS_CHALLENGE;
606 rcode = RLM_MODULE_HANDLED;
610 * When we're pulling MS-CHAPv2 out of EAP-MS-CHAPv2,
611 * we do so WITHOUT setting a reply code, as the
612 * request is being proxied.
614 if (request->options & RAD_REQUEST_OPTION_PROXY_EAP) {
615 return RLM_MODULE_HANDLED;
618 /* Should never enter here */
619 REDEBUG("Reply code %d is unknown, rejecting the request", reply->code);
620 request->reply->code = PW_CODE_ACCESS_REJECT;
621 reply->code = PW_EAP_FAILURE;
622 rcode = RLM_MODULE_REJECT;
626 RDEBUG2("Sending EAP %s (code %i) ID %d length %i",
627 eap_codes[eap_packet->code], eap_packet->code, reply->id,
628 eap_packet->length[0] * 256 + eap_packet->length[1]);
634 * Radius criteria, EAP-Message is invalid without Message-Authenticator
635 * For EAP_START, send Access-Challenge with EAP Identity request.
637 int eap_start(rlm_eap_t *inst, REQUEST *request)
639 VALUE_PAIR *vp, *proxy;
642 eap_msg = fr_pair_find_by_num(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
644 RDEBUG2("No EAP-Message, not doing EAP");
649 * Look for EAP-Type = None (FreeRADIUS specific attribute)
650 * this allows you to NOT do EAP for some users.
652 vp = fr_pair_find_by_num(request->packet->vps, PW_EAP_TYPE, 0, TAG_ANY);
653 if (vp && vp->vp_integer == 0) {
654 RDEBUG2("Found EAP-Message, but EAP-Type = None, so we're not doing EAP");
659 * http://www.freeradius.org/rfc/rfc2869.html#EAP-Message
661 * Checks for Message-Authenticator are handled by rad_recv().
665 * Check for a Proxy-To-Realm. Don't get excited over LOCAL
668 proxy = fr_pair_find_by_num(request->config, PW_PROXY_TO_REALM, 0, TAG_ANY);
673 * If it's a LOCAL realm, then we're not proxying
676 realm = realm_find(proxy->vp_strvalue);
677 if (!realm || (realm && (!realm->auth_pool))) {
683 * Check the length before de-referencing the contents.
685 * Lengths of zero are required by the RFC for EAP-Start,
686 * but we've never seen them in practice.
688 * Lengths of two are what we see in practice as
691 if ((eap_msg->vp_length == 0) || (eap_msg->vp_length == 2)) {
695 * It's a valid EAP-Start, but the request
696 * was marked as being proxied. So we don't
697 * do EAP, as the home server will do it.
701 RDEBUG2("Request is supposed to be proxied to "
702 "Realm %s. Not doing EAP.", proxy->vp_strvalue);
706 RDEBUG2("Got EAP_START message");
707 vp = fr_pair_afrom_num(request->reply, PW_EAP_MESSAGE, 0);
708 if (!vp) return EAP_FAIL;
709 fr_pair_add(&request->reply->vps, vp);
712 * Manually create an EAP Identity request
715 vp->vp_octets = p = talloc_array(vp, uint8_t, vp->vp_length);
717 p[0] = PW_EAP_REQUEST;
720 p[3] = 5; /* length */
721 p[4] = PW_EAP_IDENTITY;
724 } /* end of handling EAP-Start */
727 * The EAP packet header is 4 bytes, plus one byte of
728 * EAP sub-type. Short packets are discarded, unless
731 if (eap_msg->vp_length < (EAP_HEADER_LEN + 1)) {
732 if (proxy) goto do_proxy;
734 RDEBUG2("Ignoring EAP-Message which is too short to be meaningful");
739 * Create an EAP-Type containing the EAP-type
742 vp = fr_pair_afrom_num(request->packet, PW_EAP_TYPE, 0);
744 vp->vp_integer = eap_msg->vp_octets[4];
745 fr_pair_add(&(request->packet->vps), vp);
749 * If the request was marked to be proxied, do it now.
750 * This is done after checking for a valid length
751 * (which may not be good), and after adding the EAP-Type
752 * attribute. This lets other modules selectively cancel
753 * proxying based on EAP-Type.
755 if (proxy) goto do_proxy;
758 * From now on, we're supposed to be handling the
759 * EAP packet. We better understand it...
763 * We're allowed only a few codes. Request, Response,
764 * Success, or Failure.
766 if ((eap_msg->vp_octets[0] == 0) ||
767 (eap_msg->vp_octets[0] >= PW_EAP_MAX_CODES)) {
768 RDEBUG2("Peer sent EAP packet with unknown code %i", eap_msg->vp_octets[0]);
770 RDEBUG2("Peer sent EAP %s (code %i) ID %d length %zu",
771 eap_codes[eap_msg->vp_octets[0]],
772 eap_msg->vp_octets[0],
773 eap_msg->vp_octets[1],
778 * We handle request and responses. The only other defined
779 * codes are success and fail. The client SHOULD NOT be
780 * sending success/fail packets to us, as it doesn't make
783 if ((eap_msg->vp_octets[0] != PW_EAP_REQUEST) &&
784 (eap_msg->vp_octets[0] != PW_EAP_RESPONSE)) {
785 RDEBUG2("Ignoring EAP packet which we don't know how to handle");
790 * We've been told to ignore unknown EAP types, AND it's
791 * an unknown type. Return "NOOP", which will cause the
792 * mod_authorize() to return NOOP.
794 * EAP-Identity, Notification, and NAK are all handled
795 * internally, so they never have handlers.
797 if ((eap_msg->vp_octets[4] >= PW_EAP_MD5) &&
798 inst->ignore_unknown_types &&
799 ((eap_msg->vp_octets[4] == 0) ||
800 (eap_msg->vp_octets[4] >= PW_EAP_MAX_TYPES) ||
801 (!inst->methods[eap_msg->vp_octets[4]]))) {
802 RDEBUG2("Ignoring Unknown EAP type");
807 * They're NAKing the EAP type we wanted to use, and
808 * asking for one which we don't support.
810 * NAK is code + id + length1 + length + NAK
811 * + requested EAP type(s).
813 * We know at this point that we can't handle the
814 * request. We could either return an EAP-Fail here, but
815 * it's not too critical.
817 * By returning "noop", we can ensure that authorize()
818 * returns NOOP, and another module may choose to proxy
821 if ((eap_msg->vp_octets[4] == PW_EAP_NAK) &&
822 (eap_msg->vp_length >= (EAP_HEADER_LEN + 2)) &&
823 inst->ignore_unknown_types &&
824 ((eap_msg->vp_octets[5] == 0) ||
825 (eap_msg->vp_octets[5] >= PW_EAP_MAX_TYPES) ||
826 (!inst->methods[eap_msg->vp_octets[5]]))) {
827 RDEBUG2("Ignoring NAK with request for unknown EAP type");
831 if ((eap_msg->vp_octets[4] == PW_EAP_TTLS) ||
832 (eap_msg->vp_octets[4] == PW_EAP_PEAP)) {
833 RDEBUG2("Continuing tunnel setup");
837 * We return ok in response to EAP identity
838 * This means we can write:
846 * ...in the inner-tunnel, to avoid expensive and unnecessary SQL/LDAP lookups
848 if (eap_msg->vp_octets[4] == PW_EAP_IDENTITY) {
849 RDEBUG2("EAP-Identity reply, returning 'ok' so we can short-circuit the rest of authorize");
854 * Later EAP messages are longer than the 'start'
855 * message, so if everything is OK, this function returns
856 * 'no start found', so that the rest of the EAP code can
857 * use the State attribute to match this EAP-Message to
858 * an ongoing conversation.
860 RDEBUG2("No EAP Start, assuming it's an on-going EAP conversation");
866 * compose EAP FAILURE packet in EAP-Message
868 void eap_fail(eap_handler_t *handler)
871 * Delete any previous replies.
873 fr_pair_delete_by_num(&handler->request->reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
874 fr_pair_delete_by_num(&handler->request->reply->vps, PW_STATE, 0, TAG_ANY);
876 talloc_free(handler->eap_ds->request);
877 handler->eap_ds->request = talloc_zero(handler->eap_ds, eap_packet_t);
878 handler->eap_ds->request->code = PW_EAP_FAILURE;
879 handler->finished = true;
880 eap_compose(handler);
884 * compose EAP SUCCESS packet in EAP-Message
886 void eap_success(eap_handler_t *handler)
888 handler->eap_ds->request->code = PW_EAP_SUCCESS;
889 handler->finished = true;
890 eap_compose(handler);
894 * Basic EAP packet verfications & validations
896 static int eap_validation(REQUEST *request, eap_packet_raw_t **eap_packet_p)
899 eap_packet_raw_t *eap_packet = *eap_packet_p;
901 memcpy(&len, eap_packet->length, sizeof(uint16_t));
905 * High level EAP packet checks
907 if ((len <= EAP_HEADER_LEN) ||
908 ((eap_packet->code != PW_EAP_RESPONSE) &&
909 (eap_packet->code != PW_EAP_REQUEST))) {
910 RAUTH("Badly formatted EAP Message: Ignoring the packet");
914 if ((eap_packet->data[0] <= 0) ||
915 (eap_packet->data[0] >= PW_EAP_MAX_TYPES)) {
917 * Handle expanded types by smashing them to
920 if (eap_packet->data[0] == PW_EAP_EXPANDED_TYPE) {
923 if (len <= (EAP_HEADER_LEN + 1 + 3 + 4)) {
924 RAUTH("Expanded EAP type is too short: ignoring the packet");
928 if ((eap_packet->data[1] != 0) ||
929 (eap_packet->data[2] != 0) ||
930 (eap_packet->data[3] != 0)) {
931 RAUTH("Expanded EAP type has unknown Vendor-ID: ignoring the packet");
935 if ((eap_packet->data[4] != 0) ||
936 (eap_packet->data[5] != 0) ||
937 (eap_packet->data[6] != 0)) {
938 RAUTH("Expanded EAP type has unknown Vendor-Type: ignoring the packet");
942 if ((eap_packet->data[7] == 0) ||
943 (eap_packet->data[7] >= PW_EAP_MAX_TYPES)) {
944 RAUTH("Unsupported Expanded EAP type %s (%u): ignoring the packet",
945 eap_type2name(eap_packet->data[7]), eap_packet->data[7]);
949 if (eap_packet->data[7] == PW_EAP_NAK) {
950 RAUTH("Unsupported Expanded EAP-NAK: ignoring the packet");
955 * Re-write the EAP packet to NOT have the expanded type.
957 q = (uint8_t *) eap_packet;
958 memmove(q + EAP_HEADER_LEN, q + EAP_HEADER_LEN + 7, len - 7 - EAP_HEADER_LEN);
960 p = talloc_realloc(talloc_parent(eap_packet), eap_packet, uint8_t, len - 7);
962 RAUTH("Unsupported EAP type %s (%u): ignoring the packet",
963 eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
968 p[2] = (len >> 8) & 0xff;
971 *eap_packet_p = (eap_packet_raw_t *) p;
972 RWARN("Converting Expanded EAP to normal EAP.");
973 RWARN("Unnecessary use of Expanded EAP types is not recommened.");
978 RAUTH("Unsupported EAP type %s (%u): ignoring the packet",
979 eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
983 /* we don't expect notification, but we send it */
984 if (eap_packet->data[0] == PW_EAP_NOTIFICATION) {
985 RAUTH("Got NOTIFICATION, "
986 "Ignoring the packet");
995 * Get the user Identity only from EAP-Identity packets
997 static char *eap_identity(REQUEST *request, eap_handler_t *handler, eap_packet_raw_t *eap_packet)
1003 if ((!eap_packet) ||
1004 (eap_packet->code != PW_EAP_RESPONSE) ||
1005 (eap_packet->data[0] != PW_EAP_IDENTITY)) {
1009 memcpy(&len, eap_packet->length, sizeof(uint16_t));
1012 if ((len <= 5) || (eap_packet->data[1] == 0x00)) {
1013 REDEBUG("EAP-Identity Unknown");
1018 REDEBUG("EAP-Identity too long");
1023 identity = talloc_array(handler, char, size + 1);
1024 memcpy(identity, &eap_packet->data[1], size);
1025 identity[size] = '\0';
1032 * Create our Request-Response data structure with the eap packet
1034 static EAP_DS *eap_buildds(eap_handler_t *handler,
1035 eap_packet_raw_t **eap_packet_p)
1037 EAP_DS *eap_ds = NULL;
1038 eap_packet_raw_t *eap_packet = *eap_packet_p;
1042 if ((eap_ds = eap_ds_alloc(handler)) == NULL) {
1046 eap_ds->response->packet = (uint8_t *) eap_packet;
1047 (void) talloc_steal(eap_ds, eap_packet);
1048 eap_ds->response->code = eap_packet->code;
1049 eap_ds->response->id = eap_packet->id;
1050 eap_ds->response->type.num = eap_packet->data[0];
1052 memcpy(&len, eap_packet->length, sizeof(uint16_t));
1054 eap_ds->response->length = len;
1057 * We've eaten the eap packet into the eap_ds.
1059 *eap_packet_p = NULL;
1062 * First 5 bytes in eap, are code + id + length(2) + type.
1064 * The rest is type-specific data. We skip type while
1065 * getting typedata from data.
1067 typelen = len - 5/*code + id + length + type */;
1070 * Since the packet contains the complete
1071 * eap_packet, typedata will be a ptr in packet
1074 eap_ds->response->type.data = eap_ds->response->packet + 5/*code+id+length+type*/;
1075 eap_ds->response->type.length = typelen;
1077 eap_ds->response->type.length = 0;
1078 eap_ds->response->type.data = NULL;
1086 * If identity response then create a fresh handler & fill the identity
1087 * else handler MUST be in our list, get that.
1088 * This handler creation cannot fail
1090 * username contains REQUEST->username which might have been stripped.
1091 * identity contains the one sent in EAP-Identity response
1093 eap_handler_t *eap_handler(rlm_eap_t *inst, eap_packet_raw_t **eap_packet_p,
1096 eap_handler_t *handler = NULL;
1097 eap_packet_raw_t *eap_packet;
1101 * Ensure it's a valid EAP-Request, or EAP-Response.
1103 if (eap_validation(request, eap_packet_p) == EAP_INVALID) {
1105 talloc_free(*eap_packet_p);
1106 *eap_packet_p = NULL;
1110 eap_packet = *eap_packet_p;
1113 * eap_handler_t MUST be found in the list if it is not
1114 * EAP-Identity response
1116 if (eap_packet->data[0] != PW_EAP_IDENTITY) {
1117 handler = eaplist_find(inst, request, eap_packet);
1119 /* Either send EAP_Identity or EAP-Fail */
1120 RDEBUG("Either EAP-request timed out OR EAP-response to an unknown EAP-request");
1125 * Even more paranoia. Without this, some weird
1126 * clients could do crazy things.
1128 * It's ok to send EAP sub-type NAK in response
1129 * to a request for a particular type, but it's NOT
1130 * OK to blindly return data for another type.
1132 if ((eap_packet->data[0] != PW_EAP_NAK) &&
1133 (eap_packet->data[0] != handler->type)) {
1134 RERROR("Response appears to match a previous request, but the EAP type is wrong");
1135 RERROR("We expected EAP type %s, but received type %s",
1136 eap_type2name(handler->type),
1137 eap_type2name(eap_packet->data[0]));
1138 RERROR("Your Supplicant or NAS is probably broken");
1142 vp = fr_pair_find_by_num(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
1145 * NAS did not set the User-Name
1146 * attribute, so we set it here and
1147 * prepend it to the beginning of the
1148 * request vps so that autz's work
1151 RDEBUG2("Broken NAS did not set User-Name, setting from EAP Identity");
1152 vp = fr_pair_make(request->packet, &request->packet->vps, "User-Name", handler->identity, T_OP_EQ);
1158 * A little more paranoia. If the NAS
1159 * *did* set the User-Name, and it doesn't
1160 * match the identity, (i.e. If they
1161 * change their User-Name part way through
1162 * the EAP transaction), then reject the
1163 * request as the NAS is doing something
1166 if (strncmp(handler->identity, vp->vp_strvalue,
1167 MAX_STRING_LEN) != 0) {
1168 RDEBUG("Identity does not match User-Name. Authentication failed");
1172 } else { /* packet was EAP identity */
1173 handler = eap_handler_alloc(inst);
1179 * All fields in the handler are set to zero.
1181 handler->identity = eap_identity(request, handler, eap_packet);
1182 if (!handler->identity) {
1183 RDEBUG("Identity Unknown, authentication failed");
1185 talloc_free(handler);
1189 vp = fr_pair_find_by_num(request->packet->vps, PW_USER_NAME, 0, TAG_ANY);
1192 * NAS did not set the User-Name
1193 * attribute, so we set it here and
1194 * prepend it to the beginning of the
1195 * request vps so that autz's work
1198 RWDEBUG2("NAS did not set User-Name. Setting it locally from EAP Identity");
1199 vp = fr_pair_make(request->packet, &request->packet->vps, "User-Name", handler->identity, T_OP_EQ);
1205 * Paranoia. If the NAS *did* set the
1206 * User-Name, and it doesn't match the
1207 * identity, the NAS is doing something
1208 * funny, so reject the request.
1210 if (strncmp(handler->identity, vp->vp_strvalue,
1211 MAX_STRING_LEN) != 0) {
1212 RDEBUG("Identity does not match User-Name, setting from EAP Identity");
1218 handler->eap_ds = eap_buildds(handler, eap_packet_p);
1219 if (!handler->eap_ds) {
1223 handler->timestamp = request->timestamp;
1224 handler->request = request; /* LEAP needs this */