#include <ctype.h>
-/*
- * Post-authentication step processes the response before it is
- * sent to the NAS. It can receive both Access-Accept and Access-Reject
- * replies.
- */
-rlm_rcode_t rad_postauth(REQUEST *request)
-{
- rlm_rcode_t rcode;
- int postauth_type = 0;
- VALUE_PAIR *vp;
-
- /*
- * Do post-authentication calls. ignoring the return code.
- */
- vp = fr_pair_find_by_num(request->control, 0, FR_POST_AUTH_TYPE, TAG_ANY);
- if (vp) {
- postauth_type = vp->vp_uint32;
- RDEBUG2("Using Post-Auth-Type %s",
- fr_dict_enum_alias_by_value(vp->da, fr_box_uint32(postauth_type)));
- }
- rcode = process_post_auth(postauth_type, request);
- switch (rcode) {
- /*
- * The module failed, or said to reject the user: Do so.
- */
- case RLM_MODULE_FAIL:
- case RLM_MODULE_INVALID:
- case RLM_MODULE_REJECT:
- case RLM_MODULE_USERLOCK:
- default:
- request->reply->code = FR_CODE_ACCESS_REJECT;
- rcode = RLM_MODULE_REJECT;
- break;
- /*
- * The module handled the request, cancel the reply.
- */
- case RLM_MODULE_HANDLED:
- /* FIXME */
- break;
- /*
- * The module had a number of OK return codes.
- */
- case RLM_MODULE_NOOP:
- case RLM_MODULE_NOTFOUND:
- case RLM_MODULE_OK:
- case RLM_MODULE_UPDATED:
- rcode = RLM_MODULE_OK;
- break;
- }
- return rcode;
-}
-
-
static rlm_rcode_t virtual_server_async(REQUEST *request, bool parent)
{
fr_io_final_t final;
#include <freeradius-devel/server/request.h>
#include <freeradius-devel/server/rcode.h>
-rlm_rcode_t rad_postauth(REQUEST *);
rlm_rcode_t rad_virtual_server(REQUEST *);
#ifdef __cplusplus
/*
* Process the PEAP portion of an EAP-PEAP request.
*/
-rlm_rcode_t eap_peap_process(eap_session_t *eap_session, tls_session_t *tls_session, fr_dict_enum_t const *enumv) CC_HINT(nonnull(1,2));
+rlm_rcode_t eap_peap_process(eap_session_t *eap_session, tls_session_t *tls_session) CC_HINT(nonnull);
return rcode;
}
-#ifdef WITH_PROXY
-/*
- * Do post-proxy processing,
- */
-static int CC_HINT(nonnull) eap_peap_postproxy(eap_session_t *eap_session, void *data)
-{
- int rcode;
- tls_session_t *tls_session = talloc_get_type_abort(data, tls_session_t);
- REQUEST *fake, *request = eap_session->request;
-
- RDEBUG2("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(eap_session->request,
- eap_session->request->proxy,
- REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK);
-
- /*
- * Do the callback, if it exists, and if it was a success.
- */
- if (fake && (eap_session->request->proxy->reply->code == FR_CODE_ACCESS_ACCEPT)) {
- peap_tunnel_t *t = tls_session->opaque;
-
- t->home_access_accept = true;
-
- /*
- * Terrible hacks.
- */
- rad_assert(!fake->packet);
- fake->packet = talloc_steal(fake, request->proxy->packet);
- fake->packet->src_ipaddr = request->packet->src_ipaddr;
- request->proxy->packet = 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", cf_section_name2(fake->server_cs));
- }
-
- /*
- * Perform a post-auth stage, which will get the EAP
- * eap_session, too...
- */
- fake->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
- RDEBUG2("Passing reply back for EAP-MS-CHAP-V2");
- process_post_proxy(0, fake);
-
- /*
- * FIXME: If rcode returns fail, do something
- * intelligent...
- */
- rcode = rad_postauth(fake);
-
- if ((rad_debug_lvl > 0) && fr_log_fp) {
- fprintf(fr_log_fp, "} # server %s\n", cf_section_name2(fake->server_cs));
-
- RDEBUG("Final reply from tunneled session code %d", fake->reply->code);
- log_request_pair_list(L_DBG_LVL_1, request, fake->reply->vps, NULL);
- }
-
- /*
- * Terrible hacks.
- */
- request->proxy->packet = talloc_steal(request->proxy, fake->packet);
- fake->packet = NULL;
- request->proxy->reply = talloc_steal(request->proxy, fake->reply);
- fake->reply = NULL;
-
- /*
- * And we're done with this request.
- */
-
- switch (rcode) {
- case RLM_MODULE_FAIL:
- talloc_free(fake);
- eap_tls_fail(eap_session);
- return 0;
-
- default: /* Don't Do Anything */
- RDEBUG2("Got reply %d", request->proxy->reply->code);
- break;
- }
- }
- talloc_free(fake); /* robust if !fake */
-
- /*
- * 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(eap_session, tls_session, eap_session->request,
- eap_session->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(&eap_session->request->proxy->reply->vps);
-
- switch (rcode) {
- case RLM_MODULE_REJECT:
- RDEBUG2("Reply was rejected");
- eap_tls_fail(eap_session);
- return 0;
-
- case RLM_MODULE_HANDLED:
- RDEBUG2("Reply was handled");
- eap_tls_request(eap_session);
- request->proxy->reply->code = FR_CODE_ACCESS_CHALLENGE;
- return 1;
-
- case RLM_MODULE_OK:
- RDEBUG2("Reply was OK");
-
- /*
- * Success: Automatically return MPPE keys.
- */
- if (eap_tls_success(eap_session) < 0) return 0;
- return 1;
-
- default:
- RDEBUG2("Reply was unknown");
- break;
- }
-
- eap_tls_fail(eap_session);
- return 0;
-}
-#endif
-
static char const *peap_state(peap_tunnel_t *t)
{
/*
* Process the pseudo-EAP contents of the tunneled data.
*/
-rlm_rcode_t eap_peap_process(eap_session_t *eap_session, tls_session_t *tls_session, fr_dict_enum_t const *enumv)
+rlm_rcode_t eap_peap_process(eap_session_t *eap_session, tls_session_t *tls_session)
{
peap_tunnel_t *t = tls_session->opaque;
REQUEST *fake = NULL;
/*
* Decide what to do with the reply.
*/
- switch (fake->reply->code) {
- case 0: /* No reply code, must be proxied... */
-#ifdef WITH_PROXY
- vp = fr_pair_find_by_da(fake->control, attr_proxy_to_realm, TAG_ANY);
-
- if (vp) {
- eap_tunnel_data_t *tunnel;
- int ret;
-
- /*
- * 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) {
- CONF_SECTION *unlang;
- fake->options |= RAD_REQUEST_OPTION_PROXY_EAP;
-
- /*
- * Hmm... should we check for
- * Auth-Type & EAP-Message here?
- */
-
- if (!enumv) {
- RERROR("You must set 'inner_eap_module' in the 'peap' configuration");
- RERROR("This is required in order to proxy the inner EAP session.");
- rcode = RLM_MODULE_REJECT;
- goto finish;
- }
-
- /*
- * Run the EAP authentication.
- */
- RDEBUG2("Calling authenticate in order to initiate tunneled EAP session");
-
- unlang = cf_section_find(request->server_cs, "authenticate", enumv->alias);
- if (!unlang) {
- rcode = process_authenticate(enumv->value->vb_uint32, fake);
- } else {
- unlang_push_section(request, unlang, RLM_MODULE_FAIL, UNLANG_TOP_FRAME);
- rcode = unlang_interpret_continue(request);
- }
-
- if (rcode == RLM_MODULE_OK) {
- /*
- * Authentication succeeded! Rah!
- */
- fake->reply->code = FR_CODE_ACCESS_ACCEPT;
- goto do_process;
- }
-
- if (rcode != RLM_MODULE_HANDLED) {
- RDEBUG("Can't handle the return code %d", rcode);
- rcode = RLM_MODULE_REJECT;
- goto finish;
- }
-
- /*
- * The module decided it wasn't
- * finish. Handle it like normal.
- */
- if ((fake->options & RAD_REQUEST_OPTION_PROXY_EAP) == 0) {
- RDEBUG2("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.
- */
- fr_pair_delete_by_da(&fake->packet->vps, attr_eap_message);
- }
-
- RDEBUG2("Tunnelled authentication will be proxied to %s", vp->vp_strvalue);
-
- /*
- * Tell the original request that it's going
- * to be proxied.
- */
- fr_pair_list_copy_by_da(request, &request->control, fake->control, attr_proxy_to_realm);
-
- /*
- * Seed the proxy packet with the
- * tunneled request.
- */
- rad_assert(!request->proxy);
-
- request->proxy = request_alloc_proxy(request);
-
- request->proxy->packet = talloc_steal(request->proxy, fake->packet);
- memset(&request->proxy->packet->src_ipaddr, 0, sizeof(request->proxy->packet->src_ipaddr));
- memset(&request->proxy->packet->dst_ipaddr, 0, sizeof(request->proxy->packet->dst_ipaddr));
- request->proxy->packet->src_port = 0;
- request->proxy->packet->dst_port = 0;
- fake->packet = NULL;
- fr_radius_packet_free(&fake->reply);
- fake->reply = NULL;
-
- /*
- * Set up the callbacks for the tunnel
- */
- tunnel = talloc_zero(request, eap_tunnel_data_t);
- tunnel->tls_session = tls_session;
- tunnel->callback = eap_peap_postproxy;
-
- /*
- * Associate the callback with the request.
- */
- ret = request_data_add(request, request->proxy, REQUEST_DATA_EAP_TUNNEL_CALLBACK,
- tunnel, false, false, false);
- fr_cond_assert(ret == 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) {
- RDEBUG2("Remembering to do EAP-MS-CHAP-V2 post-proxy");
-
- /*
- * rlm_eap.c has taken care of associating
- * the eap_session with the fake request.
- *
- * So we associate the fake request with
- * this request.
- */
- ret = request_data_add(request, request->proxy,
- REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK,
- fake, true, false, false);
- fr_cond_assert(ret == 0);
-
- /*
- * Do NOT free the fake request!
- */
- rcode = RLM_MODULE_UPDATED;
- goto finish;
- }
-
- /*
- * Didn't authenticate the packet, but
- * we're proxying it.
- */
- rcode = RLM_MODULE_UPDATED;
-
- } else
-#endif /* WITH_PROXY */
- {
- REDEBUG("Unknown RADIUS packet type %d: rejecting tunneled user", fake->reply->code);
- rcode = RLM_MODULE_REJECT;
- }
- break;
-
- default:
-#ifdef WITH_PROXY
- do_process:
-#endif
+ if (!fake->reply->code) {
+ REDEBUG("Unknown RADIUS packet type %d: rejecting tunneled user", fake->reply->code);
+ rcode = RLM_MODULE_REJECT;
+ } else {
rcode = process_reply(eap_session, tls_session, request, fake->reply);
- break;
}
finish:
#include "eap_peap.h"
-static int auth_type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
- CONF_ITEM *ci, UNUSED CONF_PARSER const *rule);
-
typedef struct rlm_eap_peap_t {
char const *tls_conf_name; //!< TLS configuration.
fr_tls_conf_t *tls_conf;
- fr_dict_enum_t *inner_eap_module; //!< Auth type of the inner eap module
-
bool use_tunneled_reply; //!< Use the reply attributes from the tunneled session in
//!< the non-tunneled reply to the client.
static CONF_PARSER submodule_config[] = {
{ FR_CONF_OFFSET("tls", FR_TYPE_STRING, rlm_eap_peap_t, tls_conf_name) },
- { FR_CONF_OFFSET("inner_eap_module", FR_TYPE_VOID, rlm_eap_peap_t, inner_eap_module), .func = auth_type_parse, .dflt = "eap" },
-
{ FR_CONF_DEPRECATED("copy_request_to_tunnel", FR_TYPE_BOOL, rlm_eap_peap_t, NULL), .dflt = "no" },
{ FR_CONF_DEPRECATED("use_tunneled_reply", FR_TYPE_BOOL, rlm_eap_peap_t, NULL), .dflt = "no" },
{ NULL }
};
-/** Translate a string auth_type into an enumeration value
- *
- * @param[in] ctx to allocate data.
- * @param[out] out Where to write the auth_type we created or resolved.
- * @param[in] parent Base structure address.
- * @param[in] ci #CONF_PAIR specifying the name of the auth_type.
- * @param[in] rule unused.
- * @return
- * - 0 on success.
- * - -1 on failure.
- */
-static int auth_type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
- CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
-{
- char const *auth_type = cf_pair_value(cf_item_to_pair(ci));
-
- if (fr_dict_enum_add_alias_next(attr_auth_type, auth_type) < 0) {
- cf_log_err(ci, "Failed adding %s alias", attr_auth_type->name);
- return -1;
- }
- *((fr_dict_enum_t **)out) = fr_dict_enum_by_alias(attr_auth_type, auth_type, -1);
-
- return 0;
-}
/*
* Allocate the PEAP per-session data
/*
* Process the PEAP portion of the request.
*/
- rcode = eap_peap_process(eap_session, tls_session, inst->inner_eap_module);
+ rcode = eap_peap_process(eap_session, tls_session);
switch (rcode) {
case RLM_MODULE_REJECT:
eap_tls_fail(eap_session);
}
-#ifdef WITH_PROXY
-/*
- * Do post-proxy processing,
- */
-static int CC_HINT(nonnull) eap_ttls_postproxy(eap_session_t *eap_session, void *data)
-{
- int rcode;
- tls_session_t *tls_session = talloc_get_type_abort(data, tls_session_t);
- REQUEST *fake, *request = eap_session->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(eap_session->request,
- eap_session->request->proxy,
- REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK);
-
- /*
- * Do the callback, if it exists, and if it was a success.
- */
- if (fake && (eap_session->request->proxy->reply->code == FR_CODE_ACCESS_ACCEPT)) {
- /*
- * Terrible hacks.
- */
- rad_assert(!fake->packet);
- fake->packet = talloc_steal(fake, request->proxy->packet);
- fake->packet->src_ipaddr = request->packet->src_ipaddr;
- request->proxy->packet = 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", cf_section_name2(fake->server_cs));
- }
-
- /*
- * 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", cf_section_name2(fake->server_cs));
-
- RDEBUG("Final reply from tunneled session code %d", fake->reply->code);
- log_request_pair_list(L_DBG_LVL_1, request, fake->reply->vps, NULL);
- }
-
- /*
- * Terrible hacks.
- */
- request->proxy->packet = talloc_steal(request->proxy, fake->packet);
- fake->packet = NULL;
- request->proxy->reply = talloc_steal(request->proxy, fake->reply);
- fake->reply = NULL;
-
- /*
- * And we're done with this request.
- */
-
- switch (rcode) {
- case RLM_MODULE_FAIL:
- talloc_free(fake);
- eap_tls_fail(eap_session);
- 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(eap_session, tls_session, eap_session->request, eap_session->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(&eap_session->request->proxy->reply->vps);
-
- switch (rcode) {
- case RLM_MODULE_REJECT:
- RDEBUG("Reply was rejected");
- break;
-
- case RLM_MODULE_HANDLED:
- RDEBUG("Reply was handled");
- eap_tls_request(eap_session);
- request->proxy->reply->code = FR_CODE_ACCESS_CHALLENGE;
- return 1;
-
- case RLM_MODULE_OK:
- RDEBUG("Reply was OK");
-
- /*
- * Success: Automatically return MPPE keys.
- */
- if (eap_tls_success(eap_session) < 0) return 0;
- return 1;
-
- default:
- RDEBUG("Reply was unknown");
- break;
- }
-
- eap_tls_fail(eap_session);
- return 0;
-}
-
-#endif /* WITH_PROXY */
-
/*
* Process the "diameter" contents of the tunneled data.
*/
/*
* Decide what to do with the reply.
*/
- switch (fake->reply->code) {
- case 0: /* No reply code, must be proxied... */
-#ifdef WITH_PROXY
- vp = fr_pair_find_by_da(fake->control, attr_proxy_to_realm, TAG_ANY);
- if (vp) {
- int ret;
- eap_tunnel_data_t *tunnel;
-
- RDEBUG("Tunneled authentication will be proxied to %pV", &vp->data);
-
- /*
- * Tell the original request that it's going
- * to be proxied.
- */
- fr_pair_list_copy_by_da(request, &request->control, fake->control, attr_proxy_to_realm);
-
- /*
- * Seed the proxy packet with the
- * tunneled request.
- */
- rad_assert(!request->proxy);
-
- request->proxy = request_alloc_proxy(request);
-
- request->proxy->packet = talloc_steal(request->proxy, fake->packet);
- memset(&request->proxy->packet->src_ipaddr, 0, sizeof(request->proxy->packet->src_ipaddr));
- memset(&request->proxy->packet->src_ipaddr, 0, sizeof(request->proxy->packet->src_ipaddr));
- request->proxy->packet->src_port = 0;
- request->proxy->packet->dst_port = 0;
- fake->packet = NULL;
- fr_radius_packet_free(&fake->reply);
- fake->reply = NULL;
-
- /*
- * Set up the callbacks for the tunnel
- */
- tunnel = talloc_zero(request, eap_tunnel_data_t);
- tunnel->tls_session = tls_session;
- tunnel->callback = eap_ttls_postproxy;
-
- /*
- * Associate the callback with the request.
- */
- ret = request_data_add(request, request->proxy, REQUEST_DATA_EAP_TUNNEL_CALLBACK,
- tunnel, false, false, false);
- fr_cond_assert(ret == 0);
-
- /*
- * rlm_eap.c has taken care of associating
- * the eap_session with the fake request.
- *
- * So we associate the fake request with
- * this request.
- */
- ret = request_data_add(request, request->proxy, REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK,
- fake, true, false, false);
- fr_cond_assert(ret == 0);
-
- fake = NULL;
-
- /*
- * Didn't authenticate the packet, but
- * we're proxying it.
- */
- code = FR_CODE_STATUS_CLIENT;
-
- } else
-#endif /* WITH_PROXY */
- {
- RDEBUG("No tunneled reply was found for request %" PRIu64 ", and the request was not "
- "proxied: rejecting the user", request->number);
- code = FR_CODE_ACCESS_REJECT;
- }
- break;
-
- default:
+ if (!fake->reply->code) {
+ RDEBUG("No tunneled reply was found for request %" PRIu64 ", and the request was not "
+ "proxied: rejecting the user", request->number);
+ code = FR_CODE_ACCESS_REJECT;
+ } else {
/*
* Returns RLM_MODULE_FOO, and we want to return FR_FOO
*/
code = FR_CODE_ACCESS_REJECT;
break;
}
- break;
}
finish: