📄 peap.c
字号:
DEBUG2(" PEAP: Reply was OK"); eaptls_success(handler->eap_ds, 0); eaptls_gen_mppe_keys(&handler->request->reply->vps, tls_session->ssl, "client EAP encryption"); return 1; default: DEBUG2(" PEAP: Reply was unknown."); break; } eaptls_fail(handler->eap_ds, 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){ int err; 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; unsigned char buffer[1024];#ifndef NDEBUG int i;#endif REQUEST *request = handler->request; EAP_DS *eap_ds = handler->eap_ds; /* * Grab the dirty data, and copy it to our buffer. * * I *really* don't like these 'record_t' things... */ data_len = record_minus(&tls_session->dirty_in, buffer, sizeof(buffer)); data = buffer; /* * Write the data from the dirty buffer (i.e. packet * data) into the buffer which we will give to SSL for * decoding. * * Some of this code COULD technically go into the TLS * module, in eaptls_process(), where it returns EAPTLS_OK. * * Similarly, the writing of data to the SSL context could * go there, too... */ BIO_write(tls_session->into_ssl, buffer, data_len); record_init(&tls_session->clean_out); /* * Read (and decrypt) the tunneled data from the SSL session, * and put it into the decrypted data buffer. */ err = SSL_read(tls_session->ssl, tls_session->clean_out.data, sizeof(tls_session->clean_out.data)); if (err < 0) { /* * FIXME: Call SSL_get_error() to see what went * wrong. */ radlog(L_INFO, "rlm_eap_peap: SSL_read Error"); return RLM_MODULE_REJECT; } /* * If there's no data, maybe this is an ACK to an * MS-CHAP2-Success. */ if (err == 0) { /* * FIXME: Call SSL_get_error() to see what went * wrong. */ radlog(L_INFO, "rlm_eap_peap: No data inside of the tunnel."); return RLM_MODULE_REJECT; } data_len = tls_session->clean_out.used = err; data = tls_session->clean_out.data;#ifndef NDEBUG if (debug_flag > 2) { for (i = 0; i < data_len; i++) { if ((i & 0x0f) == 0) printf(" PEAP tunnel data in %04x: ", i); printf("%02x ", data[i]); if ((i & 0x0f) == 0x0f) printf("\n"); } if ((data_len & 0x0f) != 0) printf("\n"); }#endif if (!eapmessage_verify(data, data_len)) { return RLM_MODULE_REJECT; } DEBUG2(" rlm_eap_peap: Tunneled data is valid."); /* * If we authenticated the user, then it's OK. */ if (t->status == PEAP_STATUS_SENT_TLV_SUCCESS) { if (eappeap_check_tlv(data)) { DEBUG2(" rlm_eap_peap: Success"); return RLM_MODULE_OK; } return RLM_MODULE_REJECT; } else if (t->status == PEAP_STATUS_SENT_TLV_FAILURE) { DEBUG2(" rlm_eap_peap: Had sent TLV failure, rejecting."); return RLM_MODULE_REJECT; } fake = request_alloc_fake(request); rad_assert(fake->packet->vps == NULL); fake->packet->vps = eap2vp(eap_ds, data, data_len); if (!fake->packet->vps) { DEBUG2(" rlm_eap_peap: Unable to convert tunneled EAP packet to internal server data structures"); return PW_AUTHENTICATION_REJECT; }#ifndef NDEBUG if (debug_flag > 0) { printf(" PEAP: Got tunneled EAP-Message\n"); for (vp = fake->packet->vps; vp != NULL; vp = vp->next) { putchar('\t');vp_print(stdout, vp);putchar('\n'); } }#endif /* * 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->strvalue, data + 1, data_len - 1); t->username->length = data_len - 1; t->username->strvalue[t->username->length] = 0; DEBUG2(" PEAP: Got tunneled identity of %s", t->username->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->lvalue = 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->strvalue); } /* * Add the State attribute, too, if it exists. */ if (t->state) { DEBUG2(" PEAP: Adding old state with %02x %02x", t->state->strvalue[0], t->state->strvalue[1]); 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); } }#ifndef NDEBUG if (debug_flag > 0) { printf(" PEAP: Sending tunneled request\n"); for (vp = fake->packet->vps; vp != NULL; vp = vp->next) { putchar('\t');vp_print(stdout, vp);putchar('\n'); } }#endif /* * 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. */#ifndef NDEBUG if (debug_flag > 0) { printf(" PEAP: Got tunneled reply RADIUS code %d\n", fake->reply->code); for (vp = fake->reply->vps; vp != NULL; vp = vp->next) { putchar('\t');vp_print(stdout, vp);putchar('\n'); } }#endif /* * 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->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->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 + -