📄 rlm_eap2.c
字号:
CONF_SECTION *scs; inst = (rlm_eap_t *) malloc(sizeof(*inst)); if (!inst) { return -1; } memset(inst, 0, sizeof(*inst)); if (cf_section_parse(cs, inst, module_config) < 0) { eap_detach(inst); return -1; } /* * Create our own random pool. */ for (i = 0; i < 256; i++) { inst->rand_pool.randrsl[i] = fr_rand(); } fr_randinit(&inst->rand_pool, 1); /* * List of sessions are set to NULL by the memset * of 'inst', above. */ /* * Lookup sessions in the tree. We don't free them in * the tree, as that's taken care of elsewhere... */ inst->session_tree = rbtree_create(eap_handler_cmp, NULL, 0); if (!inst->session_tree) { radlog(L_ERR|L_CONS, "rlm_eap2: Cannot initialize tree"); eap_detach(inst); return -1; } /* * This registers ALL available methods. * * FIXME: we probably want to selectively register * some methods. */ if (eap_server_register_methods() < 0) { eap_detach(inst); return -1; } /* Load all the configured EAP-Types */ num_types = 0; has_tls = do_tls = 0; for (scs=cf_subsection_find_next(cs, NULL, NULL); scs != NULL; scs=cf_subsection_find_next(cs, scs, NULL)) { const char *auth_type; char buffer[64], *p; auth_type = cf_section_name1(scs); if (!auth_type) continue; if (num_types >= EAP_MAX_METHODS) { radlog(L_INFO, "WARNING: Ignoring EAP type %s: too many types defined", auth_type); continue; } /* * Hostapd doesn't do case-insensitive comparisons. * So we mash everything to uppercase for it. */ strlcpy(buffer, auth_type, sizeof(buffer)); for (p = buffer; *p; p++) { if (!islower((int)*p)) continue; *p = toupper((int)*p); } inst->methods[num_types] = eap_server_get_type(buffer, &inst->vendors[num_types]); if (inst->methods[num_types] == EAP_TYPE_NONE) { radlog(L_ERR|L_CONS, "rlm_eap2: Unknown EAP type %s", auth_type); eap_detach(inst); return -1; } switch (inst->methods[num_types]) { case EAP_TYPE_TLS: has_tls = TRUE; /* FALL-THROUGH */ case EAP_TYPE_TTLS: case EAP_TYPE_PEAP: case EAP_TYPE_FAST: do_tls = TRUE; break; default: break; } num_types++; /* successfully loaded one more types */ } inst->num_types = num_types; if (do_tls && !has_tls) { radlog(L_ERR|L_CONS, "rlm_eap2: TLS has not been configured. Cannot do methods that need TLS."); eap_detach(inst); return -1; } if (do_tls) { /* * Initialize TLS. */ if (eap_example_server_init_tls(inst) < 0) { radlog(L_ERR|L_CONS, "rlm_eap2: Cannot initialize TLS"); eap_detach(inst); return -1; } } pthread_mutex_init(&(inst->session_mutex), NULL); *instance = inst; return 0;}static int eap_req2vp(EAP_HANDLER *handler){ int encoded, total, size; const uint8_t *ptr; VALUE_PAIR *head = NULL; VALUE_PAIR **tail = &head; VALUE_PAIR *vp; ptr = wpabuf_head(handler->server_ctx.eap_if->eapReqData); encoded = total = wpabuf_len(handler->server_ctx.eap_if->eapReqData); do { size = total; if (size > 253) size = 253; vp = paircreate(PW_EAP_MESSAGE, PW_TYPE_OCTETS); if (!vp) { pairfree(&head); return -1; } memcpy(vp->vp_octets, ptr, size); vp->length = size; *tail = vp; tail = &(vp->next); ptr += size; total -= size; } while (total > 0); pairdelete(&handler->request->reply->vps, PW_EAP_MESSAGE); pairadd(&handler->request->reply->vps, head); return encoded;}static int eap_example_server_step(EAP_HANDLER *handler){ int res, process = 0; REQUEST *request = handler->request; res = eap_server_sm_step(handler->server_ctx.eap); if (handler->server_ctx.eap_if->eapReq) { DEBUG("==> Request"); process = 1; handler->server_ctx.eap_if->eapReq = 0; } if (handler->server_ctx.eap_if->eapSuccess) { DEBUG("==> Success"); process = 1; res = 0; if (handler->server_ctx.eap_if->eapKeyAvailable) { int length = handler->server_ctx.eap_if->eapKeyDataLen; VALUE_PAIR *vp; if (length > 64) { length = 32; } else { length /= 2; /* * FIXME: Length is zero? */ } vp = radius_pairmake(request, &request->reply->vps, "MS-MPPE-Recv-Key", "", T_OP_EQ); if (vp) { memcpy(vp->vp_octets, handler->server_ctx.eap_if->eapKeyData, length); vp->length = length; } vp = radius_pairmake(request, &request->reply->vps, "MS-MPPE-Send-Key", "", T_OP_EQ); if (vp) { memcpy(vp->vp_octets, handler->server_ctx.eap_if->eapKeyData + length, length); vp->length = length; } } } if (handler->server_ctx.eap_if->eapFail) { DEBUG("==> Fail"); process = 1; } if (process) { if (wpabuf_head(handler->server_ctx.eap_if->eapReqData)) { if (!eap_req2vp(handler)) return -1; } else { return -1; } } return res;}/* * Handles multiple EAP-Message attrs * ie concatenates all to get the complete EAP packet. * * NOTE: Sometimes Framed-MTU might contain the length of EAP-Message, * refer fragmentation in rfc2869. */static int eap_vp2data(VALUE_PAIR *vps, void **data, int *data_len){ VALUE_PAIR *first, *vp; unsigned char *ptr; uint16_t len; int total_len; /* * Get only EAP-Message attribute list */ first = pairfind(vps, PW_EAP_MESSAGE); if (first == NULL) { radlog(L_ERR, "rlm_eap2: EAP-Message not found"); return -1; } /* * Sanity check the length before doing anything. */ if (first->length < 4) { radlog(L_ERR, "rlm_eap2: EAP packet is too short."); return -1; } /* * Get the Actual length from the EAP packet * First EAP-Message contains the EAP packet header */ memcpy(&len, first->vp_strvalue + 2, sizeof(len)); len = ntohs(len); /* * Take out even more weird things. */ if (len < 4) { radlog(L_ERR, "rlm_eap2: EAP packet has invalid length."); return -1; } /* * Sanity check the length, BEFORE malloc'ing memory. */ total_len = 0; for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE)) { total_len += vp->length; if (total_len > len) { radlog(L_ERR, "rlm_eap2: Malformed EAP packet. Length in packet header does not match actual length"); return -1; } } /* * If the length is SMALLER, die, too. */ if (total_len < len) { radlog(L_ERR, "rlm_eap2: Malformed EAP packet. Length in packet header does not match actual length"); return -1; } /* * Now that we know the lengths are OK, allocate memory. */ *data = malloc(len); if (!*data) { radlog(L_ERR, "rlm_eap2: out of memory"); return -1; } *data_len = len; /* * Copy the data from EAP-Message's over to our EAP packet. */ ptr = *data; /* RADIUS ensures order of attrs, so just concatenate all */ for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE)) { memcpy(ptr, vp->vp_strvalue, vp->length); ptr += vp->length; } return 0;}/* * FIXME: Add an "authorize" section which sets Auth-Type = EAP2 * FIXME: Also in "authorize", set User-Name if not already set. *//* * Do EAP. */static int eap_authenticate(void *instance, REQUEST *request){ rlm_eap_t *inst; EAP_HANDLER *handler; void *data; int data_len; int rcode; VALUE_PAIR *vp; inst = (rlm_eap_t *) instance; vp = pairfind(request->packet->vps, PW_EAP_MESSAGE); if (!vp) { RDEBUG("No EAP-Message. Not doing EAP."); return RLM_MODULE_FAIL; } /* * Get the eap packet to start with */ data = NULL; data_len = 0; if (eap_vp2data(request->packet->vps, &data, &data_len) < 0) { radlog(L_ERR, "rlm_eap2: Malformed EAP Message"); return RLM_MODULE_FAIL; } vp = pairfind(request->packet->vps, PW_STATE); if (vp) { handler = eaplist_find(inst, request); if (!handler) { RDEBUG("No handler found"); return RLM_MODULE_FAIL; } } else { handler = malloc(sizeof(*handler)); if (!handler) return RLM_MODULE_FAIL; memset(handler, 0, sizeof(*handler)); handler->inst = inst; handler->eap_cb.get_eap_user = server_get_eap_user; handler->eap_cb.get_eap_req_id_text = server_get_eap_req_id_text; handler->eap_conf.eap_server = 1; handler->eap_conf.ssl_ctx = inst->tls_ctx; handler->server_ctx.eap = eap_server_sm_init(handler, &handler->eap_cb, &handler->eap_conf); if (handler->server_ctx.eap == NULL) { free(handler); return RLM_MODULE_FAIL; } handler->server_ctx.eap_if = eap_get_interface(handler->server_ctx.eap); /* Enable "port" and request EAP to start authentication. */ handler->server_ctx.eap_if->portEnabled = TRUE; handler->server_ctx.eap_if->eapRestart = TRUE; } handler->request = request; wpabuf_free(handler->server_ctx.eap_if->eapRespData); handler->server_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len); if (handler->server_ctx.eap_if->eapRespData) { handler->server_ctx.eap_if->eapResp = TRUE; } if (eap_example_server_step(handler) < 0) { RDEBUG("Failed in EAP library"); goto fail; } if (handler->server_ctx.eap_if->eapSuccess) { request->reply->code = PW_AUTHENTICATION_ACK; rcode = RLM_MODULE_OK; } else if (handler->server_ctx.eap_if->eapFail) { fail: request->reply->code = PW_AUTHENTICATION_REJECT; rcode = RLM_MODULE_REJECT; } else { request->reply->code = PW_ACCESS_CHALLENGE; rcode = RLM_MODULE_HANDLED; } if (handler->server_ctx.eap_if->eapFail || handler->server_ctx.eap_if->eapSuccess) { RDEBUG2("Freeing handler"); /* handler is not required any more, free it now */ eap_handler_free(handler); handler = NULL; } else { eaplist_add(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) { /* * Doesn't exist, add it in. */ vp = pairfind(request->reply->vps, PW_USER_NAME); if (!vp) { vp = pairmake("User-Name", request->username->vp_strvalue, T_OP_EQ); rad_assert(vp != NULL); pairadd(&(request->reply->vps), vp); } /* * Cisco AP1230 has a bug and needs a zero * terminated string in Access-Accept. */ if ((inst->cisco_accounting_username_bug) && (vp->length < (int) sizeof(vp->vp_strvalue))) { vp->vp_strvalue[vp->length] = '\0'; vp->length++; } } vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR); if (!vp) { vp = paircreate(PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS); memset(vp->vp_strvalue, 0, AUTH_VECTOR_LEN); vp->length = AUTH_VECTOR_LEN; pairadd(&(request->reply->vps), vp); } return rcode;}/* * The module name should be the only globally exported symbol. * That is, everything else should be 'static'. */module_t rlm_eap2 = { RLM_MODULE_INIT, "eap2", RLM_TYPE_CHECK_CONFIG_SAFE, /* type */ eap_instantiate, /* instantiation */ eap_detach, /* detach */ { eap_authenticate, /* authentication */ NULL, /* authorization */ NULL, /* preaccounting */ NULL, /* accounting */ NULL, /* checksimul */ NULL, /* pre-proxy */ NULL, /* post-proxy */ NULL /* post-auth */ },};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -