X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=wpa_supplicant%2Fwpa_priv.c;h=511df4f18148e4d495da9d89859b8028c6d53a50;hp=d361bdb2ebd15db2b8180561c475fef08c16925d;hb=6013bbe04f138f7d5d750a3e1939732cbde0426a;hpb=d01136a06eaeec50d73ce5e524e0171ad5369a4c diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c index d361bdb..511df4f 100644 --- a/wpa_supplicant/wpa_priv.c +++ b/wpa_supplicant/wpa_priv.c @@ -29,6 +29,8 @@ struct wpa_priv_interface { char *sock_name; int fd; + void *ctx; + const struct wpa_driver_ops *driver; void *drv_priv; void *drv_global_priv; @@ -40,6 +42,10 @@ struct wpa_priv_interface { struct sockaddr_un l2_addr; }; +struct wpa_priv_global { + struct wpa_priv_interface *interfaces; +}; + static void wpa_priv_cmd_register(struct wpa_priv_interface *iface, struct sockaddr_un *from) @@ -65,7 +71,8 @@ static void wpa_priv_cmd_register(struct wpa_priv_interface *iface, if (iface->driver->init2) { if (iface->driver->global_init) { - iface->drv_global_priv = iface->driver->global_init(); + iface->drv_global_priv = + iface->driver->global_init(iface->ctx); if (!iface->drv_global_priv) { wpa_printf(MSG_INFO, "Failed to initialize driver global context"); @@ -195,6 +202,58 @@ static void wpa_priv_cmd_get_scan_results(struct wpa_priv_interface *iface, } +static void wpa_priv_cmd_authenticate(struct wpa_priv_interface *iface, + void *buf, size_t len) +{ + struct wpa_driver_auth_params params; + struct privsep_cmd_authenticate *auth; + int res, i; + + if (iface->drv_priv == NULL || iface->driver->authenticate == NULL) + return; + + if (len < sizeof(*auth)) { + wpa_printf(MSG_DEBUG, "Invalid authentication request"); + return; + } + + auth = buf; + if (sizeof(*auth) + auth->ie_len + auth->sae_data_len > len) { + wpa_printf(MSG_DEBUG, "Authentication request overflow"); + return; + } + + os_memset(¶ms, 0, sizeof(params)); + params.freq = auth->freq; + params.bssid = auth->bssid; + params.ssid = auth->ssid; + if (auth->ssid_len > SSID_MAX_LEN) + return; + params.ssid_len = auth->ssid_len; + params.auth_alg = auth->auth_alg; + for (i = 0; i < 4; i++) { + if (auth->wep_key_len[i]) { + params.wep_key[i] = auth->wep_key[i]; + params.wep_key_len[i] = auth->wep_key_len[i]; + } + } + params.wep_tx_keyidx = auth->wep_tx_keyidx; + params.local_state_change = auth->local_state_change; + params.p2p = auth->p2p; + if (auth->ie_len) { + params.ie = (u8 *) (auth + 1); + params.ie_len = auth->ie_len; + } + if (auth->sae_data_len) { + params.sae_data = ((u8 *) (auth + 1)) + auth->ie_len; + params.sae_data_len = auth->sae_data_len; + } + + res = iface->driver->authenticate(iface->drv_priv, ¶ms); + wpa_printf(MSG_DEBUG, "drv->authenticate: res=%d", res); +} + + static void wpa_priv_cmd_associate(struct wpa_priv_interface *iface, void *buf, size_t len) { @@ -557,6 +616,9 @@ static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx) pos[cmd_len] = '\0'; wpa_priv_cmd_set_country(iface, pos); break; + case PRIVSEP_CMD_AUTHENTICATE: + wpa_priv_cmd_authenticate(iface, cmd_buf, cmd_len); + break; } } @@ -583,7 +645,7 @@ static void wpa_priv_interface_deinit(struct wpa_priv_interface *iface) static struct wpa_priv_interface * -wpa_priv_interface_init(const char *dir, const char *params) +wpa_priv_interface_init(void *ctx, const char *dir, const char *params) { struct wpa_priv_interface *iface; char *pos; @@ -599,6 +661,7 @@ wpa_priv_interface_init(const char *dir, const char *params) if (iface == NULL) return NULL; iface->fd = -1; + iface->ctx = ctx; len = pos - params; iface->driver_name = dup_binstr(params, len); @@ -726,6 +789,36 @@ static int wpa_priv_send_event(struct wpa_priv_interface *iface, int event, } +static void wpa_priv_send_auth(struct wpa_priv_interface *iface, + union wpa_event_data *data) +{ + size_t buflen = sizeof(struct privsep_event_auth) + data->auth.ies_len; + struct privsep_event_auth *auth; + u8 *buf, *pos; + + buf = os_malloc(buflen); + if (buf == NULL) + return; + + auth = (struct privsep_event_auth *) buf; + pos = (u8 *) (auth + 1); + + os_memcpy(auth->peer, data->auth.peer, ETH_ALEN); + os_memcpy(auth->bssid, data->auth.bssid, ETH_ALEN); + auth->auth_type = data->auth.auth_type; + auth->auth_transaction = data->auth.auth_transaction; + auth->status_code = data->auth.status_code; + if (data->auth.ies) { + os_memcpy(pos, data->auth.ies, data->auth.ies_len); + auth->ies_len = data->auth.ies_len; + } + + wpa_priv_send_event(iface, PRIVSEP_EVENT_AUTH, buf, buflen); + + os_free(buf); +} + + static void wpa_priv_send_assoc(struct wpa_priv_interface *iface, int event, union wpa_event_data *data) { @@ -879,6 +972,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, &data->michael_mic_failure.unicast, sizeof(int)); break; + case EVENT_SCAN_STARTED: + wpa_priv_send_event(iface, PRIVSEP_EVENT_SCAN_STARTED, NULL, + 0); + break; case EVENT_SCAN_RESULTS: wpa_priv_send_event(iface, PRIVSEP_EVENT_SCAN_RESULTS, NULL, 0); @@ -902,6 +999,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, case EVENT_FT_RESPONSE: wpa_priv_send_ft_response(iface, data); break; + case EVENT_AUTH: + wpa_priv_send_auth(iface, data); + break; default: wpa_printf(MSG_DEBUG, "Unsupported driver event %d (%s) - TODO", event, event_to_string(event)); @@ -910,6 +1010,37 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, } +void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event, + union wpa_event_data *data) +{ + struct wpa_priv_global *global = ctx; + struct wpa_priv_interface *iface; + + if (event != EVENT_INTERFACE_STATUS) + return; + + for (iface = global->interfaces; iface; iface = iface->next) { + if (os_strcmp(iface->ifname, data->interface_status.ifname) == + 0) + break; + } + if (iface && iface->driver->get_ifindex) { + unsigned int ifindex; + + ifindex = iface->driver->get_ifindex(iface->drv_priv); + if (ifindex != data->interface_status.ifindex) { + wpa_printf(MSG_DEBUG, + "%s: interface status ifindex %d mismatch (%d)", + iface->ifname, ifindex, + data->interface_status.ifindex); + return; + } + } + if (iface) + wpa_supplicant_event(iface, event, data); +} + + void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) { @@ -968,7 +1099,7 @@ static void wpa_priv_fd_workaround(void) static void usage(void) { printf("wpa_priv v" VERSION_STR "\n" - "Copyright (c) 2007-2009, Jouni Malinen and " + "Copyright (c) 2007-2016, Jouni Malinen and " "contributors\n" "\n" "usage:\n" @@ -985,13 +1116,17 @@ int main(int argc, char *argv[]) char *pid_file = NULL; int daemonize = 0; char *ctrl_dir = "/var/run/wpa_priv"; - struct wpa_priv_interface *interfaces = NULL, *iface; + struct wpa_priv_global global; + struct wpa_priv_interface *iface; if (os_program_init()) return -1; wpa_priv_fd_workaround(); + os_memset(&global, 0, sizeof(global)); + global.interfaces = NULL; + for (;;) { c = getopt(argc, argv, "Bc:dP:"); if (c < 0) @@ -1029,14 +1164,14 @@ int main(int argc, char *argv[]) for (i = optind; i < argc; i++) { wpa_printf(MSG_DEBUG, "Adding driver:interface %s", argv[i]); - iface = wpa_priv_interface_init(ctrl_dir, argv[i]); + iface = wpa_priv_interface_init(&global, ctrl_dir, argv[i]); if (iface == NULL) goto out; - iface->next = interfaces; - interfaces = iface; + iface->next = global.interfaces; + global.interfaces = iface; } - if (daemonize && os_daemonize(pid_file)) + if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue()) goto out; eloop_register_signal_terminate(wpa_priv_terminate, NULL); @@ -1045,7 +1180,7 @@ int main(int argc, char *argv[]) ret = 0; out: - iface = interfaces; + iface = global.interfaces; while (iface) { struct wpa_priv_interface *prev = iface; iface = iface->next;