static void eapol_test_set_anon_id(void *ctx, const u8 *id, size_t len) { struct eapol_test_data *e = ctx; struct wpa_supplicant *wpa_s = e->wpa_s; char *str; int res; wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity", id, len); if (wpa_s->current_ssid == NULL) return; if (id == NULL) { if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity", "NULL", 0) < 0) return; } else { str = os_malloc(len * 2 + 1); if (str == NULL) return; wpa_snprintf_hex(str, len * 2 + 1, id, len); res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity", str, 0); os_free(str); if (res < 0) return; } }
static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s, int registrar, const u8 *bssid) { struct wpa_ssid *ssid; ssid = wpa_config_add_network(wpa_s->conf); if (ssid == NULL) return NULL; wpas_notify_network_added(wpa_s, ssid); wpa_config_set_network_defaults(ssid); if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 || wpa_config_set(ssid, "eap", "WSC", 0) < 0 || wpa_config_set(ssid, "identity", registrar ? "\"" WSC_ID_REGISTRAR "\"" : "\"" WSC_ID_ENROLLEE "\"", 0) < 0) { wpas_notify_network_removed(wpa_s, ssid); wpa_config_remove_network(wpa_s->conf, ssid->id); return NULL; } if (bssid) { struct wpa_bss *bss; int count = 0; os_memcpy(ssid->bssid, bssid, ETH_ALEN); ssid->bssid_set = 1; dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { if (os_memcmp(bssid, bss->bssid, ETH_ALEN) != 0) continue; os_free(ssid->ssid); ssid->ssid = os_malloc(bss->ssid_len); if (ssid->ssid == NULL) break; os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); ssid->ssid_len = bss->ssid_len; wpa_hexdump_ascii(MSG_DEBUG, "WPS: Picked SSID from " "scan results", ssid->ssid, ssid->ssid_len); count++; } if (count > 1) { wpa_printf(MSG_DEBUG, "WPS: More than one SSID found " "for the AP; use wildcard"); os_free(ssid->ssid); ssid->ssid = NULL; ssid->ssid_len = 0; } } return ssid; }
static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s, int registrar, const u8 *bssid) { struct wpa_ssid *ssid; ssid = wpa_config_add_network(wpa_s->conf); if (ssid == NULL) return NULL; wpa_config_set_network_defaults(ssid); if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 || wpa_config_set(ssid, "eap", "WSC", 0) < 0 || wpa_config_set(ssid, "identity", registrar ? "\"" WSC_ID_REGISTRAR "\"" : "\"" WSC_ID_ENROLLEE "\"", 0) < 0) { wpa_config_remove_network(wpa_s->conf, ssid->id); return NULL; } if (bssid) { size_t i; struct wpa_scan_res *res; os_memcpy(ssid->bssid, bssid, ETH_ALEN); ssid->bssid_set = 1; /* Try to get SSID from scan results */ if (wpa_s->scan_res == NULL && wpa_supplicant_get_scan_results(wpa_s) < 0) return ssid; /* Could not find any scan results */ for (i = 0; i < wpa_s->scan_res->num; i++) { const u8 *ie; res = wpa_s->scan_res->res[i]; if (os_memcmp(bssid, res->bssid, ETH_ALEN) != 0) continue; ie = wpa_scan_get_ie(res, WLAN_EID_SSID); if (ie == NULL) break; os_free(ssid->ssid); ssid->ssid = os_malloc(ie[1]); if (ssid->ssid == NULL) break; os_memcpy(ssid->ssid, ie + 2, ie[1]); ssid->ssid_len = ie[1]; break; } } return ssid; }
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, int p2p_group) { struct wpa_ssid *ssid; wpas_clear_wps(wpa_s); ssid = wpas_wps_add_network(wpa_s, 0, bssid); if (ssid == NULL) return -1; ssid->temporary = 1; ssid->p2p_group = p2p_group; #ifdef CONFIG_P2P if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) { ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1); if (ssid->ssid) { ssid->ssid_len = wpa_s->go_params->ssid_len; os_memcpy(ssid->ssid, wpa_s->go_params->ssid, ssid->ssid_len); wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP " "SSID", ssid->ssid, ssid->ssid_len); } } #endif /* CONFIG_P2P */ wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0); if (wpa_s->wps_fragment_size) ssid->eap.fragment_size = wpa_s->wps_fragment_size; eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, wpa_s, NULL); wpas_wps_reassoc(wpa_s, ssid, bssid); return 0; }
static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) { struct wpa_ssid *ssid; int errors = 0, end = 0; char buf[2000], *pos, *pos2; wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block", *line); ssid = os_zalloc(sizeof(*ssid)); if (ssid == NULL) return NULL; dl_list_init(&ssid->psk_list); ssid->id = id; wpa_config_set_network_defaults(ssid); while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { if (os_strcmp(pos, "}") == 0) { end = 1; break; } pos2 = os_strchr(pos, '='); if (pos2 == NULL) { wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line " "'%s'.", *line, pos); errors++; continue; } *pos2++ = '\0'; if (*pos2 == '"') { if (os_strchr(pos2 + 1, '"') == NULL) { wpa_printf(MSG_ERROR, "Line %d: invalid " "quotation '%s'.", *line, pos2); errors++; continue; } } if (wpa_config_set(ssid, pos, pos2, *line) < 0) errors++; } if (!end) { wpa_printf(MSG_ERROR, "Line %d: network block was not " "terminated properly.", *line); errors++; } errors += wpa_config_validate_network(ssid, *line); if (errors) { wpa_config_free_ssid(ssid); ssid = NULL; } return ssid; }
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; }
int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid) { struct wpa_ssid *ssid; wpas_clear_wps(wpa_s); ssid = wpas_wps_add_network(wpa_s, 0, bssid); if (ssid == NULL) return -1; wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0); eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, wpa_s, NULL); wpas_wps_reassoc(wpa_s, ssid); return 0; }
static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len) { struct wpa_supplicant *wpa_s = ctx; char *str; int res; wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity", id, len); if (wpa_s->current_ssid == NULL) return; if (id == NULL) { if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity", "NULL", 0) < 0) return; } else { str = os_malloc(len * 2 + 1); if (str == NULL) return; wpa_snprintf_hex(str, len * 2 + 1, id, len); res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity", str, 0); os_free(str); if (res < 0) return; } if (wpa_s->conf->update_config) { res = wpa_config_write(wpa_s->confname, wpa_s->conf); if (res) { wpa_printf(MSG_DEBUG, "Failed to update config after " "anonymous_id update"); } } }
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid, const char *pin) { struct wpa_ssid *ssid; char val[30]; if (!pin) return -1; wpas_clear_wps(wpa_s); ssid = wpas_wps_add_network(wpa_s, 1, bssid); if (ssid == NULL) return -1; os_snprintf(val, sizeof(val), "\"pin=%s\"", pin); wpa_config_set(ssid, "phase1", val, 0); eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, wpa_s, NULL); wpas_wps_reassoc(wpa_s, ssid); return 0; }
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid, const char *pin, struct wps_new_ap_settings *settings) { struct wpa_ssid *ssid; char val[200]; char *pos, *end; int res; if (!pin) return -1; wpas_clear_wps(wpa_s); ssid = wpas_wps_add_network(wpa_s, 1, bssid); if (ssid == NULL) return -1; ssid->temporary = 1; pos = val; end = pos + sizeof(val); res = os_snprintf(pos, end - pos, "\"pin=%s", pin); if (res < 0 || res >= end - pos) return -1; pos += res; if (settings) { res = os_snprintf(pos, end - pos, " new_ssid=%s new_auth=%s " "new_encr=%s new_key=%s", settings->ssid_hex, settings->auth, settings->encr, settings->key_hex); if (res < 0 || res >= end - pos) return -1; pos += res; } res = os_snprintf(pos, end - pos, "\""); if (res < 0 || res >= end - pos) return -1; wpa_config_set(ssid, "phase1", val, 0); if (wpa_s->wps_fragment_size) ssid->eap.fragment_size = wpa_s->wps_fragment_size; eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, wpa_s, NULL); wpas_wps_reassoc(wpa_s, ssid, bssid); return 0; }
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid, const char *pin, int p2p_group, u16 dev_pw_id) { struct wpa_ssid *ssid; char val[128]; unsigned int rpin = 0; wpas_clear_wps(wpa_s); ssid = wpas_wps_add_network(wpa_s, 0, bssid); if (ssid == NULL) return -1; ssid->temporary = 1; ssid->p2p_group = p2p_group; #ifdef CONFIG_P2P if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) { ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1); if (ssid->ssid) { ssid->ssid_len = wpa_s->go_params->ssid_len; os_memcpy(ssid->ssid, wpa_s->go_params->ssid, ssid->ssid_len); wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP " "SSID", ssid->ssid, ssid->ssid_len); } } #endif /* CONFIG_P2P */ if (pin) os_snprintf(val, sizeof(val), "\"pin=%s dev_pw_id=%u\"", pin, dev_pw_id); else { rpin = wps_generate_pin(); os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u\"", rpin, dev_pw_id); } wpa_config_set(ssid, "phase1", val, 0); if (wpa_s->wps_fragment_size) ssid->eap.fragment_size = wpa_s->wps_fragment_size; eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, wpa_s, NULL); wpas_wps_reassoc(wpa_s, ssid, bssid); return rpin; }
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid, const char *pin) { struct wpa_ssid *ssid; char val[128]; unsigned int rpin = 0; wpas_clear_wps(wpa_s); ssid = wpas_wps_add_network(wpa_s, 0, bssid); if (ssid == NULL) return -1; if (pin) os_snprintf(val, sizeof(val), "\"pin=%s\"", pin); else { rpin = wps_generate_pin(); os_snprintf(val, sizeof(val), "\"pin=%08d\"", rpin); } wpa_config_set(ssid, "phase1", val, 0); eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, wpa_s, NULL); wpas_wps_reassoc(wpa_s, ssid); return rpin; }
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; }
static struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw, int id) { HKEY nhk; LONG ret; DWORD i; struct wpa_ssid *ssid; int errors = 0; ret = RegOpenKeyEx(hk, netw, 0, KEY_QUERY_VALUE, &nhk); if (ret != ERROR_SUCCESS) { wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config " "network '" TSTR "'", netw); return NULL; } wpa_printf(MSG_MSGDUMP, "Start of a new network '" TSTR "'", netw); ssid = os_zalloc(sizeof(*ssid)); if (ssid == NULL) { RegCloseKey(nhk); return NULL; } dl_list_init(&ssid->psk_list); ssid->id = id; wpa_config_set_network_defaults(ssid); for (i = 0; ; i++) { TCHAR name[255], data[1024]; DWORD namelen, datalen, type; namelen = 255; datalen = sizeof(data); ret = RegEnumValue(nhk, i, name, &namelen, NULL, &type, (LPBYTE) data, &datalen); if (ret == ERROR_NO_MORE_ITEMS) break; if (ret != ERROR_SUCCESS) { wpa_printf(MSG_ERROR, "RegEnumValue failed: 0x%x", (unsigned int) ret); break; } if (namelen >= 255) namelen = 255 - 1; name[namelen] = TEXT('\0'); if (datalen >= 1024) datalen = 1024 - 1; data[datalen] = TEXT('\0'); wpa_unicode2ascii_inplace(name); wpa_unicode2ascii_inplace(data); if (wpa_config_set(ssid, (char *) name, (char *) data, 0) < 0) errors++; } RegCloseKey(nhk); if (ssid->passphrase) { if (ssid->psk_set) { wpa_printf(MSG_ERROR, "Both PSK and passphrase " "configured for network '" TSTR "'.", netw); errors++; } wpa_config_update_psk(ssid); } if ((ssid->group_cipher & WPA_CIPHER_CCMP) && !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { /* Group cipher cannot be stronger than the pairwise cipher. */ wpa_printf(MSG_DEBUG, "Removed CCMP from group cipher " "list since it was not allowed for pairwise " "cipher for network '" TSTR "'.", netw); ssid->group_cipher &= ~WPA_CIPHER_CCMP; } if (errors) { wpa_config_free_ssid(ssid); ssid = NULL; } return ssid; }
/* * This installs received WPS configuration into a new network configuration. * It is optional that the new network configuration be saved to the * original configuration file. */ int wps_set_supplicant_ssid_configuration(void *ctx, u8 *buf, size_t len) { int ret = -1; struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)ctx; struct wpa_ssid *ssid = 0; struct wps_data *wps = 0; u8 str_ssid[33]; size_t ssid_length; u16 auth, encr; u8 nwKeyIdx; u8 *nwKey = 0; size_t nwKey_length; u8 macAddr[6]; char *eapType = 0; char *eapIdentity = 0; Boolean keyProvideAuto; Boolean enabled8021X; Boolean passphrase = 0; size_t length; char *var, *value; do { if (!wpa_s) break; /* Optionally share new configuration with other software, * e.g. with hostapd. */ wps_new_configuration_share(wpa_s, buf, len); ssid = wpa_config_add_network(wpa_s->conf); if (!ssid) break; wpa_config_set_network_defaults(ssid); if (wps_create_wps_data(&wps)) break; if(wps_parse_wps_data(buf, len, wps)) break; /* SSID */ ssid_length = sizeof(str_ssid); if(wps_get_value(wps, WPS_TYPE_SSID, str_ssid, &ssid_length)) break; str_ssid[ssid_length] = 0; /* Authentication Type */ if (wps_get_value(wps, WPS_TYPE_AUTH_TYPE, &auth, NULL)) break; /* Encryption Type */ if (wps_get_value(wps, WPS_TYPE_ENCR_TYPE, &encr, NULL)) break; /* Network Key Index (Option) */ if(wps_get_value(wps, WPS_TYPE_NW_KEY_INDEX, &nwKeyIdx, NULL)) nwKeyIdx = 1; if ((1 > nwKeyIdx) || (4 < nwKeyIdx)) { /* warning */ wpa_printf(MSG_WARNING, "Network Key Index is fixed. %d -> 1\n", nwKeyIdx); nwKeyIdx = 1; } /* Network Key */ nwKey_length = 0; (void)wps_get_value(wps, WPS_TYPE_NW_KEY, NULL, &nwKey_length); if (nwKey_length) { nwKey = (u8 *)calloc(1, nwKey_length + 1); if (!nwKey) break; if (wps_get_value(wps, WPS_TYPE_NW_KEY, nwKey, &nwKey_length)) { break; } nwKey[nwKey_length] = 0; } /* MAC Address */ length = sizeof(macAddr); if(wps_get_value(wps, WPS_TYPE_MAC_ADDR, macAddr, &length)) break; /* EAP Type (Option) */ length = 0; (void)wps_get_value(wps, WPS_TYPE_EAP_TYPE, NULL, &length); if (length) { eapType = (char *)calloc(1, length + 1); if (!eapType) break; if (wps_get_value(wps, WPS_TYPE_EAP_TYPE, eapType, &length)) { break; } eapType[length] = 0; } /* EAP Identity (Option) */ length = 0; (void)wps_get_value(wps, WPS_TYPE_EAP_IDENTITY, NULL, &length); if (length) { eapIdentity = (char *)calloc(1, length + 1); if (!eapIdentity) break; if (wps_get_value(wps, WPS_TYPE_EAP_IDENTITY, eapIdentity, &length)) { break; } eapIdentity[length] = 0; } /* Key Provided Automaticaly (Option) */ if(wps_get_value(wps, WPS_TYPE_KEY_PROVIDED_AUTO, &keyProvideAuto, NULL)) keyProvideAuto = 0; /* 802.1X Enabled (Option) */ if(wps_get_value(wps, WPS_TYPE_8021X_ENABLED, &enabled8021X, NULL)) enabled8021X = 0; /* Set Configuration */ /* %%%%%% Sony set disabled to 1... why? */ ssid->disabled = 0; /* ssid */ var = "ssid"; value = (char *)os_malloc(os_strlen((char *)str_ssid) + 3); if (!value) break; os_snprintf(value, os_strlen((char *)str_ssid) + 3, "\"%s\"", str_ssid); if (wpa_config_set(ssid, var, value, 0)) break; free(value); /* auth_alg */ var = "auth_alg"; if (WPS_AUTHTYPE_SHARED == auth) value = "SHARED"; else value = "OPEN"; if (wpa_config_set(ssid, var, value, 0)) break; /* key_mgmt */ var = "key_mgmt"; switch (auth) { case WPS_AUTHTYPE_OPEN: case WPS_AUTHTYPE_SHARED: if (enabled8021X) value = "IEEE8021X"; else value = "NONE"; break; case WPS_AUTHTYPE_WPAPSK: case WPS_AUTHTYPE_WPA2PSK: if (enabled8021X) value = "WPA-PSK IEEE8021X"; else value = "WPA-PSK"; break; case WPS_AUTHTYPE_WPA: case WPS_AUTHTYPE_WPA2: if (enabled8021X) value = "WPA-EAP IEEE8021X"; else value = "WPA-EAP"; break; default: value = 0; break; } if (!value | wpa_config_set(ssid, var, value, 0)) break; /* proto */ var = "proto"; switch (auth) { case WPS_AUTHTYPE_WPA: case WPS_AUTHTYPE_WPAPSK: value = "WPA"; break; case WPS_AUTHTYPE_WPA2: case WPS_AUTHTYPE_WPA2PSK: value = "RSN"; break; default: ssid->proto = 0; value = 0; break; } if (value && wpa_config_set(ssid, var, value, 0)) break; /* pariwise */ var = "pairwise"; switch (encr) { case WPS_ENCRTYPE_NONE: ssid->pairwise_cipher = WPA_CIPHER_NONE; value = 0; break; case WPS_ENCRTYPE_TKIP: value = "TKIP"; break; case WPS_ENCRTYPE_AES: value = "CCMP"; break; default: value = 0; break; } if (value && wpa_config_set(ssid, var, value, 0)) break; /* group */ var = "group"; switch (encr) { case WPS_ENCRTYPE_NONE: ssid->group_cipher = WPA_CIPHER_NONE; value = 0; break; case WPS_ENCRTYPE_WEP: value = "WEP104 WEP40"; break; case WPS_ENCRTYPE_TKIP: value = "TKIP"; break; case WPS_ENCRTYPE_AES: #if 0 /* original */ value = "CCMP"; #else /* HACK! */ /* It is not uncommon for group cipher to be * TKIP whereas the pairwise is CCMP, but * WPS makes no distinction. * Workaround by configuring both in this case. */ value = "TKIP CCMP"; #endif break; default: value = 0; break; } if (value && wpa_config_set(ssid, var, value, 0)) break; /* wep_tx_keyidx */ var = "wep_tx_keyidx"; switch (encr) { case WPS_ENCRTYPE_WEP: value = (char *)os_malloc(2); if (!value) break; os_snprintf(value, 2, "%d", nwKeyIdx - 1); break; default: value = 0; break; } if (value && wpa_config_set(ssid, var, value, 0)) { free(value); break; } else if (value) free(value); if (!value && (WPS_ENCRTYPE_WEP == encr)) break; /* wep_keyn */ switch (encr) { case WPS_ENCRTYPE_WEP: var = (char *)os_malloc(9); if (!var) break; os_snprintf(var, 9, "wep_key%d", nwKeyIdx - 1); if (is_hex(nwKey, nwKey_length)) { value = (char *)os_malloc(nwKey_length * 2 + 1); if (!value) break; wpa_snprintf_hex_uppercase(value, nwKey_length * 2 + 1, nwKey, nwKey_length); value[nwKey_length * 2] = 0; } else if ((5 == nwKey_length) || (13 == nwKey_length)) { value = (char *)os_malloc(nwKey_length + 3); if (!value) break; os_snprintf(value, nwKey_length + 3, "\"%s\"", nwKey); } else if ((nwKey_length) || (13 == nwKey_length)) { value = (char *)os_malloc(nwKey_length + 1); if (!value) break; os_memcpy(value, nwKey, nwKey_length); value[nwKey_length] = 0; } break; default: var = 0; value = 0; break; } if (var && value && wpa_config_set(ssid, var, value, 0)) break; if (var) free(var); if (value) free(value); if ((!var || !value) && (WPS_ENCRTYPE_WEP == encr)) break; /* psk */ var = "psk"; switch (auth) { case WPS_AUTHTYPE_WPA: case WPS_AUTHTYPE_WPA2: case WPS_AUTHTYPE_WPAPSK: case WPS_AUTHTYPE_WPA2PSK: if (nwKey_length) { value = (char *)os_malloc(nwKey_length + 3); if (!value) break; if (64 > nwKey_length) { os_snprintf(value, nwKey_length + 3, "\"%s\"", nwKey); passphrase = 1; } else if (64 == nwKey_length) { os_memcpy(value, nwKey, nwKey_length); value[nwKey_length] = 0; } else { free(value); value = 0; break; } } else value = 0; break; default: value = 0; break; } if (value && wpa_config_set(ssid, var, value, 0)) { free(value); break; } else if (value) free(value); if (nwKey_length && !value && ((WPS_AUTHTYPE_WPA == auth) || (WPS_AUTHTYPE_WPA2 == auth) || (WPS_AUTHTYPE_WPAPSK == auth) || (WPS_AUTHTYPE_WPA2PSK == auth))) break; /* eap */ if (eapType && os_strlen(eapType)) { var = "eap"; value = (char *)eapType; if (wpa_config_set(ssid, var, value, 0)) break; } /* identity */ if (eapIdentity && os_strlen(eapIdentity)) { var = "identity"; value = (char *)eapIdentity; if (wpa_config_set(ssid, var, value, 0)) break; } ret = 0; } while (0); (void)wps_destroy_wps_data(&wps); if (ret) { if (ssid) (void)wpa_config_remove_network(wpa_s->conf, ssid->id); } else { if (passphrase) wpa_config_update_psk(ssid); } if (nwKey) free(nwKey); if (eapType) free(eapType); if (eapIdentity) free(eapIdentity); return ret?ret:ssid->id; }
static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) { struct wpa_ssid *ssid; int errors = 0, end = 0; char buf[256], *pos, *pos2; wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block", *line); ssid = (struct wpa_ssid *) malloc(sizeof(*ssid)); if (ssid == NULL) return NULL; memset(ssid, 0, sizeof(*ssid)); ssid->id = id; ssid->proto = WPA_PROTO_WPA | WPA_PROTO_RSN; ssid->pairwise_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP; ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40; ssid->key_mgmt = WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X; ssid->eapol_flags = EAPOL_FLAG_REQUIRE_KEY_UNICAST | EAPOL_FLAG_REQUIRE_KEY_BROADCAST; ssid->eap_workaround = (unsigned int) -1; while ((pos = wpa_config_get_line(buf, sizeof(buf), f, line))) { if (strcmp(pos, "}") == 0) { end = 1; break; } pos2 = strchr(pos, '='); if (pos2 == NULL) { wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line " "'%s'.", *line, pos); errors++; continue; } *pos2++ = '\0'; if (*pos2 == '"') { if (strchr(pos2 + 1, '"') == NULL) { wpa_printf(MSG_ERROR, "Line %d: invalid " "quotation '%s'.", *line, pos2); errors++; continue; } } if (wpa_config_set(ssid, pos, pos2, *line) < 0) errors++; } if (!end) { wpa_printf(MSG_ERROR, "Line %d: network block was not " "terminated properly.", *line); errors++; } if (ssid->passphrase) { if (ssid->psk_set) { wpa_printf(MSG_ERROR, "Line %d: both PSK and " "passphrase configured.", *line); errors++; } wpa_config_update_psk(ssid); } if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) { wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key " "management, but no PSK configured.", *line); errors++; } if ((ssid->group_cipher & WPA_CIPHER_CCMP) && !(ssid->pairwise_cipher & WPA_CIPHER_CCMP)) { /* Group cipher cannot be stronger than the pairwise cipher. */ wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher" " list since it was not allowed for pairwise " "cipher", *line); ssid->group_cipher &= ~WPA_CIPHER_CCMP; } if (errors) { free(ssid); ssid = NULL; } return ssid; }
struct wpa_scan_result *wps_select_ssid(struct wpa_supplicant *wpa_s, struct wpa_scan_result *results, int num, struct wpa_ssid **ssid) { struct wpa_scan_result *bss; struct wpa_scan_result *selected = 0; int num_good; struct wpa_scan_result *maybe = 0; int num_maybe; struct wpa_ssid *tmp; int ret = -1; char *var, *value; struct wps_data *data = 0; char bssid_str[18+1]; char ssid_str[32+3]; u8 uuidSel[SIZE_UUID]; u8 uuidBss[SIZE_UUID]; size_t length; struct wps_config *wps; int i; int is_push_button; do { if (!wpa_s || !wpa_s->conf || !results || !num || !ssid) break; wps = wpa_s->conf->wps; is_push_button = (wps->dev_pwd_len == 8 && memcmp(wps->dev_pwd, "00000000", 8) == 0); if (wps->nwid_trying_wps != -1) { (void)wpa_config_remove_network(wpa_s->conf, wps->nwid_trying_wps); wps->nwid_trying_wps = -1; } *ssid = 0; num_good = 0; num_maybe = 0; for (i = 0; i < num; i++) { bss = &results[i]; if (wps->filter_bssid_flag && memcmp( wps->filter_bssid, bss->bssid, 6) != 0) { continue; } if (wps->filter_ssid_length > 0 && memcmp( wps->filter_ssid, bss->ssid, wps->filter_ssid_length) != 0) { continue; } if (bss->wps_ie_len) { u16 dev_pwd_id; do { if (wps_create_wps_data(&data)) break; if (wps_parse_wps_ie(bss->wps_ie, bss->wps_ie_len, data)) break; length = sizeof(uuidBss); /* selected bss UUID-E */ if (wps_get_value(data, WPS_TYPE_UUID_E, uuidBss, &length)) break; if (wps_get_value(data, WPS_TYPE_DEVICE_PWD_ID, &dev_pwd_id, 0)) break; if (is_push_button) { if (WPS_DEVICEPWDID_PUSH_BTN != dev_pwd_id) break; } else { /* PIN mode */ if (WPS_DEVICEPWDID_DEFAULT != dev_pwd_id) { break; } } /* In the case of a dual-band AP and a dual-band station, * the station may discover more than one Registrar in PBC mode. * If the dual-band station does discover more than one Registrar * in PBC mode, one each RF band, and the UUID in the Beacon and * Probe-Response are the same for all RF bands, then the station * shall not consider this to be a session overlap. */ if (num_good) { /* check dual-band concurrent AP case */ if (((selected->freq >= 4000) && (bss->freq <= 3000)) || ((selected->freq <= 3000) && (bss->freq >= 4000))) { /* one is 2.4GHz and another is 5GHz */ if (memcmp(uuidSel, uuidBss, length) == 0) { /* UUID-E of them are totally the same */ /* Select the 5GHz one */ if (bss->freq >= 4000) selected = bss; break; } } } selected = bss; memcpy(&uuidSel, &uuidBss, length); num_good++; } while (0); (void)wps_destroy_wps_data(&data); /* If we have WPS at all then it's a maybe * for PIN */ if (!is_push_button) { num_maybe++; if ((!maybe) || (bss->qual > maybe->qual)) { maybe = bss; } } } else { /* No WPS IE */ /* If in open mode, it may support WPS... * (some microsoft products) * take it as a maybe */ if ((bss->caps & IEEE80211_CAP_PRIVACY) == 0) { num_maybe++; if ((!maybe) || (bss->qual > maybe->qual)) { maybe = bss; } } } } /* Push button mode must have exact explicit match. * For PIN mode, due to greater security, we are willing * to be more lenient; and due to the ambiguity of the WPS * standard, it is not actually required that the AP * advertise it's PIN mode (as versus PB mode * which requires such advertisement). * But we want either one good match, or if no good match, * then just one maybe... otherwise the user should have * done pre-filtering.... * for best results, the user should do pre-filtering! */ if (is_push_button) { if (num_good > 1) { wpa_msg(wpa_s, MSG_INFO, "Must be only one AP enabled WPS-PBC"); break; } else if (num_good == 1) { /* good */ } else if (num_good == 0) { wpa_msg(wpa_s, MSG_INFO, "There are no APs which are enabled WPS-PBC"); break; } } else { /* PIN mode */ if (num_good > 1) { wpa_msg(wpa_s, MSG_INFO, "Must be only one AP enabled WPS-PIN"); break; } else if (num_good == 1) { /* good */ } else if (num_maybe > 1) { wpa_msg(wpa_s, MSG_INFO, "There are no APs which are enabled WPS-PIN" " but attaching WPS IE, concern some microsoft products," " try to connect strongest RSSI one"); selected = maybe; } else if (num_maybe == 1) { /* select this one */ selected = maybe; } else { wpa_msg(wpa_s, MSG_INFO, "There are no APs available for WPS"); break; } } if (!selected) break; *ssid = wpa_config_add_network(wpa_s->conf); if (!*ssid) break; wpa_config_set_network_defaults(*ssid); (*ssid)->disabled = 1; /* bssid */ var = "bssid"; os_snprintf(bssid_str, sizeof(bssid_str), "%02X:%02X:%02X:%02X:%02X:%02X", selected->bssid[0], selected->bssid[1], selected->bssid[2], selected->bssid[3], selected->bssid[4], selected->bssid[5]); bssid_str[18] = 0; if (wpa_config_set(*ssid, var, bssid_str, 0)) break; /* ssid */ var = "ssid"; ssid_str[0] = '"'; os_memcpy(ssid_str + 1, selected->ssid, selected->ssid_len); ssid_str[selected->ssid_len + 1] = '"'; ssid_str[selected->ssid_len + 2] = 0; if (wpa_config_set(*ssid, var, ssid_str, 0)) break; /* auth_alg */ var = "auth_alg"; value = "OPEN"; if (wpa_config_set(*ssid, var, value, 0)) break; /* key_mgmt */ var = "key_mgmt"; value = "IEEE8021X"; if (wpa_config_set(*ssid, var, value, 0)) break; /* eap */ var = "eap"; value = "WPS"; if (wpa_config_set(*ssid, var, value, 0)) break; /* identity */ var = "identity"; free((*ssid)->identity); switch (wps->reg_mode) { case WPS_SUPPLICANT_REGMODE_NONE: value = WPS_IDENTITY_ENROLLEE; break; default: value = WPS_IDENTITY_REGISTRAR; break; } (*ssid)->identity = (u8 *)os_strdup(value); (*ssid)->identity_len = os_strlen(value); ret = 0; } while (0); if (ret) { if (*ssid) (void)wpa_config_remove_network(wpa_s->conf, (*ssid)->id); selected = 0; } else { wpa_msg(wpa_s, MSG_INFO, "Found AP for WPS [%*s]", (*ssid)->ssid_len,(*ssid)->ssid); switch (wps->reg_mode) { case WPS_SUPPLICANT_REGMODE_NONE: if (wps->config) { free(wps->config); wps->config = 0; wps->config_len = 0; } break; case WPS_SUPPLICANT_REGMODE_CONFIGURE_AP: break; case WPS_SUPPLICANT_REGMODE_REGISTER_AP: case WPS_SUPPLICANT_REGMODE_REGISTER_STA: if (wps->config) { free(wps->config); wps->config = 0; wps->config_len = 0; } (void)wps_get_supplicant_ssid_configuration(wpa_s, (*ssid)->id, &wps->config, &wps->config_len); break; default: break; } if (wpa_s->current_ssid) wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); tmp = wpa_s->conf->ssid; while (tmp) { #if 0 /* original from Sony */ tmp->disabled = (*ssid)->id != tmp->id; #else /* Set bit 1 of disabled as "temporary WPS bit" */ tmp->disabled = ((*ssid)->id != tmp->id) << 1; #endif tmp = tmp->next; } wps->nwid_trying_wps = (*ssid)->id; wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); } return selected; }
int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { struct wpa_ssid *ssid; struct nai_realm *realm; struct nai_realm_eap *eap = NULL; u16 count, i; char buf[100]; const u8 *ie; if (bss == NULL) return -1; ie = wpa_bss_get_ie(bss, WLAN_EID_SSID); if (ie == NULL || ie[1] == 0) { wpa_printf(MSG_DEBUG, "Interworking: No SSID known for " MACSTR, MAC2STR(bss->bssid)); return -1; } realm = nai_realm_parse(bss->anqp_nai_realm, &count); if (realm == NULL) { wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI " "Realm list from " MACSTR, MAC2STR(bss->bssid)); count = 0; } for (i = 0; i < count; i++) { if (!nai_realm_match(&realm[i], wpa_s->conf->home_realm)) continue; eap = nai_realm_find_eap(wpa_s, &realm[i]); if (eap) break; } if (!eap) { if (interworking_connect_3gpp(wpa_s, bss) == 0) { if (realm) nai_realm_free(realm, count); return 0; } wpa_printf(MSG_DEBUG, "Interworking: No matching credentials " "and EAP method found for " MACSTR, MAC2STR(bss->bssid)); nai_realm_free(realm, count); return -1; } wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR, MAC2STR(bss->bssid)); ssid = wpa_config_add_network(wpa_s->conf); if (ssid == NULL) { nai_realm_free(realm, count); return -1; } wpas_notify_network_added(wpa_s, ssid); wpa_config_set_network_defaults(ssid); ssid->temporary = 1; ssid->ssid = os_zalloc(ie[1] + 1); if (ssid->ssid == NULL) goto fail; os_memcpy(ssid->ssid, ie + 2, ie[1]); ssid->ssid_len = ie[1]; if (wpa_config_set(ssid, "eap", eap_get_name(EAP_VENDOR_IETF, eap->method), 0) < 0) goto fail; if (wpa_s->conf->home_username && wpa_s->conf->home_username[0] && wpa_config_set_quoted(ssid, "identity", wpa_s->conf->home_username) < 0) goto fail; if (wpa_s->conf->home_password && wpa_s->conf->home_password[0] && wpa_config_set_quoted(ssid, "password", wpa_s->conf->home_password) < 0) goto fail; switch (eap->method) { case EAP_TYPE_TTLS: if (eap->inner_method) { os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", eap_get_name(EAP_VENDOR_IETF, eap->inner_method)); if (wpa_config_set(ssid, "phase2", buf, 0) < 0) goto fail; break; } switch (eap->inner_non_eap) { case NAI_REALM_INNER_NON_EAP_PAP: if (wpa_config_set(ssid, "phase2", "\"auth=PAP\"", 0) < 0) goto fail; break; case NAI_REALM_INNER_NON_EAP_CHAP: if (wpa_config_set(ssid, "phase2", "\"auth=CHAP\"", 0) < 0) goto fail; break; case NAI_REALM_INNER_NON_EAP_MSCHAP: if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAP\"", 0) < 0) goto fail; break; case NAI_REALM_INNER_NON_EAP_MSCHAPV2: if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"", 0) < 0) goto fail; break; } break; case EAP_TYPE_PEAP: os_snprintf(buf, sizeof(buf), "\"auth=%s\"", eap_get_name(EAP_VENDOR_IETF, eap->inner_method)); if (wpa_config_set(ssid, "phase2", buf, 0) < 0) goto fail; break; } if (wpa_s->conf->home_ca_cert && wpa_s->conf->home_ca_cert[0] && wpa_config_set_quoted(ssid, "ca_cert", wpa_s->conf->home_ca_cert) < 0) goto fail; nai_realm_free(realm, count); wpa_supplicant_select_network(wpa_s, ssid); return 0; fail: wpas_notify_network_removed(wpa_s, ssid); wpa_config_remove_network(wpa_s->conf, ssid->id); nai_realm_free(realm, count); return -1; }
static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { #ifdef INTERWORKING_3GPP struct wpa_ssid *ssid; const u8 *ie; ie = wpa_bss_get_ie(bss, WLAN_EID_SSID); if (ie == NULL) return -1; wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " (3GPP)", MAC2STR(bss->bssid)); ssid = wpa_config_add_network(wpa_s->conf); if (ssid == NULL) return -1; wpas_notify_network_added(wpa_s, ssid); wpa_config_set_network_defaults(ssid); ssid->temporary = 1; ssid->ssid = os_zalloc(ie[1] + 1); if (ssid->ssid == NULL) goto fail; os_memcpy(ssid->ssid, ie + 2, ie[1]); ssid->ssid_len = ie[1]; /* TODO: figure out whether to use EAP-SIM, EAP-AKA, or EAP-AKA' */ if (wpa_config_set(ssid, "eap", "SIM", 0) < 0) { wpa_printf(MSG_DEBUG, "EAP-SIM not supported"); goto fail; } if (set_root_nai(ssid, wpa_s->conf->home_imsi, '1') < 0) { wpa_printf(MSG_DEBUG, "Failed to set Root NAI"); goto fail; } if (wpa_s->conf->home_milenage && wpa_s->conf->home_milenage[0]) { if (wpa_config_set_quoted(ssid, "password", wpa_s->conf->home_milenage) < 0) goto fail; } else { /* TODO: PIN */ if (wpa_config_set_quoted(ssid, "pcsc", "") < 0) goto fail; } if (wpa_s->conf->home_password && wpa_s->conf->home_password[0] && wpa_config_set_quoted(ssid, "password", wpa_s->conf->home_password) < 0) goto fail; wpa_supplicant_select_network(wpa_s, ssid); return 0; fail: wpas_notify_network_removed(wpa_s, ssid); wpa_config_remove_network(wpa_s->conf, ssid->id); #endif /* INTERWORKING_3GPP */ return -1; }
/** * wpas_dbus_iface_set_network - Set options for a configured network * @message: Pointer to incoming dbus message * @wpa_s: wpa_supplicant structure for a network interface * @ssid: wpa_ssid structure for a configured network * Returns: a dbus message containing a UINT32 indicating success (1) or * failure (0) * * Handler function for "set" method call of a configured network. */ DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message, struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { DBusMessage *reply = NULL; struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; DBusMessageIter iter, iter_dict; dbus_message_iter_init(message, &iter); if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) { reply = wpas_dbus_new_invalid_opts_error(message, NULL); goto out; } while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { char *value = NULL; size_t size = 50; int ret; if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { reply = wpas_dbus_new_invalid_opts_error(message, NULL); goto out; } /* Type conversions, since wpa_supplicant wants strings */ if (entry.type == DBUS_TYPE_ARRAY && entry.array_type == DBUS_TYPE_BYTE) { if (entry.array_len <= 0) goto error; size = entry.array_len * 2 + 1; value = os_zalloc(size); if (value == NULL) goto error; ret = wpa_snprintf_hex(value, size, (u8 *) entry.bytearray_value, entry.array_len); if (ret <= 0) goto error; } else if (entry.type == DBUS_TYPE_STRING) { if (should_quote_opt(entry.key)) { size = os_strlen(entry.str_value); /* Zero-length option check */ if (size <= 0) goto error; size += 3; /* For quotes and terminator */ value = os_zalloc(size); if (value == NULL) goto error; ret = os_snprintf(value, size, "\"%s\"", entry.str_value); if (ret < 0 || (size_t) ret != (size - 1)) goto error; } else { value = os_strdup(entry.str_value); if (value == NULL) goto error; } } else if (entry.type == DBUS_TYPE_UINT32) { value = os_zalloc(size); if (value == NULL) goto error; ret = os_snprintf(value, size, "%u", entry.uint32_value); if (ret <= 0) goto error; } else if (entry.type == DBUS_TYPE_INT32) { value = os_zalloc(size); if (value == NULL) goto error; ret = os_snprintf(value, size, "%d", entry.int32_value); if (ret <= 0) goto error; } else goto error; if (wpa_config_set(ssid, entry.key, value, 0) < 0) goto error; if ((os_strcmp(entry.key, "psk") == 0 && value[0] == '"' && ssid->ssid_len) || (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase)) wpa_config_update_psk(ssid); else if (os_strcmp(entry.key, "priority") == 0) wpa_config_update_prio_list(wpa_s->conf); os_free(value); wpa_dbus_dict_entry_clear(&entry); continue; error: os_free(value); reply = wpas_dbus_new_invalid_opts_error(message, entry.key); wpa_dbus_dict_entry_clear(&entry); break; } if (!reply) reply = wpas_dbus_new_success_reply(message); out: return reply; }
static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s, int registrar, const u8 *bssid) { struct wpa_ssid *ssid; ssid = wpa_config_add_network(wpa_s->conf); if (ssid == NULL) return NULL; wpas_notify_network_added(wpa_s, ssid); wpa_config_set_network_defaults(ssid); ssid->temporary = 1; if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 || wpa_config_set(ssid, "eap", "WSC", 0) < 0 || wpa_config_set(ssid, "identity", registrar ? "\"" WSC_ID_REGISTRAR "\"" : "\"" WSC_ID_ENROLLEE "\"", 0) < 0) { wpas_notify_network_removed(wpa_s, ssid); wpa_config_remove_network(wpa_s->conf, ssid->id); return NULL; } if (bssid) { #ifndef CONFIG_P2P struct wpa_bss *bss; int count = 0; #endif /* CONFIG_P2P */ os_memcpy(ssid->bssid, bssid, ETH_ALEN); ssid->bssid_set = 1; /* * Note: With P2P, the SSID may change at the time the WPS * provisioning is started, so better not filter the AP based * on the current SSID in the scan results. */ #ifndef CONFIG_P2P dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { if (os_memcmp(bssid, bss->bssid, ETH_ALEN) != 0) continue; os_free(ssid->ssid); ssid->ssid = os_malloc(bss->ssid_len); if (ssid->ssid == NULL) break; os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); ssid->ssid_len = bss->ssid_len; wpa_hexdump_ascii(MSG_DEBUG, "WPS: Picked SSID from " "scan results", ssid->ssid, ssid->ssid_len); count++; } if (count > 1) { wpa_printf(MSG_DEBUG, "WPS: More than one SSID found " "for the AP; use wildcard"); os_free(ssid->ssid); ssid->ssid = NULL; ssid->ssid_len = 0; } #endif /* CONFIG_P2P */ } return ssid; }