From aac00bf33a266508862cc3a47bcbf56e01ad1ebd Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Fri, 22 Jun 2018 11:13:27 -0700 Subject: [PATCH] handshake: remove handshake related netdev events Handshake related netdev events were removed in favor of handshake events. Now events will be emitted on the handshake object related to the 4-way handshake and key settings. Events are: HANDSHAKE_EVENT_STARTED HANDSHAKE_EVENT_SETTING_KEYS HANDSHAKE_EVENT_COMPLETE HANDSHAKE_EVENT_FAILED Right now, since netdev only operates in station mode, nothing listens for COMPLETE/FAILED, as device/wsc gets notified by the connect_cb when the connection was successful. The COMPLETE/ FAILED were added in preperation for AP moving into eapol/netdev. --- src/device.c | 42 ++++++++++++++++++++++++++++++------------ src/eapol.c | 4 ++++ src/handshake.c | 22 +++++++++++++++++----- src/handshake.h | 21 ++++++++++++++++++++- src/netdev.c | 15 ++++----------- src/netdev.h | 2 -- src/wsc.c | 3 --- 7 files changed, 75 insertions(+), 34 deletions(-) diff --git a/src/device.c b/src/device.c index 7899d9a4..2bed2efc 100644 --- a/src/device.c +++ b/src/device.c @@ -640,6 +640,34 @@ static enum ie_rsn_akm_suite device_select_akm_suite(struct network *network, return 0; } +static void device_handshake_event(struct handshake_state *hs, + enum handshake_event event, + void *event_data, void *user_data) +{ + struct device *device = user_data; + struct network *network = device->connected_network; + + switch (event) { + case HANDSHAKE_EVENT_STARTED: + l_debug("Handshaking"); + break; + case HANDSHAKE_EVENT_SETTING_KEYS: + l_debug("Setting keys"); + + /* If we got here, then our PSK works. Save if required */ + network_sync_psk(network); + break; + case HANDSHAKE_EVENT_COMPLETE: + case HANDSHAKE_EVENT_FAILED: + /* + * currently we dont care about any other events. The + * netdev_connect_cb will notify us when the connection is + * complete. + */ + break; + } +} + static struct handshake_state *device_handshake_setup(struct device *device, struct network *network, struct scan_bss *bss) @@ -651,6 +679,8 @@ static struct handshake_state *device_handshake_setup(struct device *device, hs = netdev_handshake_state_new(device->netdev); + handshake_state_set_event_func(hs, device_handshake_event, device); + if (security == SECURITY_PSK || security == SECURITY_8021X) { const struct l_settings *settings = iwd_get_config(); struct ie_rsn_info bss_info; @@ -1579,12 +1609,10 @@ static void device_signal_agent_release(struct signal_agent *agent, l_dbus_send(dbus_get_bus(), msg); } - static void device_netdev_event(struct netdev *netdev, enum netdev_event event, void *user_data) { struct device *device = user_data; - struct network *network = device->connected_network; switch (event) { case NETDEV_EVENT_AUTHENTICATING: @@ -1592,16 +1620,6 @@ static void device_netdev_event(struct netdev *netdev, enum netdev_event event, break; case NETDEV_EVENT_ASSOCIATING: l_debug("Associating"); - break; - case NETDEV_EVENT_4WAY_HANDSHAKE: - l_debug("Handshaking"); - break; - case NETDEV_EVENT_SETTING_KEYS: - l_debug("Setting keys"); - - /* If we got here, then our PSK works. Save if required */ - network_sync_psk(network); - break; case NETDEV_EVENT_LOST_BEACON: device_lost_beacon(device); diff --git a/src/eapol.c b/src/eapol.c index f822ced6..fc3ce20c 100644 --- a/src/eapol.c +++ b/src/eapol.c @@ -740,6 +740,8 @@ static void eapol_sm_write(struct eapol_sm *sm, const struct eapol_frame *ef, static inline void handshake_failed(struct eapol_sm *sm, uint16_t reason_code) { + handshake_event(sm->handshake, HANDSHAKE_EVENT_FAILED, &reason_code); + if (deauthenticate) deauthenticate(sm->handshake->ifindex, sm->handshake->aa, sm->handshake->spa, @@ -799,6 +801,8 @@ static void send_eapol_start(struct l_timeout *timeout, void *user_data) uint8_t buf[sizeof(struct eapol_frame)]; struct eapol_frame *frame = (struct eapol_frame *) buf; + handshake_event(sm->handshake, HANDSHAKE_EVENT_STARTED, NULL); + l_timeout_remove(sm->eapol_start_timeout); sm->eapol_start_timeout = NULL; diff --git a/src/handshake.c b/src/handshake.c index 2dd58a26..fe225c94 100644 --- a/src/handshake.c +++ b/src/handshake.c @@ -187,11 +187,6 @@ bool handshake_state_set_own_wpa(struct handshake_state *s, return handshake_state_setup_own_ciphers(s, &info); } -void handshake_state_set_user_data(struct handshake_state *s, void *user_data) -{ - s->user_data = user_data; -} - void handshake_state_set_ssid(struct handshake_state *s, const uint8_t *ssid, size_t ssid_len) { @@ -225,6 +220,14 @@ void handshake_state_set_kh_ids(struct handshake_state *s, memcpy(s->r1khid, r1khid, 6); } +void handshake_state_set_event_func(struct handshake_state *s, + handshake_event_func_t func, + void *user_data) +{ + s->event_func = func; + s->user_data = user_data; +} + void handshake_state_new_snonce(struct handshake_state *s) { get_nonce(s->snonce); @@ -336,6 +339,8 @@ void handshake_state_install_ptk(struct handshake_state *s) uint32_t cipher = ie_rsn_cipher_suite_to_cipher( s->pairwise_cipher); + handshake_event(s, HANDSHAKE_EVENT_SETTING_KEYS, NULL); + install_tk(s, ptk->tk, cipher); } } @@ -622,3 +627,10 @@ bool handshake_decode_fte_key(struct handshake_state *s, const uint8_t *wrapped, return true; } + +void handshake_event(struct handshake_state *hs, + enum handshake_event event, void *event_data) +{ + if (hs->event_func) + hs->event_func(hs, event, event_data, hs->user_data); +} diff --git a/src/handshake.h b/src/handshake.h index 94bdec20..97f6233b 100644 --- a/src/handshake.h +++ b/src/handshake.h @@ -42,6 +42,17 @@ enum handshake_kde { HANDSHAKE_KDE_MULTIBAND_KEY_ID = 0x000fac0c, }; +enum handshake_event { + HANDSHAKE_EVENT_STARTED, + HANDSHAKE_EVENT_SETTING_KEYS, + HANDSHAKE_EVENT_COMPLETE, + HANDSHAKE_EVENT_FAILED +}; + +typedef void (*handshake_event_func_t)(struct handshake_state *hs, + enum handshake_event event, + void *event_data, void *user_data); + typedef bool (*handshake_get_nonce_func_t)(uint8_t nonce[]); typedef void (*handshake_install_tk_func_t)(struct handshake_state *hs, const uint8_t *tk, uint32_t cipher); @@ -96,6 +107,8 @@ struct handshake_state { void *user_data; void (*free)(struct handshake_state *s); + + handshake_event_func_t event_func; }; void handshake_state_free(struct handshake_state *s); @@ -104,7 +117,6 @@ void handshake_state_set_supplicant_address(struct handshake_state *s, const uint8_t *spa); void handshake_state_set_authenticator_address(struct handshake_state *s, const uint8_t *aa); -void handshake_state_set_user_data(struct handshake_state *s, void *user_data); void handshake_state_set_pmk(struct handshake_state *s, const uint8_t *pmk, size_t pmk_len); void handshake_state_set_8021x_config(struct handshake_state *s, @@ -128,6 +140,10 @@ void handshake_state_set_kh_ids(struct handshake_state *s, const uint8_t *r0khid, size_t r0khid_len, const uint8_t *r1khid); +void handshake_state_set_event_func(struct handshake_state *s, + handshake_event_func_t func, + void *user_data); + void handshake_state_new_snonce(struct handshake_state *s); void handshake_state_new_anonce(struct handshake_state *s); void handshake_state_set_anonce(struct handshake_state *s, @@ -164,3 +180,6 @@ const uint8_t *handshake_util_find_igtk_kde(const uint8_t *data, size_t data_len, size_t *out_igtk_len); const uint8_t *handshake_util_find_pmkid_kde(const uint8_t *data, size_t data_len); + +void handshake_event(struct handshake_state *hs, enum handshake_event event, + void *event_data); diff --git a/src/netdev.c b/src/netdev.c index 0fa4a1d0..b6fc86bf 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -943,6 +943,7 @@ static void netdev_setting_keys_failed(struct netdev_handshake_state *nhs, nhs->set_station_cmd_id = 0; netdev->result = NETDEV_RESULT_KEY_SETTING_FAILED; + msg = netdev_build_cmd_disconnect(netdev, MMPDU_REASON_CODE_UNSPECIFIED); netdev->disconnect_cmd_id = l_genl_family_send(nl80211, msg, @@ -972,6 +973,8 @@ static void netdev_set_station_cb(struct l_genl_msg *msg, void *user_data) return; } + handshake_event(&nhs->super, HANDSHAKE_EVENT_COMPLETE, NULL); + done: netdev_connect_ok(netdev); } @@ -1248,10 +1251,6 @@ static void netdev_set_tk(struct handshake_state *hs, l_debug("%d", netdev->index); - if (netdev->event_filter) - netdev->event_filter(netdev, NETDEV_EVENT_SETTING_KEYS, - netdev->user_data); - rc = MMPDU_REASON_CODE_INVALID_PAIRWISE_CIPHER; if (!netdev_copy_tk(tk_buf, tk, cipher, false)) goto invalid_key; @@ -1599,14 +1598,8 @@ static void netdev_connect_event(struct l_genl_msg *msg, if (!eapol_start(netdev->sm)) goto error; - if (!netdev->in_ft) { - if (netdev->event_filter) - netdev->event_filter(netdev, - NETDEV_EVENT_4WAY_HANDSHAKE, - netdev->user_data); - + if (!netdev->in_ft) return; - } } if (netdev->in_ft) { diff --git a/src/netdev.h b/src/netdev.h index 1f1ee45c..938dac96 100644 --- a/src/netdev.h +++ b/src/netdev.h @@ -40,8 +40,6 @@ enum netdev_result { enum netdev_event { NETDEV_EVENT_AUTHENTICATING, NETDEV_EVENT_ASSOCIATING, - NETDEV_EVENT_4WAY_HANDSHAKE, - NETDEV_EVENT_SETTING_KEYS, NETDEV_EVENT_LOST_BEACON, NETDEV_EVENT_DISCONNECT_BY_AP, NETDEV_EVENT_DISCONNECT_BY_SME, diff --git a/src/wsc.c b/src/wsc.c index 99524a9f..74ec0cbd 100644 --- a/src/wsc.c +++ b/src/wsc.c @@ -367,9 +367,6 @@ static void wsc_netdev_event(struct netdev *netdev, enum netdev_event event, case NETDEV_EVENT_AUTHENTICATING: case NETDEV_EVENT_ASSOCIATING: break; - case NETDEV_EVENT_4WAY_HANDSHAKE: - l_info("Running EAP-WSC"); - break; case NETDEV_EVENT_LOST_BEACON: l_debug("Lost beacon"); break;