00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00030
00031
00032
00033 struct parse_data {
00034
00035 char *name;
00036
00037
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
00043
00044 char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
00045 #endif
00046
00047
00048 void *param1, *param2, *param3, *param4;
00049
00050
00051
00052
00053
00054
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
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
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
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
00356 wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not "
00357 "supported.", line);
00358 return -1;
00359 #endif
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
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
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
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
00523 #ifdef CONFIG_WPS
00524 else if (os_strcmp(start, "WPS") == 0)
00525 val |= WPA_KEY_MGMT_WPS;
00526 #endif
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
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
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
00638
00639 return buf;
00640 }
00641 #endif
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
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
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
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
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
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
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
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
01345
01346
01347
01348
01349 #ifdef OFFSET
01350 #undef OFFSET
01351 #endif
01352
01353 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
01354
01355
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
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
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
01369
01370
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
01378
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
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
01392
01393
01394 #define INT(f) _INT(f), NULL, NULL, 0
01395 #define INTe(f) _INTe(f), NULL, NULL, 0
01396
01397
01398 #define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
01399
01400
01401
01402 #ifdef NO_CONFIG_WRITE
01403 #define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL
01404 #else
01405 #define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
01406 NULL, NULL, NULL, NULL
01407 #endif
01408 #define FUNC(f) _FUNC(f), 0
01409 #define FUNC_KEY(f) _FUNC(f), 1
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
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
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
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
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
01547
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
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
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
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
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
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
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
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
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
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