/* * Do authentication, by letting EAP-TLS do most of the work. */ static int mod_authenticate(void *arg, eap_handler_t *handler) { int rcode; fr_tls_status_t status; rlm_eap_peap_t *inst = (rlm_eap_peap_t *) arg; tls_session_t *tls_session = (tls_session_t *) handler->opaque; peap_tunnel_t *peap = tls_session->opaque; REQUEST *request = handler->request; /* * Session resumption requires the storage of data, so * allocate it if it doesn't already exist. */ if (!tls_session->opaque) { peap = tls_session->opaque = peap_alloc(tls_session, inst); } status = eaptls_process(handler); RDEBUG2("eaptls_process returned %d\n", status); switch (status) { /* * EAP-TLS handshake was successful, tell the * client to keep talking. * * If this was EAP-TLS, we would just return * an EAP-TLS-Success packet here. */ case FR_TLS_SUCCESS: RDEBUG2("FR_TLS_SUCCESS"); peap->status = PEAP_STATUS_TUNNEL_ESTABLISHED; break; /* * The TLS code is still working on the TLS * exchange, and it's a valid TLS request. * do nothing. */ case FR_TLS_HANDLED: /* * FIXME: If the SSL session is established, grab the state * and EAP id from the inner tunnel, and update it with * the expected EAP id! */ RDEBUG2("FR_TLS_HANDLED"); return 1; /* * Handshake is done, proceed with decoding tunneled * data. */ case FR_TLS_OK: RDEBUG2("FR_TLS_OK"); break; /* * Anything else: fail. */ default: RDEBUG2("FR_TLS_OTHERS"); return 0; } /* * Session is established, proceed with decoding * tunneled data. */ RDEBUG2("Session established. Decoding tunneled attributes"); /* * We may need PEAP data associated with the session, so * allocate it here, if it wasn't already alloacted. */ if (!tls_session->opaque) { tls_session->opaque = peap_alloc(tls_session, inst); } /* * Process the PEAP portion of the request. */ rcode = eappeap_process(handler, tls_session); switch (rcode) { case RLM_MODULE_REJECT: eaptls_fail(handler, 0); return 0; case RLM_MODULE_HANDLED: eaptls_request(handler->eap_ds, tls_session); return 1; case RLM_MODULE_OK: /* * Move the saved VP's from the Access-Accept to * our Access-Accept. */ peap = tls_session->opaque; if (peap->soh_reply_vps) { RDEBUG2("Using saved attributes from the SoH reply"); debug_pair_list(peap->soh_reply_vps); pairfilter(handler->request->reply, &handler->request->reply->vps, &peap->soh_reply_vps, 0, 0, TAG_ANY); } if (peap->accept_vps) { RDEBUG2("Using saved attributes from the original Access-Accept"); debug_pair_list(peap->accept_vps); pairfilter(handler->request->reply, &handler->request->reply->vps, &peap->accept_vps, 0, 0, TAG_ANY); } /* * Success: Automatically return MPPE keys. */ return eaptls_success(handler, 0); /* * No response packet, MUST be proxying it. * The main EAP module will take care of discovering * that the request now has a "proxy" packet, and * will proxy it, rather than returning an EAP packet. */ case RLM_MODULE_UPDATED: #ifdef WITH_PROXY rad_assert(handler->request->proxy != NULL); #endif return 1; break; default: break; } eaptls_fail(handler, 0); return 0; }
/* * Do authentication, by letting EAP-TLS do most of the work. */ static int eapttls_authenticate(void *arg, EAP_HANDLER *handler) { int rcode; fr_tls_status_t status; rlm_eap_ttls_t *inst = (rlm_eap_ttls_t *) arg; tls_session_t *tls_session = (tls_session_t *) handler->opaque; ttls_tunnel_t *t = (ttls_tunnel_t *) tls_session->opaque; REQUEST *request = handler->request; RDEBUG2("Authenticate"); tls_session->length_flag = inst->include_length; /* * Process TLS layer until done. */ status = eaptls_process(handler); RDEBUG2("eaptls_process returned %d\n", status); switch (status) { /* * EAP-TLS handshake was successful, tell the * client to keep talking. * * If this was EAP-TLS, we would just return * an EAP-TLS-Success packet here. */ case FR_TLS_SUCCESS: if (SSL_session_reused(tls_session->ssl)) { RDEBUG("Skipping Phase2 due to session resumption"); goto do_keys; } if (t && t->authenticated) { RDEBUG2("Using saved attributes from the original Access-Accept"); debug_pair_list(t->accept_vps); pairadd(&handler->request->reply->vps, t->accept_vps); t->accept_vps = NULL; do_keys: /* * Success: Automatically return MPPE keys. */ return eaptls_success(handler, 0); } else { eaptls_request(handler->eap_ds, tls_session); } return 1; /* * The TLS code is still working on the TLS * exchange, and it's a valid TLS request. * do nothing. */ case FR_TLS_HANDLED: return 1; /* * Handshake is done, proceed with decoding tunneled * data. */ case FR_TLS_OK: break; /* * Anything else: fail. */ default: return 0; } /* * Session is established, proceed with decoding * tunneled data. */ RDEBUG2("Session established. Proceeding to decode tunneled attributes."); /* * We may need TTLS data associated with the session, so * allocate it here, if it wasn't already alloacted. */ if (!tls_session->opaque) { tls_session->opaque = ttls_alloc(inst); tls_session->free_opaque = ttls_free; } /* * Process the TTLS portion of the request. */ rcode = eapttls_process(handler, tls_session); switch (rcode) { case PW_AUTHENTICATION_REJECT: eaptls_fail(handler, 0); return 0; /* * Access-Challenge, continue tunneled conversation. */ case PW_ACCESS_CHALLENGE: eaptls_request(handler->eap_ds, tls_session); return 1; /* * Success: Automatically return MPPE keys. */ case PW_AUTHENTICATION_ACK: return eaptls_success(handler, 0); /* * No response packet, MUST be proxying it. * The main EAP module will take care of discovering * that the request now has a "proxy" packet, and * will proxy it, rather than returning an EAP packet. */ case PW_STATUS_CLIENT: #ifdef WITH_PROXY rad_assert(handler->request->proxy != NULL); #endif return 1; break; default: break; } /* * Something we don't understand: Reject it. */ eaptls_fail(handler, 0); return 0; }
/* * Do authentication, by letting EAP-TLS do most of the work. */ static int CC_HINT(nonnull) mod_authenticate(void *type_arg, eap_handler_t *handler) { fr_tls_status_t status; tls_session_t *tls_session = (tls_session_t *) handler->opaque; REQUEST *request = handler->request; rlm_eap_tls_t *inst; inst = type_arg; RDEBUG2("Authenticate"); status = eaptls_process(handler); RDEBUG2("eaptls_process returned %d\n", status); switch (status) { /* * EAP-TLS handshake was successful, return an * EAP-TLS-Success packet here. * * If a virtual server was configured, check that * it accepts the certificates, too. */ case FR_TLS_SUCCESS: if (inst->virtual_server) { VALUE_PAIR *vp; REQUEST *fake; /* create a fake request */ fake = request_alloc_fake(request); rad_assert(!fake->packet->vps); fake->packet->vps = paircopy(fake->packet, request->packet->vps); /* set the virtual server to use */ if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) { fake->server = vp->vp_strvalue; } else { fake->server = inst->virtual_server; } RDEBUG("Processing EAP-TLS Certificate check:"); debug_pair_list(fake->packet->vps); RDEBUG("server %s {", fake->server); rad_virtual_server(fake); RDEBUG("} # server %s", fake->server); /* copy the reply vps back to our reply */ pairfilter(request->reply, &request->reply->vps, &fake->reply->vps, 0, 0, TAG_ANY); /* reject if virtual server didn't return accept */ if (fake->reply->code != PW_CODE_AUTHENTICATION_ACK) { RDEBUG2("Certificates were rejected by the virtual server"); request_free(&fake); eaptls_fail(handler, 0); return 0; } request_free(&fake); /* success */ } break; /* * The TLS code is still working on the TLS * exchange, and it's a valid TLS request. * do nothing. */ case FR_TLS_HANDLED: return 1; /* * Handshake is done, proceed with decoding tunneled * data. */ case FR_TLS_OK: RDEBUG2("Received unexpected tunneled data after successful handshake"); #ifndef NDEBUG if ((debug_flag > 2) && fr_log_fp) { unsigned int i; unsigned int data_len; unsigned char buffer[1024]; data_len = (tls_session->record_minus)(&tls_session->dirty_in, buffer, sizeof(buffer)); DEBUG(" Tunneled data (%u bytes)", data_len); for (i = 0; i < data_len; i++) { if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, " %x: ", i); if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n"); fprintf(fr_log_fp, "%02x ", buffer[i]); } fprintf(fr_log_fp, "\n"); } #endif eaptls_fail(handler, 0); return 0; break; /* * Anything else: fail. * * Also, remove the session from the cache so that * the client can't re-use it. */ default: tls_fail(tls_session); return 0; } /* * Success: Automatically return MPPE keys. */ return eaptls_success(handler, 0); }
/* * Do authentication, by letting EAP-TLS do most of the work. */ static int eaptls_authenticate(void *arg, EAP_HANDLER *handler) { eaptls_status_t status; tls_session_t *tls_session = (tls_session_t *) handler->opaque; REQUEST *request = handler->request; eap_tls_t *inst = (eap_tls_t *) arg; RDEBUG2("Authenticate"); status = eaptls_process(handler); RDEBUG2("eaptls_process returned %d\n", status); switch (status) { /* * EAP-TLS handshake was successful, return an * EAP-TLS-Success packet here. */ case EAPTLS_SUCCESS: break; /* * The TLS code is still working on the TLS * exchange, and it's a valid TLS request. * do nothing. */ case EAPTLS_HANDLED: return 1; /* * Handshake is done, proceed with decoding tunneled * data. */ case EAPTLS_OK: RDEBUG2("Received unexpected tunneled data after successful handshake."); #ifndef NDEBUG if ((debug_flag > 2) && fr_log_fp) { unsigned int i; unsigned int data_len; unsigned char buffer[1024]; data_len = (tls_session->record_minus)(&tls_session->dirty_in, buffer, sizeof(buffer)); log_debug(" Tunneled data (%u bytes)\n", data_len); for (i = 0; i < data_len; i++) { if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, " %x: ", i); if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n"); fprintf(fr_log_fp, "%02x ", buffer[i]); } fprintf(fr_log_fp, "\n"); } #endif eaptls_fail(handler, 0); return 0; break; /* * Anything else: fail. * * Also, remove the session from the cache so that * the client can't re-use it. */ default: if (inst->conf->session_cache_enable) { SSL_CTX_remove_session(inst->ctx, tls_session->ssl->session); } return 0; } /* * New sessions cause some additional information to be * cached. */ if (!SSL_session_reused(tls_session->ssl)) { /* * FIXME: Store miscellaneous data. */ RDEBUG2("Adding user data to cached session"); #if 0 SSL_SESSION_set_ex_data(tls_session->ssl->session, ssl_session_idx_user_session, session_data); #endif } else { /* * FIXME: Retrieve miscellaneous data. */ #if 0 data = SSL_SESSION_get_ex_data(tls_session->ssl->session, ssl_session_idx_user_session); if (!session_data) { radlog_request(L_ERR, 0, request, "No user session data in cached session - " " REJECTING"); return 0; } #endif RDEBUG2("Retrieved session data from cached session"); } /* * Success: Automatically return MPPE keys. */ return eaptls_success(handler, 0); }
/* * Do post-proxy processing, */ static int CC_HINT(nonnull) eapttls_postproxy(eap_handler_t *handler, void *data) { int rcode; tls_session_t *tls_session = (tls_session_t *) data; REQUEST *fake, *request = handler->request; RDEBUG("Passing reply from proxy back into the tunnel"); /* * If there was a fake request associated with the proxied * request, do more processing of it. */ fake = (REQUEST *) request_data_get(handler->request, handler->request->proxy, REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK); /* * Do the callback, if it exists, and if it was a success. */ if (fake && (handler->request->proxy_reply->code == PW_CODE_ACCESS_ACCEPT)) { /* * Terrible hacks. */ rad_assert(!fake->packet); fake->packet = talloc_steal(fake, request->proxy); fake->packet->src_ipaddr = request->packet->src_ipaddr; request->proxy = NULL; rad_assert(!fake->reply); fake->reply = talloc_steal(fake, request->proxy_reply); request->proxy_reply = NULL; if ((rad_debug_lvl > 0) && fr_log_fp) { fprintf(fr_log_fp, "server %s {\n", (!fake->server) ? "" : fake->server); } /* * Perform a post-auth stage for the tunneled * session. */ fake->options &= ~RAD_REQUEST_OPTION_PROXY_EAP; rcode = rad_postauth(fake); RDEBUG2("post-auth returns %d", rcode); if ((rad_debug_lvl > 0) && fr_log_fp) { fprintf(fr_log_fp, "} # server %s\n", (!fake->server) ? "" : fake->server); RDEBUG("Final reply from tunneled session code %d", fake->reply->code); rdebug_pair_list(L_DBG_LVL_1, request, fake->reply->vps, NULL); } /* * Terrible hacks. */ request->proxy = talloc_steal(request, fake->packet); fake->packet = NULL; request->proxy_reply = talloc_steal(request, fake->reply); fake->reply = NULL; /* * And we're done with this request. */ switch (rcode) { case RLM_MODULE_FAIL: talloc_free(fake); eaptls_fail(handler, 0); return 0; default: /* Don't Do Anything */ RDEBUG2("Got reply %d", request->proxy_reply->code); break; } } talloc_free(fake); /* robust if !fake */ /* * 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. */ fr_pair_list_free(&handler->request->proxy_reply->vps); switch (rcode) { case RLM_MODULE_REJECT: RDEBUG("Reply was rejected"); break; case RLM_MODULE_HANDLED: RDEBUG("Reply was handled"); eaptls_request(handler->eap_ds, tls_session); request->proxy_reply->code = PW_CODE_ACCESS_CHALLENGE; return 1; case RLM_MODULE_OK: RDEBUG("Reply was OK"); /* * Success: Automatically return MPPE keys. */ return eaptls_success(handler, 0); default: RDEBUG("Reply was unknown"); break; } eaptls_fail(handler, 0); return 0; }