/*
* WPA Supplicant / Configuration parser and common functions
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
static char * wpa_config_parse_string(const char *value, size_t *len)
{
if (*value == '"') {
- char *pos;
+ const char *pos;
+ char *str;
value++;
pos = os_strrchr(value, '"');
if (pos == NULL || pos[1] != '\0')
return NULL;
- *pos = '\0';
- *len = os_strlen(value);
- return os_strdup(value);
+ *len = pos - value;
+ str = os_malloc(*len + 1);
+ if (str == NULL)
+ return NULL;
+ os_memcpy(str, value, *len);
+ str[*len] = '\0';
+ return str;
} else {
u8 *str;
size_t tlen, hlen = os_strlen(value);
size_t res_len, *dst_len;
char **dst, *tmp;
+ if (os_strcmp(value, "NULL") == 0) {
+ wpa_printf(MSG_DEBUG, "Unset configuration string '%s'",
+ data->name);
+ tmp = NULL;
+ res_len = 0;
+ goto set;
+ }
+
tmp = wpa_config_parse_string(value, &res_len);
if (tmp == NULL) {
wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
return -1;
}
+set:
dst = (char **) (((u8 *) ssid) + (long) data->param1);
dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
os_free(*dst);
else if (os_strcmp(start, "FT-EAP") == 0)
val |= WPA_KEY_MGMT_FT_IEEE8021X;
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IEEE80211W
+ else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
+ val |= WPA_KEY_MGMT_PSK_SHA256;
+ else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
+ val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_WPS
+ else if (os_strcmp(start, "WPS") == 0)
+ val |= WPA_KEY_MGMT_WPS;
+#endif /* CONFIG_WPS */
else {
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
line, start);
pos == buf ? "" : " ");
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IEEE80211W
+ if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
+ pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
+ pos == buf ? "" : " ");
+
+ if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
+ pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256",
+ pos == buf ? "" : " ");
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_WPS
+ if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
+ pos += os_snprintf(pos, end - pos, "%sWPS",
+ pos == buf ? "" : " ");
+#endif /* CONFIG_WPS */
+
return buf;
}
#endif /* NO_CONFIG_WRITE */
#endif /* NO_CONFIG_WRITE */
+static int wpa_config_parse_scan_freq(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ int *freqs;
+ size_t used, len;
+ const char *pos;
+
+ used = 0;
+ len = 10;
+ freqs = os_zalloc((len + 1) * sizeof(int));
+ if (freqs == NULL)
+ return -1;
+
+ pos = value;
+ while (pos) {
+ while (*pos == ' ')
+ pos++;
+ if (used == len) {
+ int *n;
+ size_t i;
+ n = os_realloc(freqs, (len * 2 + 1) * sizeof(int));
+ if (n == NULL) {
+ os_free(freqs);
+ return -1;
+ }
+ for (i = len; i <= len * 2; i++)
+ n[i] = 0;
+ freqs = n;
+ len *= 2;
+ }
+
+ freqs[used] = atoi(pos);
+ if (freqs[used] == 0)
+ break;
+ used++;
+ pos = os_strchr(pos + 1, ' ');
+ }
+
+ os_free(ssid->scan_freq);
+ ssid->scan_freq = freqs;
+
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_scan_freq(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ char *buf, *pos, *end;
+ int i, ret;
+ size_t count;
+
+ if (ssid->scan_freq == NULL)
+ return NULL;
+
+ count = 0;
+ for (i = 0; ssid->scan_freq[i]; i++)
+ count++;
+
+ pos = buf = os_zalloc(10 * count + 1);
+ if (buf == NULL)
+ return NULL;
+ end = buf + 10 * count + 1;
+
+ for (i = 0; ssid->scan_freq[i]; i++) {
+ ret = os_snprintf(pos, end - pos, "%s%u",
+ i == 0 ? "" : " ", ssid->scan_freq[i]);
+ if (ret < 0 || ret >= end - pos) {
+ end[-1] = '\0';
+ return buf;
+ }
+ pos += ret;
+ }
+
+ return buf;
+}
+#endif /* NO_CONFIG_WRITE */
+
+
#ifdef IEEE8021X_EAPOL
static int wpa_config_parse_eap(const struct parse_data *data,
struct wpa_ssid *ssid, int line,
{
u8 *hash;
+ if (os_strcmp(value, "NULL") == 0) {
+ wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
+ os_free(ssid->eap.password);
+ ssid->eap.password = NULL;
+ ssid->eap.password_len = 0;
+ return 0;
+ }
+
if (os_strncmp(value, "hash:", 5) != 0) {
char *tmp;
size_t res_len;
"password.", line);
return -1;
}
- wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
- (u8 *) tmp, res_len);
+ wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
+ (u8 *) tmp, res_len);
os_free(ssid->eap.password);
ssid->eap.password = (u8 *) tmp;
{ FUNC(pairwise) },
{ FUNC(group) },
{ FUNC(auth_alg) },
+ { FUNC(scan_freq) },
#ifdef IEEE8021X_EAPOL
{ FUNC(eap) },
{ STR_LENe(identity) },
{ STR_LENe(anonymous_identity) },
- { FUNC(password) },
+ { FUNC_KEY(password) },
{ STRe(ca_cert) },
{ STRe(ca_path) },
{ STRe(client_cert) },
{ STRe(key_id) },
{ STRe(cert_id) },
{ STRe(ca_cert_id) },
+ { STR_KEYe(pin2) },
+ { STRe(engine2_id) },
{ STRe(key2_id) },
{ STRe(cert2_id) },
{ STRe(ca_cert2_id) },
{ INTe(engine) },
+ { INTe(engine2) },
{ INT(eapol_flags) },
#endif /* IEEE8021X_EAPOL */
{ FUNC_KEY(wep_key0) },
{ STRe(pac_file) },
{ INTe(fragment_size) },
#endif /* IEEE8021X_EAPOL */
- { INT_RANGE(mode, 0, 1) },
+ { INT_RANGE(mode, 0, 2) },
{ INT_RANGE(proactive_key_caching, 0, 1) },
{ INT_RANGE(disabled, 0, 1) },
{ STR(id_str) },
#endif /* CONFIG_IEEE80211W */
{ INT_RANGE(peerkey, 0, 1) },
{ INT_RANGE(mixed_cell, 0, 1) },
- { INT_RANGE(frequency, 0, 10000) }
+ { INT_RANGE(frequency, 0, 10000) },
+ { INT(wpa_ptk_rekey) }
};
#undef OFFSET
os_free(eap->key2_id);
os_free(eap->cert2_id);
os_free(eap->ca_cert2_id);
+ os_free(eap->pin2);
+ os_free(eap->engine2_id);
os_free(eap->otp);
os_free(eap->pending_req_otp);
os_free(eap->pac_file);
eap_peer_config_free(&ssid->eap);
#endif /* IEEE8021X_EAPOL */
os_free(ssid->id_str);
+ os_free(ssid->scan_freq);
os_free(ssid);
}
os_free(config->pkcs11_module_path);
#endif /* EAP_TLS_OPENSSL */
os_free(config->driver_param);
+ os_free(config->device_name);
+ os_free(config->manufacturer);
+ os_free(config->model_name);
+ os_free(config->model_number);
+ os_free(config->serial_number);
+ os_free(config->device_type);
os_free(config->pssid);
os_free(config);
}