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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2000-2003 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 static const char rcsid[] = "$Id$";
61 static const char *eap_codes[] = {
62 "", /* 0 is invalid */
70 * Load all the required eap authentication types.
71 * Get all the supported EAP-types from config file.
73 int eaptype_load(EAP_TYPES **type, int eap_type, CONF_SECTION *cs)
77 const char *eaptype_name;
81 eaptype_name = eaptype_type2name(eap_type, namebuf, sizeof(namebuf));
82 snprintf(buffer, sizeof(buffer), "rlm_eap_%s", eaptype_name);
84 /* Link the loaded EAP-Type */
85 handle = lt_dlopenext(buffer);
87 radlog(L_ERR, "rlm_eap: Failed to link EAP-Type/%s: %s",
88 eaptype_name, lt_dlerror());
92 /* Make room for the EAP-Type */
93 node = (EAP_TYPES *)malloc(sizeof(EAP_TYPES));
95 radlog(L_ERR, "rlm_eap: out of memory");
98 memset(node, 0, sizeof(*node));
100 /* fill in the structure */
101 node->handle = handle;
105 * In general, this is a terrible idea. It works here
106 * solely because the eap_type2name function returns a
107 * 'static const char *' pointer sometimes, and we can
108 * ONLY link to module which are named in that static
111 node->typename = eaptype_name;
112 node->type_data = NULL;
114 node->type = (EAP_TYPE *)lt_dlsym(node->handle, buffer);
116 radlog(L_ERR, "rlm_eap: Failed linking to %s structure in %s: %s",
117 buffer, eaptype_name, lt_dlerror());
118 lt_dlclose(node->handle); /* ignore any errors */
122 if ((node->type->attach) &&
123 ((node->type->attach)(node->cs, &(node->type_data)) < 0)) {
125 radlog(L_ERR, "rlm_eap: Failed to initialize type %s",
127 lt_dlclose(node->handle);
132 DEBUG("rlm_eap: Loaded and initialized type %s", eaptype_name);
138 * Call the appropriate handle with the right eap_type.
140 static int eaptype_call(EAP_TYPES *atype, EAP_HANDLER *handler)
144 DEBUG2(" rlm_eap: processing type %s", atype->typename);
146 rad_assert(atype != NULL);
148 switch (handler->stage) {
150 if (!atype->type->initiate(atype->type_data, handler))
156 * The called function updates the EAP reply packet.
158 if (!atype->type->authorize ||
159 !atype->type->authorize(atype->type_data, handler))
165 * The called function updates the EAP reply packet.
167 if (!atype->type->authenticate ||
168 !atype->type->authenticate(atype->type_data, handler))
173 /* Should never enter here */
174 radlog(L_DBG, "rlm_eap: Invalid operation on eap_type");
183 * Based on TYPE, call the appropriate EAP-type handler
184 * Default to the configured EAP-Type
185 * for all Unsupported EAP-Types
187 int eaptype_select(rlm_eap_t *inst, EAP_HANDLER *handler)
189 unsigned int default_eap_type = inst->default_eap_type;
193 const char *eaptype_name;
195 eaptype = &handler->eap_ds->response->type;
198 * Don't trust anyone.
200 if ((eaptype->type == 0) ||
201 (eaptype->type > PW_EAP_MAX_TYPES)) {
202 DEBUG2(" rlm_eap: Asked to select bad type");
207 * Figure out what to do.
209 switch(eaptype->type) {
210 case PW_EAP_IDENTITY:
211 DEBUG2(" rlm_eap: EAP Identity");
214 * Allow per-user configuration of EAP types.
216 vp = pairfind(handler->request->config_items,
218 if (vp) default_eap_type = vp->lvalue;
224 if ((default_eap_type < PW_EAP_MD5) ||
225 (default_eap_type > PW_EAP_MAX_TYPES) ||
226 (inst->types[default_eap_type] == NULL)) {
227 DEBUG2(" rlm_eap: No such EAP type %s",
228 eaptype_type2name(default_eap_type,
229 namebuf, sizeof(namebuf)));
233 handler->stage = INITIATE;
234 handler->eap_type = default_eap_type;
237 * Wild & crazy stuff! For TTLS & PEAP, we
238 * initiate a TLS session, and then pass that
239 * session data to TTLS or PEAP for the
240 * authenticate stage.
242 * Handler->eap_type holds the TRUE type.
244 if ((default_eap_type == PW_EAP_TTLS) ||
245 (default_eap_type == PW_EAP_PEAP)) {
246 default_eap_type = PW_EAP_TLS;
251 * We don't do TLS inside of TLS, as it's a bad
254 if (((handler->request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) &&
255 (default_eap_type == PW_EAP_TLS)) {
256 DEBUG2(" rlm_eap: Unable to tunnel TLS inside of TLS");
260 if (eaptype_call(inst->types[default_eap_type],
262 DEBUG2(" rlm_eap: Default EAP type %s failed in initiate",
263 eaptype_type2name(default_eap_type,
264 namebuf, sizeof(namebuf)));
271 * The NAK data is the preferred EAP type(s) of
274 * RFC 3748 says to list one or more proposed
275 * alternative types, one per octet, or to use
276 * 0 for no alternative.
278 DEBUG2(" rlm_eap: EAP NAK");
281 * Delete old data, if necessary.
283 if (handler->opaque && handler->free_opaque) {
284 handler->free_opaque(handler->opaque);
285 handler->free_opaque = NULL;
286 handler->opaque = NULL;
290 * It is invalid to request identity,
291 * notification & nak in nak
293 if (eaptype->data == NULL) {
294 DEBUG2(" rlm_eap: Empty NAK packet, cannot decide what EAP type the client wants.");
299 * FIXME: Pick one type out of the one they asked
300 * for, as they may have asked for many.
302 if ((eaptype->data[0] < PW_EAP_MD5) ||
303 (eaptype->data[0] > PW_EAP_MAX_TYPES)) {
304 DEBUG2(" rlm_eap: NAK asked for bad type %d",
309 default_eap_type = eaptype->data[0];
310 eaptype_name = eaptype_type2name(default_eap_type,
311 namebuf, sizeof(namebuf));
312 DEBUG2(" rlm_eap: EAP-NAK asked for EAP-Type/%s",
316 * Prevent a firestorm if the client is confused.
318 if (handler->eap_type == default_eap_type) {
319 DEBUG2(" rlm_eap: ERROR! Our request for %s was NAK'd with a request for %s, what is the client thinking?",
320 eaptype_name, eaptype_name);
325 * Enforce per-user configuration of EAP types.
327 vp = pairfind(handler->request->config_items,
329 if (vp && (vp->lvalue != default_eap_type)) {
331 DEBUG2(" rlm_eap: Client wants %s, while we require %s, rejecting the user.",
333 eaptype_type2name(vp->lvalue,
342 * Key off of the configured sub-modules.
345 eaptype_name = eaptype_type2name(eaptype->type,
348 DEBUG2(" rlm_eap: EAP/%s", eaptype_name);
351 * We haven't configured it, it doesn't exit.
353 if (!inst->types[eaptype->type]) {
354 DEBUG2(" rlm_eap: EAP type %d is unsupported",
359 rad_assert(handler->stage == AUTHENTICATE);
360 handler->eap_type = eaptype->type;
361 if (eaptype_call(inst->types[eaptype->type],
363 DEBUG2(" rlm_eap: Handler failed in EAP/%s",
375 * EAP packet format to be sent over the wire
377 * i.e. code+id+length+data where data = null/type+typedata
380 static int eap_wireformat(EAP_PACKET *reply)
383 uint16_t total_length = 0;
385 if (reply == NULL) return EAP_INVALID;
387 total_length = EAP_HEADER_LEN;
388 if (reply->code < 3) {
389 total_length += 1/*EAPtype*/;
390 if (reply->type.data && reply->type.length > 0) {
391 total_length += reply->type.length;
395 reply->packet = (unsigned char *)malloc(total_length);
396 hdr = (eap_packet_t *)reply->packet;
398 radlog(L_ERR, "rlm_eap: out of memory");
402 hdr->code = (reply->code & 0xFF);
403 hdr->id = (reply->id & 0xFF);
404 total_length = htons(total_length);
405 memcpy(hdr->length, &total_length, sizeof(uint16_t));
408 * Request and Response packets are special.
410 if ((reply->code == PW_EAP_REQUEST) ||
411 (reply->code == PW_EAP_RESPONSE)) {
412 hdr->data[0] = (reply->type.type & 0xFF);
415 * Here since we cannot know the typedata format and length
417 * Type_data is expected to be wired by each EAP-Type
419 * Zero length/No typedata is supported as long as
422 if (reply->type.data && reply->type.length > 0) {
423 memcpy(&hdr->data[1], reply->type.data, reply->type.length);
424 free(reply->type.data);
425 reply->type.data = reply->packet + EAP_HEADER_LEN + 1/*EAPtype*/;
433 * compose EAP reply packet in EAP-Message attr of RADIUS. If
434 * EAP exceeds 253, frame it in multiple EAP-Message attrs.
436 * Set the RADIUS reply codes based on EAP request codes. Append
437 * any additonal VPs to RADIUS reply
439 int eap_compose(EAP_HANDLER *handler)
441 uint16_t eap_len, len;
444 eap_packet_t *eap_packet;
446 REQUEST *request = handler->request;
447 EAP_DS *eap_ds = handler->eap_ds;
448 EAP_PACKET *reply = eap_ds->request;
452 * The Id for the EAP packet to the NAS wasn't set.
455 * LEAP requires the Id to be incremented on EAP-Success
456 * in Stage 4, so that we can carry on the conversation
457 * where the client asks us to authenticate ourselves
460 if (!eap_ds->set_request_id) {
462 * Id serves to suppport request/response
463 * retransmission in the EAP layer and as such
464 * must be different for 'adjacent' packets
465 * except in case of success/failure-replies.
467 * RFC2716 (EAP-TLS) requires this to be
468 * incremented, RFC2284 only makes the above-
469 * mentioned restriction.
471 reply->id = handler->eap_ds->response->id;
473 switch (reply->code) {
475 * The Id is a simple "ack" for success
478 * RFC 3748 section 4.2 says
480 * ... The Identifier field MUST match
481 * the Identifier field of the Response
482 * packet that it is sent in response
490 * We've sent a response to their
491 * request, the Id is incremented.
497 DEBUG2(" rlm_eap: Underlying EAP-Type set EAP ID to %d",
502 * For Request & Response packets, set the EAP sub-type,
503 * if the EAP sub-module didn't already set it.
505 * This allows the TLS module to be "morphic", and means
506 * that the TTLS and PEAP modules can call it to do most
507 * of their dirty work.
509 if (((eap_ds->request->code == PW_EAP_REQUEST) ||
510 (eap_ds->request->code == PW_EAP_RESPONSE)) &&
511 (eap_ds->request->type.type == 0)) {
512 rad_assert(handler->eap_type >= PW_EAP_MD5);
513 rad_assert(handler->eap_type <= PW_EAP_MAX_TYPES);
515 eap_ds->request->type.type = handler->eap_type;
519 if (eap_wireformat(reply) == EAP_INVALID) {
520 return RLM_MODULE_INVALID;
522 eap_packet = (eap_packet_t *)reply->packet;
524 memcpy(&eap_len, &(eap_packet->length), sizeof(uint16_t));
525 len = eap_len = ntohs(eap_len);
526 ptr = (unsigned char *)eap_packet;
538 * create a value pair & append it to the request reply list
539 * This memory gets freed up when request is freed up
541 eap_msg = paircreate(PW_EAP_MESSAGE, PW_TYPE_OCTETS);
542 memcpy(eap_msg->strvalue, ptr, len);
543 eap_msg->length = len;
544 pairadd(&(request->reply->vps), eap_msg);
550 * EAP-Message is always associated with
551 * Message-Authenticator but not vice-versa.
553 * Don't add a Message-Authenticator if it's already
556 vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR);
558 vp = paircreate(PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
559 memset(vp->strvalue, 0, AUTH_VECTOR_LEN);
560 vp->length = AUTH_VECTOR_LEN;
561 pairadd(&(request->reply->vps), vp);
564 /* Set request reply code, but only if it's not already set. */
565 rcode = RLM_MODULE_OK;
566 if (!request->reply->code) switch(reply->code) {
567 case PW_EAP_RESPONSE:
568 request->reply->code = PW_AUTHENTICATION_ACK;
569 rcode = RLM_MODULE_HANDLED; /* leap weirdness */
572 request->reply->code = PW_AUTHENTICATION_ACK;
573 rcode = RLM_MODULE_OK;
576 request->reply->code = PW_AUTHENTICATION_REJECT;
577 rcode = RLM_MODULE_REJECT;
580 request->reply->code = PW_ACCESS_CHALLENGE;
581 rcode = RLM_MODULE_HANDLED;
585 * When we're pulling MS-CHAPv2 out of EAP-MS-CHAPv2,
586 * we do so WITHOUT setting a reply code, as the
587 * request is being proxied.
589 if (request->options & RAD_REQUEST_OPTION_PROXY_EAP) {
590 return RLM_MODULE_HANDLED;
593 /* Should never enter here */
594 radlog(L_ERR, "rlm_eap: reply code %d is unknown, Rejecting the request.", reply->code);
595 request->reply->code = PW_AUTHENTICATION_REJECT;
596 reply->code = PW_EAP_FAILURE;
597 rcode = RLM_MODULE_REJECT;
605 * Radius criteria, EAP-Message is invalid without Message-Authenticator
606 * For EAP_START, send Access-Challenge with EAP Identity request.
608 int eap_start(rlm_eap_t *inst, REQUEST *request)
610 VALUE_PAIR *vp, *proxy;
613 eap_msg = pairfind(request->packet->vps, PW_EAP_MESSAGE);
614 if (eap_msg == NULL) {
615 DEBUG2(" rlm_eap: No EAP-Message, not doing EAP");
620 * Look for EAP-Type = None (FreeRADIUS specific attribute)
621 * this allows you to NOT do EAP for some users.
623 vp = pairfind(request->packet->vps, PW_EAP_TYPE);
624 if (vp && vp->lvalue == 0) {
625 DEBUG2(" rlm_eap: Found EAP-Message, but EAP-Type = None, so we're not doing EAP.");
630 * http://www.freeradius.org/rfc/rfc2869.html#EAP-Message
632 * Checks for Message-Authenticator are handled by rad_recv().
636 * Check for a Proxy-To-Realm. Don't get excited over LOCAL
639 proxy = pairfind(request->config_items, PW_PROXY_TO_REALM);
644 * If it's a LOCAL realm, then we're not proxying
647 realm = realm_find(proxy->strvalue, 0);
648 if (realm && (realm->ipaddr == htonl(INADDR_NONE))) {
654 * Check the length before de-referencing the contents.
656 * Lengths of zero are required by the RFC for EAP-Start,
657 * but we've never seen them in practice.
659 * Lengths of two are what we see in practice as
662 if ((eap_msg->length == 0) || (eap_msg->length == 2)) {
667 * It's a valid EAP-Start, but the request
668 * was marked as being proxied. So we don't
669 * do EAP, as the home server will do it.
673 DEBUG2(" rlm_eap: Request is supposed to be proxied to Realm %s. Not doing EAP.", proxy->strvalue);
677 DEBUG2(" rlm_eap: Got EAP_START message");
678 if ((eap_ds = eap_ds_alloc()) == NULL) {
679 DEBUG2(" rlm_eap: EAP Start failed in allocation");
684 * It's an EAP-Start packet. Tell them to stop wasting
685 * our time, and give us an EAP-Identity packet.
687 * Hmm... we should probably check the contents of the
688 * EAP-Start packet for something...
690 eap_ds->request->code = PW_EAP_REQUEST;
691 eap_ds->request->type.type = PW_EAP_IDENTITY;
694 * We don't have a handler, but eap_compose needs one,
695 * (for various reasons), so we fake it out here.
697 memset(&handler, 0, sizeof(handler));
698 handler.request = request;
699 handler.eap_ds = eap_ds;
701 eap_compose(&handler);
703 eap_ds_free(&eap_ds);
705 } /* end of handling EAP-Start */
708 * The EAP packet header is 4 bytes, plus one byte of
709 * EAP sub-type. Short packets are discarded, unless
712 if (eap_msg->length < (EAP_HEADER_LEN + 1)) {
713 if (proxy) goto do_proxy;
715 DEBUG2(" rlm_eap: Ignoring EAP-Message which is too short to be meaningful.");
720 * Create an EAP-Type containing the EAP-type
723 vp = paircreate(PW_EAP_TYPE, PW_TYPE_INTEGER);
725 vp->lvalue = eap_msg->strvalue[4];
726 pairadd(&(request->packet->vps), vp);
730 * If the request was marked to be proxied, do it now.
731 * This is done after checking for a valid length
732 * (which may not be good), and after adding the EAP-Type
733 * attribute. This lets other modules selectively cancel
734 * proxying based on EAP-Type.
736 if (proxy) goto do_proxy;
739 * From now on, we're supposed to be handling the
740 * EAP packet. We better understand it...
744 * We're allowed only a few codes. Request, Response,
745 * Success, or Failure.
747 if ((eap_msg->strvalue[0] == 0) ||
748 (eap_msg->strvalue[0] > PW_EAP_MAX_CODES)) {
749 DEBUG2(" rlm_eap: Unknown EAP packet");
751 DEBUG2(" rlm_eap: EAP packet type %s id %d length %d",
752 eap_codes[eap_msg->strvalue[0]],
753 eap_msg->strvalue[1],
758 * We handle request and responses. The only other defined
759 * codes are success and fail. The client SHOULD NOT be
760 * sending success/fail packets to us, as it doesn't make
763 if ((eap_msg->strvalue[0] != PW_EAP_REQUEST) &&
764 (eap_msg->strvalue[0] != PW_EAP_RESPONSE)) {
765 DEBUG2(" rlm_eap: Ignoring EAP packet which we don't know how to handle.");
770 * We've been told to ignore unknown EAP types, AND it's
771 * an unknown type. Return "NOOP", which will cause the
772 * eap_authorize() to return NOOP.
774 * EAP-Identity, Notification, and NAK are all handled
775 * internally, so they never have handlers.
777 if ((eap_msg->strvalue[4] >= PW_EAP_MD5) &&
778 inst->ignore_unknown_eap_types &&
779 ((eap_msg->strvalue[4] == 0) ||
780 (eap_msg->strvalue[4] > PW_EAP_MAX_TYPES) ||
781 (inst->types[eap_msg->strvalue[4]] == NULL))) {
782 DEBUG2(" rlm_eap: Ignoring Unknown EAP type");
787 * They're NAKing the EAP type we wanted to use, and
788 * asking for one which we don't support.
790 * NAK is code + id + length1 + length + NAK
791 * + requested EAP type(s).
793 * We know at this point that we can't handle the
794 * request. We could either return an EAP-Fail here, but
795 * it's not too critical.
797 * By returning "noop", we can ensure that authorize()
798 * returns NOOP, and another module may choose to proxy
801 if ((eap_msg->strvalue[4] == PW_EAP_NAK) &&
802 (eap_msg->length >= (EAP_HEADER_LEN + 2)) &&
803 inst->ignore_unknown_eap_types &&
804 ((eap_msg->strvalue[5] == 0) ||
805 (eap_msg->strvalue[5] > PW_EAP_MAX_TYPES) ||
806 (inst->types[eap_msg->strvalue[5]] == NULL))) {
807 DEBUG2(" rlm_eap: Ignoring NAK with request for unknown EAP type");
812 * Later EAP messages are longer than the 'start'
813 * message, so if everything is OK, this function returns
814 * 'no start found', so that the rest of the EAP code can
815 * use the State attribute to match this EAP-Message to
816 * an ongoing conversation.
818 DEBUG2(" rlm_eap: No EAP Start, assuming it's an on-going EAP conversation");
824 * compose EAP FAILURE packet in EAP-Message
826 void eap_fail(EAP_HANDLER *handler)
828 handler->eap_ds->request->code = PW_EAP_FAILURE;
829 eap_compose(handler);
833 * compose EAP SUCCESS packet in EAP-Message
835 void eap_success(EAP_HANDLER *handler)
837 handler->eap_ds->request->code = PW_EAP_SUCCESS;
838 eap_compose(handler);
842 * Basic EAP packet verfications & validations
844 static int eap_validation(eap_packet_t *eap_packet)
848 memcpy(&len, eap_packet->length, sizeof(uint16_t));
852 * High level EAP packet checks
854 if ((len <= EAP_HEADER_LEN) ||
855 ((eap_packet->code != PW_EAP_RESPONSE) &&
856 (eap_packet->code != PW_EAP_REQUEST)) ||
857 (eap_packet->data[0] <= 0) ||
858 (eap_packet->data[0] > PW_EAP_MAX_TYPES)) {
860 radlog(L_AUTH, "rlm_eap: Incorrect EAP Message, "
861 "Ignoring the packet");
865 /* we don't expect notification, but we send it */
866 if (eap_packet->data[0] == PW_EAP_NOTIFICATION) {
867 radlog(L_AUTH, "rlm_eap: Got NOTIFICATION, "
868 "Ignoring the packet");
877 * Get the user Identity only from EAP-Identity packets
879 static char *eap_identity(eap_packet_t *eap_packet)
885 if ((eap_packet == NULL) ||
886 (eap_packet->code != PW_EAP_RESPONSE) ||
887 (eap_packet->data[0] != PW_EAP_IDENTITY)) {
891 memcpy(&len, eap_packet->length, sizeof(uint16_t));
894 if ((len <= 5) || (eap_packet->data[1] == 0x00)) {
895 radlog(L_ERR, "rlm_eap: UserIdentity Unknown ");
900 identity = (char *)malloc(size + 1);
901 if (identity == NULL) {
902 radlog(L_ERR, "rlm_eap: out of memory");
905 memcpy(identity, &eap_packet->data[1], size);
906 identity[size] = '\0';
913 * Create our Request-Response data structure with the eap packet
915 static EAP_DS *eap_buildds(eap_packet_t **eap_packet_p)
917 EAP_DS *eap_ds = NULL;
918 eap_packet_t *eap_packet = *eap_packet_p;
922 if ((eap_ds = eap_ds_alloc()) == NULL) {
926 eap_ds->response->packet = (unsigned char *)eap_packet;
927 eap_ds->response->code = eap_packet->code;
928 eap_ds->response->id = eap_packet->id;
929 eap_ds->response->type.type = eap_packet->data[0];
931 memcpy(&len, eap_packet->length, sizeof(uint16_t));
933 eap_ds->response->length = len;
936 * We've eaten the eap packet into the eap_ds.
938 *eap_packet_p = NULL;
941 * First 5 bytes in eap, are code + id + length(2) + type.
943 * The rest is type-specific data. We skip type while
944 * getting typedata from data.
946 typelen = len - 5/*code + id + length + type */;
949 * Since the packet contains the complete
950 * eap_packet, typedata will be a ptr in packet
953 eap_ds->response->type.data = eap_ds->response->packet + 5/*code+id+length+type*/;
954 eap_ds->response->type.length = typelen;
956 eap_ds->response->type.length = 0;
957 eap_ds->response->type.data = NULL;
965 * If identity response then create a fresh handler & fill the identity
966 * else handler MUST be in our list, get that.
967 * This handler creation cannot fail
969 * username contains REQUEST->username which might have been stripped.
970 * identity contains the one sent in EAP-Identity response
972 EAP_HANDLER *eap_handler(rlm_eap_t *inst, eap_packet_t **eap_packet_p,
975 EAP_HANDLER *handler = NULL;
976 eap_packet_t *eap_packet = *eap_packet_p;
980 * Ensure it's a valid EAP-Request, or EAP-Response.
982 if (eap_validation(eap_packet) == EAP_INVALID) {
984 *eap_packet_p = NULL;
989 * EAP_HANDLER MUST be found in the list if it is not
990 * EAP-Identity response
992 if (eap_packet->data[0] != PW_EAP_IDENTITY) {
993 handler = eaplist_find(inst, request, eap_packet);
994 if (handler == NULL) {
995 /* Either send EAP_Identity or EAP-Fail */
996 radlog(L_ERR, "rlm_eap: Either EAP-request timed out OR"
997 " EAP-response to an unknown EAP-request");
999 *eap_packet_p = NULL;
1004 * Even more paranoia. Without this, some weird
1005 * clients could do crazy things.
1007 * It's ok to send EAP sub-type NAK in response
1008 * to a request for a particular type, but it's NOT
1009 * OK to blindly return data for another type.
1011 if ((eap_packet->data[0] != PW_EAP_NAK) &&
1012 (eap_packet->data[0] != handler->eap_type)) {
1013 radlog(L_ERR, "rlm_eap: Response appears to match, but EAP type is wrong.");
1014 free(*eap_packet_p);
1015 *eap_packet_p = NULL;
1019 vp = pairfind(request->packet->vps, PW_USER_NAME);
1022 * NAS did not set the User-Name
1023 * attribute, so we set it here and
1024 * prepend it to the beginning of the
1025 * request vps so that autz's work
1028 radlog(L_INFO, "rlm_eap: Broken NAS did not set User-Name, setting from EAP Identity");
1029 vp = pairmake("User-Name", handler->identity, T_OP_EQ);
1031 radlog(L_ERR, "rlm_eap: out of memory");
1032 free(*eap_packet_p);
1033 *eap_packet_p = NULL;
1036 vp->next = request->packet->vps;
1037 request->packet->vps = vp;
1041 * A little more paranoia. If the NAS
1042 * *did* set the User-Name, and it doesn't
1043 * match the identity, (i.e. If they
1044 * change their User-Name part way through
1045 * the EAP transaction), then reject the
1046 * request as the NAS is doing something
1049 if (strncmp(handler->identity, vp->strvalue,
1050 MAX_STRING_LEN) != 0) {
1051 radlog(L_ERR, "rlm_eap: Identity does not match User-Name. Authentication failed.");
1052 free(*eap_packet_p);
1053 *eap_packet_p = NULL;
1057 } else { /* packet was EAP identity */
1058 handler = eap_handler_alloc();
1059 if (handler == NULL) {
1060 radlog(L_ERR, "rlm_eap: out of memory");
1061 free(*eap_packet_p);
1062 *eap_packet_p = NULL;
1067 * All fields in the handler are set to zero.
1069 handler->identity = eap_identity(eap_packet);
1070 if (handler->identity == NULL) {
1071 radlog(L_ERR, "rlm_eap: Identity Unknown, authentication failed");
1072 free(*eap_packet_p);
1073 *eap_packet_p = NULL;
1074 eap_handler_free(handler);
1078 vp = pairfind(request->packet->vps, PW_USER_NAME);
1081 * NAS did not set the User-Name
1082 * attribute, so we set it here and
1083 * prepend it to the beginning of the
1084 * request vps so that autz's work
1087 radlog(L_INFO, "rlm_eap: WARNING NAS did not set User-Name. Setting it locally from EAP Identity");
1088 vp = pairmake("User-Name", handler->identity, T_OP_EQ);
1090 radlog(L_ERR, "rlm_eap: out of memory");
1091 free(*eap_packet_p);
1092 *eap_packet_p = NULL;
1095 vp->next = request->packet->vps;
1096 request->packet->vps = vp;
1099 * Paranoia. If the NAS *did* set the
1100 * User-Name, and it doesn't match the
1101 * identity, the NAS is doing something
1102 * funny, so reject the request.
1104 if (strncmp(handler->identity, vp->strvalue,
1105 MAX_STRING_LEN) != 0) {
1106 radlog(L_ERR, "rlm_eap: Identity does not match User-Name, setting from EAP Identity.");
1107 free(*eap_packet_p);
1108 *eap_packet_p = NULL;
1109 eap_handler_free(handler);
1115 handler->eap_ds = eap_buildds(eap_packet_p);
1116 if (handler->eap_ds == NULL) {
1117 free(*eap_packet_p);
1118 *eap_packet_p = NULL;
1119 eap_handler_free(handler);
1123 handler->timestamp = request->timestamp;
1124 handler->request = request; /* LEAP needs this */