static int eap_post_auth(void *instance, REQUEST *request) { rlm_eap_t *inst = instance; VALUE_PAIR *vp; EAP_HANDLER *handler; eap_packet_t *eap_packet; /* * Only build a failure message if something previously rejected the request */ vp = pairfind(request->config_items, PW_POSTAUTHTYPE, 0, TAG_ANY); if (!vp || (vp->vp_integer != PW_POSTAUTHTYPE_REJECT)) return RLM_MODULE_NOOP; if (!pairfind(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY)) { RDEBUG2("Request didn't contain an EAP-Message, not inserting EAP-Failure"); return RLM_MODULE_NOOP; } if (pairfind(request->reply->vps, PW_EAP_MESSAGE, 0, TAG_ANY)) { RDEBUG2("Reply already contained an EAP-Message, not inserting EAP-Failure"); return RLM_MODULE_NOOP; } eap_packet = eap_vp2packet(request->packet->vps); if (eap_packet == NULL) { radlog_request(L_ERR, 0, request, "Malformed EAP Message"); return RLM_MODULE_FAIL; } handler = eap_handler(inst, &eap_packet, request); if (handler == NULL) { RDEBUG2("Failed to get handler, probably already removed, not inserting EAP-Failure"); return RLM_MODULE_NOOP; } RDEBUG2("Request was previously rejected, inserting EAP-Failure"); eap_fail(handler); eap_handler_free(inst, handler); /* * Make sure there's a message authenticator attribute in the response * RADIUS protocol code will calculate the correct value later... */ vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY); if (!vp) { vp = pairmake("Message-Authenticator", "0x00", T_OP_EQ); rad_assert(vp != NULL); pairadd(&(request->reply->vps), vp); } return RLM_MODULE_UPDATED; }
/* * For backwards compatibility. */ static rlm_rcode_t mod_authenticate(void *instance, REQUEST *request) { rlm_eap_t *inst; eap_handler_t *handler; eap_packet_raw_t *eap_packet; eap_rcode_t status; rlm_rcode_t rcode; inst = (rlm_eap_t *) instance; if (!pairfind(request->packet->vps, PW_EAP_MESSAGE, 0, TAG_ANY)) { RDEBUGE("You set 'Auth-Type = EAP' for a request that does " "not contain an EAP-Message attribute!"); return RLM_MODULE_INVALID; } /* * Get the eap packet to start with */ eap_packet = eap_vp2packet(request, request->packet->vps); if (!eap_packet) { radlog_request(L_ERR, 0, request, "Malformed EAP Message"); return RLM_MODULE_FAIL; } /* * Create the eap handler. The eap_packet will end up being * "swallowed" into the handler, so we can't access it after * this call. */ handler = eap_handler(inst, &eap_packet, request); if (!handler) { RDEBUG2("Failed in handler"); return RLM_MODULE_INVALID; } /* * Select the appropriate method or default to the * configured one */ status = eap_method_select(inst, handler); /* * If it failed, die. */ if (status == EAP_INVALID) { eap_fail(handler); eap_handler_free(inst, handler); RDEBUG2("Failed in EAP select"); return RLM_MODULE_INVALID; } #ifdef WITH_PROXY /* * If we're doing horrible tunneling work, remember it. */ if ((request->options & RAD_REQUEST_OPTION_PROXY_EAP) != 0) { RDEBUG2(" Not-EAP proxy set. Not composing EAP"); /* * Add the handle to the proxied list, so that we * can retrieve it in the post-proxy stage, and * send a response. */ handler->inst_holder = inst; status = request_data_add(request, inst, REQUEST_DATA_eap_handler_t, handler, (void *) eap_opaque_free); rad_assert(status == 0); return RLM_MODULE_HANDLED; } #endif #ifdef WITH_PROXY /* * Maybe the request was marked to be proxied. If so, * proxy it. */ if (request->proxy != NULL) { VALUE_PAIR *vp = NULL; rad_assert(!request->proxy_reply); /* * Add the handle to the proxied list, so that we * can retrieve it in the post-proxy stage, and * send a response. */ handler->inst_holder = inst; status = request_data_add(request, inst, REQUEST_DATA_eap_handler_t, handler, (void *) eap_opaque_free); rad_assert(status == 0); /* * Some simple sanity checks. These should really * be handled by the radius library... */ vp = pairfind(request->proxy->vps, PW_EAP_MESSAGE, 0, TAG_ANY); if (vp) { vp = pairfind(request->proxy->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY); if (!vp) { pairmake(request->proxy, &request->proxy->vps, "Message-Authenticator", "0x00", T_OP_EQ); } } /* * Delete the "proxied to" attribute, as it's * set to 127.0.0.1 for tunneled requests, and * we don't want to tell the world that... */ pairdelete(&request->proxy->vps, PW_FREERADIUS_PROXIED_TO, VENDORPEC_FREERADIUS, TAG_ANY); RDEBUG2(" Tunneled session will be proxied. Not doing EAP."); return RLM_MODULE_HANDLED; } #endif /* * We are done, wrap the EAP-request in RADIUS to send * with all other required radius attributes */ rcode = eap_compose(handler); /* * Add to the list only if it is EAP-Request, OR if * it's LEAP, and a response. */ if (((handler->eap_ds->request->code == PW_EAP_REQUEST) && (handler->eap_ds->request->type.num >= PW_EAP_MD5)) || /* * LEAP is a little different. At Stage 4, * it sends an EAP-Success message, but we still * need to keep the State attribute & session * data structure around for the AP Challenge. * * At stage 6, LEAP sends an EAP-Response, which * isn't put into the list. */ ((handler->eap_ds->response->code == PW_EAP_RESPONSE) && (handler->eap_ds->response->type.num == PW_EAP_LEAP) && (handler->eap_ds->request->code == PW_EAP_SUCCESS) && (handler->eap_ds->request->type.num == 0))) { /* * Return FAIL if we can't remember the handler. * This is actually disallowed by the * specification, as unexpected FAILs could have * been forged. However, we want to signal to * everyone else involved that we are * intentionally failing the session, as opposed * to accidentally failing it. */ if (!eaplist_add(inst, handler)) { RDEBUG("Failed adding handler to the list"); eap_fail(handler); eap_handler_free(inst, handler); return RLM_MODULE_FAIL; } } else { RDEBUG2("Freeing handler"); /* handler is not required any more, free it now */ eap_handler_free(inst, handler); } /* * If it's an Access-Accept, RFC 2869, Section 2.3.1 * says that we MUST include a User-Name attribute in the * Access-Accept. */ if ((request->reply->code == PW_AUTHENTICATION_ACK) && request->username) { VALUE_PAIR *vp; /* * Doesn't exist, add it in. */ vp = pairfind(request->reply->vps, PW_USER_NAME, 0, TAG_ANY); if (!vp) { vp = pairmake_reply("User-Name", "", T_OP_EQ); strlcpy(vp->vp_strvalue, request->username->vp_strvalue, sizeof(vp->vp_strvalue)); vp->length = request->username->length; } /* * Cisco AP1230 has a bug and needs a zero * terminated string in Access-Accept. */ if ((inst->mod_accounting_username_bug) && (vp->length < (int) sizeof(vp->vp_strvalue))) { vp->vp_strvalue[vp->length] = '\0'; vp->length++; } } return rcode; }