static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, char *cmd) { char *pos; int id; struct wpa_ssid *ssid; u8 bssid[ETH_ALEN]; /* cmd: "<network id> <BSSID>" */ pos = os_strchr(cmd, ' '); if (pos == NULL) return -1; *pos++ = '\0'; id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); if (hwaddr_aton(pos, bssid)) { wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); return -1; } ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " "to update", id); return -1; } os_memcpy(ssid->bssid, bssid, ETH_ALEN); ssid->bssid_set = os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0; return 0; }
/** * wpas_dbus_iface_select_network - Attempt association with a configured network * @message: Pointer to incoming dbus message * @wpa_s: wpa_supplicant structure for a network interface * Returns: A dbus message containing a UINT32 indicating success (1) or * failure (0) * * Handler function for "selectNetwork" method call of network interface. */ DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message, struct wpa_supplicant *wpa_s) { DBusMessage *reply = NULL; const char *op; struct wpa_ssid *ssid; char *iface_obj_path = NULL; char *network = NULL; if (os_strlen(dbus_message_get_signature(message)) == 0) { /* Any network */ ssid = NULL; } else { int nid; if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, DBUS_TYPE_INVALID)) { reply = wpas_dbus_new_invalid_opts_error(message, NULL); goto out; } /* Extract the network number */ iface_obj_path = wpas_dbus_decompose_object_path(op, &network, NULL); if (iface_obj_path == NULL) { reply = wpas_dbus_new_invalid_iface_error(message); goto out; } /* Ensure the object path really points to this interface */ if (os_strcmp(iface_obj_path, wpa_s->dbus_path) != 0) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } nid = strtoul(network, NULL, 10); if (errno == EINVAL) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } ssid = wpa_config_get_network(wpa_s->conf, nid); if (ssid == NULL) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } } /* Finally, associate with the network */ wpa_supplicant_select_network(wpa_s, ssid); reply = wpas_dbus_new_success_reply(message); out: os_free(iface_obj_path); os_free(network); return reply; }
static int wpa_supplicant_ctrl_iface_enable_network( struct wpa_supplicant *wpa_s, char *cmd) { int id; struct wpa_ssid *ssid; /* cmd: "<network id>" */ id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " "id=%d", id); return -1; } if (wpa_s->current_ssid == NULL && ssid->disabled) { /* * Try to reassociate since there is no current configuration * and a new network was made available. */ wpa_s->reassociate = 1; #ifdef ANDROID wpa_supplicant_req_scan(wpa_s, 2, 0); #else wpa_supplicant_req_scan(wpa_s, 0, 0); #endif } ssid->disabled = 0; return 0; }
static int wpa_supplicant_ctrl_iface_remove_network( struct wpa_supplicant *wpa_s, char *cmd) { int id; struct wpa_ssid *ssid; /* cmd: "<network id>" */ id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL || wpa_config_remove_network(wpa_s->conf, id) < 0) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " "id=%d", id); return -1; } if (ssid == wpa_s->current_ssid) { /* * Invalidate the EAP session cache if the current network is * removed. */ eapol_sm_invalidate_cached_session(wpa_s->eapol); wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); } return 0; }
/** * wpas_dbus_iface_remove_network - Remove a configured network * @message: Pointer to incoming dbus message * @wpa_s: wpa_supplicant structure for a network interface * Returns: A dbus message containing a UINT32 indicating success (1) or * failure (0) * * Handler function for "removeNetwork" method call of a network interface. */ DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message, struct wpa_supplicant *wpa_s) { DBusMessage *reply = NULL; const char *op; char *iface = NULL, *net_id = NULL; int id; struct wpa_ssid *ssid; if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, DBUS_TYPE_INVALID)) { reply = wpas_dbus_new_invalid_opts_error(message, NULL); goto out; } /* Extract the network ID */ iface = wpas_dbus_decompose_object_path(op, &net_id, NULL); if (iface == NULL) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } /* Ensure the network is actually a child of this interface */ if (os_strcmp(iface, wpa_s->dbus_path) != 0) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } id = strtoul(net_id, NULL, 10); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } wpas_notify_network_removed(wpa_s, ssid); if (wpa_config_remove_network(wpa_s->conf, id) < 0) { reply = dbus_message_new_error(message, WPAS_ERROR_REMOVE_NETWORK_ERROR, "error removing the specified " "on this interface."); goto out; } if (ssid == wpa_s->current_ssid) wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); reply = wpas_dbus_new_success_reply(message); out: os_free(iface); os_free(net_id); return reply; }
static int wpa_supplicant_ctrl_iface_set_network( struct wpa_supplicant *wpa_s, char *cmd) { int id; struct wpa_ssid *ssid; char *name, *value; /* cmd: "<network id> <variable name> <value>" */ name = os_strchr(cmd, ' '); if (name == NULL) return -1; *name++ = '\0'; value = os_strchr(name, ' '); if (value == NULL) return -1; *value++ = '\0'; id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", id, name); wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", (u8 *) value, os_strlen(value)); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " "id=%d", id); return -1; } if (wpa_config_set(ssid, name, value, 0) < 0) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " "variable '%s'", name); return -1; } else { if (os_strcmp(name, "priority") == 0) { wpa_config_update_prio_list(wpa_s->conf); } } if (wpa_s->current_ssid == ssid) { /* * Invalidate the EAP session cache if anything in the current * configuration changes. */ eapol_sm_invalidate_cached_session(wpa_s->eapol); } if ((os_strcmp(name, "psk") == 0 && value[0] == '"' && ssid->ssid_len) || (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) wpa_config_update_psk(ssid); return 0; }
static int wpa_supplicant_ctrl_iface_select_network( struct wpa_supplicant *wpa_s, char *cmd) { int id; struct wpa_ssid *ssid; /* cmd: "<network id>" or "any" */ if (os_strcmp(cmd, "any") == 0) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); ssid = wpa_s->conf->ssid; while (ssid) { ssid->disabled = 0; ssid = ssid->next; } wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); return 0; } id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " "id=%d", id); return -1; } if (ssid != wpa_s->current_ssid && wpa_s->current_ssid) wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); /* Mark all other networks disabled and trigger reassociation */ ssid = wpa_s->conf->ssid; while (ssid) { ssid->disabled = id != ssid->id; ssid = ssid->next; } wpa_s->reassociate = 1; wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; wpa_supplicant_req_scan(wpa_s, 0, 0); return 0; }
static int wpa_supplicant_ctrl_iface_disable_network( struct wpa_supplicant *wpa_s, char *cmd) { int id; struct wpa_ssid *ssid; /* cmd: "<network id>" or "all" */ if (os_strcmp(cmd, "all") == 0) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); ssid = wpa_s->conf->ssid; while (ssid) { ssid->disabled = 1; ssid = ssid->next; } if (wpa_s->current_ssid) wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); return 0; } id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " "id=%d", id); return -1; } #ifdef ANDROID if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not disable WPS network " "id=%d", id); return -1; } #endif if (ssid == wpa_s->current_ssid) wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); ssid->disabled = 1; return 0; }
static int wpa_supplicant_ctrl_iface_get_network( struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) { int id; struct wpa_ssid *ssid; char *name, *value; /* cmd: "<network id> <variable name>" */ name = os_strchr(cmd, ' '); if (name == NULL || buflen == 0) return -1; *name++ = '\0'; id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", id, name); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " "id=%d", id); return -1; } value = wpa_config_get_no_key(ssid, name); if (value == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " "variable '%s'", name); return -1; } #ifdef ANDROID_IBSS_HACK if ((os_strcmp(name, "ssid") == 0) && (ssid->mode == IEEE80211_MODE_IBSS)) os_snprintf(buf, buflen, "\"%s%s", ANDROID_IBSS_PREFIX, value+1); else #endif os_snprintf(buf, buflen, "%s", value); buf[buflen - 1] = '\0'; os_free(value); return os_strlen(buf); }
static int wpa_supplicant_ctrl_iface_enable_network( struct wpa_supplicant *wpa_s, char *cmd) { int id; struct wpa_ssid *ssid; /* cmd: "<network id>" or "all" */ if (os_strcmp(cmd, "all") == 0) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); ssid = wpa_s->conf->ssid; while (ssid) { if (ssid == wpa_s->current_ssid && ssid->disabled) wpa_s->reassociate = 1; ssid->disabled = 0; ssid = ssid->next; } if (wpa_s->reassociate) wpa_supplicant_req_scan(wpa_s, 0, 0); return 0; } id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " "id=%d", id); return -1; } if (wpa_s->current_ssid == NULL && ssid->disabled) { /* * Try to reassociate since there is no current configuration * and a new network was made available. */ wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); } ssid->disabled = 0; return 0; }
static int wpa_supplicant_ctrl_iface_get_network( struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) { int id; size_t res; struct wpa_ssid *ssid; char *name, *value; /* cmd: "<network id> <variable name>" */ name = os_strchr(cmd, ' '); if (name == NULL || buflen == 0) return -1; *name++ = '\0'; id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", id, name); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " "id=%d", id); return -1; } value = wpa_config_get_no_key(ssid, name); if (value == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " "variable '%s'", name); return -1; } res = os_strlcpy(buf, value, buflen); if (res >= buflen) { os_free(value); return -1; } os_free(value); return res; }
int wpas_wps_er_set_config(struct wpa_supplicant *wpa_s, const char *uuid, int id) { u8 u[UUID_LEN]; struct wpa_ssid *ssid; struct wps_credential cred; if (uuid_str2bin(uuid, u)) return -1; ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL || ssid->ssid == NULL) return -1; os_memset(&cred, 0, sizeof(cred)); if (ssid->ssid_len > 32) return -1; os_memcpy(cred.ssid, ssid->ssid, ssid->ssid_len); cred.ssid_len = ssid->ssid_len; if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { cred.auth_type = (ssid->proto & WPA_PROTO_RSN) ? WPS_AUTH_WPA2PSK : WPS_AUTH_WPAPSK; if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) cred.encr_type = WPS_ENCR_AES; else cred.encr_type = WPS_ENCR_TKIP; if (ssid->passphrase) { cred.key_len = os_strlen(ssid->passphrase); if (cred.key_len >= 64) return -1; os_memcpy(cred.key, ssid->passphrase, cred.key_len); } else if (ssid->psk_set) { cred.key_len = 32; os_memcpy(cred.key, ssid->psk, 32); } else return -1; } else { cred.auth_type = WPS_AUTH_OPEN; cred.encr_type = WPS_ENCR_NONE; } return wps_er_set_config(wpa_s->wps_er, u, &cred); }
/** * wpas_dispatch_network_method - dispatch messages for configured networks * @message: the incoming dbus message * @wpa_s: a network interface's data * @network_id: id of the configured network we're interested in * Returns: a reply dbus message, or a dbus error message * * This function dispatches all incoming dbus messages for configured networks. */ static DBusMessage * wpas_dispatch_network_method(DBusMessage *message, struct wpa_supplicant *wpa_s, int network_id) { DBusMessage *reply = NULL; const char *method = dbus_message_get_member(message); struct wpa_ssid *ssid; ssid = wpa_config_get_network(wpa_s->conf, network_id); if (ssid == NULL) return wpas_dbus_new_invalid_network_error(message); if (!strcmp(method, "set")) reply = wpas_dbus_iface_set_network(message, wpa_s, ssid); else if (!strcmp(method, "enable")) reply = wpas_dbus_iface_enable_network(message, wpa_s, ssid); else if (!strcmp(method, "disable")) reply = wpas_dbus_iface_disable_network(message, wpa_s, ssid); return reply; }
static int wpa_supplicant_ctrl_iface_disable_network( struct wpa_supplicant *wpa_s, char *cmd) { int id; struct wpa_ssid *ssid; /* cmd: "<network id>" */ id = atoi(cmd); wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " "id=%d", id); return -1; } if (ssid == wpa_s->current_ssid) wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); ssid->disabled = 1; return 0; }
/** * wpas_dbus_iface_select_network - Attempt association with a configured network * @message: Pointer to incoming dbus message * @wpa_s: wpa_supplicant structure for a network interface * Returns: A dbus message containing a UINT32 indicating success (1) or * failure (0) * * Handler function for "selectNetwork" method call of network interface. */ DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message, struct wpa_supplicant *wpa_s) { DBusMessage *reply = NULL; const char *op; struct wpa_ssid *ssid; char *iface_obj_path = NULL; char *network = NULL; if (strlen(dbus_message_get_signature(message)) == 0) { /* Any network */ ssid = wpa_s->conf->ssid; while (ssid) { ssid->disabled = 0; ssid = ssid->next; } wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); } else { const char *obj_path; int nid; if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, DBUS_TYPE_INVALID)) { reply = wpas_dbus_new_invalid_opts_error(message, NULL); goto out; } /* Extract the network number */ iface_obj_path = wpas_dbus_decompose_object_path(op, &network, NULL); if (iface_obj_path == NULL) { reply = wpas_dbus_new_invalid_iface_error(message); goto out; } /* Ensure the object path really points to this interface */ obj_path = wpa_supplicant_get_dbus_path(wpa_s); if (strcmp(iface_obj_path, obj_path) != 0) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } nid = strtoul(network, NULL, 10); if (errno == EINVAL) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } ssid = wpa_config_get_network(wpa_s->conf, nid); if (ssid == NULL) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } /* Finally, associate with the network */ if (ssid != wpa_s->current_ssid && wpa_s->current_ssid) wpa_supplicant_disassociate( wpa_s, WLAN_REASON_DEAUTH_LEAVING); /* Mark all other networks disabled and trigger reassociation */ ssid = wpa_s->conf->ssid; while (ssid) { ssid->disabled = (nid != ssid->id); ssid = ssid->next; } wpa_s->disconnected = 0; wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); } reply = wpas_dbus_new_success_reply(message); out: free(iface_obj_path); free(network); return reply; }
static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, char *rsp) { #ifdef IEEE8021X_EAPOL char *pos, *id_pos; int id; struct wpa_ssid *ssid; pos = os_strchr(rsp, '-'); if (pos == NULL) return -1; *pos++ = '\0'; id_pos = pos; pos = os_strchr(pos, ':'); if (pos == NULL) return -1; *pos++ = '\0'; id = atoi(id_pos); wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", (u8 *) pos, os_strlen(pos)); ssid = wpa_config_get_network(wpa_s->conf, id); if (ssid == NULL) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " "to update", id); return -1; } if (os_strcmp(rsp, "IDENTITY") == 0) { os_free(ssid->identity); ssid->identity = (u8 *) os_strdup(pos); ssid->identity_len = os_strlen(pos); ssid->pending_req_identity = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (os_strcmp(rsp, "PASSWORD") == 0) { os_free(ssid->password); ssid->password = (u8 *) os_strdup(pos); ssid->password_len = os_strlen(pos); ssid->pending_req_password = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) { os_free(ssid->new_password); ssid->new_password = (u8 *) os_strdup(pos); ssid->new_password_len = os_strlen(pos); ssid->pending_req_new_password = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (os_strcmp(rsp, "PIN") == 0) { os_free(ssid->pin); ssid->pin = os_strdup(pos); ssid->pending_req_pin = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else if (os_strcmp(rsp, "OTP") == 0) { os_free(ssid->otp); ssid->otp = (u8 *) os_strdup(pos); ssid->otp_len = os_strlen(pos); os_free(ssid->pending_req_otp); ssid->pending_req_otp = NULL; ssid->pending_req_otp_len = 0; } else if (os_strcmp(rsp, "PASSPHRASE") == 0) { os_free(ssid->private_key_passwd); ssid->private_key_passwd = (u8 *) os_strdup(pos); ssid->pending_req_passphrase = 0; if (ssid == wpa_s->current_ssid) wpa_s->reassociate = 1; } else { wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp); return -1; } return 0; #else /* IEEE8021X_EAPOL */ wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); return -1; #endif /* IEEE8021X_EAPOL */ }
int wps_get_supplicant_ssid_configuration(void *ctx, int index, u8 **buf, size_t *len) { int ret = -1; struct wpa_supplicant *wpa_s = ctx; struct wpa_ssid *ssid; struct wps_data *wps = 0; u16 auth, encr; Boolean enabled8021x = 0; u8 nwKeyIdx = -1; u8 nwKey[64 + 1]; Boolean blval; size_t length; u8 nwIdx; do { if (!buf || !len) break; *buf = 0; *len = 0; ssid = wpa_config_get_network(wpa_s->conf, index); if (!ssid) break; if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) { if (ssid->proto & WPA_PROTO_RSN) auth = WPS_AUTHTYPE_WPA2; else auth = WPS_AUTHTYPE_WPA; if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) encr = WPS_ENCRTYPE_AES; else encr = WPS_ENCRTYPE_TKIP; enabled8021x = 1; } else if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { if (ssid->proto & WPA_PROTO_RSN) auth = WPS_AUTHTYPE_WPA2PSK; else auth = WPS_AUTHTYPE_WPAPSK; if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) encr = WPS_ENCRTYPE_AES; else encr = WPS_ENCRTYPE_TKIP; nwKeyIdx = 0; } else if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) { if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) { auth = WPS_AUTHTYPE_SHARED; nwKeyIdx = ssid->wep_tx_keyidx + 1; } else auth = WPS_AUTHTYPE_OPEN; if ((ssid->pairwise_cipher & (WPA_CIPHER_WEP40|WPA_CIPHER_WEP104)) || (ssid->group_cipher & (WPA_CIPHER_WEP40|WPA_CIPHER_WEP104))) { encr = WPS_ENCRTYPE_WEP; nwKeyIdx = ssid->wep_tx_keyidx + 1; } else encr = WPS_ENCRTYPE_NONE; } else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { auth = WPS_AUTHTYPE_OPEN; encr = WPS_ENCRTYPE_WEP; enabled8021x = 1; } if (wps_create_wps_data(&wps)) break; /* Network Index */ nwIdx = ssid->id; if (wps_set_value(wps, WPS_TYPE_NW_INDEX, &nwIdx, 0)) break; /* SSID */ if (wps_set_value(wps, WPS_TYPE_SSID, ssid->ssid, ssid->ssid_len)) break; /* Authentication Type */ if (wps_set_value(wps, WPS_TYPE_AUTH_TYPE, &auth, 0)) break; /* Encryption Type */ if (wps_set_value(wps, WPS_TYPE_ENCR_TYPE, &encr, 0)) break; if (nwKeyIdx != (u8)-1) { if (encr == WPS_ENCRTYPE_WEP) { if ((1 > nwKeyIdx) || (4 < nwKeyIdx)) { wpa_printf(MSG_WARNING, "Network Key Index is fixed. %d -> 1\n", nwKeyIdx); nwKeyIdx = 1; } /* Network Key Index (Option) */ if (wps_set_value(wps, WPS_TYPE_NW_KEY_INDEX, &nwKeyIdx, 0)) break; } /* Network Key */ if (ssid->passphrase) { length = os_strlen(ssid->passphrase); strncpy((char *)nwKey, ssid->passphrase, length); nwKey[length] = 0; } else if (ssid->psk_set) { length = PMK_LEN * 2; wpa_snprintf_hex_uppercase((char *)nwKey, sizeof(nwKey), ssid->psk, length); nwKey[length] = 0; } else { if (is_hex(ssid->wep_key[nwKeyIdx - 1], ssid->wep_key_len[nwKeyIdx - 1])) { length = (u16)ssid->wep_key_len[nwKeyIdx - 1] * 2; wpa_snprintf_hex_uppercase((char *)nwKey, sizeof(nwKey), ssid->wep_key[nwKeyIdx - 1], length); nwKey[length] = 0; } else { length = (u16)ssid->wep_key_len[nwKeyIdx - 1]; strncpy((char *)nwKey, (char *)ssid->wep_key[nwKeyIdx - 1], length); nwKey[length] = 0; } } if (wps_set_value(wps, WPS_TYPE_NW_KEY, nwKey, length)) break; } else { /* Network Key (No Key) */ if (wps_set_value(wps, WPS_TYPE_NW_KEY, 0, 0)) { break; } } /* MAC Address */ if (wps_set_value(wps, WPS_TYPE_MAC_ADDR, wpa_s->own_addr, ETH_ALEN)) break; if (enabled8021x) { char *value; /* EAP Type (Option) */ value = wpa_config_get(ssid, "eap"); if (value) { if (wps_set_value(wps, WPS_TYPE_EAP_TYPE, value, os_strlen(value))) { free(value); break; } free(value); } /* EAP Identity (Option) */ value = wpa_config_get(ssid, "identity"); if (value) { if (wps_set_value(wps, WPS_TYPE_EAP_IDENTITY, value, os_strlen(value))) { free(value); break; } free(value); } /* Key Provided Automaticaly (Option) */ blval = 1; if (wps_set_value(wps, WPS_TYPE_KEY_PROVIDED_AUTO, &blval, 0)) break; /* 802.1X Enabled (Option) */ if (wps_set_value(wps, WPS_TYPE_8021X_ENABLED, &enabled8021x, 0)) break; } if (wps_write_wps_data(wps, buf, len)) break; ret = 0; } while (0); (void)wps_destroy_wps_data(&wps); if (ret) { if (buf && *buf) { free(*buf); *buf = 0; } if (len) *len = 0; } return ret; }
status_t WPASupplicantApp::_JoinNetwork(BMessage *message) { const char *interfaceName = NULL; status_t status = message->FindString("device", &interfaceName); if (status != B_OK) return status; // Check if we already registered this interface. wpa_supplicant *interface = wpa_supplicant_get_iface(fWPAGlobal, interfaceName); if (interface == NULL) { wpa_interface interfaceOptions; memset(&interfaceOptions, 0, sizeof(wpa_interface)); interfaceOptions.ifname = interfaceName; interface = wpa_supplicant_add_iface(fWPAGlobal, &interfaceOptions); if (interface == NULL) return B_NO_MEMORY; } else { // Disable everything wpa_supplicant_disable_network(interface, NULL); // Try to remove any existing network while (true) { wpa_ssid *network = wpa_config_get_network(interface->conf, 0); if (network == NULL) break; wpas_notify_network_removed(interface, network); wpa_config_remove_network(interface->conf, network->id); } } const char *networkName = NULL; status = message->FindString("name", &networkName); if (status != B_OK) return status; uint32 authMode = B_NETWORK_AUTHENTICATION_NONE; status = message->FindUInt32("authentication", &authMode); if (status != B_OK) return status; uint32 encapMode = B_NETWORK_EAP_ENCAPSULATION_NONE; if (authMode == B_NETWORK_AUTHENTICATION_EAP) message->FindUInt32("encapsulation", &encapMode); const char *username = NULL; if (encapMode > B_NETWORK_EAP_ENCAPSULATION_NONE) { status = message->FindString("username", &username); if (status != B_OK) return status; } const char *password = NULL; if (authMode > B_NETWORK_AUTHENTICATION_NONE) { status = message->FindString("password", &password); if (status != B_OK) return status; } wpa_ssid *network = wpa_config_add_network(interface->conf); if (network == NULL) return B_NO_MEMORY; wpas_notify_network_added(interface, network); network->disabled = 1; wpa_config_set_network_defaults(network); // Fill in the info from the join request // The format includes the quotes BString value; value = "\""; value += networkName; value += "\""; int result = wpa_config_set(network, "ssid", value.String(), 0); if (result == 0) result = wpa_config_set(network, "scan_ssid", "1", 1); if (authMode >= B_NETWORK_AUTHENTICATION_WPA) { if (result == 0) result = wpa_config_set(network, "proto", "WPA RSN", 2); if (result == 0) { switch (authMode) { case B_NETWORK_AUTHENTICATION_WPA: case B_NETWORK_AUTHENTICATION_WPA2: default: result = wpa_config_set(network, "key_mgmt", "WPA-PSK", 3); break; case B_NETWORK_AUTHENTICATION_EAP: result = wpa_config_set(network, "key_mgmt", "WPA-EAP", 3); break; } } if (result == 0) result = wpa_config_set(network, "pairwise", "CCMP TKIP NONE", 4); if (result == 0) { result = wpa_config_set(network, "group", "CCMP TKIP WEP104 WEP40", 5); } if (result == 0) { if (encapMode > B_NETWORK_EAP_ENCAPSULATION_NONE) { switch (encapMode) { case B_NETWORK_EAP_ENCAPSULATION_PEAP: result = wpa_config_set(network, "eap", "PEAP", 6); break; case B_NETWORK_EAP_ENCAPSULATION_TLS: result = wpa_config_set(network, "eap", "TLS", 6); break; } } } } else { // Open or WEP. if (result == 0) result = wpa_config_set(network, "key_mgmt", "NONE", 6); } if (result == 0) { if (authMode == B_NETWORK_AUTHENTICATION_WEP) { if (strncmp("0x", password, 2) == 0) { // interpret as hex key // TODO: make this non-ambiguous result = wpa_config_set(network, "wep_key0", password + 2, 7); } else { value = "\""; value += password; value += "\""; result = wpa_config_set(network, "wep_key0", value.String(), 8); } if (result == 0) result = wpa_config_set(network, "wep_tx_keyidx", "0", 9); } else if (authMode == B_NETWORK_AUTHENTICATION_EAP) { // EAP value = "\""; value += password; value += "\""; result = wpa_config_set(network, "password", value.String(), 10); if (encapMode > B_NETWORK_EAP_ENCAPSULATION_NONE) { value = "\""; value += username; value += "\""; result = wpa_config_set(network, "identity", value.String(), 11); } // TODO: Does EAP need the same thing? #if 0 if (result == 0) { // We need to actually "apply" the PSK wpa_config_update_psk(network); } #endif } else if (authMode >= B_NETWORK_AUTHENTICATION_WPA) { // WPA/WPA2 value = "\""; value += password; value += "\""; result = wpa_config_set(network, "psk", value.String(), 10); if (result == 0) { // We need to actually "apply" the PSK wpa_config_update_psk(network); } } if (result != 0) { // The key format is invalid, we need to ask for another password. BMessage newJoinRequest = *message; newJoinRequest.RemoveName("password"); newJoinRequest.AddString("error", "Password format invalid"); newJoinRequest.AddBool("forceDialog", true); PostMessage(&newJoinRequest); } } if (result != 0) { wpas_notify_network_removed(interface, network); wpa_config_remove_network(interface->conf, network->id); return B_ERROR; } // Set up watching for the completion event _StartWatchingInterfaceChanges(interface, _InterfaceStateChangeCallback, message); // Now attempt to connect wpa_supplicant_select_network(interface, network); // Use a message runner to return a timeout and stop watching after a while BMessage timeout(kMsgJoinTimeout); timeout.AddPointer("interface", interface); BMessageRunner::StartSending(be_app_messenger, &timeout, 15 * 1000 * 1000, 1); // Note that we don't need to cancel this. If joining works before the // timeout happens, it will take the StateChangeWatchingEntry with it // and the timeout message won't match anything and be discarded. return B_OK; }