diff --git a/src/netdev.c b/src/netdev.c index dcba5439..487b080f 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -50,6 +50,7 @@ #include "src/netdev.h" #include "src/wscutil.h" #include "src/ftutil.h" +#include "src/util.h" struct netdev { uint32_t index; @@ -87,6 +88,12 @@ struct netdev { bool in_ft : 1; }; +struct netdev_preauth_state { + netdev_preauthenticate_cb_t cb; + void *user_data; + struct netdev *netdev; +}; + struct netdev_watch { uint32_t id; netdev_watch_func_t callback; @@ -281,6 +288,17 @@ static void netdev_operstate_down_cb(bool success, void *user_data) l_debug("netdev: %d, success: %d", index, success); } +static void netdev_preauth_destroy(void *data) +{ + struct netdev_preauth_state *state = data; + + if (state->cb) + state->cb(state->netdev, NETDEV_RESULT_ABORTED, NULL, + state->user_data); + + l_free(state); +} + static void netdev_connect_free(struct netdev *netdev) { if (netdev->sm) { @@ -288,6 +306,8 @@ static void netdev_connect_free(struct netdev *netdev) netdev->sm = NULL; } + eapol_preauth_cancel(netdev->index); + if (netdev->handshake) { handshake_state_free(netdev->handshake); netdev->handshake = NULL; @@ -1039,7 +1059,7 @@ static void netdev_handshake_failed(uint32_t ifindex, if (!netdev) return; - l_error("4-Way Handshake failed for ifindex: %d", ifindex); + l_error("4-Way handshake failed for ifindex: %d", ifindex); netdev->sm = NULL; @@ -2340,6 +2360,43 @@ restore_snonce: return err; } +static void netdev_preauth_cb(const uint8_t *pmk, void *user_data) +{ + struct netdev_preauth_state *preauth = user_data; + netdev_preauthenticate_cb_t cb = preauth->cb; + + preauth->cb = NULL; + + cb(preauth->netdev, + pmk ? NETDEV_RESULT_OK : NETDEV_RESULT_HANDSHAKE_FAILED, + pmk, preauth->user_data); +} + +int netdev_preauthenticate(struct netdev *netdev, struct scan_bss *target_bss, + netdev_preauthenticate_cb_t cb, void *user_data) +{ + struct netdev_preauth_state *preauth; + + if (!netdev->operational) + return -ENOTCONN; + + preauth = l_new(struct netdev_preauth_state, 1); + + if (!eapol_preauth_start(target_bss->addr, netdev->handshake, + netdev_preauth_cb, preauth, + netdev_preauth_destroy)) { + l_free(preauth); + + return -EIO; + } + + preauth->cb = cb; + preauth->user_data = user_data; + preauth->netdev = netdev; + + return 0; +} + static uint32_t netdev_send_action_frame(struct netdev *netdev, const uint8_t *to, const uint8_t *body, size_t body_len, diff --git a/src/netdev.h b/src/netdev.h index 64f2981d..c35fcba2 100644 --- a/src/netdev.h +++ b/src/netdev.h @@ -76,6 +76,9 @@ typedef void (*netdev_eapol_event_func_t)(unsigned int event, typedef void (*netdev_neighbor_report_cb_t)(struct netdev *netdev, int err, const uint8_t *reports, size_t reports_len, void *user_data); +typedef void (*netdev_preauthenticate_cb_t)(struct netdev *netdev, + enum netdev_result result, + const uint8_t *pmk, void *user_data); const uint8_t *netdev_get_address(struct netdev *netdev); uint32_t netdev_get_ifindex(struct netdev *netdev); @@ -101,6 +104,9 @@ int netdev_reassociate(struct netdev *netdev, struct scan_bss *target_bss, netdev_connect_cb_t cb); int netdev_fast_transition(struct netdev *netdev, struct scan_bss *target_bss, netdev_connect_cb_t cb); +int netdev_preauthenticate(struct netdev *netdev, struct scan_bss *target_bss, + netdev_preauthenticate_cb_t cb, + void *user_data); int netdev_set_powered(struct netdev *netdev, bool powered, netdev_set_powered_cb_t cb, void *user_data,