Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * WPA Supplicant / Configuration parser and common functions
      3  * Copyright (c) 2003-2006, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License version 2 as
      7  * published by the Free Software Foundation.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 #include "includes.h"
     16 
     17 #include "common.h"
     18 #include "wpa.h"
     19 #include "sha1.h"
     20 #include "eapol_sm.h"
     21 #include "eap.h"
     22 #include "l2_packet.h"
     23 #include "config.h"
     24 
     25 
     26 /*
     27  * Structure for network configuration parsing. This data is used to implement
     28  * a generic parser for each network block variable. The table of configuration
     29  * variables is defined below in this file (ssid_fields[]).
     30  */
     31 struct parse_data {
     32 	/* Configuration variable name */
     33 	char *name;
     34 
     35 	/* Parser function for this variable */
     36 	int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
     37 		      int line, const char *value);
     38 
     39 	/* Writer function (i.e., to get the variable in text format from
     40 	 * internal presentation). */
     41 	char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
     42 
     43 	/* Variable specific parameters for the parser. */
     44 	void *param1, *param2, *param3, *param4;
     45 
     46 	/* 0 = this variable can be included in debug output and ctrl_iface
     47 	 * 1 = this variable contains key/private data and it must not be
     48 	 *     included in debug output unless explicitly requested. In
     49 	 *     addition, this variable will not be readable through the
     50 	 *     ctrl_iface.
     51 	 */
     52 	int key_data;
     53 };
     54 
     55 
     56 static char * wpa_config_parse_string(const char *value, size_t *len)
     57 {
     58 	if (*value == '"') {
     59 		char *pos;
     60 		value++;
     61 		pos = os_strrchr(value, '"');
     62 		if (pos == NULL || pos[1] != '\0')
     63 			return NULL;
     64 		*pos = '\0';
     65 		*len = os_strlen(value);
     66 		return os_strdup(value);
     67 	} else {
     68 		u8 *str;
     69 		size_t tlen, hlen = os_strlen(value);
     70 		if (hlen & 1)
     71 			return NULL;
     72 		tlen = hlen / 2;
     73 		str = os_malloc(tlen + 1);
     74 		if (str == NULL)
     75 			return NULL;
     76 		if (hexstr2bin(value, str, tlen)) {
     77 			os_free(str);
     78 			return NULL;
     79 		}
     80 		str[tlen] = '\0';
     81 		*len = tlen;
     82 		return (char *) str;
     83 	}
     84 }
     85 
     86 
     87 static int wpa_config_parse_str(const struct parse_data *data,
     88 				struct wpa_ssid *ssid,
     89 				int line, const char *value)
     90 {
     91 	size_t res_len, *dst_len;
     92 	char **dst, *tmp;
     93 
     94 	if (os_strcmp(value, "NULL") == 0) {
     95 		wpa_printf(MSG_DEBUG, "Unset configuration string '%s'",
     96 			   data->name);
     97 		tmp = NULL;
     98 		res_len = 0;
     99 		goto set;
    100 	}
    101 
    102 	tmp = wpa_config_parse_string(value, &res_len);
    103 	if (tmp == NULL) {
    104 		wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
    105 			   line, data->name,
    106 			   data->key_data ? "[KEY DATA REMOVED]" : value);
    107 		return -1;
    108 	}
    109 
    110 	if (data->key_data) {
    111 		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
    112 				      (u8 *) tmp, res_len);
    113 	} else {
    114 		wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
    115 				  (u8 *) tmp, res_len);
    116 	}
    117 
    118 	if (data->param3 && res_len < (size_t) data->param3) {
    119 		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
    120 			   "min_len=%ld)", line, data->name,
    121 			   (unsigned long) res_len, (long) data->param3);
    122 		os_free(tmp);
    123 		return -1;
    124 	}
    125 
    126 	if (data->param4 && res_len > (size_t) data->param4) {
    127 		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
    128 			   "max_len=%ld)", line, data->name,
    129 			   (unsigned long) res_len, (long) data->param4);
    130 		os_free(tmp);
    131 		return -1;
    132 	}
    133 
    134 set:
    135 	dst = (char **) (((u8 *) ssid) + (long) data->param1);
    136 	dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
    137 	os_free(*dst);
    138 	*dst = tmp;
    139 	if (data->param2)
    140 		*dst_len = res_len;
    141 
    142 	return 0;
    143 }
    144 
    145 
    146 static int is_hex(const u8 *data, size_t len)
    147 {
    148 	size_t i;
    149 
    150 	for (i = 0; i < len; i++) {
    151 		if (data[i] < 32 || data[i] >= 127)
    152 			return 1;
    153 	}
    154 	return 0;
    155 }
    156 
    157 
    158 static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
    159 {
    160 	char *buf;
    161 
    162 	buf = os_malloc(len + 3);
    163 	if (buf == NULL)
    164 		return NULL;
    165 	buf[0] = '"';
    166 	os_memcpy(buf + 1, value, len);
    167 	buf[len + 1] = '"';
    168 	buf[len + 2] = '\0';
    169 
    170 	return buf;
    171 }
    172 
    173 
    174 static char * wpa_config_write_string_hex(const u8 *value, size_t len)
    175 {
    176 	char *buf;
    177 
    178 	buf = os_zalloc(2 * len + 1);
    179 	if (buf == NULL)
    180 		return NULL;
    181 	wpa_snprintf_hex(buf, 2 * len + 1, value, len);
    182 
    183 	return buf;
    184 }
    185 
    186 
    187 static char * wpa_config_write_string(const u8 *value, size_t len)
    188 {
    189 	if (value == NULL)
    190 		return NULL;
    191 
    192 	if (is_hex(value, len))
    193 		return wpa_config_write_string_hex(value, len);
    194 	else
    195 		return wpa_config_write_string_ascii(value, len);
    196 }
    197 
    198 
    199 static char * wpa_config_write_str(const struct parse_data *data,
    200 				   struct wpa_ssid *ssid)
    201 {
    202 	size_t len;
    203 	char **src;
    204 
    205 	src = (char **) (((u8 *) ssid) + (long) data->param1);
    206 	if (*src == NULL)
    207 		return NULL;
    208 
    209 	if (data->param2)
    210 		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
    211 	else
    212 		len = os_strlen(*src);
    213 
    214 	return wpa_config_write_string((const u8 *) *src, len);
    215 }
    216 
    217 #ifdef WPA_UNICODE_SSID
    218 static char * wpa_config_write_str_unicode(const struct parse_data *data,
    219 				   struct wpa_ssid *ssid)
    220 {
    221 	size_t len;
    222 	char **src;
    223 
    224 	src = (char **) (((u8 *) ssid) + (long) data->param1);
    225 	if (*src == NULL)
    226 		return NULL;
    227 
    228 	if (data->param2)
    229 		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
    230 	else
    231 		len = os_strlen(*src);
    232 
    233 	return wpa_config_write_string_ascii((const u8 *) *src, len);
    234 }
    235 #endif
    236 
    237 static int wpa_config_parse_int(const struct parse_data *data,
    238 				struct wpa_ssid *ssid,
    239 				int line, const char *value)
    240 {
    241 	int *dst;
    242 
    243 	dst = (int *) (((u8 *) ssid) + (long) data->param1);
    244 	*dst = atoi(value);
    245 	wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
    246 
    247 	if (data->param3 && *dst < (long) data->param3) {
    248 		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
    249 			   "min_value=%ld)", line, data->name, *dst,
    250 			   (long) data->param3);
    251 		*dst = (long) data->param3;
    252 		return -1;
    253 	}
    254 
    255 	if (data->param4 && *dst > (long) data->param4) {
    256 		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
    257 			   "max_value=%ld)", line, data->name, *dst,
    258 			   (long) data->param4);
    259 		*dst = (long) data->param4;
    260 		return -1;
    261 	}
    262 
    263 	return 0;
    264 }
    265 
    266 
    267 static char * wpa_config_write_int(const struct parse_data *data,
    268 				   struct wpa_ssid *ssid)
    269 {
    270 	int *src;
    271 	char *value;
    272 
    273 	src = (int *) (((u8 *) ssid) + (long) data->param1);
    274 
    275 	value = os_malloc(20);
    276 	if (value == NULL)
    277 		return NULL;
    278 	os_snprintf(value, 20, "%d", *src);
    279 	value[20 - 1] = '\0';
    280 	return value;
    281 }
    282 
    283 
    284 static int wpa_config_parse_bssid(const struct parse_data *data,
    285 				  struct wpa_ssid *ssid, int line,
    286 				  const char *value)
    287 {
    288 	if (hwaddr_aton(value, ssid->bssid)) {
    289 		wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
    290 			   line, value);
    291 		return -1;
    292 	}
    293 	ssid->bssid_set = 1;
    294 	wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
    295 	return 0;
    296 }
    297 
    298 
    299 static char * wpa_config_write_bssid(const struct parse_data *data,
    300 				     struct wpa_ssid *ssid)
    301 {
    302 	char *value;
    303 
    304 	if (!ssid->bssid_set)
    305 		return NULL;
    306 
    307 	value = os_malloc(20);
    308 	if (value == NULL)
    309 		return NULL;
    310 	os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
    311 	value[20 - 1] = '\0';
    312 	return value;
    313 }
    314 
    315 
    316 static int wpa_config_parse_psk(const struct parse_data *data,
    317 				struct wpa_ssid *ssid, int line,
    318 				const char *value)
    319 {
    320 	if (*value == '"') {
    321 		const char *pos;
    322 		size_t len;
    323 
    324 		value++;
    325 		pos = os_strrchr(value, '"');
    326 		if (pos)
    327 			len = pos - value;
    328 		else
    329 			len = os_strlen(value);
    330 		if (len < 8 || len > 63) {
    331 			wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
    332 				   "length %lu (expected: 8..63) '%s'.",
    333 				   line, (unsigned long) len, value);
    334 			return -1;
    335 		}
    336 		wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
    337 				      (u8 *) value, len);
    338 		if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
    339 		    os_memcmp(ssid->passphrase, value, len) == 0)
    340 			return 0;
    341 		ssid->psk_set = 0;
    342 		os_free(ssid->passphrase);
    343 		ssid->passphrase = os_malloc(len + 1);
    344 		if (ssid->passphrase == NULL)
    345 			return -1;
    346 		os_memcpy(ssid->passphrase, value, len);
    347 		ssid->passphrase[len] = '\0';
    348 		return 0;
    349 	}
    350 
    351 	if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
    352 	    value[PMK_LEN * 2] != '\0') {
    353 		wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
    354 			   line, value);
    355 		return -1;
    356 	}
    357 
    358 	os_free(ssid->passphrase);
    359 	ssid->passphrase = NULL;
    360 
    361 	ssid->psk_set = 1;
    362 	wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
    363 	return 0;
    364 }
    365 
    366 
    367 static char * wpa_config_write_psk(const struct parse_data *data,
    368 				   struct wpa_ssid *ssid)
    369 {
    370 	if (ssid->passphrase)
    371 		return wpa_config_write_string_ascii(
    372 			(const u8 *) ssid->passphrase,
    373 			os_strlen(ssid->passphrase));
    374 
    375 	if (ssid->psk_set)
    376 		return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
    377 
    378 	return NULL;
    379 }
    380 
    381 
    382 static int wpa_config_parse_proto(const struct parse_data *data,
    383 				  struct wpa_ssid *ssid, int line,
    384 				  const char *value)
    385 {
    386 	int val = 0, last, errors = 0;
    387 	char *start, *end, *buf;
    388 
    389 	buf = os_strdup(value);
    390 	if (buf == NULL)
    391 		return -1;
    392 	start = buf;
    393 
    394 	while (*start != '\0') {
    395 		while (*start == ' ' || *start == '\t')
    396 			start++;
    397 		if (*start == '\0')
    398 			break;
    399 		end = start;
    400 		while (*end != ' ' && *end != '\t' && *end != '\0')
    401 			end++;
    402 		last = *end == '\0';
    403 		*end = '\0';
    404 		if (os_strcmp(start, "WPA") == 0)
    405 			val |= WPA_PROTO_WPA;
    406 		else if (os_strcmp(start, "RSN") == 0 ||
    407 			 os_strcmp(start, "WPA2") == 0)
    408 			val |= WPA_PROTO_RSN;
    409 		else {
    410 			wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
    411 				   line, start);
    412 			errors++;
    413 		}
    414 
    415 		if (last)
    416 			break;
    417 		start = end + 1;
    418 	}
    419 	os_free(buf);
    420 
    421 	if (val == 0) {
    422 		wpa_printf(MSG_ERROR,
    423 			   "Line %d: no proto values configured.", line);
    424 		errors++;
    425 	}
    426 
    427 	wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
    428 	ssid->proto = val;
    429 	return errors ? -1 : 0;
    430 }
    431 
    432 
    433 static char * wpa_config_write_proto(const struct parse_data *data,
    434 				     struct wpa_ssid *ssid)
    435 {
    436 	int first = 1, ret;
    437 	char *buf, *pos, *end;
    438 
    439 	pos = buf = os_zalloc(10);
    440 	if (buf == NULL)
    441 		return NULL;
    442 	end = buf + 10;
    443 
    444 	if (ssid->proto & WPA_PROTO_WPA) {
    445 		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
    446 		if (ret < 0 || ret >= end - pos)
    447 			return buf;
    448 		pos += ret;
    449 		first = 0;
    450 	}
    451 
    452 	if (ssid->proto & WPA_PROTO_RSN) {
    453 		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
    454 		if (ret < 0 || ret >= end - pos)
    455 			return buf;
    456 		pos += ret;
    457 		first = 0;
    458 	}
    459 
    460 	return buf;
    461 }
    462 
    463 
    464 static int wpa_config_parse_key_mgmt(const struct parse_data *data,
    465 				     struct wpa_ssid *ssid, int line,
    466 				     const char *value)
    467 {
    468 	int val = 0, last, errors = 0;
    469 	char *start, *end, *buf;
    470 
    471 	buf = os_strdup(value);
    472 	if (buf == NULL)
    473 		return -1;
    474 	start = buf;
    475 
    476 	while (*start != '\0') {
    477 		while (*start == ' ' || *start == '\t')
    478 			start++;
    479 		if (*start == '\0')
    480 			break;
    481 		end = start;
    482 		while (*end != ' ' && *end != '\t' && *end != '\0')
    483 			end++;
    484 		last = *end == '\0';
    485 		*end = '\0';
    486 		if (os_strcmp(start, "WPA-PSK") == 0)
    487 			val |= WPA_KEY_MGMT_PSK;
    488 		else if (os_strcmp(start, "WPA-EAP") == 0)
    489 			val |= WPA_KEY_MGMT_IEEE8021X;
    490 		else if (os_strcmp(start, "IEEE8021X") == 0)
    491 			val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
    492 		else if (os_strcmp(start, "NONE") == 0)
    493 			val |= WPA_KEY_MGMT_NONE;
    494 		else if (os_strcmp(start, "WPA-NONE") == 0)
    495 			val |= WPA_KEY_MGMT_WPA_NONE;
    496 		else {
    497 			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
    498 				   line, start);
    499 			errors++;
    500 		}
    501 
    502 		if (last)
    503 			break;
    504 		start = end + 1;
    505 	}
    506 	os_free(buf);
    507 
    508 	if (val == 0) {
    509 		wpa_printf(MSG_ERROR,
    510 			   "Line %d: no key_mgmt values configured.", line);
    511 		errors++;
    512 	}
    513 
    514 	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
    515 	ssid->key_mgmt = val;
    516 	return errors ? -1 : 0;
    517 }
    518 
    519 
    520 static char * wpa_config_write_key_mgmt(const struct parse_data *data,
    521 					struct wpa_ssid *ssid)
    522 {
    523 	char *buf, *pos, *end;
    524 	int ret;
    525 
    526 	pos = buf = os_zalloc(50);
    527 	if (buf == NULL)
    528 		return NULL;
    529 	end = buf + 50;
    530 
    531 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
    532 		ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
    533 				  pos == buf ? "" : " ");
    534 		if (ret < 0 || ret >= end - pos) {
    535 			end[-1] = '\0';
    536 			return buf;
    537 		}
    538 		pos += ret;
    539 	}
    540 
    541 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
    542 		ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
    543 				  pos == buf ? "" : " ");
    544 		if (ret < 0 || ret >= end - pos) {
    545 			end[-1] = '\0';
    546 			return buf;
    547 		}
    548 		pos += ret;
    549 	}
    550 
    551 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
    552 		ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
    553 				  pos == buf ? "" : " ");
    554 		if (ret < 0 || ret >= end - pos) {
    555 			end[-1] = '\0';
    556 			return buf;
    557 		}
    558 		pos += ret;
    559 	}
    560 
    561 	if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
    562 		ret = os_snprintf(pos, end - pos, "%sNONE",
    563 				  pos == buf ? "" : " ");
    564 		if (ret < 0 || ret >= end - pos) {
    565 			end[-1] = '\0';
    566 			return buf;
    567 		}
    568 		pos += ret;
    569 	}
    570 
    571 	if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
    572 		ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
    573 				  pos == buf ? "" : " ");
    574 		if (ret < 0 || ret >= end - pos) {
    575 			end[-1] = '\0';
    576 			return buf;
    577 		}
    578 		pos += ret;
    579 	}
    580 
    581 	return buf;
    582 }
    583 
    584 
    585 static int wpa_config_parse_cipher(int line, const char *value)
    586 {
    587 	int val = 0, last;
    588 	char *start, *end, *buf;
    589 
    590 	buf = os_strdup(value);
    591 	if (buf == NULL)
    592 		return -1;
    593 	start = buf;
    594 
    595 	while (*start != '\0') {
    596 		while (*start == ' ' || *start == '\t')
    597 			start++;
    598 		if (*start == '\0')
    599 			break;
    600 		end = start;
    601 		while (*end != ' ' && *end != '\t' && *end != '\0')
    602 			end++;
    603 		last = *end == '\0';
    604 		*end = '\0';
    605 		if (os_strcmp(start, "CCMP") == 0)
    606 			val |= WPA_CIPHER_CCMP;
    607 		else if (os_strcmp(start, "TKIP") == 0)
    608 			val |= WPA_CIPHER_TKIP;
    609 		else if (os_strcmp(start, "WEP104") == 0)
    610 			val |= WPA_CIPHER_WEP104;
    611 		else if (os_strcmp(start, "WEP40") == 0)
    612 			val |= WPA_CIPHER_WEP40;
    613 		else if (os_strcmp(start, "NONE") == 0)
    614 			val |= WPA_CIPHER_NONE;
    615 		else {
    616 			wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
    617 				   line, start);
    618 			os_free(buf);
    619 			return -1;
    620 		}
    621 
    622 		if (last)
    623 			break;
    624 		start = end + 1;
    625 	}
    626 	os_free(buf);
    627 
    628 	if (val == 0) {
    629 		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
    630 			   line);
    631 		return -1;
    632 	}
    633 	return val;
    634 }
    635 
    636 
    637 static char * wpa_config_write_cipher(int cipher)
    638 {
    639 	char *buf, *pos, *end;
    640 	int ret;
    641 
    642 	pos = buf = os_zalloc(50);
    643 	if (buf == NULL)
    644 		return NULL;
    645 	end = buf + 50;
    646 
    647 	if (cipher & WPA_CIPHER_CCMP) {
    648 		ret = os_snprintf(pos, end - pos, "%sCCMP",
    649 				  pos == buf ? "" : " ");
    650 		if (ret < 0 || ret >= end - pos) {
    651 			end[-1] = '\0';
    652 			return buf;
    653 		}
    654 		pos += ret;
    655 	}
    656 
    657 	if (cipher & WPA_CIPHER_TKIP) {
    658 		ret = os_snprintf(pos, end - pos, "%sTKIP",
    659 				  pos == buf ? "" : " ");
    660 		if (ret < 0 || ret >= end - pos) {
    661 			end[-1] = '\0';
    662 			return buf;
    663 		}
    664 		pos += ret;
    665 	}
    666 
    667 	if (cipher & WPA_CIPHER_WEP104) {
    668 		ret = os_snprintf(pos, end - pos, "%sWEP104",
    669 				  pos == buf ? "" : " ");
    670 		if (ret < 0 || ret >= end - pos) {
    671 			end[-1] = '\0';
    672 			return buf;
    673 		}
    674 		pos += ret;
    675 	}
    676 
    677 	if (cipher & WPA_CIPHER_WEP40) {
    678 		ret = os_snprintf(pos, end - pos, "%sWEP40",
    679 				  pos == buf ? "" : " ");
    680 		if (ret < 0 || ret >= end - pos) {
    681 			end[-1] = '\0';
    682 			return buf;
    683 		}
    684 		pos += ret;
    685 	}
    686 
    687 	if (cipher & WPA_CIPHER_NONE) {
    688 		ret = os_snprintf(pos, end - pos, "%sNONE",
    689 				  pos == buf ? "" : " ");
    690 		if (ret < 0 || ret >= end - pos) {
    691 			end[-1] = '\0';
    692 			return buf;
    693 		}
    694 		pos += ret;
    695 	}
    696 
    697 	return buf;
    698 }
    699 
    700 
    701 static int wpa_config_parse_pairwise(const struct parse_data *data,
    702 				     struct wpa_ssid *ssid, int line,
    703 				     const char *value)
    704 {
    705 	int val;
    706 	val = wpa_config_parse_cipher(line, value);
    707 	if (val == -1)
    708 		return -1;
    709 	if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) {
    710 		wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
    711 			   "(0x%x).", line, val);
    712 		return -1;
    713 	}
    714 
    715 	wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
    716 	ssid->pairwise_cipher = val;
    717 	return 0;
    718 }
    719 
    720 
    721 static char * wpa_config_write_pairwise(const struct parse_data *data,
    722 					struct wpa_ssid *ssid)
    723 {
    724 	return wpa_config_write_cipher(ssid->pairwise_cipher);
    725 }
    726 
    727 
    728 static int wpa_config_parse_group(const struct parse_data *data,
    729 				  struct wpa_ssid *ssid, int line,
    730 				  const char *value)
    731 {
    732 	int val;
    733 	val = wpa_config_parse_cipher(line, value);
    734 	if (val == -1)
    735 		return -1;
    736 	if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 |
    737 		    WPA_CIPHER_WEP40)) {
    738 		wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
    739 			   "(0x%x).", line, val);
    740 		return -1;
    741 	}
    742 
    743 	wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
    744 	ssid->group_cipher = val;
    745 	return 0;
    746 }
    747 
    748 
    749 static char * wpa_config_write_group(const struct parse_data *data,
    750 				     struct wpa_ssid *ssid)
    751 {
    752 	return wpa_config_write_cipher(ssid->group_cipher);
    753 }
    754 
    755 
    756 static int wpa_config_parse_auth_alg(const struct parse_data *data,
    757 				     struct wpa_ssid *ssid, int line,
    758 				     const char *value)
    759 {
    760 	int val = 0, last, errors = 0;
    761 	char *start, *end, *buf;
    762 
    763 	buf = os_strdup(value);
    764 	if (buf == NULL)
    765 		return -1;
    766 	start = buf;
    767 
    768 	while (*start != '\0') {
    769 		while (*start == ' ' || *start == '\t')
    770 			start++;
    771 		if (*start == '\0')
    772 			break;
    773 		end = start;
    774 		while (*end != ' ' && *end != '\t' && *end != '\0')
    775 			end++;
    776 		last = *end == '\0';
    777 		*end = '\0';
    778 		if (os_strcmp(start, "OPEN") == 0)
    779 			val |= WPA_AUTH_ALG_OPEN;
    780 		else if (os_strcmp(start, "SHARED") == 0)
    781 			val |= WPA_AUTH_ALG_SHARED;
    782 		else if (os_strcmp(start, "LEAP") == 0)
    783 			val |= WPA_AUTH_ALG_LEAP;
    784 		else {
    785 			wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
    786 				   line, start);
    787 			errors++;
    788 		}
    789 
    790 		if (last)
    791 			break;
    792 		start = end + 1;
    793 	}
    794 	os_free(buf);
    795 
    796 	if (val == 0) {
    797 		wpa_printf(MSG_ERROR,
    798 			   "Line %d: no auth_alg values configured.", line);
    799 		errors++;
    800 	}
    801 
    802 	wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
    803 	ssid->auth_alg = val;
    804 	return errors ? -1 : 0;
    805 }
    806 
    807 
    808 static char * wpa_config_write_auth_alg(const struct parse_data *data,
    809 					struct wpa_ssid *ssid)
    810 {
    811 	char *buf, *pos, *end;
    812 	int ret;
    813 
    814 	pos = buf = os_zalloc(30);
    815 	if (buf == NULL)
    816 		return NULL;
    817 	end = buf + 30;
    818 
    819 	if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
    820 		ret = os_snprintf(pos, end - pos, "%sOPEN",
    821 				  pos == buf ? "" : " ");
    822 		if (ret < 0 || ret >= end - pos) {
    823 			end[-1] = '\0';
    824 			return buf;
    825 		}
    826 		pos += ret;
    827 	}
    828 
    829 	if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
    830 		ret = os_snprintf(pos, end - pos, "%sSHARED",
    831 				  pos == buf ? "" : " ");
    832 		if (ret < 0 || ret >= end - pos) {
    833 			end[-1] = '\0';
    834 			return buf;
    835 		}
    836 		pos += ret;
    837 	}
    838 
    839 	if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
    840 		ret = os_snprintf(pos, end - pos, "%sLEAP",
    841 				  pos == buf ? "" : " ");
    842 		if (ret < 0 || ret >= end - pos) {
    843 			end[-1] = '\0';
    844 			return buf;
    845 		}
    846 		pos += ret;
    847 	}
    848 
    849 	return buf;
    850 }
    851 
    852 
    853 #ifdef IEEE8021X_EAPOL
    854 static int wpa_config_parse_eap(const struct parse_data *data,
    855 				struct wpa_ssid *ssid, int line,
    856 				const char *value)
    857 {
    858 	int last, errors = 0;
    859 	char *start, *end, *buf;
    860 	struct eap_method_type *methods = NULL, *tmp;
    861 	size_t num_methods = 0;
    862 
    863 	buf = os_strdup(value);
    864 	if (buf == NULL)
    865 		return -1;
    866 	start = buf;
    867 
    868 	while (*start != '\0') {
    869 		while (*start == ' ' || *start == '\t')
    870 			start++;
    871 		if (*start == '\0')
    872 			break;
    873 		end = start;
    874 		while (*end != ' ' && *end != '\t' && *end != '\0')
    875 			end++;
    876 		last = *end == '\0';
    877 		*end = '\0';
    878 		tmp = methods;
    879 		methods = os_realloc(methods,
    880 				     (num_methods + 1) * sizeof(*methods));
    881 		if (methods == NULL) {
    882 			os_free(tmp);
    883 			os_free(buf);
    884 			return -1;
    885 		}
    886 		methods[num_methods].method = eap_get_type(
    887 			start, &methods[num_methods].vendor);
    888 		if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
    889 		    methods[num_methods].method == EAP_TYPE_NONE) {
    890 			wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
    891 				   "'%s'", line, start);
    892 			wpa_printf(MSG_ERROR, "You may need to add support for"
    893 				   " this EAP method during wpa_supplicant\n"
    894 				   "build time configuration.\n"
    895 				   "See README for more information.");
    896 			errors++;
    897 		} else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
    898 			   methods[num_methods].method == EAP_TYPE_LEAP)
    899 			ssid->leap++;
    900 		else
    901 			ssid->non_leap++;
    902 		num_methods++;
    903 		if (last)
    904 			break;
    905 		start = end + 1;
    906 	}
    907 	os_free(buf);
    908 
    909 	tmp = methods;
    910 	methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods));
    911 	if (methods == NULL) {
    912 		os_free(tmp);
    913 		return -1;
    914 	}
    915 	methods[num_methods].vendor = EAP_VENDOR_IETF;
    916 	methods[num_methods].method = EAP_TYPE_NONE;
    917 	num_methods++;
    918 
    919 	wpa_hexdump(MSG_MSGDUMP, "eap methods",
    920 		    (u8 *) methods, num_methods * sizeof(*methods));
    921 	ssid->eap_methods = methods;
    922 	return errors ? -1 : 0;
    923 }
    924 
    925 
    926 static char * wpa_config_write_eap(const struct parse_data *data,
    927 				   struct wpa_ssid *ssid)
    928 {
    929 	int i, ret;
    930 	char *buf, *pos, *end;
    931 	const struct eap_method_type *eap_methods = ssid->eap_methods;
    932 	const char *name;
    933 
    934 	if (eap_methods == NULL)
    935 		return NULL;
    936 
    937 	pos = buf = os_zalloc(100);
    938 	if (buf == NULL)
    939 		return NULL;
    940 	end = buf + 100;
    941 
    942 	for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
    943 		     eap_methods[i].method != EAP_TYPE_NONE; i++) {
    944 		name = eap_get_name(eap_methods[i].vendor,
    945 				    eap_methods[i].method);
    946 		if (name) {
    947 			ret = os_snprintf(pos, end - pos, "%s%s",
    948 					  pos == buf ? "" : " ", name);
    949 			if (ret < 0 || ret >= end - pos)
    950 				break;
    951 			pos += ret;
    952 		}
    953 	}
    954 
    955 	end[-1] = '\0';
    956 
    957 	return buf;
    958 }
    959 #endif /* IEEE8021X_EAPOL */
    960 
    961 
    962 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
    963 				    const char *value, int idx)
    964 {
    965 	char *buf, title[20];
    966 
    967 	buf = wpa_config_parse_string(value, len);
    968 	if (buf == NULL) {
    969 		wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
    970 			   line, idx, value);
    971 		return -1;
    972 	}
    973 	if (*len > MAX_WEP_KEY_LEN) {
    974 		wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
    975 			   line, idx, value);
    976 		os_free(buf);
    977 		return -1;
    978 	}
    979 	os_memcpy(key, buf, *len);
    980 	os_free(buf);
    981 	os_snprintf(title, sizeof(title), "wep_key%d", idx);
    982 	wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
    983 	return 0;
    984 }
    985 
    986 
    987 static int wpa_config_parse_wep_key0(const struct parse_data *data,
    988 				     struct wpa_ssid *ssid, int line,
    989 				     const char *value)
    990 {
    991 	return wpa_config_parse_wep_key(ssid->wep_key[0],
    992 					&ssid->wep_key_len[0], line,
    993 					value, 0);
    994 }
    995 
    996 
    997 static int wpa_config_parse_wep_key1(const struct parse_data *data,
    998 				     struct wpa_ssid *ssid, int line,
    999 				     const char *value)
   1000 {
   1001 	return wpa_config_parse_wep_key(ssid->wep_key[1],
   1002 					&ssid->wep_key_len[1], line,
   1003 					value, 1);
   1004 }
   1005 
   1006 
   1007 static int wpa_config_parse_wep_key2(const struct parse_data *data,
   1008 				     struct wpa_ssid *ssid, int line,
   1009 				     const char *value)
   1010 {
   1011 	return wpa_config_parse_wep_key(ssid->wep_key[2],
   1012 					&ssid->wep_key_len[2], line,
   1013 					value, 2);
   1014 }
   1015 
   1016 
   1017 static int wpa_config_parse_wep_key3(const struct parse_data *data,
   1018 				     struct wpa_ssid *ssid, int line,
   1019 				     const char *value)
   1020 {
   1021 	return wpa_config_parse_wep_key(ssid->wep_key[3],
   1022 					&ssid->wep_key_len[3], line,
   1023 					value, 3);
   1024 }
   1025 
   1026 
   1027 static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
   1028 {
   1029 	if (ssid->wep_key_len[idx] == 0)
   1030 		return NULL;
   1031 	return wpa_config_write_string(ssid->wep_key[idx],
   1032 				       ssid->wep_key_len[idx]);
   1033 }
   1034 
   1035 
   1036 static char * wpa_config_write_wep_key0(const struct parse_data *data,
   1037 					struct wpa_ssid *ssid)
   1038 {
   1039 	return wpa_config_write_wep_key(ssid, 0);
   1040 }
   1041 
   1042 
   1043 static char * wpa_config_write_wep_key1(const struct parse_data *data,
   1044 					struct wpa_ssid *ssid)
   1045 {
   1046 	return wpa_config_write_wep_key(ssid, 1);
   1047 }
   1048 
   1049 
   1050 static char * wpa_config_write_wep_key2(const struct parse_data *data,
   1051 					struct wpa_ssid *ssid)
   1052 {
   1053 	return wpa_config_write_wep_key(ssid, 2);
   1054 }
   1055 
   1056 
   1057 static char * wpa_config_write_wep_key3(const struct parse_data *data,
   1058 					struct wpa_ssid *ssid)
   1059 {
   1060 	return wpa_config_write_wep_key(ssid, 3);
   1061 }
   1062 
   1063 
   1064 /* Helper macros for network block parser */
   1065 
   1066 #ifdef OFFSET
   1067 #undef OFFSET
   1068 #endif /* OFFSET */
   1069 /* OFFSET: Get offset of a variable within the wpa_ssid structure */
   1070 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
   1071 
   1072 /* STR: Define a string variable for an ASCII string; f = field name */
   1073 #define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
   1074 #define STR(f) _STR(f), NULL, NULL, NULL, 0
   1075 #define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
   1076 
   1077 /* STR_LEN: Define a string variable with a separate variable for storing the
   1078  * data length. Unlike STR(), this can be used to store arbitrary binary data
   1079  * (i.e., even nul termination character). */
   1080 #define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
   1081 #define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
   1082 #define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
   1083 
   1084 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
   1085  * explicitly specified. */
   1086 #define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
   1087 #define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
   1088 #define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
   1089 
   1090 #ifdef WPA_UNICODE_SSID
   1091 /* STR_* variants that do not force conversion to ASCII */
   1092 #define _STR_UNICODE(f) #f, wpa_config_parse_str, wpa_config_write_str_unicode, OFFSET(f)
   1093 #define STR_UNICODE(f) _STR_UNICODE(f), NULL, NULL, NULL, 0
   1094 #define _STR_LEN_UNICODE(f) _STR_UNICODE(f), OFFSET(f ## _len)
   1095 #define STR_LEN_UNICODE(f) _STR_LEN_UNICODE(f), NULL, NULL, 0
   1096 #define _STR_RANGE_UNICODE(f, min, max) _STR_LEN_UNICODE(f), (void *) (min), (void *) (max)
   1097 #define STR_RANGE_UNICODE(f, min, max) _STR_RANGE_UNICODE(f, min, max), 0
   1098 #endif
   1099 
   1100 #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
   1101 	OFFSET(f), (void *) 0
   1102 
   1103 /* INT: Define an integer variable */
   1104 #define INT(f) _INT(f), NULL, NULL, 0
   1105 
   1106 /* INT_RANGE: Define an integer variable with allowed value range */
   1107 #define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
   1108 
   1109 /* FUNC: Define a configuration variable that uses a custom function for
   1110  * parsing and writing the value. */
   1111 #define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
   1112 	NULL, NULL, NULL, NULL
   1113 #define FUNC(f) _FUNC(f), 0
   1114 #define FUNC_KEY(f) _FUNC(f), 1
   1115 
   1116 /*
   1117  * Table of network configuration variables. This table is used to parse each
   1118  * network configuration variable, e.g., each line in wpa_supplicant.conf file
   1119  * that is inside a network block.
   1120  *
   1121  * This table is generated using the helper macros defined above and with
   1122  * generous help from the C pre-processor. The field name is stored as a string
   1123  * into .name and for STR and INT types, the offset of the target buffer within
   1124  * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
   1125  * offset to the field containing the length of the configuration variable.
   1126  * .param3 and .param4 can be used to mark the allowed range (length for STR
   1127  * and value for INT).
   1128  *
   1129  * For each configuration line in wpa_supplicant.conf, the parser goes through
   1130  * this table and select the entry that matches with the field name. The parser
   1131  * function (.parser) is then called to parse the actual value of the field.
   1132  *
   1133  * This kind of mechanism makes it easy to add new configuration parameters,
   1134  * since only one line needs to be added into this table and into the
   1135  * struct wpa_ssid definition if the new variable is either a string or
   1136  * integer. More complex types will need to use their own parser and writer
   1137  * functions.
   1138  */
   1139 static const struct parse_data ssid_fields[] = {
   1140 #ifdef WPA_UNICODE_SSID
   1141 	{ STR_RANGE_UNICODE(ssid, 0, MAX_SSID_LEN) },
   1142 #else
   1143 	{ STR_RANGE(ssid, 0, MAX_SSID_LEN) },
   1144 #endif
   1145 	{ INT_RANGE(scan_ssid, 0, 1) },
   1146 	{ FUNC(bssid) },
   1147 	{ FUNC_KEY(psk) },
   1148 	{ FUNC(proto) },
   1149 	{ FUNC(key_mgmt) },
   1150 	{ FUNC(pairwise) },
   1151 	{ FUNC(group) },
   1152 	{ FUNC(auth_alg) },
   1153 #ifdef IEEE8021X_EAPOL
   1154 	{ FUNC(eap) },
   1155 	{ STR_LEN(identity) },
   1156 	{ STR_LEN(anonymous_identity) },
   1157 	{ STR_RANGE_KEY(eappsk, EAP_PSK_LEN_MIN, EAP_PSK_LEN_MAX) },
   1158 	{ STR_LEN(nai) },
   1159 	{ STR_LEN_KEY(password) },
   1160 	{ STR(ca_cert) },
   1161 	{ STR(ca_path) },
   1162 	{ STR(client_cert) },
   1163 	{ STR(private_key) },
   1164 	{ STR_KEY(private_key_passwd) },
   1165 	{ STR(dh_file) },
   1166 	{ STR(subject_match) },
   1167 	{ STR(altsubject_match) },
   1168 	{ STR(ca_cert2) },
   1169 	{ STR(ca_path2) },
   1170 	{ STR(client_cert2) },
   1171 	{ STR(private_key2) },
   1172 	{ STR_KEY(private_key2_passwd) },
   1173 	{ STR(dh_file2) },
   1174 	{ STR(subject_match2) },
   1175 	{ STR(altsubject_match2) },
   1176 	{ STR(phase1) },
   1177 	{ STR(phase2) },
   1178 	{ STR(pcsc) },
   1179 	{ STR_KEY(pin) },
   1180 	{ STR(engine_id) },
   1181 	{ STR(key_id) },
   1182 	{ INT(engine) },
   1183 	{ INT(eapol_flags) },
   1184 #endif /* IEEE8021X_EAPOL */
   1185 	{ FUNC_KEY(wep_key0) },
   1186 	{ FUNC_KEY(wep_key1) },
   1187 	{ FUNC_KEY(wep_key2) },
   1188 	{ FUNC_KEY(wep_key3) },
   1189 	{ INT(wep_tx_keyidx) },
   1190 	{ INT(priority) },
   1191 #ifdef IEEE8021X_EAPOL
   1192 	{ INT(eap_workaround) },
   1193 	{ STR(pac_file) },
   1194 	{ INT(fragment_size) },
   1195 #endif /* IEEE8021X_EAPOL */
   1196 	{ INT_RANGE(mode, 0, 1) },
   1197 	{ INT_RANGE(proactive_key_caching, 0, 1) },
   1198 	{ INT_RANGE(disabled, 0, 1) },
   1199 	{ STR(id_str) },
   1200 #ifdef CONFIG_IEEE80211W
   1201 	{ INT_RANGE(ieee80211w, 0, 2) },
   1202 #endif /* CONFIG_IEEE80211W */
   1203 	{ INT_RANGE(peerkey, 0, 1) },
   1204 	{ INT_RANGE(mixed_cell, 0, 1) },
   1205 	{ INT_RANGE(frequency, 0, 10000) }
   1206 };
   1207 
   1208 #ifdef WPA_UNICODE_SSID
   1209 #undef _STR_UNICODE
   1210 #undef STR_UNICODE
   1211 #undef _STR_LEN_UNICODE
   1212 #undef STR_LEN_UNICODE
   1213 #undef _STR_RANGE_UNICODE
   1214 #undef STR_RANGE_UNICODE
   1215 #endif
   1216 
   1217 #undef OFFSET
   1218 #undef _STR
   1219 #undef STR
   1220 #undef STR_KEY
   1221 #undef _STR_LEN
   1222 #undef STR_LEN
   1223 #undef STR_LEN_KEY
   1224 #undef _STR_RANGE
   1225 #undef STR_RANGE
   1226 #undef STR_RANGE_KEY
   1227 #undef _INT
   1228 #undef INT
   1229 #undef INT_RANGE
   1230 #undef _FUNC
   1231 #undef FUNC
   1232 #undef FUNC_KEY
   1233 #define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
   1234 
   1235 
   1236 /**
   1237  * wpa_config_add_prio_network - Add a network to priority lists
   1238  * @config: Configuration data from wpa_config_read()
   1239  * @ssid: Pointer to the network configuration to be added to the list
   1240  * Returns: 0 on success, -1 on failure
   1241  *
   1242  * This function is used to add a network block to the priority list of
   1243  * networks. This must be called for each network when reading in the full
   1244  * configuration. In addition, this can be used indirectly when updating
   1245  * priorities by calling wpa_config_update_prio_list().
   1246  */
   1247 int wpa_config_add_prio_network(struct wpa_config *config,
   1248 				struct wpa_ssid *ssid)
   1249 {
   1250 	int prio;
   1251 	struct wpa_ssid *prev, **nlist;
   1252 
   1253 	/*
   1254 	 * Add to an existing priority list if one is available for the
   1255 	 * configured priority level for this network.
   1256 	 */
   1257 	for (prio = 0; prio < config->num_prio; prio++) {
   1258 		prev = config->pssid[prio];
   1259 		if (prev->priority == ssid->priority) {
   1260 			while (prev->pnext)
   1261 				prev = prev->pnext;
   1262 			prev->pnext = ssid;
   1263 			return 0;
   1264 		}
   1265 	}
   1266 
   1267 	/* First network for this priority - add a new priority list */
   1268 	nlist = os_realloc(config->pssid,
   1269 			   (config->num_prio + 1) * sizeof(struct wpa_ssid *));
   1270 	if (nlist == NULL)
   1271 		return -1;
   1272 
   1273 	for (prio = 0; prio < config->num_prio; prio++) {
   1274 		if (nlist[prio]->priority < ssid->priority)
   1275 			break;
   1276 	}
   1277 
   1278 	os_memmove(&nlist[prio + 1], &nlist[prio],
   1279 		   (config->num_prio - prio) * sizeof(struct wpa_ssid *));
   1280 
   1281 	nlist[prio] = ssid;
   1282 	config->num_prio++;
   1283 	config->pssid = nlist;
   1284 
   1285 	return 0;
   1286 }
   1287 
   1288 
   1289 /**
   1290  * wpa_config_update_prio_list - Update network priority list
   1291  * @config: Configuration data from wpa_config_read()
   1292  * Returns: 0 on success, -1 on failure
   1293  *
   1294  * This function is called to update the priority list of networks in the
   1295  * configuration when a network is being added or removed. This is also called
   1296  * if a priority for a network is changed.
   1297  */
   1298 int wpa_config_update_prio_list(struct wpa_config *config)
   1299 {
   1300 	struct wpa_ssid *ssid;
   1301 	int ret = 0;
   1302 
   1303 	os_free(config->pssid);
   1304 	config->pssid = NULL;
   1305 	config->num_prio = 0;
   1306 
   1307 	ssid = config->ssid;
   1308 	while (ssid) {
   1309 		ssid->pnext = NULL;
   1310 		if (wpa_config_add_prio_network(config, ssid) < 0)
   1311 			ret = -1;
   1312 		ssid = ssid->next;
   1313 	}
   1314 
   1315 	return ret;
   1316 }
   1317 
   1318 
   1319 /**
   1320  * wpa_config_free_ssid - Free network/ssid configuration data
   1321  * @ssid: Configuration data for the network
   1322  *
   1323  * This function frees all resources allocated for the network configuration
   1324  * data.
   1325  */
   1326 void wpa_config_free_ssid(struct wpa_ssid *ssid)
   1327 {
   1328 	os_free(ssid->ssid);
   1329 	os_free(ssid->passphrase);
   1330 #ifdef IEEE8021X_EAPOL
   1331 	os_free(ssid->eap_methods);
   1332 	os_free(ssid->identity);
   1333 	os_free(ssid->anonymous_identity);
   1334 	os_free(ssid->eappsk);
   1335 	os_free(ssid->nai);
   1336 	os_free(ssid->password);
   1337 	os_free(ssid->ca_cert);
   1338 	os_free(ssid->ca_path);
   1339 	os_free(ssid->client_cert);
   1340 	os_free(ssid->private_key);
   1341 	os_free(ssid->private_key_passwd);
   1342 	os_free(ssid->dh_file);
   1343 	os_free(ssid->subject_match);
   1344 	os_free(ssid->altsubject_match);
   1345 	os_free(ssid->ca_cert2);
   1346 	os_free(ssid->ca_path2);
   1347 	os_free(ssid->client_cert2);
   1348 	os_free(ssid->private_key2);
   1349 	os_free(ssid->private_key2_passwd);
   1350 	os_free(ssid->dh_file2);
   1351 	os_free(ssid->subject_match2);
   1352 	os_free(ssid->altsubject_match2);
   1353 	os_free(ssid->phase1);
   1354 	os_free(ssid->phase2);
   1355 	os_free(ssid->pcsc);
   1356 	os_free(ssid->pin);
   1357 	os_free(ssid->engine_id);
   1358 	os_free(ssid->key_id);
   1359 	os_free(ssid->otp);
   1360 	os_free(ssid->pending_req_otp);
   1361 	os_free(ssid->pac_file);
   1362 	os_free(ssid->new_password);
   1363 #endif /* IEEE8021X_EAPOL */
   1364 	os_free(ssid->id_str);
   1365 	os_free(ssid);
   1366 }
   1367 
   1368 
   1369 /**
   1370  * wpa_config_free - Free configuration data
   1371  * @config: Configuration data from wpa_config_read()
   1372  *
   1373  * This function frees all resources allocated for the configuration data by
   1374  * wpa_config_read().
   1375  */
   1376 void wpa_config_free(struct wpa_config *config)
   1377 {
   1378 	struct wpa_config_blob *blob, *prevblob;
   1379 	struct wpa_ssid *ssid, *prev = NULL;
   1380 	ssid = config->ssid;
   1381 	while (ssid) {
   1382 		prev = ssid;
   1383 		ssid = ssid->next;
   1384 		wpa_config_free_ssid(prev);
   1385 	}
   1386 
   1387 	blob = config->blobs;
   1388 	prevblob = NULL;
   1389 	while (blob) {
   1390 		prevblob = blob;
   1391 		blob = blob->next;
   1392 		wpa_config_free_blob(prevblob);
   1393 	}
   1394 
   1395 	os_free(config->ctrl_interface);
   1396 	os_free(config->ctrl_interface_group);
   1397 	os_free(config->opensc_engine_path);
   1398 	os_free(config->pkcs11_engine_path);
   1399 	os_free(config->pkcs11_module_path);
   1400 	os_free(config->driver_param);
   1401 	os_free(config->pssid);
   1402 	os_free(config);
   1403 }
   1404 
   1405 
   1406 #ifdef IEEE8021X_EAPOL
   1407 /**
   1408  * wpa_config_allowed_eap_method - Check whether EAP method is allowed
   1409  * @ssid: Pointer to configuration data
   1410  * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
   1411  * @method: EAP type
   1412  * Returns: 1 = allowed EAP method, 0 = not allowed
   1413  */
   1414 int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int vendor,
   1415 				  u32 method)
   1416 {
   1417 	int i;
   1418 	struct eap_method_type *m;
   1419 
   1420 	if (ssid == NULL || ssid->eap_methods == NULL)
   1421 		return 1;
   1422 
   1423 	m = ssid->eap_methods;
   1424 	for (i = 0; m[i].vendor != EAP_VENDOR_IETF ||
   1425 		     m[i].method != EAP_TYPE_NONE; i++) {
   1426 		if (m[i].vendor == vendor && m[i].method == method)
   1427 			return 1;
   1428 	}
   1429 	return 0;
   1430 }
   1431 #endif /* IEEE8021X_EAPOL */
   1432 
   1433 
   1434 /**
   1435  * wpa_config_get_network - Get configured network based on id
   1436  * @config: Configuration data from wpa_config_read()
   1437  * @id: Unique network id to search for
   1438  * Returns: Network configuration or %NULL if not found
   1439  */
   1440 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
   1441 {
   1442 	struct wpa_ssid *ssid;
   1443 
   1444 	ssid = config->ssid;
   1445 	while (ssid) {
   1446 		if (id == ssid->id)
   1447 			break;
   1448 		ssid = ssid->next;
   1449 	}
   1450 
   1451 	return ssid;
   1452 }
   1453 
   1454 
   1455 /**
   1456  * wpa_config_add_network - Add a new network with empty configuration
   1457  * @config: Configuration data from wpa_config_read()
   1458  * Returns: The new network configuration or %NULL if operation failed
   1459  */
   1460 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
   1461 {
   1462 	int id;
   1463 	struct wpa_ssid *ssid, *last = NULL;
   1464 
   1465 	id = -1;
   1466 	ssid = config->ssid;
   1467 	while (ssid) {
   1468 		if (ssid->id > id)
   1469 			id = ssid->id;
   1470 		last = ssid;
   1471 		ssid = ssid->next;
   1472 	}
   1473 	id++;
   1474 
   1475 	ssid = os_zalloc(sizeof(*ssid));
   1476 	if (ssid == NULL)
   1477 		return NULL;
   1478 	ssid->id = id;
   1479 	if (last)
   1480 		last->next = ssid;
   1481 	else
   1482 		config->ssid = ssid;
   1483 
   1484 	wpa_config_update_prio_list(config);
   1485 
   1486 	return ssid;
   1487 }
   1488 
   1489 
   1490 /**
   1491  * wpa_config_remove_network - Remove a configured network based on id
   1492  * @config: Configuration data from wpa_config_read()
   1493  * @id: Unique network id to search for
   1494  * Returns: 0 on success, or -1 if the network was not found
   1495  */
   1496 int wpa_config_remove_network(struct wpa_config *config, int id)
   1497 {
   1498 	struct wpa_ssid *ssid, *prev = NULL;
   1499 
   1500 	ssid = config->ssid;
   1501 	while (ssid) {
   1502 		if (id == ssid->id)
   1503 			break;
   1504 		prev = ssid;
   1505 		ssid = ssid->next;
   1506 	}
   1507 
   1508 	if (ssid == NULL)
   1509 		return -1;
   1510 
   1511 	if (prev)
   1512 		prev->next = ssid->next;
   1513 	else
   1514 		config->ssid = ssid->next;
   1515 
   1516 	wpa_config_update_prio_list(config);
   1517 	wpa_config_free_ssid(ssid);
   1518 	return 0;
   1519 }
   1520 
   1521 
   1522 /**
   1523  * wpa_config_set_network_defaults - Set network default values
   1524  * @ssid: Pointer to network configuration data
   1525  */
   1526 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
   1527 {
   1528 	ssid->proto = DEFAULT_PROTO;
   1529 	ssid->pairwise_cipher = DEFAULT_PAIRWISE;
   1530 	ssid->group_cipher = DEFAULT_GROUP;
   1531 	ssid->key_mgmt = DEFAULT_KEY_MGMT;
   1532 #ifdef IEEE8021X_EAPOL
   1533 	ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
   1534 	ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
   1535 	ssid->fragment_size = DEFAULT_FRAGMENT_SIZE;
   1536 #endif /* IEEE8021X_EAPOL */
   1537 }
   1538 
   1539 
   1540 /**
   1541  * wpa_config_set - Set a variable in network configuration
   1542  * @ssid: Pointer to network configuration data
   1543  * @var: Variable name, e.g., "ssid"
   1544  * @value: Variable value
   1545  * @line: Line number in configuration file or 0 if not used
   1546  * Returns: 0 on success, -1 on failure
   1547  *
   1548  * This function can be used to set network configuration variables based on
   1549  * both the configuration file and management interface input. The value
   1550  * parameter must be in the same format as the text-based configuration file is
   1551  * using. For example, strings are using double quotation marks.
   1552  */
   1553 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
   1554 		   int line)
   1555 {
   1556 	size_t i;
   1557 	int ret = 0;
   1558 
   1559 	if (ssid == NULL || var == NULL || value == NULL)
   1560 		return -1;
   1561 
   1562 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   1563 		const struct parse_data *field = &ssid_fields[i];
   1564 		if (os_strcmp(var, field->name) != 0)
   1565 			continue;
   1566 
   1567 		if (field->parser(field, ssid, line, value)) {
   1568 			if (line) {
   1569 				wpa_printf(MSG_ERROR, "Line %d: failed to "
   1570 					   "parse %s '%s'.", line, var, value);
   1571 			}
   1572 			ret = -1;
   1573 		}
   1574 		break;
   1575 	}
   1576 	if (i == NUM_SSID_FIELDS) {
   1577 		if (line) {
   1578 			wpa_printf(MSG_ERROR, "Line %d: unknown network field "
   1579 				   "'%s'.", line, var);
   1580 		}
   1581 		ret = -1;
   1582 	}
   1583 
   1584 	return ret;
   1585 }
   1586 
   1587 
   1588 /**
   1589  * wpa_config_get - Get a variable in network configuration
   1590  * @ssid: Pointer to network configuration data
   1591  * @var: Variable name, e.g., "ssid"
   1592  * Returns: Value of the variable or %NULL on failure
   1593  *
   1594  * This function can be used to get network configuration variables. The
   1595  * returned value is a copy of the configuration variable in text format, i.e,.
   1596  * the same format that the text-based configuration file and wpa_config_set()
   1597  * are using for the value. The caller is responsible for freeing the returned
   1598  * value.
   1599  */
   1600 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
   1601 {
   1602 	size_t i;
   1603 
   1604 	if (ssid == NULL || var == NULL)
   1605 		return NULL;
   1606 
   1607 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   1608 		const struct parse_data *field = &ssid_fields[i];
   1609 		if (os_strcmp(var, field->name) == 0)
   1610 			return field->writer(field, ssid);
   1611 	}
   1612 
   1613 	return NULL;
   1614 }
   1615 
   1616 
   1617 /**
   1618  * wpa_config_get_no_key - Get a variable in network configuration (no keys)
   1619  * @ssid: Pointer to network configuration data
   1620  * @var: Variable name, e.g., "ssid"
   1621  * Returns: Value of the variable or %NULL on failure
   1622  *
   1623  * This function can be used to get network configuration variable like
   1624  * wpa_config_get(). The only difference is that this functions does not expose
   1625  * key/password material from the configuration. In case a key/password field
   1626  * is requested, the returned value is an empty string or %NULL if the variable
   1627  * is not set or "*" if the variable is set (regardless of its value). The
   1628  * returned value is a copy of the configuration variable in text format, i.e,.
   1629  * the same format that the text-based configuration file and wpa_config_set()
   1630  * are using for the value. The caller is responsible for freeing the returned
   1631  * value.
   1632  */
   1633 char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
   1634 {
   1635 	size_t i;
   1636 
   1637 	if (ssid == NULL || var == NULL)
   1638 		return NULL;
   1639 
   1640 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
   1641 		const struct parse_data *field = &ssid_fields[i];
   1642 		if (os_strcmp(var, field->name) == 0) {
   1643 			char *res = field->writer(field, ssid);
   1644 			if (field->key_data) {
   1645 				if (res && res[0]) {
   1646 					wpa_printf(MSG_DEBUG, "Do not allow "
   1647 						   "key_data field to be "
   1648 						   "exposed");
   1649 					os_free(res);
   1650 					return os_strdup("*");
   1651 				}
   1652 
   1653 				os_free(res);
   1654 				return NULL;
   1655 			}
   1656 			return res;
   1657 		}
   1658 	}
   1659 
   1660 	return NULL;
   1661 }
   1662 
   1663 
   1664 /**
   1665  * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
   1666  * @ssid: Pointer to network configuration data
   1667  *
   1668  * This function must be called to update WPA PSK when either SSID or the
   1669  * passphrase has changed for the network configuration.
   1670  */
   1671 void wpa_config_update_psk(struct wpa_ssid *ssid)
   1672 {
   1673 	pbkdf2_sha1(ssid->passphrase,
   1674 		    (char *) ssid->ssid, ssid->ssid_len, 4096,
   1675 		    ssid->psk, PMK_LEN);
   1676 	wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
   1677 			ssid->psk, PMK_LEN);
   1678 	ssid->psk_set = 1;
   1679 }
   1680 
   1681 
   1682 /**
   1683  * wpa_config_get_blob - Get a named configuration blob
   1684  * @config: Configuration data from wpa_config_read()
   1685  * @name: Name of the blob
   1686  * Returns: Pointer to blob data or %NULL if not found
   1687  */
   1688 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
   1689 						   const char *name)
   1690 {
   1691 	struct wpa_config_blob *blob = config->blobs;
   1692 
   1693 	while (blob) {
   1694 		if (os_strcmp(blob->name, name) == 0)
   1695 			return blob;
   1696 		blob = blob->next;
   1697 	}
   1698 	return NULL;
   1699 }
   1700 
   1701 
   1702 /**
   1703  * wpa_config_set_blob - Set or add a named configuration blob
   1704  * @config: Configuration data from wpa_config_read()
   1705  * @blob: New value for the blob
   1706  *
   1707  * Adds a new configuration blob or replaces the current value of an existing
   1708  * blob.
   1709  */
   1710 void wpa_config_set_blob(struct wpa_config *config,
   1711 			 struct wpa_config_blob *blob)
   1712 {
   1713 	wpa_config_remove_blob(config, blob->name);
   1714 	blob->next = config->blobs;
   1715 	config->blobs = blob;
   1716 }
   1717 
   1718 
   1719 /**
   1720  * wpa_config_free_blob - Free blob data
   1721  * @blob: Pointer to blob to be freed
   1722  */
   1723 void wpa_config_free_blob(struct wpa_config_blob *blob)
   1724 {
   1725 	if (blob) {
   1726 		os_free(blob->name);
   1727 		os_free(blob->data);
   1728 		os_free(blob);
   1729 	}
   1730 }
   1731 
   1732 
   1733 /**
   1734  * wpa_config_remove_blob - Remove a named configuration blob
   1735  * @config: Configuration data from wpa_config_read()
   1736  * @name: Name of the blob to remove
   1737  * Returns: 0 if blob was removed or -1 if blob was not found
   1738  */
   1739 int wpa_config_remove_blob(struct wpa_config *config, const char *name)
   1740 {
   1741 	struct wpa_config_blob *pos = config->blobs, *prev = NULL;
   1742 
   1743 	while (pos) {
   1744 		if (os_strcmp(pos->name, name) == 0) {
   1745 			if (prev)
   1746 				prev->next = pos->next;
   1747 			else
   1748 				config->blobs = pos->next;
   1749 			wpa_config_free_blob(pos);
   1750 			return 0;
   1751 		}
   1752 		prev = pos;
   1753 		pos = pos->next;
   1754 	}
   1755 
   1756 	return -1;
   1757 }
   1758 
   1759 
   1760 /**
   1761  * wpa_config_alloc_empty - Allocate an empty configuration
   1762  * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
   1763  * socket
   1764  * @driver_param: Driver parameters
   1765  * Returns: Pointer to allocated configuration data or %NULL on failure
   1766  */
   1767 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
   1768 					   const char *driver_param)
   1769 {
   1770 	struct wpa_config *config;
   1771 
   1772 	config = os_zalloc(sizeof(*config));
   1773 	if (config == NULL)
   1774 		return NULL;
   1775 	config->eapol_version = DEFAULT_EAPOL_VERSION;
   1776 	config->ap_scan = DEFAULT_AP_SCAN;
   1777 	config->fast_reauth = DEFAULT_FAST_REAUTH;
   1778 
   1779 	if (ctrl_interface)
   1780 		config->ctrl_interface = os_strdup(ctrl_interface);
   1781 	if (driver_param)
   1782 		config->driver_param = os_strdup(driver_param);
   1783 
   1784 	return config;
   1785 }
   1786 
   1787 
   1788 #ifndef CONFIG_NO_STDOUT_DEBUG
   1789 /**
   1790  * wpa_config_debug_dump_networks - Debug dump of configured networks
   1791  * @config: Configuration data from wpa_config_read()
   1792  */
   1793 void wpa_config_debug_dump_networks(struct wpa_config *config)
   1794 {
   1795 	int prio;
   1796 	struct wpa_ssid *ssid;
   1797 
   1798 	for (prio = 0; prio < config->num_prio; prio++) {
   1799 		ssid = config->pssid[prio];
   1800 		wpa_printf(MSG_DEBUG, "Priority group %d",
   1801 			   ssid->priority);
   1802 		while (ssid) {
   1803 			wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
   1804 				   ssid->id,
   1805 				   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
   1806 			ssid = ssid->pnext;
   1807 		}
   1808 	}
   1809 }
   1810 #endif /* CONFIG_NO_STDOUT_DEBUG */
   1811