wpa_supplicant: Report EAP connection progress to DBus
Send an "EAP" signal via the new DBus interface under various conditions during EAP authentication: - During method selection (ACK and NAK) - During certificate verification - While sending and receiving TLS alert messages - EAP success and failure messages This provides DBus callers a number of new tools: - The ability to probe an AP for available EAP methods (given an identity). - The ability to identify why the remote certificate was not verified. - The ability to identify why the remote peer refused a TLS connection. Signed-hostap: Paul Stewart <pstew@chromium.org>
This commit is contained in:
parent
24b5bd8b42
commit
dd7fec1f29
11 changed files with 156 additions and 3 deletions
|
@ -21,8 +21,10 @@ struct tls_keys {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum tls_event {
|
enum tls_event {
|
||||||
|
TLS_CERT_CHAIN_SUCCESS,
|
||||||
TLS_CERT_CHAIN_FAILURE,
|
TLS_CERT_CHAIN_FAILURE,
|
||||||
TLS_PEER_CERTIFICATE
|
TLS_PEER_CERTIFICATE,
|
||||||
|
TLS_ALERT
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -57,6 +59,12 @@ union tls_event_data {
|
||||||
const u8 *hash;
|
const u8 *hash;
|
||||||
size_t hash_len;
|
size_t hash_len;
|
||||||
} peer_cert;
|
} peer_cert;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int is_local;
|
||||||
|
const char *type;
|
||||||
|
const char *description;
|
||||||
|
} alert;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tls_config {
|
struct tls_config {
|
||||||
|
|
|
@ -525,6 +525,15 @@ static void ssl_info_cb(const SSL *ssl, int where, int ret)
|
||||||
else
|
else
|
||||||
conn->write_alerts++;
|
conn->write_alerts++;
|
||||||
}
|
}
|
||||||
|
if (tls_global->event_cb != NULL) {
|
||||||
|
union tls_event_data ev;
|
||||||
|
os_memset(&ev, 0, sizeof(ev));
|
||||||
|
ev.alert.is_local = !(where & SSL_CB_READ);
|
||||||
|
ev.alert.type = SSL_alert_type_string_long(ret);
|
||||||
|
ev.alert.description = SSL_alert_desc_string_long(ret);
|
||||||
|
tls_global->event_cb(tls_global->cb_ctx, TLS_ALERT,
|
||||||
|
&ev);
|
||||||
|
}
|
||||||
} else if (where & SSL_CB_EXIT && ret <= 0) {
|
} else if (where & SSL_CB_EXIT && ret <= 0) {
|
||||||
wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
|
wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
|
||||||
str, ret == 0 ? "failed" : "error",
|
str, ret == 0 ? "failed" : "error",
|
||||||
|
@ -1265,6 +1274,10 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
|
||||||
TLS_FAIL_SERVER_CHAIN_PROBE);
|
TLS_FAIL_SERVER_CHAIN_PROBE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (preverify_ok && tls_global->event_cb != NULL)
|
||||||
|
tls_global->event_cb(tls_global->cb_ctx,
|
||||||
|
TLS_CERT_CHAIN_SUCCESS, NULL);
|
||||||
|
|
||||||
return preverify_ok;
|
return preverify_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,16 @@ static struct wpabuf * eapol_get_eapReqData(struct eap_sm *sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void eap_notify_status(struct eap_sm *sm, const char *status,
|
||||||
|
const char *parameter)
|
||||||
|
{
|
||||||
|
wpa_printf(MSG_DEBUG, "EAP: Status notification: %s (param=%s)",
|
||||||
|
status, parameter);
|
||||||
|
if (sm->eapol_cb->notify_status)
|
||||||
|
sm->eapol_cb->notify_status(sm->eapol_ctx, status, parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
|
static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
|
||||||
{
|
{
|
||||||
if (sm->m == NULL || sm->eap_method_priv == NULL)
|
if (sm->m == NULL || sm->eap_method_priv == NULL)
|
||||||
|
@ -213,6 +223,7 @@ SM_STATE(EAP, GET_METHOD)
|
||||||
{
|
{
|
||||||
int reinit;
|
int reinit;
|
||||||
EapType method;
|
EapType method;
|
||||||
|
const struct eap_method *eap_method;
|
||||||
|
|
||||||
SM_ENTRY(EAP, GET_METHOD);
|
SM_ENTRY(EAP, GET_METHOD);
|
||||||
|
|
||||||
|
@ -221,18 +232,24 @@ SM_STATE(EAP, GET_METHOD)
|
||||||
else
|
else
|
||||||
method = sm->reqMethod;
|
method = sm->reqMethod;
|
||||||
|
|
||||||
|
eap_method = eap_peer_get_eap_method(sm->reqVendor, method);
|
||||||
|
|
||||||
if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
|
if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
|
||||||
wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
|
wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
|
||||||
sm->reqVendor, method);
|
sm->reqVendor, method);
|
||||||
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
|
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
|
||||||
"vendor=%u method=%u -> NAK",
|
"vendor=%u method=%u -> NAK",
|
||||||
sm->reqVendor, method);
|
sm->reqVendor, method);
|
||||||
|
eap_notify_status(sm, "refuse proposed method",
|
||||||
|
eap_method ? eap_method->name : "unknown");
|
||||||
goto nak;
|
goto nak;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
|
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
|
||||||
"vendor=%u method=%u", sm->reqVendor, method);
|
"vendor=%u method=%u", sm->reqVendor, method);
|
||||||
|
|
||||||
|
eap_notify_status(sm, "accept proposed method",
|
||||||
|
eap_method ? eap_method->name : "unknown");
|
||||||
/*
|
/*
|
||||||
* RFC 4137 does not define specific operation for fast
|
* RFC 4137 does not define specific operation for fast
|
||||||
* re-authentication (session resumption). The design here is to allow
|
* re-authentication (session resumption). The design here is to allow
|
||||||
|
@ -256,7 +273,7 @@ SM_STATE(EAP, GET_METHOD)
|
||||||
|
|
||||||
sm->selectedMethod = sm->reqMethod;
|
sm->selectedMethod = sm->reqMethod;
|
||||||
if (sm->m == NULL)
|
if (sm->m == NULL)
|
||||||
sm->m = eap_peer_get_eap_method(sm->reqVendor, method);
|
sm->m = eap_method;
|
||||||
if (!sm->m) {
|
if (!sm->m) {
|
||||||
wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
|
wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
|
||||||
"vendor %d method %d",
|
"vendor %d method %d",
|
||||||
|
@ -1235,10 +1252,12 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
|
||||||
break;
|
break;
|
||||||
case EAP_CODE_SUCCESS:
|
case EAP_CODE_SUCCESS:
|
||||||
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
|
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
|
||||||
|
eap_notify_status(sm, "completion", "success");
|
||||||
sm->rxSuccess = TRUE;
|
sm->rxSuccess = TRUE;
|
||||||
break;
|
break;
|
||||||
case EAP_CODE_FAILURE:
|
case EAP_CODE_FAILURE:
|
||||||
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
|
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
|
||||||
|
eap_notify_status(sm, "completion", "failure");
|
||||||
sm->rxFailure = TRUE;
|
sm->rxFailure = TRUE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1256,6 +1275,10 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
|
||||||
char *hash_hex = NULL;
|
char *hash_hex = NULL;
|
||||||
|
|
||||||
switch (ev) {
|
switch (ev) {
|
||||||
|
case TLS_CERT_CHAIN_SUCCESS:
|
||||||
|
eap_notify_status(sm, "remote certificate verification",
|
||||||
|
"success");
|
||||||
|
break;
|
||||||
case TLS_CERT_CHAIN_FAILURE:
|
case TLS_CERT_CHAIN_FAILURE:
|
||||||
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
|
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
|
||||||
"reason=%d depth=%d subject='%s' err='%s'",
|
"reason=%d depth=%d subject='%s' err='%s'",
|
||||||
|
@ -1263,6 +1286,8 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
|
||||||
data->cert_fail.depth,
|
data->cert_fail.depth,
|
||||||
data->cert_fail.subject,
|
data->cert_fail.subject,
|
||||||
data->cert_fail.reason_txt);
|
data->cert_fail.reason_txt);
|
||||||
|
eap_notify_status(sm, "remote certificate verification",
|
||||||
|
data->cert_fail.reason_txt);
|
||||||
break;
|
break;
|
||||||
case TLS_PEER_CERTIFICATE:
|
case TLS_PEER_CERTIFICATE:
|
||||||
if (!sm->eapol_cb->notify_cert)
|
if (!sm->eapol_cb->notify_cert)
|
||||||
|
@ -1283,6 +1308,14 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
|
||||||
data->peer_cert.subject,
|
data->peer_cert.subject,
|
||||||
hash_hex, data->peer_cert.cert);
|
hash_hex, data->peer_cert.cert);
|
||||||
break;
|
break;
|
||||||
|
case TLS_ALERT:
|
||||||
|
if (data->alert.is_local)
|
||||||
|
eap_notify_status(sm, "local TLS alert",
|
||||||
|
data->alert.description);
|
||||||
|
else
|
||||||
|
eap_notify_status(sm, "remote TLS alert",
|
||||||
|
data->alert.description);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
os_free(hash_hex);
|
os_free(hash_hex);
|
||||||
|
|
|
@ -226,6 +226,15 @@ struct eapol_callbacks {
|
||||||
*/
|
*/
|
||||||
void (*notify_cert)(void *ctx, int depth, const char *subject,
|
void (*notify_cert)(void *ctx, int depth, const char *subject,
|
||||||
const char *cert_hash, const struct wpabuf *cert);
|
const char *cert_hash, const struct wpabuf *cert);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* notify_status - Notification of the current EAP state
|
||||||
|
* @ctx: eapol_ctx from eap_peer_sm_init() call
|
||||||
|
* @status: Step in the process of EAP authentication
|
||||||
|
* @parameter: Step-specific parameter, e.g., EAP method name
|
||||||
|
*/
|
||||||
|
void (*notify_status)(void *ctx, const char *status,
|
||||||
|
const char *parameter);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1847,6 +1847,17 @@ static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
|
||||||
cert_hash, cert);
|
cert_hash, cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void eapol_sm_notify_status(void *ctx, const char *status,
|
||||||
|
const char *parameter)
|
||||||
|
{
|
||||||
|
struct eapol_sm *sm = ctx;
|
||||||
|
|
||||||
|
if (sm->ctx->status_cb)
|
||||||
|
sm->ctx->status_cb(sm->ctx->ctx, status, parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct eapol_callbacks eapol_cb =
|
static struct eapol_callbacks eapol_cb =
|
||||||
{
|
{
|
||||||
eapol_sm_get_config,
|
eapol_sm_get_config,
|
||||||
|
@ -1859,7 +1870,8 @@ static struct eapol_callbacks eapol_cb =
|
||||||
eapol_sm_get_config_blob,
|
eapol_sm_get_config_blob,
|
||||||
eapol_sm_notify_pending,
|
eapol_sm_notify_pending,
|
||||||
eapol_sm_eap_param_needed,
|
eapol_sm_eap_param_needed,
|
||||||
eapol_sm_notify_cert
|
eapol_sm_notify_cert,
|
||||||
|
eapol_sm_notify_status
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -230,6 +230,15 @@ struct eapol_ctx {
|
||||||
* cert_in_cb - Include server certificates in callback
|
* cert_in_cb - Include server certificates in callback
|
||||||
*/
|
*/
|
||||||
int cert_in_cb;
|
int cert_in_cb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* status_cb - Notification of a change in EAP status
|
||||||
|
* @ctx: Callback context (ctx)
|
||||||
|
* @status: Step in the process of EAP authentication
|
||||||
|
* @parameter: Step-specific parameter, e.g., EAP method name
|
||||||
|
*/
|
||||||
|
void (*status_cb)(void *ctx, const char *status,
|
||||||
|
const char *parameter);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -840,6 +840,41 @@ nomem:
|
||||||
dbus_message_unref(msg);
|
dbus_message_unref(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
|
||||||
|
const char *status, const char *parameter)
|
||||||
|
{
|
||||||
|
struct wpas_dbus_priv *iface;
|
||||||
|
DBusMessage *msg;
|
||||||
|
DBusMessageIter iter;
|
||||||
|
|
||||||
|
iface = wpa_s->global->dbus;
|
||||||
|
|
||||||
|
/* Do nothing if the control interface is not turned on */
|
||||||
|
if (iface == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
msg = dbus_message_new_signal(wpa_s->dbus_new_path,
|
||||||
|
WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||||
|
"EAP");
|
||||||
|
if (msg == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(msg, &iter);
|
||||||
|
|
||||||
|
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &status)
|
||||||
|
||
|
||||||
|
!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
|
||||||
|
¶meter))
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
|
dbus_connection_send(iface->con, msg, NULL);
|
||||||
|
|
||||||
|
nomem:
|
||||||
|
dbus_message_unref(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2934,6 +2969,13 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
|
||||||
END_ARGS
|
END_ARGS
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{ "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||||
|
{
|
||||||
|
{ "status", "s", ARG_OUT },
|
||||||
|
{ "parameter", "s", ARG_OUT },
|
||||||
|
END_ARGS
|
||||||
|
}
|
||||||
|
},
|
||||||
{ NULL, NULL, { END_ARGS } }
|
{ NULL, NULL, { END_ARGS } }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -224,6 +224,8 @@ void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
|
||||||
void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
|
void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *addr, const u8 *dst, const u8 *bssid,
|
const u8 *addr, const u8 *dst, const u8 *bssid,
|
||||||
const u8 *ie, size_t ie_len, u32 ssi_signal);
|
const u8 *ie, size_t ie_len, u32 ssi_signal);
|
||||||
|
void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
|
||||||
|
const char *status, const char *parameter);
|
||||||
|
|
||||||
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
||||||
|
|
||||||
|
@ -489,6 +491,12 @@ static inline void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
|
||||||
|
const char *status,
|
||||||
|
const char *parameter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
||||||
|
|
||||||
#endif /* CTRL_IFACE_DBUS_H_NEW */
|
#endif /* CTRL_IFACE_DBUS_H_NEW */
|
||||||
|
|
|
@ -612,3 +612,10 @@ void wpas_notify_preq(struct wpa_supplicant *wpa_s,
|
||||||
wpas_dbus_signal_preq(wpa_s, addr, dst, bssid, ie, ie_len, ssi_signal);
|
wpas_dbus_signal_preq(wpa_s, addr, dst, bssid, ie, ie_len, ssi_signal);
|
||||||
#endif /* CONFIG_AP */
|
#endif /* CONFIG_AP */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status,
|
||||||
|
const char *parameter)
|
||||||
|
{
|
||||||
|
wpas_dbus_signal_eap_status(wpa_s, status, parameter);
|
||||||
|
}
|
||||||
|
|
|
@ -124,5 +124,7 @@ void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth,
|
||||||
void wpas_notify_preq(struct wpa_supplicant *wpa_s,
|
void wpas_notify_preq(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *addr, const u8 *dst, const u8 *bssid,
|
const u8 *addr, const u8 *dst, const u8 *bssid,
|
||||||
const u8 *ie, size_t ie_len, u32 ssi_signal);
|
const u8 *ie, size_t ie_len, u32 ssi_signal);
|
||||||
|
void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status,
|
||||||
|
const char *parameter);
|
||||||
|
|
||||||
#endif /* NOTIFY_H */
|
#endif /* NOTIFY_H */
|
||||||
|
|
|
@ -720,6 +720,15 @@ static void wpa_supplicant_cert_cb(void *ctx, int depth, const char *subject,
|
||||||
|
|
||||||
wpas_notify_certification(wpa_s, depth, subject, cert_hash, cert);
|
wpas_notify_certification(wpa_s, depth, subject, cert_hash, cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpa_supplicant_status_cb(void *ctx, const char *status,
|
||||||
|
const char *parameter)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s = ctx;
|
||||||
|
|
||||||
|
wpas_notify_eap_status(wpa_s, status, parameter);
|
||||||
|
}
|
||||||
#endif /* IEEE8021X_EAPOL */
|
#endif /* IEEE8021X_EAPOL */
|
||||||
|
|
||||||
|
|
||||||
|
@ -751,6 +760,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
|
||||||
ctx->port_cb = wpa_supplicant_port_cb;
|
ctx->port_cb = wpa_supplicant_port_cb;
|
||||||
ctx->cb = wpa_supplicant_eapol_cb;
|
ctx->cb = wpa_supplicant_eapol_cb;
|
||||||
ctx->cert_cb = wpa_supplicant_cert_cb;
|
ctx->cert_cb = wpa_supplicant_cert_cb;
|
||||||
|
ctx->status_cb = wpa_supplicant_status_cb;
|
||||||
ctx->cb_ctx = wpa_s;
|
ctx->cb_ctx = wpa_s;
|
||||||
wpa_s->eapol = eapol_sm_init(ctx);
|
wpa_s->eapol = eapol_sm_init(ctx);
|
||||||
if (wpa_s->eapol == NULL) {
|
if (wpa_s->eapol == NULL) {
|
||||||
|
|
Loading…
Reference in a new issue