From 4bc181ecc7e918759a032c4c37ac4e7f6f47e147 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 22 Apr 2009 16:01:37 +0300 Subject: [PATCH] Add new wpa_supplicant driver op for setting 802.1X port status This can be used with drivers that implement PAE to control whether normal data frames (non-EAPOL) are allowed. --- src/drivers/driver.h | 8 ++++++++ src/drivers/driver_ndis.c | 3 ++- src/eapol_supp/eapol_supp_sm.c | 24 ++++++++++++++++++++++++ src/eapol_supp/eapol_supp_sm.h | 7 +++++++ wpa_supplicant/driver_i.h | 10 ++++++++++ wpa_supplicant/wpas_glue.c | 10 ++++++++++ 6 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 8339127e9..855100498 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1333,6 +1333,14 @@ struct wpa_driver_ops { const u8 *ie, size_t len); int (*set_wps_probe_resp_ie)(const char *ifname, void *priv, const u8 *ie, size_t len); + + /** + * set_supp_port - Set IEEE 802.1X Supplicant Port status + * @priv: Private driver interface data + * @authorized: Whether the port is authorized + * Returns: 0 on success, -1 on failure + */ + int (*set_supp_port)(void *priv, int authorized); }; /** diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c index fd0e97e0c..e45b2318a 100644 --- a/src/drivers/driver_ndis.c +++ b/src/drivers/driver_ndis.c @@ -3264,5 +3264,6 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = { NULL /* set_radius_acl_expire */, NULL /* set_ht_params */, NULL /* set_wps_beacon_ie */, - NULL /* set_wps_probe_resp_ie */ + NULL /* set_wps_probe_resp_ie */, + NULL /* set_supp_port */ }; diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c index 537f06d31..e4c070061 100644 --- a/src/eapol_supp/eapol_supp_sm.c +++ b/src/eapol_supp/eapol_supp_sm.c @@ -193,6 +193,8 @@ static void eapol_sm_txSuppRsp(struct eapol_sm *sm); static void eapol_sm_abortSupp(struct eapol_sm *sm); static void eapol_sm_abort_cached(struct eapol_sm *sm); static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx); +static void eapol_sm_set_port_authorized(struct eapol_sm *sm); +static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm); /* Port Timers state machine - implemented as a function that will be called @@ -250,6 +252,7 @@ SM_STATE(SUPP_PAE, LOGOFF) eapol_sm_txLogoff(sm); sm->logoffSent = TRUE; sm->suppPortStatus = Unauthorized; + eapol_sm_set_port_unauthorized(sm); } @@ -260,6 +263,7 @@ SM_STATE(SUPP_PAE, DISCONNECTED) sm->startCount = 0; sm->logoffSent = FALSE; sm->suppPortStatus = Unauthorized; + eapol_sm_set_port_unauthorized(sm); sm->suppAbort = TRUE; sm->unicast_key_received = FALSE; @@ -315,6 +319,7 @@ SM_STATE(SUPP_PAE, HELD) sm->heldWhile = sm->heldPeriod; eapol_enable_timer_tick(sm); sm->suppPortStatus = Unauthorized; + eapol_sm_set_port_unauthorized(sm); sm->cb_status = EAPOL_CB_FAILURE; } @@ -323,6 +328,7 @@ SM_STATE(SUPP_PAE, AUTHENTICATED) { SM_ENTRY(SUPP_PAE, AUTHENTICATED); sm->suppPortStatus = Authorized; + eapol_sm_set_port_authorized(sm); sm->cb_status = EAPOL_CB_SUCCESS; } @@ -338,6 +344,7 @@ SM_STATE(SUPP_PAE, S_FORCE_AUTH) { SM_ENTRY(SUPP_PAE, S_FORCE_AUTH); sm->suppPortStatus = Authorized; + eapol_sm_set_port_authorized(sm); sm->sPortMode = ForceAuthorized; } @@ -346,6 +353,7 @@ SM_STATE(SUPP_PAE, S_FORCE_UNAUTH) { SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH); sm->suppPortStatus = Unauthorized; + eapol_sm_set_port_unauthorized(sm); sm->sPortMode = ForceUnauthorized; eapol_sm_txLogoff(sm); } @@ -862,6 +870,20 @@ static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx) } +static void eapol_sm_set_port_authorized(struct eapol_sm *sm) +{ + if (sm->ctx->port_cb) + sm->ctx->port_cb(sm->ctx->ctx, 1); +} + + +static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm) +{ + if (sm->ctx->port_cb) + sm->ctx->port_cb(sm->ctx->ctx, 0); +} + + /** * eapol_sm_step - EAPOL state machine step function * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() @@ -1456,6 +1478,7 @@ void eapol_sm_notify_cached(struct eapol_sm *sm) wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL"); sm->SUPP_PAE_state = SUPP_PAE_AUTHENTICATED; sm->suppPortStatus = Authorized; + eapol_sm_set_port_authorized(sm); sm->portValid = TRUE; eap_notify_success(sm->eap); eapol_sm_step(sm); @@ -1492,6 +1515,7 @@ static void eapol_sm_abort_cached(struct eapol_sm *sm) sm->cached_pmk = FALSE; sm->SUPP_PAE_state = SUPP_PAE_CONNECTING; sm->suppPortStatus = Unauthorized; + eapol_sm_set_port_unauthorized(sm); /* Make sure we do not start sending EAPOL-Start frames first, but * instead move to RESTART state to start EAPOL authentication. */ diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h index 57d7bc1ab..e6e8cc6d6 100644 --- a/src/eapol_supp/eapol_supp_sm.h +++ b/src/eapol_supp/eapol_supp_sm.h @@ -215,6 +215,13 @@ struct eapol_ctx { */ void (*eap_param_needed)(void *ctx, const char *field, const char *txt); + + /** + * port_cb - Set port authorized/unauthorized callback (optional) + * @ctx: Callback context (ctx) + * @authorized: Whether the supplicant port is now in authorized state + */ + void (*port_cb)(void *ctx, int authorized); }; diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 75a800cef..4cb53728e 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -438,4 +438,14 @@ static inline int wpa_drv_sta_set_flags(struct wpa_supplicant *wpa_s, return -1; } +static inline int wpa_drv_set_supp_port(struct wpa_supplicant *wpa_s, + int authorized) +{ + if (wpa_s->driver->set_supp_port) { + return wpa_s->driver->set_supp_port(wpa_s->drv_priv, + authorized); + } + return 0; +} + #endif /* DRIVER_I_H */ diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index d8af14da9..c2eb13151 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -537,6 +537,15 @@ static void wpa_supplicant_eap_param_needed(void *ctx, const char *field, #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ +static void wpa_supplicant_port_cb(void *ctx, int authorized) +{ + struct wpa_supplicant *wpa_s = ctx; + wpa_printf(MSG_DEBUG, "EAPOL: Supplicant port status: %s", + authorized ? "Authorized" : "Unauthorized"); + wpa_drv_set_supp_port(wpa_s, authorized); +} + + int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) { #ifdef IEEE8021X_EAPOL @@ -564,6 +573,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) #endif /* EAP_TLS_OPENSSL */ ctx->wps = wpa_s->wps; ctx->eap_param_needed = wpa_supplicant_eap_param_needed; + ctx->port_cb = wpa_supplicant_port_cb; ctx->cb = wpa_supplicant_eapol_cb; ctx->cb_ctx = wpa_s; wpa_s->eapol = eapol_sm_init(ctx);