static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) { int errors = 0; 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 | WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_PSK_SHA256)) && !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) && !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { /* 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; } return errors; }
static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) { int errors = 0; 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->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, "Line %d: removed CCMP from group cipher" " list since it was not allowed for pairwise " "cipher", line); ssid->group_cipher &= ~WPA_CIPHER_CCMP; } if (ssid->mode == WPAS_MODE_MESH && (ssid->key_mgmt != WPA_KEY_MGMT_NONE && ssid->key_mgmt != WPA_KEY_MGMT_SAE)) { wpa_printf(MSG_ERROR, "Line %d: key_mgmt for mesh network should be open or SAE", line); errors++; } return errors; }
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_wps_cred(void *ctx, const struct wps_credential *cred) { struct wpa_supplicant *wpa_s = ctx; struct wpa_ssid *ssid = wpa_s->current_ssid; u8 key_idx = 0; u16 auth_type; if ((wpa_s->conf->wps_cred_processing == 1 || wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) { size_t blen = cred->cred_attr_len * 2 + 1; char *buf = os_malloc(blen); if (buf) { wpa_snprintf_hex(buf, blen, cred->cred_attr, cred->cred_attr_len); wpa_msg(wpa_s, MSG_INFO, "%s%s", WPS_EVENT_CRED_RECEIVED, buf); os_free(buf); } wpas_notify_wps_credential(wpa_s, cred); } else wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED); wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", cred->cred_attr, cred->cred_attr_len); if (wpa_s->conf->wps_cred_processing == 1) return 0; wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len); wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x", cred->auth_type); wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type); wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx); wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", cred->key, cred->key_len); wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(cred->mac_addr)); auth_type = cred->auth_type; if (auth_type == (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) { wpa_printf(MSG_DEBUG, "WPS: Workaround - convert mixed-mode " "auth_type into WPA2PSK"); auth_type = WPS_AUTH_WPA2PSK; } if (auth_type != WPS_AUTH_OPEN && auth_type != WPS_AUTH_SHARED && auth_type != WPS_AUTH_WPAPSK && auth_type != WPS_AUTH_WPA2PSK) { wpa_printf(MSG_DEBUG, "WPS: Ignored credentials for " "unsupported authentication type 0x%x", auth_type); return 0; } if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { wpa_printf(MSG_DEBUG, "WPS: Replace WPS network block based " "on the received credential"); os_free(ssid->eap.identity); ssid->eap.identity = NULL; ssid->eap.identity_len = 0; os_free(ssid->eap.phase1); ssid->eap.phase1 = NULL; os_free(ssid->eap.eap_methods); ssid->eap.eap_methods = NULL; } else { wpa_printf(MSG_DEBUG, "WPS: Create a new network based on the " "received credential"); 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); os_free(ssid->ssid); ssid->ssid = os_malloc(cred->ssid_len); if (ssid->ssid) { os_memcpy(ssid->ssid, cred->ssid, cred->ssid_len); ssid->ssid_len = cred->ssid_len; } switch (cred->encr_type) { case WPS_ENCR_NONE: break; case WPS_ENCR_WEP: if (cred->key_len <= 0) break; if (cred->key_len != 5 && cred->key_len != 13 && cred->key_len != 10 && cred->key_len != 26) { wpa_printf(MSG_ERROR, "WPS: Invalid WEP Key length " "%lu", (unsigned long) cred->key_len); return -1; } if (cred->key_idx > NUM_WEP_KEYS) { wpa_printf(MSG_ERROR, "WPS: Invalid WEP Key index %d", cred->key_idx); return -1; } if (cred->key_idx) key_idx = cred->key_idx - 1; if (cred->key_len == 10 || cred->key_len == 26) { if (hexstr2bin((char *) cred->key, ssid->wep_key[key_idx], cred->key_len / 2) < 0) { wpa_printf(MSG_ERROR, "WPS: Invalid WEP Key " "%d", key_idx); return -1; } ssid->wep_key_len[key_idx] = cred->key_len / 2; } else { os_memcpy(ssid->wep_key[key_idx], cred->key, cred->key_len); ssid->wep_key_len[key_idx] = cred->key_len; } ssid->wep_tx_keyidx = key_idx; break; case WPS_ENCR_TKIP: ssid->pairwise_cipher = WPA_CIPHER_TKIP; break; case WPS_ENCR_AES: ssid->pairwise_cipher = WPA_CIPHER_CCMP; break; } switch (auth_type) { case WPS_AUTH_OPEN: ssid->auth_alg = WPA_AUTH_ALG_OPEN; ssid->key_mgmt = WPA_KEY_MGMT_NONE; ssid->proto = 0; break; case WPS_AUTH_SHARED: ssid->auth_alg = WPA_AUTH_ALG_SHARED; ssid->key_mgmt = WPA_KEY_MGMT_NONE; ssid->proto = 0; break; case WPS_AUTH_WPAPSK: ssid->auth_alg = WPA_AUTH_ALG_OPEN; ssid->key_mgmt = WPA_KEY_MGMT_PSK; ssid->proto = WPA_PROTO_WPA; break; case WPS_AUTH_WPA: ssid->auth_alg = WPA_AUTH_ALG_OPEN; ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X; ssid->proto = WPA_PROTO_WPA; break; case WPS_AUTH_WPA2: ssid->auth_alg = WPA_AUTH_ALG_OPEN; ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X; ssid->proto = WPA_PROTO_RSN; break; case WPS_AUTH_WPA2PSK: ssid->auth_alg = WPA_AUTH_ALG_OPEN; ssid->key_mgmt = WPA_KEY_MGMT_PSK; ssid->proto = WPA_PROTO_RSN; break; } if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) { if (cred->key_len == 2 * PMK_LEN) { if (hexstr2bin((const char *) cred->key, ssid->psk, PMK_LEN)) { wpa_printf(MSG_ERROR, "WPS: Invalid Network " "Key"); return -1; } ssid->psk_set = 1; } else if (cred->key_len >= 8 && cred->key_len < 2 * PMK_LEN) { os_free(ssid->passphrase); ssid->passphrase = os_malloc(cred->key_len + 1); if (ssid->passphrase == NULL) return -1; os_memcpy(ssid->passphrase, cred->key, cred->key_len); ssid->passphrase[cred->key_len] = '\0'; wpa_config_update_psk(ssid); } else { wpa_printf(MSG_ERROR, "WPS: Invalid Network Key " "length %lu", (unsigned long) cred->key_len); return -1; } } wpas_wps_security_workaround(wpa_s, ssid, cred); #ifndef CONFIG_NO_CONFIG_WRITE if (wpa_s->conf->update_config && wpa_config_write(wpa_s->confname, wpa_s->conf)) { wpa_printf(MSG_DEBUG, "WPS: Failed to update configuration"); return -1; } #endif /* CONFIG_NO_CONFIG_WRITE */ return 0; }
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; }
static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) { int errors = 0; #ifdef WAPI if ( ((ssid->proto & WPA_PROTO_WAPI) || (ssid->wapi !=0)) && (ssid->key_mgmt != WPA_KEY_MGMT_WAPI_PSK) && (ssid->key_mgmt != WPA_KEY_MGMT_WAPI_CERT) ) { /* map original IWNCOMM .conf structure to WPA Supplicant style */ if (ssid->wapi & 0x08) { ssid->key_mgmt = WPA_KEY_MGMT_WAPI_CERT; } else if (ssid->wapi & 0x04) { ssid->key_mgmt = WPA_KEY_MGMT_WAPI_PSK; } else { wpa_printf(MSG_ERROR, "Line %d: unknown wapi policy %d\n", line, ssid->wapi); errors++; } if (ssid->pairwise_cipher != WPA_CIPHER_SMS4) { ssid->pairwise_cipher = WPA_CIPHER_SMS4; } if (ssid->group_cipher != WPA_CIPHER_SMS4) { ssid->group_cipher = WPA_CIPHER_SMS4; } } else if ( ((ssid->key_mgmt == WPA_KEY_MGMT_WAPI_PSK) || (ssid->key_mgmt == WPA_KEY_MGMT_WAPI_CERT)) && (((ssid->proto & WPA_PROTO_WAPI) == 0) || (ssid->wapi==0)) ) { /* map WPA supplicant style to IWNCOMM .conf structure */ if (ssid->key_mgmt == WPA_KEY_MGMT_WAPI_PSK) { ssid->proto = WPA_PROTO_WAPI; ssid->wapi = 7; } if (ssid->key_mgmt == WPA_KEY_MGMT_WAPI_CERT) { ssid->proto = WPA_PROTO_WAPI; ssid->wapi = 11; } if (ssid->pairwise_cipher != WPA_CIPHER_SMS4) { ssid->pairwise_cipher = WPA_CIPHER_SMS4; } if (ssid->group_cipher != WPA_CIPHER_SMS4) { ssid->group_cipher = WPA_CIPHER_SMS4; } } else { #endif 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) && !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { /* 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; } #ifdef WAPI } #endif return errors; }
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; }
/** * 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; }
/* * 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; }
void wsc_supplicant_EapSuccess(TStaEncryptSettings* pStaEncryptSettings) { struct wpa_ssid *ssid = WscSupplicantConfig.ssid; int i; /* for now we only support one credential inside M8 settings */ TTlvCredential *p_Credentials = &(pStaEncryptSettings->credential); WscSupplicantConfig.smState = WSC_STATE_SUCCESS; wpa_drv_set_wsc_mode(WscSupplicantConfig.wpa_s, WSC_MODE_OFF, NULL, 0); wpa_printf (MSG_DEBUG, "wsc_supplicant: wsc_supplicant_EapSuccess: Acquired network block authType = 0x%x",p_Credentials->authType); if ((p_Credentials->authType & WSC_AUTHTYPE_WPAPSK) || (p_Credentials->authType & WSC_AUTHTYPE_WPA2PSK) || (p_Credentials->authType & WSC_AUTHTYPE_OPEN) || (p_Credentials->authType & WSC_AUTHTYPE_SHARED)) { ssid->mode = IEEE80211_MODE_INFRA; ssid->proto = DEFAULT_PROTO; ssid->key_mgmt = WPA_KEY_MGMT_NONE; ssid->auth_alg = AUTH_ALG_OPEN_SYSTEM; if ((p_Credentials->authType & WSC_AUTHTYPE_WPAPSK) || (p_Credentials->authType & WSC_AUTHTYPE_WPA2PSK)) { wpa_printf (MSG_DEBUG, "wsc_supplicant: wsc_supplicant_EapSuccess: length of nw_key = %d",p_Credentials->nwKey[DEFAULT_KEY_INDEX].length); if (p_Credentials->nwKey[DEFAULT_KEY_INDEX].length == 64) { if( 0 == hexstr2bin ((char *)(p_Credentials->nwKey[DEFAULT_KEY_INDEX].pValue), (u8 *)(&ssid->psk), (p_Credentials->nwKey[DEFAULT_KEY_INDEX].length / 2))) { wpa_printf (MSG_DEBUG, "wsc_supplicant: wsc_supplicant_EapSuccess: successfully converted hex string into binary data"); ssid->psk_set=1; } else { wpa_printf (MSG_ERROR, "wsc_supplicant: wsc_supplicant_EapSuccess: sorry but I couldn't convert hex string into binary data"); } } else if ((p_Credentials->nwKey[DEFAULT_KEY_INDEX].length < 64) && (p_Credentials->nwKey[DEFAULT_KEY_INDEX].length > 0)) { /* put PSK */ if(ssid->passphrase) free(ssid->passphrase); ssid->passphrase = malloc(p_Credentials->nwKey[DEFAULT_KEY_INDEX].length+1); strncpy(ssid->passphrase, p_Credentials->nwKey[DEFAULT_KEY_INDEX].pValue, p_Credentials->nwKey[DEFAULT_KEY_INDEX].length); ssid->passphrase[p_Credentials->nwKey[DEFAULT_KEY_INDEX].length] = '\0'; ssid->psk_set=0; wpa_config_update_psk(ssid); wpa_printf (MSG_DEBUG,"wsc_supplicant: wsc_supplicant_EapSuccess: psk string (ASCII): %s",ssid->passphrase); } } else if (p_Credentials->authType & WSC_AUTHTYPE_SHARED) { ssid->auth_alg = WPA_AUTH_ALG_SHARED; } /* In case of WEP shared or open - get WEP key and TX key index*/ if (p_Credentials->encrType & WSC_ENCRTYPE_WEP) { ssid->pairwise_cipher = WPA_CIPHER_NONE; ssid->group_cipher = WPA_CIPHER_NONE; ssid->wep_tx_keyidx = p_Credentials->WEP_transmit_key; for (i=0; i<MAX_NETWORK_KEY_NUM; i++) { /* In case of ASCII encoded keys */ if ((p_Credentials->nwKey[DEFAULT_KEY_INDEX].length == 5) || (p_Credentials->nwKey[DEFAULT_KEY_INDEX].length == 13)) { /* ssid->wep_key */ } /* In case of HEX encoded keys */ else if ((p_Credentials->nwKey[DEFAULT_KEY_INDEX].length == 10) || (p_Credentials->nwKey[DEFAULT_KEY_INDEX].length == 26)) { /* ssid->wep_key */ } else { wpa_printf (MSG_ERROR,"wsc_supplicant: wrong WEP key length"); } } } if (p_Credentials->authType & WSC_AUTHTYPE_WPAPSK) { ssid->key_mgmt = WPA_KEY_MGMT_PSK; ssid->proto = WPA_PROTO_WPA; ssid->pairwise_cipher = WPA_CIPHER_TKIP; ssid->group_cipher = WPA_CIPHER_TKIP; } else if (p_Credentials->authType & WSC_AUTHTYPE_WPA2PSK) { ssid->key_mgmt = WPA_KEY_MGMT_PSK; ssid->proto = WPA_PROTO_RSN; ssid->pairwise_cipher = WPA_CIPHER_CCMP; // TI - we have no way to know that we are woking with MIX MODE , so this is the reason we configuere the group to CCMP|TKIP ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP; } else if (p_Credentials->authType & WSC_AUTHTYPE_OPEN) { ssid->key_mgmt = WPA_KEY_MGMT_NONE; } wpa_config_write(((struct wpa_supplicant*)WscSupplicantConfig.wpa_s)->confname, ((struct wpa_supplicant*)WscSupplicantConfig.wpa_s)->conf); } else { wpa_printf (MSG_ERROR, "wsc_supplicant: wsc_supplicant_EapSuccess: Invalid Authentication algotirhm...aborting..."); return; } ssid->disabled = 0; ssid->wsc_mode = WSC_MODE_OFF; ((struct wpa_supplicant*)WscSupplicantConfig.wpa_s)->reassociate = 1; wpa_supplicant_req_scan(WscSupplicantConfig.wpa_s, 0, 0); }
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; }