📄 peap.c
字号:
/* * If there was no EAP-Message in the reply packet, then * we know that we're supposed to re-run the "authenticate" * stage, in order to get the right kind of handling... */ /* * Process the reply from the home server. */ rcode = process_reply(handler, tls_session, handler->request, handler->request->proxy_reply); /* * The proxy code uses the reply from the home server as * the basis for the reply to the NAS. We don't want that, * so we toss it, after we've had our way with it. */ pairfree(&handler->request->proxy_reply->vps); switch (rcode) { case RLM_MODULE_REJECT: RDEBUG2("Reply was rejected"); eaptls_fail(handler, 0); return 0; case RLM_MODULE_HANDLED: RDEBUG2("Reply was handled"); eaptls_request(handler->eap_ds, tls_session); return 1; case RLM_MODULE_OK: RDEBUG2("Reply was OK"); /* * Success: Automatically return MPPE keys. */ return eaptls_success(handler, 0); default: RDEBUG2("Reply was unknown."); break; } eaptls_fail(handler, 0); return 0;}/* * Free a request. */static void my_request_free(void *data){ REQUEST *request = (REQUEST *)data; request_free(&request);}/* * Process the pseudo-EAP contents of the tunneled data. */int eappeap_process(EAP_HANDLER *handler, tls_session_t *tls_session){ peap_tunnel_t *t = tls_session->opaque; REQUEST *fake; VALUE_PAIR *vp; int rcode = RLM_MODULE_REJECT; const uint8_t *data; unsigned int data_len;#ifndef NDEBUG size_t i;#endif REQUEST *request = handler->request; EAP_DS *eap_ds = handler->eap_ds; /* * Just look at the buffer directly, without doing * record_minus. This lets us avoid another data copy. */ data_len = tls_session->clean_out.used; tls_session->clean_out.used = 0; data = tls_session->clean_out.data;#ifndef NDEBUG if ((debug_flag > 2) && fr_log_fp) { for (i = 0; i < data_len; i++) { if ((i & 0x0f) == 0) fprintf(fr_log_fp, " PEAP tunnel data in %04x: ", i); fprintf(fr_log_fp, "%02x ", data[i]); if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n"); } if ((data_len & 0x0f) != 0) fprintf(fr_log_fp, "\n"); }#endif if (!eapmessage_verify(request, data, data_len)) { RDEBUG2("Tunneled data is invalid."); return RLM_MODULE_REJECT; } /* * If we authenticated the user, then it's OK. */ if (t->status == PEAP_STATUS_SENT_TLV_SUCCESS) { if (eappeap_check_tlv(request, data)) { RDEBUG2("Success"); return RLM_MODULE_OK; } /* * Otherwise, the client rejected the session * resumption. If the session is being re-used, * we need to do a full authentication. * * We do this by sending an EAP-Identity request * inside of the PEAP tunnel. */ if ((t->session_resumption_state != PEAP_RESUMPTION_NO) && SSL_session_reused(tls_session->ssl)) { eap_packet_t eap_packet; RDEBUG2("Client rejected session resumption. Re-starting full authentication"); eap_packet.code = PW_EAP_REQUEST; eap_packet.id = handler->eap_ds->response->id + 1; eap_packet.length[0] = 0; eap_packet.length[1] = EAP_HEADER_LEN + 1; eap_packet.data[0] = PW_EAP_IDENTITY; /* * Mark session resumption status. */ t->status = 0; t->session_resumption_state = PEAP_RESUMPTION_NO; (tls_session->record_plus)(&tls_session->clean_in, &eap_packet, sizeof(eap_packet)); tls_handshake_send(tls_session); return RLM_MODULE_HANDLED; } return RLM_MODULE_REJECT; } if (t->status == PEAP_STATUS_SENT_TLV_FAILURE) { RDEBUG2(" Had sent TLV failure. User was rejected earlier in this session."); return RLM_MODULE_REJECT; } fake = request_alloc_fake(request); rad_assert(fake->packet->vps == NULL); fake->packet->vps = eap2vp(request, eap_ds, data, data_len); if (!fake->packet->vps) { request_free(&fake); RDEBUG2("Unable to convert tunneled EAP packet to internal server data structures"); return PW_AUTHENTICATION_REJECT; } if ((debug_flag > 0) && fr_log_fp) { RDEBUG("Got tunneled request"); debug_pair_list(fake->packet->vps); fprintf(fr_log_fp, "server %s {\n", (fake->server == NULL) ? "" : fake->server); } /* * Tell the request that it's a fake one. */ vp = pairmake("Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ); if (vp) { pairadd(&fake->packet->vps, vp); } /* * Update other items in the REQUEST data structure. */ if (!t->username) { /* * There's no User-Name in the tunneled session, * so we add one here, by pulling it out of the * EAP-Identity packet. */ if ((data[0] == PW_EAP_IDENTITY) && (data_len > 1)) { t->username = pairmake("User-Name", "", T_OP_EQ); rad_assert(t->username != NULL); memcpy(t->username->vp_strvalue, data + 1, data_len - 1); t->username->length = data_len - 1; t->username->vp_strvalue[t->username->length] = 0; DEBUG2(" PEAP: Got tunneled identity of %s", t->username->vp_strvalue); /* * If there's a default EAP type, * set it here. */ if (t->default_eap_type != 0) { DEBUG2(" PEAP: Setting default EAP type for tunneled EAP session."); vp = pairmake("EAP-Type", "0", T_OP_EQ); vp->vp_integer = t->default_eap_type; pairadd(&fake->config_items, vp); } } } /* else there WAS a t->username */ if (t->username) { vp = paircopy(t->username); pairadd(&fake->packet->vps, vp); fake->username = pairfind(fake->packet->vps, PW_USER_NAME); DEBUG2(" PEAP: Setting User-Name to %s", fake->username->vp_strvalue); } /* * Add the State attribute, too, if it exists. */ if (t->state) { vp = paircopy(t->state); if (vp) pairadd(&fake->packet->vps, vp); } /* * If this is set, we copy SOME of the request attributes * from outside of the tunnel to inside of the tunnel. * * We copy ONLY those attributes which do NOT already * exist in the tunneled request. * * This code is copied from ../rlm_eap_ttls/ttls.c */ if (t->copy_request_to_tunnel) { VALUE_PAIR *copy; for (vp = request->packet->vps; vp != NULL; vp = vp->next) { /* * The attribute is a server-side thingy, * don't copy it. */ if ((vp->attribute > 255) && (((vp->attribute >> 16) & 0xffff) == 0)) { continue; } /* * The outside attribute is already in the * tunnel, don't copy it. * * This works for BOTH attributes which * are originally in the tunneled request, * AND attributes which are copied there * from below. */ if (pairfind(fake->packet->vps, vp->attribute)) { continue; } /* * Some attributes are handled specially. */ switch (vp->attribute) { /* * NEVER copy Message-Authenticator, * EAP-Message, or State. They're * only for outside of the tunnel. */ case PW_USER_NAME: case PW_USER_PASSWORD: case PW_CHAP_PASSWORD: case PW_CHAP_CHALLENGE: case PW_PROXY_STATE: case PW_MESSAGE_AUTHENTICATOR: case PW_EAP_MESSAGE: case PW_STATE: continue; break; /* * By default, copy it over. */ default: break; } /* * Don't copy from the head, we've already * checked it. */ copy = paircopy2(vp, vp->attribute); pairadd(&fake->packet->vps, copy); } } if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER)) != NULL) { fake->server = vp->vp_strvalue; } else if (t->virtual_server) { fake->server = t->virtual_server; } /* else fake->server == request->server */ if ((debug_flag > 0) && fr_log_fp) { fprintf(fr_log_fp, "Sending tunneled request\n"); debug_pair_list(fake->packet->vps); fprintf(fr_log_fp, "server %s {\n", (fake->server == NULL) ? "" : fake->server); } /* * Call authentication recursively, which will * do PAP, CHAP, MS-CHAP, etc. */ rad_authenticate(fake); /* * Note that we don't do *anything* with the reply * attributes. */ if ((debug_flag > 0) && fr_log_fp) { fprintf(fr_log_fp, "} # server %s\n", (fake->server == NULL) ? "" : fake->server); RDEBUG("Got tunneled reply code %d", fake->reply->code); debug_pair_list(fake->reply->vps); } /* * Decide what to do with the reply. */ switch (fake->reply->code) { case 0: /* No reply code, must be proxied... */ vp = pairfind(fake->config_items, PW_PROXY_TO_REALM); if (vp) { eap_tunnel_data_t *tunnel; /* * The tunneled request was NOT handled, * it has to be proxied. This means that * the "authenticate" stage was never * performed. * * If we are told to NOT proxy the * tunneled request as EAP, then this * means that we've got to decode it, * which means that we MUST run the * "authenticate" portion by hand, here. * * Once the tunneled EAP session is ALMOST * done, THEN we proxy it... */ if (!t->proxy_tunneled_request_as_eap) { fake->options |= RAD_REQUEST_OPTION_PROXY_EAP; /* * Hmm... should we check for * Auth-Type & EAP-Message here? */ /* * Run the EAP authentication. */ DEBUG2(" PEAP: Calling authenticate in order to initiate tunneled EAP session."); rcode = module_authenticate(PW_AUTHTYPE_EAP, fake); if (rcode == RLM_MODULE_OK) { /* * Authentication succeeded! Rah! */ fake->reply->code = PW_AUTHENTICATION_ACK; goto do_process; } if (rcode != RLM_MODULE_HANDLED) { DEBUG2(" PEAP: Can't handle the return code %d", rcode); rcode = RLM_MODULE_REJECT; goto done; } /* * The module decided it wasn't * done. Handle it like normal. */ if ((fake->options & RAD_REQUEST_OPTION_PROXY_EAP) == 0) { DEBUG2(" PEAP: Cancelling proxy to realm %s until the tunneled EAP session has been established", vp->vp_strvalue); goto do_process; } /* * The module has decoded the * EAP-Message into another set * of attributes. */ pairdelete(&fake->packet->vps, PW_EAP_MESSAGE); } DEBUG2(" PEAP: Tunneled authentication will be proxied to %s", vp->vp_strvalue); /* * Tell the original request that it's going * to be proxied. */ pairmove2(&(request->config_items), &(fake->config_items), PW_PROXY_TO_REALM); /* * Seed the proxy packet with the * tunneled request. */ rad_assert(request->proxy == NULL); request->proxy = fake->packet; fake->packet = NULL; rad_free(&fake->reply); fake->reply = NULL; /* * Set up the callbacks for the tunnel */ tunnel = rad_malloc(sizeof(*tunnel)); memset(tunnel, 0, sizeof(*tunnel)); tunnel->tls_session = tls_session; tunnel->callback = eappeap_postproxy; /* * Associate the callback with the request. */ rcode = request_data_add(request, request->proxy, REQUEST_DATA_EAP_TUNNEL_CALLBACK, tunnel, free); rad_assert(rcode == 0); /* * We're not proxying it as EAP, so we've got * to do the callback later. */ if ((fake->options & RAD_REQUEST_OPTION_PROXY_EAP) != 0) { DEBUG2(" PEAP: Remembering to do EAP-MS-CHAP-V2 post-proxy."); /* * rlm_eap.c has taken care of associating * the handler with the fake request. * * So we associate the fake request with * this request. */ rcode = request_data_add(request, request->proxy, REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK, fake, my_request_free); rad_assert(rcode == 0); /* * Do NOT free the fake request! */ return RLM_MODULE_UPDATED; } /* * Didn't authenticate the packet, but * we're proxying it. */ rcode = RLM_MODULE_UPDATED; } else { DEBUG2(" PEAP: Unknown RADIUS packet type %d: rejecting tunneled user", fake->reply->code); rcode = RLM_MODULE_REJECT; } break; default: do_process: rcode = process_reply(handler, tls_session, request, fake->reply); break; } done: request_free(&fake); return rcode;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -