$search
00001 /* 00002 * WPA Supplicant / Configuration parser and common functions 00003 * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "crypto/sha1.h" 00019 #include "rsn_supp/wpa.h" 00020 #include "eap_peer/eap.h" 00021 #include "config.h" 00022 00023 00024 #if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE) 00025 #define NO_CONFIG_WRITE 00026 #endif 00027 00028 /* 00029 * Structure for network configuration parsing. This data is used to implement 00030 * a generic parser for each network block variable. The table of configuration 00031 * variables is defined below in this file (ssid_fields[]). 00032 */ 00033 struct parse_data { 00034 /* Configuration variable name */ 00035 char *name; 00036 00037 /* Parser function for this variable */ 00038 int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid, 00039 int line, const char *value); 00040 00041 #ifndef NO_CONFIG_WRITE 00042 /* Writer function (i.e., to get the variable in text format from 00043 * internal presentation). */ 00044 char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid); 00045 #endif /* NO_CONFIG_WRITE */ 00046 00047 /* Variable specific parameters for the parser. */ 00048 void *param1, *param2, *param3, *param4; 00049 00050 /* 0 = this variable can be included in debug output and ctrl_iface 00051 * 1 = this variable contains key/private data and it must not be 00052 * included in debug output unless explicitly requested. In 00053 * addition, this variable will not be readable through the 00054 * ctrl_iface. 00055 */ 00056 int key_data; 00057 }; 00058 00059 00060 static char * wpa_config_parse_string(const char *value, size_t *len) 00061 { 00062 if (*value == '"') { 00063 const char *pos; 00064 char *str; 00065 value++; 00066 pos = os_strrchr(value, '"'); 00067 if (pos == NULL || pos[1] != '\0') 00068 return NULL; 00069 *len = pos - value; 00070 str = os_malloc(*len + 1); 00071 if (str == NULL) 00072 return NULL; 00073 os_memcpy(str, value, *len); 00074 str[*len] = '\0'; 00075 return str; 00076 } else { 00077 u8 *str; 00078 size_t tlen, hlen = os_strlen(value); 00079 if (hlen & 1) 00080 return NULL; 00081 tlen = hlen / 2; 00082 str = os_malloc(tlen + 1); 00083 if (str == NULL) 00084 return NULL; 00085 if (hexstr2bin(value, str, tlen)) { 00086 os_free(str); 00087 return NULL; 00088 } 00089 str[tlen] = '\0'; 00090 *len = tlen; 00091 return (char *) str; 00092 } 00093 } 00094 00095 00096 static int wpa_config_parse_str(const struct parse_data *data, 00097 struct wpa_ssid *ssid, 00098 int line, const char *value) 00099 { 00100 size_t res_len, *dst_len; 00101 char **dst, *tmp; 00102 00103 if (os_strcmp(value, "NULL") == 0) { 00104 wpa_printf(MSG_DEBUG, "Unset configuration string '%s'", 00105 data->name); 00106 tmp = NULL; 00107 res_len = 0; 00108 goto set; 00109 } 00110 00111 tmp = wpa_config_parse_string(value, &res_len); 00112 if (tmp == NULL) { 00113 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.", 00114 line, data->name, 00115 data->key_data ? "[KEY DATA REMOVED]" : value); 00116 return -1; 00117 } 00118 00119 if (data->key_data) { 00120 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, 00121 (u8 *) tmp, res_len); 00122 } else { 00123 wpa_hexdump_ascii(MSG_MSGDUMP, data->name, 00124 (u8 *) tmp, res_len); 00125 } 00126 00127 if (data->param3 && res_len < (size_t) data->param3) { 00128 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " 00129 "min_len=%ld)", line, data->name, 00130 (unsigned long) res_len, (long) data->param3); 00131 os_free(tmp); 00132 return -1; 00133 } 00134 00135 if (data->param4 && res_len > (size_t) data->param4) { 00136 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " 00137 "max_len=%ld)", line, data->name, 00138 (unsigned long) res_len, (long) data->param4); 00139 os_free(tmp); 00140 return -1; 00141 } 00142 00143 set: 00144 dst = (char **) (((u8 *) ssid) + (long) data->param1); 00145 dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2); 00146 os_free(*dst); 00147 *dst = tmp; 00148 if (data->param2) 00149 *dst_len = res_len; 00150 00151 return 0; 00152 } 00153 00154 00155 #ifndef NO_CONFIG_WRITE 00156 static int is_hex(const u8 *data, size_t len) 00157 { 00158 size_t i; 00159 00160 for (i = 0; i < len; i++) { 00161 if (data[i] < 32 || data[i] >= 127) 00162 return 1; 00163 } 00164 return 0; 00165 } 00166 00167 00168 static char * wpa_config_write_string_ascii(const u8 *value, size_t len) 00169 { 00170 char *buf; 00171 00172 buf = os_malloc(len + 3); 00173 if (buf == NULL) 00174 return NULL; 00175 buf[0] = '"'; 00176 os_memcpy(buf + 1, value, len); 00177 buf[len + 1] = '"'; 00178 buf[len + 2] = '\0'; 00179 00180 return buf; 00181 } 00182 00183 00184 static char * wpa_config_write_string_hex(const u8 *value, size_t len) 00185 { 00186 char *buf; 00187 00188 buf = os_zalloc(2 * len + 1); 00189 if (buf == NULL) 00190 return NULL; 00191 wpa_snprintf_hex(buf, 2 * len + 1, value, len); 00192 00193 return buf; 00194 } 00195 00196 00197 static char * wpa_config_write_string(const u8 *value, size_t len) 00198 { 00199 if (value == NULL) 00200 return NULL; 00201 00202 if (is_hex(value, len)) 00203 return wpa_config_write_string_hex(value, len); 00204 else 00205 return wpa_config_write_string_ascii(value, len); 00206 } 00207 00208 00209 static char * wpa_config_write_str(const struct parse_data *data, 00210 struct wpa_ssid *ssid) 00211 { 00212 size_t len; 00213 char **src; 00214 00215 src = (char **) (((u8 *) ssid) + (long) data->param1); 00216 if (*src == NULL) 00217 return NULL; 00218 00219 if (data->param2) 00220 len = *((size_t *) (((u8 *) ssid) + (long) data->param2)); 00221 else 00222 len = os_strlen(*src); 00223 00224 return wpa_config_write_string((const u8 *) *src, len); 00225 } 00226 #endif /* NO_CONFIG_WRITE */ 00227 00228 00229 static int wpa_config_parse_int(const struct parse_data *data, 00230 struct wpa_ssid *ssid, 00231 int line, const char *value) 00232 { 00233 int *dst; 00234 00235 dst = (int *) (((u8 *) ssid) + (long) data->param1); 00236 *dst = atoi(value); 00237 wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst); 00238 00239 if (data->param3 && *dst < (long) data->param3) { 00240 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " 00241 "min_value=%ld)", line, data->name, *dst, 00242 (long) data->param3); 00243 *dst = (long) data->param3; 00244 return -1; 00245 } 00246 00247 if (data->param4 && *dst > (long) data->param4) { 00248 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " 00249 "max_value=%ld)", line, data->name, *dst, 00250 (long) data->param4); 00251 *dst = (long) data->param4; 00252 return -1; 00253 } 00254 00255 return 0; 00256 } 00257 00258 00259 #ifndef NO_CONFIG_WRITE 00260 static char * wpa_config_write_int(const struct parse_data *data, 00261 struct wpa_ssid *ssid) 00262 { 00263 int *src, res; 00264 char *value; 00265 00266 src = (int *) (((u8 *) ssid) + (long) data->param1); 00267 00268 value = os_malloc(20); 00269 if (value == NULL) 00270 return NULL; 00271 res = os_snprintf(value, 20, "%d", *src); 00272 if (res < 0 || res >= 20) { 00273 os_free(value); 00274 return NULL; 00275 } 00276 value[20 - 1] = '\0'; 00277 return value; 00278 } 00279 #endif /* NO_CONFIG_WRITE */ 00280 00281 00282 static int wpa_config_parse_bssid(const struct parse_data *data, 00283 struct wpa_ssid *ssid, int line, 00284 const char *value) 00285 { 00286 if (hwaddr_aton(value, ssid->bssid)) { 00287 wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.", 00288 line, value); 00289 return -1; 00290 } 00291 ssid->bssid_set = 1; 00292 wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN); 00293 return 0; 00294 } 00295 00296 00297 #ifndef NO_CONFIG_WRITE 00298 static char * wpa_config_write_bssid(const struct parse_data *data, 00299 struct wpa_ssid *ssid) 00300 { 00301 char *value; 00302 int res; 00303 00304 if (!ssid->bssid_set) 00305 return NULL; 00306 00307 value = os_malloc(20); 00308 if (value == NULL) 00309 return NULL; 00310 res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid)); 00311 if (res < 0 || res >= 20) { 00312 os_free(value); 00313 return NULL; 00314 } 00315 value[20 - 1] = '\0'; 00316 return value; 00317 } 00318 #endif /* NO_CONFIG_WRITE */ 00319 00320 00321 static int wpa_config_parse_psk(const struct parse_data *data, 00322 struct wpa_ssid *ssid, int line, 00323 const char *value) 00324 { 00325 if (*value == '"') { 00326 #ifndef CONFIG_NO_PBKDF2 00327 const char *pos; 00328 size_t len; 00329 00330 value++; 00331 pos = os_strrchr(value, '"'); 00332 if (pos) 00333 len = pos - value; 00334 else 00335 len = os_strlen(value); 00336 if (len < 8 || len > 63) { 00337 wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase " 00338 "length %lu (expected: 8..63) '%s'.", 00339 line, (unsigned long) len, value); 00340 return -1; 00341 } 00342 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)", 00343 (u8 *) value, len); 00344 if (ssid->passphrase && os_strlen(ssid->passphrase) == len && 00345 os_memcmp(ssid->passphrase, value, len) == 0) 00346 return 0; 00347 ssid->psk_set = 0; 00348 os_free(ssid->passphrase); 00349 ssid->passphrase = os_malloc(len + 1); 00350 if (ssid->passphrase == NULL) 00351 return -1; 00352 os_memcpy(ssid->passphrase, value, len); 00353 ssid->passphrase[len] = '\0'; 00354 return 0; 00355 #else /* CONFIG_NO_PBKDF2 */ 00356 wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not " 00357 "supported.", line); 00358 return -1; 00359 #endif /* CONFIG_NO_PBKDF2 */ 00360 } 00361 00362 if (hexstr2bin(value, ssid->psk, PMK_LEN) || 00363 value[PMK_LEN * 2] != '\0') { 00364 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", 00365 line, value); 00366 return -1; 00367 } 00368 00369 os_free(ssid->passphrase); 00370 ssid->passphrase = NULL; 00371 00372 ssid->psk_set = 1; 00373 wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN); 00374 return 0; 00375 } 00376 00377 00378 #ifndef NO_CONFIG_WRITE 00379 static char * wpa_config_write_psk(const struct parse_data *data, 00380 struct wpa_ssid *ssid) 00381 { 00382 if (ssid->passphrase) 00383 return wpa_config_write_string_ascii( 00384 (const u8 *) ssid->passphrase, 00385 os_strlen(ssid->passphrase)); 00386 00387 if (ssid->psk_set) 00388 return wpa_config_write_string_hex(ssid->psk, PMK_LEN); 00389 00390 return NULL; 00391 } 00392 #endif /* NO_CONFIG_WRITE */ 00393 00394 00395 static int wpa_config_parse_proto(const struct parse_data *data, 00396 struct wpa_ssid *ssid, int line, 00397 const char *value) 00398 { 00399 int val = 0, last, errors = 0; 00400 char *start, *end, *buf; 00401 00402 buf = os_strdup(value); 00403 if (buf == NULL) 00404 return -1; 00405 start = buf; 00406 00407 while (*start != '\0') { 00408 while (*start == ' ' || *start == '\t') 00409 start++; 00410 if (*start == '\0') 00411 break; 00412 end = start; 00413 while (*end != ' ' && *end != '\t' && *end != '\0') 00414 end++; 00415 last = *end == '\0'; 00416 *end = '\0'; 00417 if (os_strcmp(start, "WPA") == 0) 00418 val |= WPA_PROTO_WPA; 00419 else if (os_strcmp(start, "RSN") == 0 || 00420 os_strcmp(start, "WPA2") == 0) 00421 val |= WPA_PROTO_RSN; 00422 else { 00423 wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'", 00424 line, start); 00425 errors++; 00426 } 00427 00428 if (last) 00429 break; 00430 start = end + 1; 00431 } 00432 os_free(buf); 00433 00434 if (val == 0) { 00435 wpa_printf(MSG_ERROR, 00436 "Line %d: no proto values configured.", line); 00437 errors++; 00438 } 00439 00440 wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val); 00441 ssid->proto = val; 00442 return errors ? -1 : 0; 00443 } 00444 00445 00446 #ifndef NO_CONFIG_WRITE 00447 static char * wpa_config_write_proto(const struct parse_data *data, 00448 struct wpa_ssid *ssid) 00449 { 00450 int first = 1, ret; 00451 char *buf, *pos, *end; 00452 00453 pos = buf = os_zalloc(10); 00454 if (buf == NULL) 00455 return NULL; 00456 end = buf + 10; 00457 00458 if (ssid->proto & WPA_PROTO_WPA) { 00459 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); 00460 if (ret < 0 || ret >= end - pos) 00461 return buf; 00462 pos += ret; 00463 first = 0; 00464 } 00465 00466 if (ssid->proto & WPA_PROTO_RSN) { 00467 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); 00468 if (ret < 0 || ret >= end - pos) 00469 return buf; 00470 pos += ret; 00471 first = 0; 00472 } 00473 00474 return buf; 00475 } 00476 #endif /* NO_CONFIG_WRITE */ 00477 00478 00479 static int wpa_config_parse_key_mgmt(const struct parse_data *data, 00480 struct wpa_ssid *ssid, int line, 00481 const char *value) 00482 { 00483 int val = 0, last, errors = 0; 00484 char *start, *end, *buf; 00485 00486 buf = os_strdup(value); 00487 if (buf == NULL) 00488 return -1; 00489 start = buf; 00490 00491 while (*start != '\0') { 00492 while (*start == ' ' || *start == '\t') 00493 start++; 00494 if (*start == '\0') 00495 break; 00496 end = start; 00497 while (*end != ' ' && *end != '\t' && *end != '\0') 00498 end++; 00499 last = *end == '\0'; 00500 *end = '\0'; 00501 if (os_strcmp(start, "WPA-PSK") == 0) 00502 val |= WPA_KEY_MGMT_PSK; 00503 else if (os_strcmp(start, "WPA-EAP") == 0) 00504 val |= WPA_KEY_MGMT_IEEE8021X; 00505 else if (os_strcmp(start, "IEEE8021X") == 0) 00506 val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA; 00507 else if (os_strcmp(start, "NONE") == 0) 00508 val |= WPA_KEY_MGMT_NONE; 00509 else if (os_strcmp(start, "WPA-NONE") == 0) 00510 val |= WPA_KEY_MGMT_WPA_NONE; 00511 #ifdef CONFIG_IEEE80211R 00512 else if (os_strcmp(start, "FT-PSK") == 0) 00513 val |= WPA_KEY_MGMT_FT_PSK; 00514 else if (os_strcmp(start, "FT-EAP") == 0) 00515 val |= WPA_KEY_MGMT_FT_IEEE8021X; 00516 #endif /* CONFIG_IEEE80211R */ 00517 #ifdef CONFIG_IEEE80211W 00518 else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) 00519 val |= WPA_KEY_MGMT_PSK_SHA256; 00520 else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) 00521 val |= WPA_KEY_MGMT_IEEE8021X_SHA256; 00522 #endif /* CONFIG_IEEE80211W */ 00523 #ifdef CONFIG_WPS 00524 else if (os_strcmp(start, "WPS") == 0) 00525 val |= WPA_KEY_MGMT_WPS; 00526 #endif /* CONFIG_WPS */ 00527 else { 00528 wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", 00529 line, start); 00530 errors++; 00531 } 00532 00533 if (last) 00534 break; 00535 start = end + 1; 00536 } 00537 os_free(buf); 00538 00539 if (val == 0) { 00540 wpa_printf(MSG_ERROR, 00541 "Line %d: no key_mgmt values configured.", line); 00542 errors++; 00543 } 00544 00545 wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val); 00546 ssid->key_mgmt = val; 00547 return errors ? -1 : 0; 00548 } 00549 00550 00551 #ifndef NO_CONFIG_WRITE 00552 static char * wpa_config_write_key_mgmt(const struct parse_data *data, 00553 struct wpa_ssid *ssid) 00554 { 00555 char *buf, *pos, *end; 00556 int ret; 00557 00558 pos = buf = os_zalloc(50); 00559 if (buf == NULL) 00560 return NULL; 00561 end = buf + 50; 00562 00563 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { 00564 ret = os_snprintf(pos, end - pos, "%sWPA-PSK", 00565 pos == buf ? "" : " "); 00566 if (ret < 0 || ret >= end - pos) { 00567 end[-1] = '\0'; 00568 return buf; 00569 } 00570 pos += ret; 00571 } 00572 00573 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 00574 ret = os_snprintf(pos, end - pos, "%sWPA-EAP", 00575 pos == buf ? "" : " "); 00576 if (ret < 0 || ret >= end - pos) { 00577 end[-1] = '\0'; 00578 return buf; 00579 } 00580 pos += ret; 00581 } 00582 00583 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 00584 ret = os_snprintf(pos, end - pos, "%sIEEE8021X", 00585 pos == buf ? "" : " "); 00586 if (ret < 0 || ret >= end - pos) { 00587 end[-1] = '\0'; 00588 return buf; 00589 } 00590 pos += ret; 00591 } 00592 00593 if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) { 00594 ret = os_snprintf(pos, end - pos, "%sNONE", 00595 pos == buf ? "" : " "); 00596 if (ret < 0 || ret >= end - pos) { 00597 end[-1] = '\0'; 00598 return buf; 00599 } 00600 pos += ret; 00601 } 00602 00603 if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 00604 ret = os_snprintf(pos, end - pos, "%sWPA-NONE", 00605 pos == buf ? "" : " "); 00606 if (ret < 0 || ret >= end - pos) { 00607 end[-1] = '\0'; 00608 return buf; 00609 } 00610 pos += ret; 00611 } 00612 00613 #ifdef CONFIG_IEEE80211R 00614 if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK) 00615 pos += os_snprintf(pos, end - pos, "%sFT-PSK", 00616 pos == buf ? "" : " "); 00617 00618 if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 00619 pos += os_snprintf(pos, end - pos, "%sFT-EAP", 00620 pos == buf ? "" : " "); 00621 #endif /* CONFIG_IEEE80211R */ 00622 00623 #ifdef CONFIG_IEEE80211W 00624 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 00625 pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256", 00626 pos == buf ? "" : " "); 00627 00628 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 00629 pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256", 00630 pos == buf ? "" : " "); 00631 #endif /* CONFIG_IEEE80211W */ 00632 00633 #ifdef CONFIG_WPS 00634 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) 00635 pos += os_snprintf(pos, end - pos, "%sWPS", 00636 pos == buf ? "" : " "); 00637 #endif /* CONFIG_WPS */ 00638 00639 return buf; 00640 } 00641 #endif /* NO_CONFIG_WRITE */ 00642 00643 00644 static int wpa_config_parse_cipher(int line, const char *value) 00645 { 00646 int val = 0, last; 00647 char *start, *end, *buf; 00648 00649 buf = os_strdup(value); 00650 if (buf == NULL) 00651 return -1; 00652 start = buf; 00653 00654 while (*start != '\0') { 00655 while (*start == ' ' || *start == '\t') 00656 start++; 00657 if (*start == '\0') 00658 break; 00659 end = start; 00660 while (*end != ' ' && *end != '\t' && *end != '\0') 00661 end++; 00662 last = *end == '\0'; 00663 *end = '\0'; 00664 if (os_strcmp(start, "CCMP") == 0) 00665 val |= WPA_CIPHER_CCMP; 00666 else if (os_strcmp(start, "TKIP") == 0) 00667 val |= WPA_CIPHER_TKIP; 00668 else if (os_strcmp(start, "WEP104") == 0) 00669 val |= WPA_CIPHER_WEP104; 00670 else if (os_strcmp(start, "WEP40") == 0) 00671 val |= WPA_CIPHER_WEP40; 00672 else if (os_strcmp(start, "NONE") == 0) 00673 val |= WPA_CIPHER_NONE; 00674 else { 00675 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", 00676 line, start); 00677 os_free(buf); 00678 return -1; 00679 } 00680 00681 if (last) 00682 break; 00683 start = end + 1; 00684 } 00685 os_free(buf); 00686 00687 if (val == 0) { 00688 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", 00689 line); 00690 return -1; 00691 } 00692 return val; 00693 } 00694 00695 00696 #ifndef NO_CONFIG_WRITE 00697 static char * wpa_config_write_cipher(int cipher) 00698 { 00699 char *buf, *pos, *end; 00700 int ret; 00701 00702 pos = buf = os_zalloc(50); 00703 if (buf == NULL) 00704 return NULL; 00705 end = buf + 50; 00706 00707 if (cipher & WPA_CIPHER_CCMP) { 00708 ret = os_snprintf(pos, end - pos, "%sCCMP", 00709 pos == buf ? "" : " "); 00710 if (ret < 0 || ret >= end - pos) { 00711 end[-1] = '\0'; 00712 return buf; 00713 } 00714 pos += ret; 00715 } 00716 00717 if (cipher & WPA_CIPHER_TKIP) { 00718 ret = os_snprintf(pos, end - pos, "%sTKIP", 00719 pos == buf ? "" : " "); 00720 if (ret < 0 || ret >= end - pos) { 00721 end[-1] = '\0'; 00722 return buf; 00723 } 00724 pos += ret; 00725 } 00726 00727 if (cipher & WPA_CIPHER_WEP104) { 00728 ret = os_snprintf(pos, end - pos, "%sWEP104", 00729 pos == buf ? "" : " "); 00730 if (ret < 0 || ret >= end - pos) { 00731 end[-1] = '\0'; 00732 return buf; 00733 } 00734 pos += ret; 00735 } 00736 00737 if (cipher & WPA_CIPHER_WEP40) { 00738 ret = os_snprintf(pos, end - pos, "%sWEP40", 00739 pos == buf ? "" : " "); 00740 if (ret < 0 || ret >= end - pos) { 00741 end[-1] = '\0'; 00742 return buf; 00743 } 00744 pos += ret; 00745 } 00746 00747 if (cipher & WPA_CIPHER_NONE) { 00748 ret = os_snprintf(pos, end - pos, "%sNONE", 00749 pos == buf ? "" : " "); 00750 if (ret < 0 || ret >= end - pos) { 00751 end[-1] = '\0'; 00752 return buf; 00753 } 00754 pos += ret; 00755 } 00756 00757 return buf; 00758 } 00759 #endif /* NO_CONFIG_WRITE */ 00760 00761 00762 static int wpa_config_parse_pairwise(const struct parse_data *data, 00763 struct wpa_ssid *ssid, int line, 00764 const char *value) 00765 { 00766 int val; 00767 val = wpa_config_parse_cipher(line, value); 00768 if (val == -1) 00769 return -1; 00770 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) { 00771 wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher " 00772 "(0x%x).", line, val); 00773 return -1; 00774 } 00775 00776 wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val); 00777 ssid->pairwise_cipher = val; 00778 return 0; 00779 } 00780 00781 00782 #ifndef NO_CONFIG_WRITE 00783 static char * wpa_config_write_pairwise(const struct parse_data *data, 00784 struct wpa_ssid *ssid) 00785 { 00786 return wpa_config_write_cipher(ssid->pairwise_cipher); 00787 } 00788 #endif /* NO_CONFIG_WRITE */ 00789 00790 00791 static int wpa_config_parse_group(const struct parse_data *data, 00792 struct wpa_ssid *ssid, int line, 00793 const char *value) 00794 { 00795 int val; 00796 val = wpa_config_parse_cipher(line, value); 00797 if (val == -1) 00798 return -1; 00799 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 | 00800 WPA_CIPHER_WEP40)) { 00801 wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher " 00802 "(0x%x).", line, val); 00803 return -1; 00804 } 00805 00806 wpa_printf(MSG_MSGDUMP, "group: 0x%x", val); 00807 ssid->group_cipher = val; 00808 return 0; 00809 } 00810 00811 00812 #ifndef NO_CONFIG_WRITE 00813 static char * wpa_config_write_group(const struct parse_data *data, 00814 struct wpa_ssid *ssid) 00815 { 00816 return wpa_config_write_cipher(ssid->group_cipher); 00817 } 00818 #endif /* NO_CONFIG_WRITE */ 00819 00820 00821 static int wpa_config_parse_auth_alg(const struct parse_data *data, 00822 struct wpa_ssid *ssid, int line, 00823 const char *value) 00824 { 00825 int val = 0, last, errors = 0; 00826 char *start, *end, *buf; 00827 00828 buf = os_strdup(value); 00829 if (buf == NULL) 00830 return -1; 00831 start = buf; 00832 00833 while (*start != '\0') { 00834 while (*start == ' ' || *start == '\t') 00835 start++; 00836 if (*start == '\0') 00837 break; 00838 end = start; 00839 while (*end != ' ' && *end != '\t' && *end != '\0') 00840 end++; 00841 last = *end == '\0'; 00842 *end = '\0'; 00843 if (os_strcmp(start, "OPEN") == 0) 00844 val |= WPA_AUTH_ALG_OPEN; 00845 else if (os_strcmp(start, "SHARED") == 0) 00846 val |= WPA_AUTH_ALG_SHARED; 00847 else if (os_strcmp(start, "LEAP") == 0) 00848 val |= WPA_AUTH_ALG_LEAP; 00849 else { 00850 wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'", 00851 line, start); 00852 errors++; 00853 } 00854 00855 if (last) 00856 break; 00857 start = end + 1; 00858 } 00859 os_free(buf); 00860 00861 if (val == 0) { 00862 wpa_printf(MSG_ERROR, 00863 "Line %d: no auth_alg values configured.", line); 00864 errors++; 00865 } 00866 00867 wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val); 00868 ssid->auth_alg = val; 00869 return errors ? -1 : 0; 00870 } 00871 00872 00873 #ifndef NO_CONFIG_WRITE 00874 static char * wpa_config_write_auth_alg(const struct parse_data *data, 00875 struct wpa_ssid *ssid) 00876 { 00877 char *buf, *pos, *end; 00878 int ret; 00879 00880 pos = buf = os_zalloc(30); 00881 if (buf == NULL) 00882 return NULL; 00883 end = buf + 30; 00884 00885 if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) { 00886 ret = os_snprintf(pos, end - pos, "%sOPEN", 00887 pos == buf ? "" : " "); 00888 if (ret < 0 || ret >= end - pos) { 00889 end[-1] = '\0'; 00890 return buf; 00891 } 00892 pos += ret; 00893 } 00894 00895 if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) { 00896 ret = os_snprintf(pos, end - pos, "%sSHARED", 00897 pos == buf ? "" : " "); 00898 if (ret < 0 || ret >= end - pos) { 00899 end[-1] = '\0'; 00900 return buf; 00901 } 00902 pos += ret; 00903 } 00904 00905 if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) { 00906 ret = os_snprintf(pos, end - pos, "%sLEAP", 00907 pos == buf ? "" : " "); 00908 if (ret < 0 || ret >= end - pos) { 00909 end[-1] = '\0'; 00910 return buf; 00911 } 00912 pos += ret; 00913 } 00914 00915 return buf; 00916 } 00917 #endif /* NO_CONFIG_WRITE */ 00918 00919 00920 static int * wpa_config_parse_freqs(const struct parse_data *data, 00921 struct wpa_ssid *ssid, int line, 00922 const char *value) 00923 { 00924 int *freqs; 00925 size_t used, len; 00926 const char *pos; 00927 00928 used = 0; 00929 len = 10; 00930 freqs = os_zalloc((len + 1) * sizeof(int)); 00931 if (freqs == NULL) 00932 return NULL; 00933 00934 pos = value; 00935 while (pos) { 00936 while (*pos == ' ') 00937 pos++; 00938 if (used == len) { 00939 int *n; 00940 size_t i; 00941 n = os_realloc(freqs, (len * 2 + 1) * sizeof(int)); 00942 if (n == NULL) { 00943 os_free(freqs); 00944 return NULL; 00945 } 00946 for (i = len; i <= len * 2; i++) 00947 n[i] = 0; 00948 freqs = n; 00949 len *= 2; 00950 } 00951 00952 freqs[used] = atoi(pos); 00953 if (freqs[used] == 0) 00954 break; 00955 used++; 00956 pos = os_strchr(pos + 1, ' '); 00957 } 00958 00959 return freqs; 00960 } 00961 00962 00963 static int wpa_config_parse_scan_freq(const struct parse_data *data, 00964 struct wpa_ssid *ssid, int line, 00965 const char *value) 00966 { 00967 int *freqs; 00968 00969 freqs = wpa_config_parse_freqs(data, ssid, line, value); 00970 if (freqs == NULL) 00971 return -1; 00972 os_free(ssid->scan_freq); 00973 ssid->scan_freq = freqs; 00974 00975 return 0; 00976 } 00977 00978 00979 static int wpa_config_parse_freq_list(const struct parse_data *data, 00980 struct wpa_ssid *ssid, int line, 00981 const char *value) 00982 { 00983 int *freqs; 00984 00985 freqs = wpa_config_parse_freqs(data, ssid, line, value); 00986 if (freqs == NULL) 00987 return -1; 00988 os_free(ssid->freq_list); 00989 ssid->freq_list = freqs; 00990 00991 return 0; 00992 } 00993 00994 00995 #ifndef NO_CONFIG_WRITE 00996 static char * wpa_config_write_freqs(const struct parse_data *data, 00997 const int *freqs) 00998 { 00999 char *buf, *pos, *end; 01000 int i, ret; 01001 size_t count; 01002 01003 if (freqs == NULL) 01004 return NULL; 01005 01006 count = 0; 01007 for (i = 0; freqs[i]; i++) 01008 count++; 01009 01010 pos = buf = os_zalloc(10 * count + 1); 01011 if (buf == NULL) 01012 return NULL; 01013 end = buf + 10 * count + 1; 01014 01015 for (i = 0; freqs[i]; i++) { 01016 ret = os_snprintf(pos, end - pos, "%s%u", 01017 i == 0 ? "" : " ", freqs[i]); 01018 if (ret < 0 || ret >= end - pos) { 01019 end[-1] = '\0'; 01020 return buf; 01021 } 01022 pos += ret; 01023 } 01024 01025 return buf; 01026 } 01027 01028 01029 static char * wpa_config_write_scan_freq(const struct parse_data *data, 01030 struct wpa_ssid *ssid) 01031 { 01032 return wpa_config_write_freqs(data, ssid->scan_freq); 01033 } 01034 01035 01036 static char * wpa_config_write_freq_list(const struct parse_data *data, 01037 struct wpa_ssid *ssid) 01038 { 01039 return wpa_config_write_freqs(data, ssid->freq_list); 01040 } 01041 #endif /* NO_CONFIG_WRITE */ 01042 01043 01044 #ifdef IEEE8021X_EAPOL 01045 static int wpa_config_parse_eap(const struct parse_data *data, 01046 struct wpa_ssid *ssid, int line, 01047 const char *value) 01048 { 01049 int last, errors = 0; 01050 char *start, *end, *buf; 01051 struct eap_method_type *methods = NULL, *tmp; 01052 size_t num_methods = 0; 01053 01054 buf = os_strdup(value); 01055 if (buf == NULL) 01056 return -1; 01057 start = buf; 01058 01059 while (*start != '\0') { 01060 while (*start == ' ' || *start == '\t') 01061 start++; 01062 if (*start == '\0') 01063 break; 01064 end = start; 01065 while (*end != ' ' && *end != '\t' && *end != '\0') 01066 end++; 01067 last = *end == '\0'; 01068 *end = '\0'; 01069 tmp = methods; 01070 methods = os_realloc(methods, 01071 (num_methods + 1) * sizeof(*methods)); 01072 if (methods == NULL) { 01073 os_free(tmp); 01074 os_free(buf); 01075 return -1; 01076 } 01077 methods[num_methods].method = eap_peer_get_type( 01078 start, &methods[num_methods].vendor); 01079 if (methods[num_methods].vendor == EAP_VENDOR_IETF && 01080 methods[num_methods].method == EAP_TYPE_NONE) { 01081 wpa_printf(MSG_ERROR, "Line %d: unknown EAP method " 01082 "'%s'", line, start); 01083 wpa_printf(MSG_ERROR, "You may need to add support for" 01084 " this EAP method during wpa_supplicant\n" 01085 "build time configuration.\n" 01086 "See README for more information."); 01087 errors++; 01088 } else if (methods[num_methods].vendor == EAP_VENDOR_IETF && 01089 methods[num_methods].method == EAP_TYPE_LEAP) 01090 ssid->leap++; 01091 else 01092 ssid->non_leap++; 01093 num_methods++; 01094 if (last) 01095 break; 01096 start = end + 1; 01097 } 01098 os_free(buf); 01099 01100 tmp = methods; 01101 methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods)); 01102 if (methods == NULL) { 01103 os_free(tmp); 01104 return -1; 01105 } 01106 methods[num_methods].vendor = EAP_VENDOR_IETF; 01107 methods[num_methods].method = EAP_TYPE_NONE; 01108 num_methods++; 01109 01110 wpa_hexdump(MSG_MSGDUMP, "eap methods", 01111 (u8 *) methods, num_methods * sizeof(*methods)); 01112 ssid->eap.eap_methods = methods; 01113 return errors ? -1 : 0; 01114 } 01115 01116 01117 static char * wpa_config_write_eap(const struct parse_data *data, 01118 struct wpa_ssid *ssid) 01119 { 01120 int i, ret; 01121 char *buf, *pos, *end; 01122 const struct eap_method_type *eap_methods = ssid->eap.eap_methods; 01123 const char *name; 01124 01125 if (eap_methods == NULL) 01126 return NULL; 01127 01128 pos = buf = os_zalloc(100); 01129 if (buf == NULL) 01130 return NULL; 01131 end = buf + 100; 01132 01133 for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF || 01134 eap_methods[i].method != EAP_TYPE_NONE; i++) { 01135 name = eap_get_name(eap_methods[i].vendor, 01136 eap_methods[i].method); 01137 if (name) { 01138 ret = os_snprintf(pos, end - pos, "%s%s", 01139 pos == buf ? "" : " ", name); 01140 if (ret < 0 || ret >= end - pos) 01141 break; 01142 pos += ret; 01143 } 01144 } 01145 01146 end[-1] = '\0'; 01147 01148 return buf; 01149 } 01150 01151 01152 static int wpa_config_parse_password(const struct parse_data *data, 01153 struct wpa_ssid *ssid, int line, 01154 const char *value) 01155 { 01156 u8 *hash; 01157 01158 if (os_strcmp(value, "NULL") == 0) { 01159 wpa_printf(MSG_DEBUG, "Unset configuration string 'password'"); 01160 os_free(ssid->eap.password); 01161 ssid->eap.password = NULL; 01162 ssid->eap.password_len = 0; 01163 return 0; 01164 } 01165 01166 if (os_strncmp(value, "hash:", 5) != 0) { 01167 char *tmp; 01168 size_t res_len; 01169 01170 tmp = wpa_config_parse_string(value, &res_len); 01171 if (tmp == NULL) { 01172 wpa_printf(MSG_ERROR, "Line %d: failed to parse " 01173 "password.", line); 01174 return -1; 01175 } 01176 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, 01177 (u8 *) tmp, res_len); 01178 01179 os_free(ssid->eap.password); 01180 ssid->eap.password = (u8 *) tmp; 01181 ssid->eap.password_len = res_len; 01182 ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH; 01183 01184 return 0; 01185 } 01186 01187 01188 /* NtPasswordHash: hash:<32 hex digits> */ 01189 if (os_strlen(value + 5) != 2 * 16) { 01190 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length " 01191 "(expected 32 hex digits)", line); 01192 return -1; 01193 } 01194 01195 hash = os_malloc(16); 01196 if (hash == NULL) 01197 return -1; 01198 01199 if (hexstr2bin(value + 5, hash, 16)) { 01200 os_free(hash); 01201 wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line); 01202 return -1; 01203 } 01204 01205 wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16); 01206 01207 os_free(ssid->eap.password); 01208 ssid->eap.password = hash; 01209 ssid->eap.password_len = 16; 01210 ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH; 01211 01212 return 0; 01213 } 01214 01215 01216 static char * wpa_config_write_password(const struct parse_data *data, 01217 struct wpa_ssid *ssid) 01218 { 01219 char *buf; 01220 01221 if (ssid->eap.password == NULL) 01222 return NULL; 01223 01224 if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) { 01225 return wpa_config_write_string( 01226 ssid->eap.password, ssid->eap.password_len); 01227 } 01228 01229 buf = os_malloc(5 + 32 + 1); 01230 if (buf == NULL) 01231 return NULL; 01232 01233 os_memcpy(buf, "hash:", 5); 01234 wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16); 01235 01236 return buf; 01237 } 01238 #endif /* IEEE8021X_EAPOL */ 01239 01240 01241 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line, 01242 const char *value, int idx) 01243 { 01244 char *buf, title[20]; 01245 int res; 01246 01247 buf = wpa_config_parse_string(value, len); 01248 if (buf == NULL) { 01249 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.", 01250 line, idx, value); 01251 return -1; 01252 } 01253 if (*len > MAX_WEP_KEY_LEN) { 01254 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.", 01255 line, idx, value); 01256 os_free(buf); 01257 return -1; 01258 } 01259 os_memcpy(key, buf, *len); 01260 os_free(buf); 01261 res = os_snprintf(title, sizeof(title), "wep_key%d", idx); 01262 if (res >= 0 && (size_t) res < sizeof(title)) 01263 wpa_hexdump_key(MSG_MSGDUMP, title, key, *len); 01264 return 0; 01265 } 01266 01267 01268 static int wpa_config_parse_wep_key0(const struct parse_data *data, 01269 struct wpa_ssid *ssid, int line, 01270 const char *value) 01271 { 01272 return wpa_config_parse_wep_key(ssid->wep_key[0], 01273 &ssid->wep_key_len[0], line, 01274 value, 0); 01275 } 01276 01277 01278 static int wpa_config_parse_wep_key1(const struct parse_data *data, 01279 struct wpa_ssid *ssid, int line, 01280 const char *value) 01281 { 01282 return wpa_config_parse_wep_key(ssid->wep_key[1], 01283 &ssid->wep_key_len[1], line, 01284 value, 1); 01285 } 01286 01287 01288 static int wpa_config_parse_wep_key2(const struct parse_data *data, 01289 struct wpa_ssid *ssid, int line, 01290 const char *value) 01291 { 01292 return wpa_config_parse_wep_key(ssid->wep_key[2], 01293 &ssid->wep_key_len[2], line, 01294 value, 2); 01295 } 01296 01297 01298 static int wpa_config_parse_wep_key3(const struct parse_data *data, 01299 struct wpa_ssid *ssid, int line, 01300 const char *value) 01301 { 01302 return wpa_config_parse_wep_key(ssid->wep_key[3], 01303 &ssid->wep_key_len[3], line, 01304 value, 3); 01305 } 01306 01307 01308 #ifndef NO_CONFIG_WRITE 01309 static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx) 01310 { 01311 if (ssid->wep_key_len[idx] == 0) 01312 return NULL; 01313 return wpa_config_write_string(ssid->wep_key[idx], 01314 ssid->wep_key_len[idx]); 01315 } 01316 01317 01318 static char * wpa_config_write_wep_key0(const struct parse_data *data, 01319 struct wpa_ssid *ssid) 01320 { 01321 return wpa_config_write_wep_key(ssid, 0); 01322 } 01323 01324 01325 static char * wpa_config_write_wep_key1(const struct parse_data *data, 01326 struct wpa_ssid *ssid) 01327 { 01328 return wpa_config_write_wep_key(ssid, 1); 01329 } 01330 01331 01332 static char * wpa_config_write_wep_key2(const struct parse_data *data, 01333 struct wpa_ssid *ssid) 01334 { 01335 return wpa_config_write_wep_key(ssid, 2); 01336 } 01337 01338 01339 static char * wpa_config_write_wep_key3(const struct parse_data *data, 01340 struct wpa_ssid *ssid) 01341 { 01342 return wpa_config_write_wep_key(ssid, 3); 01343 } 01344 #endif /* NO_CONFIG_WRITE */ 01345 01346 01347 /* Helper macros for network block parser */ 01348 01349 #ifdef OFFSET 01350 #undef OFFSET 01351 #endif /* OFFSET */ 01352 /* OFFSET: Get offset of a variable within the wpa_ssid structure */ 01353 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v) 01354 01355 /* STR: Define a string variable for an ASCII string; f = field name */ 01356 #ifdef NO_CONFIG_WRITE 01357 #define _STR(f) #f, wpa_config_parse_str, OFFSET(f) 01358 #define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f) 01359 #else /* NO_CONFIG_WRITE */ 01360 #define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f) 01361 #define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f) 01362 #endif /* NO_CONFIG_WRITE */ 01363 #define STR(f) _STR(f), NULL, NULL, NULL, 0 01364 #define STRe(f) _STRe(f), NULL, NULL, NULL, 0 01365 #define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1 01366 #define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1 01367 01368 /* STR_LEN: Define a string variable with a separate variable for storing the 01369 * data length. Unlike STR(), this can be used to store arbitrary binary data 01370 * (i.e., even nul termination character). */ 01371 #define _STR_LEN(f) _STR(f), OFFSET(f ## _len) 01372 #define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len) 01373 #define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0 01374 #define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0 01375 #define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1 01376 01377 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length 01378 * explicitly specified. */ 01379 #define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max) 01380 #define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0 01381 #define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1 01382 01383 #ifdef NO_CONFIG_WRITE 01384 #define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0 01385 #define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0 01386 #else /* NO_CONFIG_WRITE */ 01387 #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \ 01388 OFFSET(f), (void *) 0 01389 #define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \ 01390 OFFSET(eap.f), (void *) 0 01391 #endif /* NO_CONFIG_WRITE */ 01392 01393 /* INT: Define an integer variable */ 01394 #define INT(f) _INT(f), NULL, NULL, 0 01395 #define INTe(f) _INTe(f), NULL, NULL, 0 01396 01397 /* INT_RANGE: Define an integer variable with allowed value range */ 01398 #define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0 01399 01400 /* FUNC: Define a configuration variable that uses a custom function for 01401 * parsing and writing the value. */ 01402 #ifdef NO_CONFIG_WRITE 01403 #define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL 01404 #else /* NO_CONFIG_WRITE */ 01405 #define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \ 01406 NULL, NULL, NULL, NULL 01407 #endif /* NO_CONFIG_WRITE */ 01408 #define FUNC(f) _FUNC(f), 0 01409 #define FUNC_KEY(f) _FUNC(f), 1 01410 01411 /* 01412 * Table of network configuration variables. This table is used to parse each 01413 * network configuration variable, e.g., each line in wpa_supplicant.conf file 01414 * that is inside a network block. 01415 * 01416 * This table is generated using the helper macros defined above and with 01417 * generous help from the C pre-processor. The field name is stored as a string 01418 * into .name and for STR and INT types, the offset of the target buffer within 01419 * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar 01420 * offset to the field containing the length of the configuration variable. 01421 * .param3 and .param4 can be used to mark the allowed range (length for STR 01422 * and value for INT). 01423 * 01424 * For each configuration line in wpa_supplicant.conf, the parser goes through 01425 * this table and select the entry that matches with the field name. The parser 01426 * function (.parser) is then called to parse the actual value of the field. 01427 * 01428 * This kind of mechanism makes it easy to add new configuration parameters, 01429 * since only one line needs to be added into this table and into the 01430 * struct wpa_ssid definition if the new variable is either a string or 01431 * integer. More complex types will need to use their own parser and writer 01432 * functions. 01433 */ 01434 static const struct parse_data ssid_fields[] = { 01435 { STR_RANGE(ssid, 0, MAX_SSID_LEN) }, 01436 { INT_RANGE(scan_ssid, 0, 1) }, 01437 { FUNC(bssid) }, 01438 { FUNC_KEY(psk) }, 01439 { FUNC(proto) }, 01440 { FUNC(key_mgmt) }, 01441 { FUNC(pairwise) }, 01442 { FUNC(group) }, 01443 { FUNC(auth_alg) }, 01444 { FUNC(scan_freq) }, 01445 { FUNC(freq_list) }, 01446 #ifdef IEEE8021X_EAPOL 01447 { FUNC(eap) }, 01448 { STR_LENe(identity) }, 01449 { STR_LENe(anonymous_identity) }, 01450 { FUNC_KEY(password) }, 01451 { STRe(ca_cert) }, 01452 { STRe(ca_path) }, 01453 { STRe(client_cert) }, 01454 { STRe(private_key) }, 01455 { STR_KEYe(private_key_passwd) }, 01456 { STRe(dh_file) }, 01457 { STRe(subject_match) }, 01458 { STRe(altsubject_match) }, 01459 { STRe(ca_cert2) }, 01460 { STRe(ca_path2) }, 01461 { STRe(client_cert2) }, 01462 { STRe(private_key2) }, 01463 { STR_KEYe(private_key2_passwd) }, 01464 { STRe(dh_file2) }, 01465 { STRe(subject_match2) }, 01466 { STRe(altsubject_match2) }, 01467 { STRe(phase1) }, 01468 { STRe(phase2) }, 01469 { STRe(pcsc) }, 01470 { STR_KEYe(pin) }, 01471 { STRe(engine_id) }, 01472 { STRe(key_id) }, 01473 { STRe(cert_id) }, 01474 { STRe(ca_cert_id) }, 01475 { STR_KEYe(pin2) }, 01476 { STRe(engine2_id) }, 01477 { STRe(key2_id) }, 01478 { STRe(cert2_id) }, 01479 { STRe(ca_cert2_id) }, 01480 { INTe(engine) }, 01481 { INTe(engine2) }, 01482 { INT(eapol_flags) }, 01483 #endif /* IEEE8021X_EAPOL */ 01484 { FUNC_KEY(wep_key0) }, 01485 { FUNC_KEY(wep_key1) }, 01486 { FUNC_KEY(wep_key2) }, 01487 { FUNC_KEY(wep_key3) }, 01488 { INT(wep_tx_keyidx) }, 01489 { INT(priority) }, 01490 #ifdef IEEE8021X_EAPOL 01491 { INT(eap_workaround) }, 01492 { STRe(pac_file) }, 01493 { INTe(fragment_size) }, 01494 #endif /* IEEE8021X_EAPOL */ 01495 { INT_RANGE(mode, 0, 2) }, 01496 { INT_RANGE(proactive_key_caching, 0, 1) }, 01497 { INT_RANGE(disabled, 0, 1) }, 01498 { STR(id_str) }, 01499 #ifdef CONFIG_IEEE80211W 01500 { INT_RANGE(ieee80211w, 0, 2) }, 01501 #endif /* CONFIG_IEEE80211W */ 01502 { INT_RANGE(peerkey, 0, 1) }, 01503 { INT_RANGE(mixed_cell, 0, 1) }, 01504 { INT_RANGE(frequency, 0, 10000) }, 01505 { INT(wpa_ptk_rekey) }, 01506 { STR(bgscan) }, 01507 }; 01508 01509 #undef OFFSET 01510 #undef _STR 01511 #undef STR 01512 #undef STR_KEY 01513 #undef _STR_LEN 01514 #undef STR_LEN 01515 #undef STR_LEN_KEY 01516 #undef _STR_RANGE 01517 #undef STR_RANGE 01518 #undef STR_RANGE_KEY 01519 #undef _INT 01520 #undef INT 01521 #undef INT_RANGE 01522 #undef _FUNC 01523 #undef FUNC 01524 #undef FUNC_KEY 01525 #define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0])) 01526 01527 01539 int wpa_config_add_prio_network(struct wpa_config *config, 01540 struct wpa_ssid *ssid) 01541 { 01542 int prio; 01543 struct wpa_ssid *prev, **nlist; 01544 01545 /* 01546 * Add to an existing priority list if one is available for the 01547 * configured priority level for this network. 01548 */ 01549 for (prio = 0; prio < config->num_prio; prio++) { 01550 prev = config->pssid[prio]; 01551 if (prev->priority == ssid->priority) { 01552 while (prev->pnext) 01553 prev = prev->pnext; 01554 prev->pnext = ssid; 01555 return 0; 01556 } 01557 } 01558 01559 /* First network for this priority - add a new priority list */ 01560 nlist = os_realloc(config->pssid, 01561 (config->num_prio + 1) * sizeof(struct wpa_ssid *)); 01562 if (nlist == NULL) 01563 return -1; 01564 01565 for (prio = 0; prio < config->num_prio; prio++) { 01566 if (nlist[prio]->priority < ssid->priority) 01567 break; 01568 } 01569 01570 os_memmove(&nlist[prio + 1], &nlist[prio], 01571 (config->num_prio - prio) * sizeof(struct wpa_ssid *)); 01572 01573 nlist[prio] = ssid; 01574 config->num_prio++; 01575 config->pssid = nlist; 01576 01577 return 0; 01578 } 01579 01580 01590 int wpa_config_update_prio_list(struct wpa_config *config) 01591 { 01592 struct wpa_ssid *ssid; 01593 int ret = 0; 01594 01595 os_free(config->pssid); 01596 config->pssid = NULL; 01597 config->num_prio = 0; 01598 01599 ssid = config->ssid; 01600 while (ssid) { 01601 ssid->pnext = NULL; 01602 if (wpa_config_add_prio_network(config, ssid) < 0) 01603 ret = -1; 01604 ssid = ssid->next; 01605 } 01606 01607 return ret; 01608 } 01609 01610 01611 #ifdef IEEE8021X_EAPOL 01612 static void eap_peer_config_free(struct eap_peer_config *eap) 01613 { 01614 os_free(eap->eap_methods); 01615 os_free(eap->identity); 01616 os_free(eap->anonymous_identity); 01617 os_free(eap->password); 01618 os_free(eap->ca_cert); 01619 os_free(eap->ca_path); 01620 os_free(eap->client_cert); 01621 os_free(eap->private_key); 01622 os_free(eap->private_key_passwd); 01623 os_free(eap->dh_file); 01624 os_free(eap->subject_match); 01625 os_free(eap->altsubject_match); 01626 os_free(eap->ca_cert2); 01627 os_free(eap->ca_path2); 01628 os_free(eap->client_cert2); 01629 os_free(eap->private_key2); 01630 os_free(eap->private_key2_passwd); 01631 os_free(eap->dh_file2); 01632 os_free(eap->subject_match2); 01633 os_free(eap->altsubject_match2); 01634 os_free(eap->phase1); 01635 os_free(eap->phase2); 01636 os_free(eap->pcsc); 01637 os_free(eap->pin); 01638 os_free(eap->engine_id); 01639 os_free(eap->key_id); 01640 os_free(eap->cert_id); 01641 os_free(eap->ca_cert_id); 01642 os_free(eap->key2_id); 01643 os_free(eap->cert2_id); 01644 os_free(eap->ca_cert2_id); 01645 os_free(eap->pin2); 01646 os_free(eap->engine2_id); 01647 os_free(eap->otp); 01648 os_free(eap->pending_req_otp); 01649 os_free(eap->pac_file); 01650 os_free(eap->new_password); 01651 } 01652 #endif /* IEEE8021X_EAPOL */ 01653 01654 01662 void wpa_config_free_ssid(struct wpa_ssid *ssid) 01663 { 01664 os_free(ssid->ssid); 01665 os_free(ssid->passphrase); 01666 #ifdef IEEE8021X_EAPOL 01667 eap_peer_config_free(&ssid->eap); 01668 #endif /* IEEE8021X_EAPOL */ 01669 os_free(ssid->id_str); 01670 os_free(ssid->scan_freq); 01671 os_free(ssid->freq_list); 01672 os_free(ssid->bgscan); 01673 os_free(ssid); 01674 } 01675 01676 01684 void wpa_config_free(struct wpa_config *config) 01685 { 01686 #ifndef CONFIG_NO_CONFIG_BLOBS 01687 struct wpa_config_blob *blob, *prevblob; 01688 #endif /* CONFIG_NO_CONFIG_BLOBS */ 01689 struct wpa_ssid *ssid, *prev = NULL; 01690 ssid = config->ssid; 01691 while (ssid) { 01692 prev = ssid; 01693 ssid = ssid->next; 01694 wpa_config_free_ssid(prev); 01695 } 01696 01697 #ifndef CONFIG_NO_CONFIG_BLOBS 01698 blob = config->blobs; 01699 prevblob = NULL; 01700 while (blob) { 01701 prevblob = blob; 01702 blob = blob->next; 01703 wpa_config_free_blob(prevblob); 01704 } 01705 #endif /* CONFIG_NO_CONFIG_BLOBS */ 01706 01707 os_free(config->ctrl_interface); 01708 os_free(config->ctrl_interface_group); 01709 os_free(config->opensc_engine_path); 01710 os_free(config->pkcs11_engine_path); 01711 os_free(config->pkcs11_module_path); 01712 os_free(config->driver_param); 01713 os_free(config->device_name); 01714 os_free(config->manufacturer); 01715 os_free(config->model_name); 01716 os_free(config->model_number); 01717 os_free(config->serial_number); 01718 os_free(config->device_type); 01719 os_free(config->config_methods); 01720 os_free(config->pssid); 01721 os_free(config); 01722 } 01723 01724 01731 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id) 01732 { 01733 struct wpa_ssid *ssid; 01734 01735 ssid = config->ssid; 01736 while (ssid) { 01737 if (id == ssid->id) 01738 break; 01739 ssid = ssid->next; 01740 } 01741 01742 return ssid; 01743 } 01744 01745 01751 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config) 01752 { 01753 int id; 01754 struct wpa_ssid *ssid, *last = NULL; 01755 01756 id = -1; 01757 ssid = config->ssid; 01758 while (ssid) { 01759 if (ssid->id > id) 01760 id = ssid->id; 01761 last = ssid; 01762 ssid = ssid->next; 01763 } 01764 id++; 01765 01766 ssid = os_zalloc(sizeof(*ssid)); 01767 if (ssid == NULL) 01768 return NULL; 01769 ssid->id = id; 01770 if (last) 01771 last->next = ssid; 01772 else 01773 config->ssid = ssid; 01774 01775 wpa_config_update_prio_list(config); 01776 01777 return ssid; 01778 } 01779 01780 01787 int wpa_config_remove_network(struct wpa_config *config, int id) 01788 { 01789 struct wpa_ssid *ssid, *prev = NULL; 01790 01791 ssid = config->ssid; 01792 while (ssid) { 01793 if (id == ssid->id) 01794 break; 01795 prev = ssid; 01796 ssid = ssid->next; 01797 } 01798 01799 if (ssid == NULL) 01800 return -1; 01801 01802 if (prev) 01803 prev->next = ssid->next; 01804 else 01805 config->ssid = ssid->next; 01806 01807 wpa_config_update_prio_list(config); 01808 wpa_config_free_ssid(ssid); 01809 return 0; 01810 } 01811 01812 01817 void wpa_config_set_network_defaults(struct wpa_ssid *ssid) 01818 { 01819 ssid->proto = DEFAULT_PROTO; 01820 ssid->pairwise_cipher = DEFAULT_PAIRWISE; 01821 ssid->group_cipher = DEFAULT_GROUP; 01822 ssid->key_mgmt = DEFAULT_KEY_MGMT; 01823 #ifdef IEEE8021X_EAPOL 01824 ssid->eapol_flags = DEFAULT_EAPOL_FLAGS; 01825 ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; 01826 ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE; 01827 #endif /* IEEE8021X_EAPOL */ 01828 } 01829 01830 01844 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, 01845 int line) 01846 { 01847 size_t i; 01848 int ret = 0; 01849 01850 if (ssid == NULL || var == NULL || value == NULL) 01851 return -1; 01852 01853 for (i = 0; i < NUM_SSID_FIELDS; i++) { 01854 const struct parse_data *field = &ssid_fields[i]; 01855 if (os_strcmp(var, field->name) != 0) 01856 continue; 01857 01858 if (field->parser(field, ssid, line, value)) { 01859 if (line) { 01860 wpa_printf(MSG_ERROR, "Line %d: failed to " 01861 "parse %s '%s'.", line, var, value); 01862 } 01863 ret = -1; 01864 } 01865 break; 01866 } 01867 if (i == NUM_SSID_FIELDS) { 01868 if (line) { 01869 wpa_printf(MSG_ERROR, "Line %d: unknown network field " 01870 "'%s'.", line, var); 01871 } 01872 ret = -1; 01873 } 01874 01875 return ret; 01876 } 01877 01878 01890 char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys) 01891 { 01892 const struct parse_data *field; 01893 char *key, *value; 01894 size_t i; 01895 char **props; 01896 int fields_num; 01897 01898 props = os_zalloc(sizeof(char *) * ((2 * NUM_SSID_FIELDS) + 1)); 01899 if (!props) 01900 return NULL; 01901 01902 fields_num = 0; 01903 for (i = 0; i < NUM_SSID_FIELDS; i++) { 01904 field = &ssid_fields[i]; 01905 if (field->key_data && !get_keys) 01906 continue; 01907 value = field->writer(field, ssid); 01908 if (value == NULL) 01909 continue; 01910 if (os_strlen(value) == 0) { 01911 os_free(value); 01912 continue; 01913 } 01914 01915 key = os_strdup(field->name); 01916 if (key == NULL) { 01917 os_free(value); 01918 goto err; 01919 } 01920 01921 props[fields_num * 2] = key; 01922 props[fields_num * 2 + 1] = value; 01923 01924 fields_num++; 01925 } 01926 01927 return props; 01928 01929 err: 01930 value = *props; 01931 while (value) 01932 os_free(value++); 01933 os_free(props); 01934 return NULL; 01935 } 01936 01937 01938 #ifndef NO_CONFIG_WRITE 01939 01951 char * wpa_config_get(struct wpa_ssid *ssid, const char *var) 01952 { 01953 size_t i; 01954 01955 if (ssid == NULL || var == NULL) 01956 return NULL; 01957 01958 for (i = 0; i < NUM_SSID_FIELDS; i++) { 01959 const struct parse_data *field = &ssid_fields[i]; 01960 if (os_strcmp(var, field->name) == 0) 01961 return field->writer(field, ssid); 01962 } 01963 01964 return NULL; 01965 } 01966 01967 01984 char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var) 01985 { 01986 size_t i; 01987 01988 if (ssid == NULL || var == NULL) 01989 return NULL; 01990 01991 for (i = 0; i < NUM_SSID_FIELDS; i++) { 01992 const struct parse_data *field = &ssid_fields[i]; 01993 if (os_strcmp(var, field->name) == 0) { 01994 char *res = field->writer(field, ssid); 01995 if (field->key_data) { 01996 if (res && res[0]) { 01997 wpa_printf(MSG_DEBUG, "Do not allow " 01998 "key_data field to be " 01999 "exposed"); 02000 os_free(res); 02001 return os_strdup("*"); 02002 } 02003 02004 os_free(res); 02005 return NULL; 02006 } 02007 return res; 02008 } 02009 } 02010 02011 return NULL; 02012 } 02013 #endif /* NO_CONFIG_WRITE */ 02014 02015 02023 void wpa_config_update_psk(struct wpa_ssid *ssid) 02024 { 02025 #ifndef CONFIG_NO_PBKDF2 02026 pbkdf2_sha1(ssid->passphrase, 02027 (char *) ssid->ssid, ssid->ssid_len, 4096, 02028 ssid->psk, PMK_LEN); 02029 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", 02030 ssid->psk, PMK_LEN); 02031 ssid->psk_set = 1; 02032 #endif /* CONFIG_NO_PBKDF2 */ 02033 } 02034 02035 02036 #ifndef CONFIG_NO_CONFIG_BLOBS 02037 02043 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config, 02044 const char *name) 02045 { 02046 struct wpa_config_blob *blob = config->blobs; 02047 02048 while (blob) { 02049 if (os_strcmp(blob->name, name) == 0) 02050 return blob; 02051 blob = blob->next; 02052 } 02053 return NULL; 02054 } 02055 02056 02065 void wpa_config_set_blob(struct wpa_config *config, 02066 struct wpa_config_blob *blob) 02067 { 02068 wpa_config_remove_blob(config, blob->name); 02069 blob->next = config->blobs; 02070 config->blobs = blob; 02071 } 02072 02073 02078 void wpa_config_free_blob(struct wpa_config_blob *blob) 02079 { 02080 if (blob) { 02081 os_free(blob->name); 02082 os_free(blob->data); 02083 os_free(blob); 02084 } 02085 } 02086 02087 02094 int wpa_config_remove_blob(struct wpa_config *config, const char *name) 02095 { 02096 struct wpa_config_blob *pos = config->blobs, *prev = NULL; 02097 02098 while (pos) { 02099 if (os_strcmp(pos->name, name) == 0) { 02100 if (prev) 02101 prev->next = pos->next; 02102 else 02103 config->blobs = pos->next; 02104 wpa_config_free_blob(pos); 02105 return 0; 02106 } 02107 prev = pos; 02108 pos = pos->next; 02109 } 02110 02111 return -1; 02112 } 02113 #endif /* CONFIG_NO_CONFIG_BLOBS */ 02114 02115 02123 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, 02124 const char *driver_param) 02125 { 02126 struct wpa_config *config; 02127 02128 config = os_zalloc(sizeof(*config)); 02129 if (config == NULL) 02130 return NULL; 02131 config->eapol_version = DEFAULT_EAPOL_VERSION; 02132 config->ap_scan = DEFAULT_AP_SCAN; 02133 config->fast_reauth = DEFAULT_FAST_REAUTH; 02134 config->bss_max_count = DEFAULT_BSS_MAX_COUNT; 02135 02136 if (ctrl_interface) 02137 config->ctrl_interface = os_strdup(ctrl_interface); 02138 if (driver_param) 02139 config->driver_param = os_strdup(driver_param); 02140 02141 return config; 02142 } 02143 02144 02145 #ifndef CONFIG_NO_STDOUT_DEBUG 02146 02150 void wpa_config_debug_dump_networks(struct wpa_config *config) 02151 { 02152 int prio; 02153 struct wpa_ssid *ssid; 02154 02155 for (prio = 0; prio < config->num_prio; prio++) { 02156 ssid = config->pssid[prio]; 02157 wpa_printf(MSG_DEBUG, "Priority group %d", 02158 ssid->priority); 02159 while (ssid) { 02160 wpa_printf(MSG_DEBUG, " id=%d ssid='%s'", 02161 ssid->id, 02162 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 02163 ssid = ssid->pnext; 02164 } 02165 } 02166 } 02167 #endif /* CONFIG_NO_STDOUT_DEBUG */