]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wpa_supplicant: Report EAP connection progress to DBus
authorPaul Stewart <pstew@chromium.org>
Mon, 4 Jun 2012 18:10:01 +0000 (21:10 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 4 Jun 2012 18:10:01 +0000 (21:10 +0300)
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>

src/crypto/tls.h
src/crypto/tls_openssl.c
src/eap_peer/eap.c
src/eap_peer/eap.h
src/eapol_supp/eapol_supp_sm.c
src/eapol_supp/eapol_supp_sm.h
wpa_supplicant/dbus/dbus_new.c
wpa_supplicant/dbus/dbus_new.h
wpa_supplicant/notify.c
wpa_supplicant/notify.h
wpa_supplicant/wpas_glue.c

index 2bd3bbbb0f3e9098c74c408d02ffde48e8b1f618..990f6e6eda1f37aa6bb6435e23467db8c5241d4f 100644 (file)
@@ -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 {
index 772f0b2f1ea5b9aff156e8aa7bf226c92e3e47d8..3bbd457063bf05593e8dafbf84f18bd998c4c602 100644 (file)
@@ -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;
 }
 
index 50a7797863018a4172569429bd80490ccf2916b0..8b43be4386a7cffbb52e474205ba487f87dc1577 100644 (file)
@@ -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)
 {
        if (sm->m == NULL || sm->eap_method_priv == NULL)
@@ -213,6 +223,7 @@ SM_STATE(EAP, GET_METHOD)
 {
        int reinit;
        EapType method;
+       const struct eap_method *eap_method;
 
        SM_ENTRY(EAP, GET_METHOD);
 
@@ -221,18 +232,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 +273,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 +1252,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:
@@ -1256,6 +1275,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 +1286,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 +1308,14 @@ 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);
index b95a285e59a0c62b348f8edb44277d275d33a704..6e87475d35e227fca2c490731d790dccb45894b8 100644 (file)
@@ -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);
 };
 
 /**
index c83709f86445a09cb5f2d2ef7030875863cf9f93..f0cae700d68cef9024c45b8a3b73238d9addd88f 100644 (file)
@@ -1847,6 +1847,17 @@ 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 +1870,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
 };
 
 
index 3260c614810bb24dd426ee620d1bd3fd70882a9f..1a20e4b98fd238d52bbfa18b5ff747940e8a0df0 100644 (file)
@@ -230,6 +230,15 @@ 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);
 };
 
 
index 1760dd2e324488ea3c6e32625c43e0f814310b3c..f7393d9343079f535ff5817267002e422718fb77 100644 (file)
@@ -840,6 +840,41 @@ 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,
+                                           &parameter))
+               goto nomem;
+
+       dbus_connection_send(iface->con, msg, NULL);
+
+nomem:
+       dbus_message_unref(msg);
+}
+
+
 #ifdef CONFIG_P2P
 
 /**
@@ -2934,6 +2969,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 } }
 };
 
index a2d701139df8c29ea3880523989ca905557bb2e8..4d322a1e84b6e9f93e34faa36e0259be45c92245 100644 (file)
@@ -224,6 +224,8 @@ 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 +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 /* CTRL_IFACE_DBUS_H_NEW */
index d471dfb16f84abb8e264e253c9002b8d227c3cc8..c4d7e939fc2b01073a20e47e144223ab18547f1e 100644 (file)
@@ -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);
 #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);
+}
index 0c483bc13f52c4458f8ec42ed0157532ebbcd536..e2bf788422e0fdae8d1e2b8e461a3470980865af 100644 (file)
@@ -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 */
index 5b9dc9ee5d2845462cb4200390a53a4e97660888..fb4fa224498c7520c87b29b0a8242afd6b97c7a8 100644 (file)
@@ -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) {