[PATCH] wpa_supplicant: Report EAP connection progress to DBus
Paul Stewart
pstew
Thu May 31 18:29:26 PDT 2012
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 at chromium.org>
---
src/crypto/tls.h | 10 +++++++++-
src/crypto/tls_openssl.c | 13 +++++++++++++
src/eap_peer/eap.c | 36 +++++++++++++++++++++++++++++++++---
src/eap_peer/eap.h | 9 +++++++++
src/eapol_supp/eapol_supp_sm.c | 12 +++++++++++-
src/eapol_supp/eapol_supp_sm.h | 8 ++++++++
wpa_supplicant/dbus/dbus_new.c | 40 ++++++++++++++++++++++++++++++++++++++++
wpa_supplicant/dbus/dbus_new.h | 9 +++++++++
wpa_supplicant/notify.c | 6 +++++-
wpa_supplicant/notify.h | 2 ++
wpa_supplicant/wpas_glue.c | 10 ++++++++++
11 files changed, 149 insertions(+), 6 deletions(-)
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 2bd3bbb..990f6e6 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -21,8 +21,10 @@ struct tls_keys {
};
enum tls_event {
+ TLS_CERT_CHAIN_SUCCESS,
TLS_CERT_CHAIN_FAILURE,
- TLS_PEER_CERTIFICATE
+ TLS_PEER_CERTIFICATE,
+ TLS_ALERT
};
/*
@@ -57,6 +59,12 @@ union tls_event_data {
const u8 *hash;
size_t hash_len;
} peer_cert;
+
+ struct {
+ int is_local;
+ const char *type;
+ const char *description;
+ } alert;
};
struct tls_config {
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 772f0b2..3bbd457 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -525,6 +525,15 @@ static void ssl_info_cb(const SSL *ssl, int where, int ret)
else
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) {
wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
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);
}
+ if (preverify_ok && tls_global->event_cb != NULL)
+ tls_global->event_cb(tls_global->cb_ctx,
+ TLS_CERT_CHAIN_SUCCESS, NULL);
+
return preverify_ok;
}
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 50a7797..08afb2c 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -48,7 +48,6 @@ static const char * eap_sm_decision_txt(EapDecision decision);
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
-
static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
{
return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
@@ -81,6 +80,14 @@ 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)
+{
+ 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)
{
if (sm->m == NULL || sm->eap_method_priv == NULL)
@@ -213,6 +220,7 @@ SM_STATE(EAP, GET_METHOD)
{
int reinit;
EapType method;
+ const struct eap_method *eap_method;
SM_ENTRY(EAP, GET_METHOD);
@@ -221,18 +229,24 @@ SM_STATE(EAP, GET_METHOD)
else
method = sm->reqMethod;
+ eap_method = eap_peer_get_eap_method(sm->reqVendor, method);
+
if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
sm->reqVendor, method);
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
"vendor=%u method=%u -> NAK",
sm->reqVendor, method);
+ eap_notify_status(sm, "refuse proposed method",
+ eap_method ? eap_method->name : "unknown");
goto nak;
}
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_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
* re-authentication (session resumption). The design here is to allow
@@ -256,7 +270,7 @@ SM_STATE(EAP, GET_METHOD)
sm->selectedMethod = sm->reqMethod;
if (sm->m == NULL)
- sm->m = eap_peer_get_eap_method(sm->reqVendor, method);
+ sm->m = eap_method;
if (!sm->m) {
wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
"vendor %d method %d",
@@ -1235,10 +1249,12 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
break;
case EAP_CODE_SUCCESS:
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
+ eap_notify_status(sm, "completion", "success");
sm->rxSuccess = TRUE;
break;
case EAP_CODE_FAILURE:
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
+ eap_notify_status(sm, "completion", "failure");
sm->rxFailure = TRUE;
break;
default:
@@ -1248,7 +1264,6 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
}
}
-
static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
union tls_event_data *data)
{
@@ -1256,6 +1271,10 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
char *hash_hex = NULL;
switch (ev) {
+ case TLS_CERT_CHAIN_SUCCESS:
+ eap_notify_status(sm, "remote certificate verification",
+ "success");
+ break;
case TLS_CERT_CHAIN_FAILURE:
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
"reason=%d depth=%d subject='%s' err='%s'",
@@ -1263,6 +1282,8 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
data->cert_fail.depth,
data->cert_fail.subject,
data->cert_fail.reason_txt);
+ eap_notify_status(sm, "remote certificate verification",
+ data->cert_fail.reason_txt);
break;
case TLS_PEER_CERTIFICATE:
if (!sm->eapol_cb->notify_cert)
@@ -1283,6 +1304,15 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
data->peer_cert.subject,
hash_hex, data->peer_cert.cert);
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);
diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h
index b95a285..6e87475 100644
--- a/src/eap_peer/eap.h
+++ b/src/eap_peer/eap.h
@@ -226,6 +226,15 @@ struct eapol_callbacks {
*/
void (*notify_cert)(void *ctx, int depth, const char *subject,
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);
};
/**
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index c83709f..6814c5c 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -1847,6 +1847,15 @@ static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
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 =
{
eapol_sm_get_config,
@@ -1859,7 +1868,8 @@ static struct eapol_callbacks eapol_cb =
eapol_sm_get_config_blob,
eapol_sm_notify_pending,
eapol_sm_eap_param_needed,
- eapol_sm_notify_cert
+ eapol_sm_notify_cert,
+ eapol_sm_notify_status
};
diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h
index 3260c61..ad23d9d 100644
--- a/src/eapol_supp/eapol_supp_sm.h
+++ b/src/eapol_supp/eapol_supp_sm.h
@@ -230,6 +230,14 @@ struct eapol_ctx {
* cert_in_cb - Include server certificates in callback
*/
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);
};
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 1760dd2..ca77011 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -840,6 +840,39 @@ nomem:
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
/**
@@ -2934,6 +2967,13 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
END_ARGS
}
},
+ { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "status", "s", ARG_OUT },
+ { "parameter", "s", ARG_OUT },
+ END_ARGS
+ }
+ },
{ NULL, NULL, { END_ARGS } }
};
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index a2d7011..cd240b2 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -224,6 +224,9 @@ void wpas_dbus_signal_certification(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 *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 */
@@ -489,6 +492,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 /* CTRL_IFACE_DBUS_H_NEW */
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index d471dfb..6b5222a 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -603,7 +603,6 @@ void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth,
wpas_dbus_signal_certification(wpa_s, depth, subject, cert_hash, cert);
}
-
void wpas_notify_preq(struct wpa_supplicant *wpa_s,
const u8 *addr, const u8 *dst, const u8 *bssid,
const u8 *ie, size_t ie_len, u32 ssi_signal)
@@ -612,3 +611,8 @@ void wpas_notify_preq(struct wpa_supplicant *wpa_s,
wpas_dbus_signal_preq(wpa_s, addr, dst, bssid, ie, ie_len, ssi_signal);
#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);
+}
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index 0c483bc..e2bf788 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -124,5 +124,7 @@ void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth,
void wpas_notify_preq(struct wpa_supplicant *wpa_s,
const u8 *addr, const u8 *dst, const u8 *bssid,
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 */
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 5b9dc9e..fb4fa22 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -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);
}
+
+
+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 */
@@ -751,6 +760,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
ctx->port_cb = wpa_supplicant_port_cb;
ctx->cb = wpa_supplicant_eapol_cb;
ctx->cert_cb = wpa_supplicant_cert_cb;
+ ctx->status_cb = wpa_supplicant_status_cb;
ctx->cb_ctx = wpa_s;
wpa_s->eapol = eapol_sm_init(ctx);
if (wpa_s->eapol == NULL) {
--
1.7.7.3
More information about the Hostap
mailing list