00001
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019
00020 #include "common.h"
00021 #include "wpa.h"
00022 #include "sha1.h"
00023 #include "wpa_supplicant.h"
00024 #include "eapol_sm.h"
00025 #include "eap.h"
00026 #include "l2_packet.h"
00027 #include "config.h"
00028
00029
00030
00031
00032
00033
00034
00035 struct parse_data {
00036
00037 char *name;
00038
00039
00040 int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
00041 int line, const char *value);
00042
00043
00044
00045 char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
00046
00047
00048 void *param1, *param2, *param3, *param4;
00049
00050
00051
00052
00053
00054 int key_data;
00055 };
00056
00057
00058 static char * wpa_config_parse_string(const char *value, size_t *len)
00059 {
00060 if (*value == '"') {
00061 char *pos;
00062 value++;
00063 pos = strrchr(value, '"');
00064 if (pos == NULL || pos[1] != '\0')
00065 return NULL;
00066 *pos = '\0';
00067 *len = strlen(value);
00068 return strdup(value);
00069 } else {
00070 u8 *str;
00071 size_t hlen = strlen(value);
00072 if (hlen % 1)
00073 return NULL;
00074 *len = hlen / 2;
00075 str = malloc(*len);
00076 if (str == NULL)
00077 return NULL;
00078 if (hexstr2bin(value, str, *len)) {
00079 free(str);
00080 return NULL;
00081 }
00082 return (char *) str;
00083 }
00084 }
00085
00086
00087 static int wpa_config_parse_str(const struct parse_data *data,
00088 struct wpa_ssid *ssid,
00089 int line, const char *value)
00090 {
00091 size_t res_len, *dst_len;
00092 char **dst;
00093
00094 dst = (char **) (((u8 *) ssid) + (long) data->param1);
00095 dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
00096
00097 free(*dst);
00098 *dst = wpa_config_parse_string(value, &res_len);
00099 if (*dst == NULL) {
00100 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
00101 line, data->name,
00102 data->key_data ? "[KEY DATA REMOVED]" : value);
00103 return -1;
00104 }
00105 if (data->param2)
00106 *dst_len = res_len;
00107
00108 if (data->key_data) {
00109 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
00110 (u8 *) *dst, res_len);
00111 } else {
00112 wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
00113 (u8 *) *dst, res_len);
00114 }
00115
00116 if (data->param3 && res_len < (size_t) data->param3) {
00117 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
00118 "min_len=%ld)", line, data->name,
00119 (unsigned long) res_len, (long) data->param3);
00120 free(*dst);
00121 *dst = NULL;
00122 return -1;
00123 }
00124
00125 if (data->param4 && res_len > (size_t) data->param4) {
00126 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
00127 "max_len=%ld)", line, data->name,
00128 (unsigned long) res_len, (long) data->param4);
00129 free(*dst);
00130 *dst = NULL;
00131 return -1;
00132 }
00133
00134 return 0;
00135 }
00136
00137
00138 static int is_hex(const u8 *data, size_t len)
00139 {
00140 int i;
00141
00142 for (i = 0; i < len; i++) {
00143 if (data[i] < 32 || data[i] >= 127)
00144 return 1;
00145 }
00146 return 0;
00147 }
00148
00149
00150 static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
00151 {
00152 int i;
00153 char *buf, *pos, *end;
00154
00155 pos = buf = malloc(len + 3);
00156 if (buf == NULL)
00157 return NULL;
00158 end = buf + len + 3;
00159 pos += snprintf(pos, end - pos, "\"");
00160 for (i = 0; i < len; i++)
00161 pos += snprintf(pos, end - pos, "%c", value[i]);
00162 pos += snprintf(pos, end - pos, "\"");
00163
00164 return buf;
00165 }
00166
00167
00168 static char * wpa_config_write_string_hex(const u8 *value, size_t len)
00169 {
00170 int i;
00171 char *buf, *pos, *end;
00172
00173 pos = buf = malloc(2 * len + 1);
00174 if (buf == NULL)
00175 return NULL;
00176 memset(buf, 0, 2 * len + 1);
00177 end = buf + 2 * len + 1;
00178 for (i = 0; i < len; i++)
00179 pos += snprintf(pos, end - pos, "%02x", value[i]);
00180
00181 return buf;
00182 }
00183
00184
00185 static char * wpa_config_write_string(const u8 *value, size_t len)
00186 {
00187 if (value == NULL)
00188 return NULL;
00189
00190 if (is_hex(value, len))
00191 return wpa_config_write_string_hex(value, len);
00192 else
00193 return wpa_config_write_string_ascii(value, len);
00194 }
00195
00196
00197 static char * wpa_config_write_str(const struct parse_data *data,
00198 struct wpa_ssid *ssid)
00199 {
00200 size_t len;
00201 char **src;
00202
00203 src = (char **) (((u8 *) ssid) + (long) data->param1);
00204 if (*src == NULL)
00205 return NULL;
00206
00207 if (data->param2)
00208 len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
00209 else
00210 len = strlen(*src);
00211
00212 return wpa_config_write_string((const u8 *) *src, len);
00213 }
00214
00215
00216 static int wpa_config_parse_int(const struct parse_data *data,
00217 struct wpa_ssid *ssid,
00218 int line, const char *value)
00219 {
00220 int *dst;
00221
00222 dst = (int *) (((u8 *) ssid) + (long) data->param1);
00223 *dst = atoi(value);
00224 wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
00225
00226 if (data->param3 && *dst < (long) data->param3) {
00227 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
00228 "min_value=%ld)", line, data->name, *dst,
00229 (long) data->param3);
00230 *dst = (long) data->param3;
00231 return -1;
00232 }
00233
00234 if (data->param4 && *dst > (long) data->param4) {
00235 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
00236 "max_value=%ld)", line, data->name, *dst,
00237 (long) data->param4);
00238 *dst = (long) data->param4;
00239 return -1;
00240 }
00241
00242 return 0;
00243 }
00244
00245
00246 static char * wpa_config_write_int(const struct parse_data *data,
00247 struct wpa_ssid *ssid)
00248 {
00249 int *src;
00250 char *value;
00251
00252 src = (int *) (((u8 *) ssid) + (long) data->param1);
00253
00254 value = malloc(20);
00255 if (value == NULL)
00256 return NULL;
00257 snprintf(value, 20, "%d", *src);
00258 return value;
00259 }
00260
00261
00262 static int wpa_config_parse_bssid(const struct parse_data *data,
00263 struct wpa_ssid *ssid, int line,
00264 const char *value)
00265 {
00266 if (hwaddr_aton(value, ssid->bssid)) {
00267 wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
00268 line, value);
00269 return -1;
00270 }
00271 ssid->bssid_set = 1;
00272 wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
00273 return 0;
00274 }
00275
00276
00277 static char * wpa_config_write_bssid(const struct parse_data *data,
00278 struct wpa_ssid *ssid)
00279 {
00280 char *value;
00281
00282 if (!ssid->bssid_set)
00283 return NULL;
00284
00285 value = malloc(20);
00286 if (value == NULL)
00287 return NULL;
00288 snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
00289 return value;
00290 }
00291
00292
00293 static int wpa_config_parse_psk(const struct parse_data *data,
00294 struct wpa_ssid *ssid, int line,
00295 const char *value)
00296 {
00297 if (*value == '"') {
00298 const char *pos;
00299 size_t len;
00300
00301 value++;
00302 pos = strrchr(value, '"');
00303 if (pos)
00304 len = pos - value;
00305 else
00306 len = strlen(value);
00307 if (len < 8 || len > 63) {
00308 wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
00309 "length %lu (expected: 8..63) '%s'.",
00310 line, (unsigned long) len, value);
00311 return -1;
00312 }
00313 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
00314 (u8 *) value, len);
00315 ssid->passphrase = malloc(len + 1);
00316 if (ssid->passphrase == NULL)
00317 return -1;
00318 memcpy(ssid->passphrase, value, len);
00319 ssid->passphrase[len] = '\0';
00320 return 0;
00321 }
00322
00323 if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
00324 value[PMK_LEN * 2] != '\0') {
00325 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
00326 line, value);
00327 return -1;
00328 }
00329 ssid->psk_set = 1;
00330 wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
00331 return 0;
00332 }
00333
00334
00335 static char * wpa_config_write_psk(const struct parse_data *data,
00336 struct wpa_ssid *ssid)
00337 {
00338 if (ssid->passphrase)
00339 return wpa_config_write_string_ascii(
00340 (const u8 *) ssid->passphrase,
00341 strlen(ssid->passphrase));
00342
00343 if (ssid->psk_set)
00344 return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
00345
00346 return NULL;
00347 }
00348
00349
00350 static int wpa_config_parse_proto(const struct parse_data *data,
00351 struct wpa_ssid *ssid, int line,
00352 const char *value)
00353 {
00354 int val = 0, last, errors = 0;
00355 char *start, *end, *buf;
00356
00357 buf = strdup(value);
00358 if (buf == NULL)
00359 return -1;
00360 start = buf;
00361
00362 while (*start != '\0') {
00363 while (*start == ' ' || *start == '\t')
00364 start++;
00365 if (*start == '\0')
00366 break;
00367 end = start;
00368 while (*end != ' ' && *end != '\t' && *end != '\0')
00369 end++;
00370 last = *end == '\0';
00371 *end = '\0';
00372 if (strcmp(start, "WPA") == 0)
00373 val |= WPA_PROTO_WPA;
00374 else if (strcmp(start, "RSN") == 0 ||
00375 strcmp(start, "WPA2") == 0)
00376 val |= WPA_PROTO_RSN;
00377 else {
00378 wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
00379 line, start);
00380 errors++;
00381 }
00382
00383 if (last)
00384 break;
00385 start = end + 1;
00386 }
00387 free(buf);
00388
00389 if (val == 0) {
00390 wpa_printf(MSG_ERROR,
00391 "Line %d: no proto values configured.", line);
00392 errors++;
00393 }
00394
00395 wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
00396 ssid->proto = val;
00397 return errors ? -1 : 0;
00398 }
00399
00400
00401 static char * wpa_config_write_proto(const struct parse_data *data,
00402 struct wpa_ssid *ssid)
00403 {
00404 int first = 1;
00405 char *buf, *pos, *end;
00406
00407 pos = buf = malloc(10);
00408 if (buf == NULL)
00409 return NULL;
00410 memset(buf, 0, 10);
00411 end = buf + 10;
00412
00413 if (ssid->proto & WPA_PROTO_WPA) {
00414 pos += snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
00415 first = 0;
00416 }
00417
00418 if (ssid->proto & WPA_PROTO_RSN) {
00419 pos += snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
00420 first = 0;
00421 }
00422
00423 return buf;
00424 }
00425
00426
00427 static int wpa_config_parse_key_mgmt(const struct parse_data *data,
00428 struct wpa_ssid *ssid, int line,
00429 const char *value)
00430 {
00431 int val = 0, last, errors = 0;
00432 char *start, *end, *buf;
00433
00434 buf = strdup(value);
00435 if (buf == NULL)
00436 return -1;
00437 start = buf;
00438
00439 while (*start != '\0') {
00440 while (*start == ' ' || *start == '\t')
00441 start++;
00442 if (*start == '\0')
00443 break;
00444 end = start;
00445 while (*end != ' ' && *end != '\t' && *end != '\0')
00446 end++;
00447 last = *end == '\0';
00448 *end = '\0';
00449 if (strcmp(start, "WPA-PSK") == 0)
00450 val |= WPA_KEY_MGMT_PSK;
00451 else if (strcmp(start, "WPA-EAP") == 0)
00452 val |= WPA_KEY_MGMT_IEEE8021X;
00453 else if (strcmp(start, "IEEE8021X") == 0)
00454 val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
00455 else if (strcmp(start, "NONE") == 0)
00456 val |= WPA_KEY_MGMT_NONE;
00457 else if (strcmp(start, "WPA-NONE") == 0)
00458 val |= WPA_KEY_MGMT_WPA_NONE;
00459 else {
00460 wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
00461 line, start);
00462 errors++;
00463 }
00464
00465 if (last)
00466 break;
00467 start = end + 1;
00468 }
00469 free(buf);
00470
00471 if (val == 0) {
00472 wpa_printf(MSG_ERROR,
00473 "Line %d: no key_mgmt values configured.", line);
00474 errors++;
00475 }
00476
00477 wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
00478 ssid->key_mgmt = val;
00479 return errors ? -1 : 0;
00480 }
00481
00482
00483 static char * wpa_config_write_key_mgmt(const struct parse_data *data,
00484 struct wpa_ssid *ssid)
00485 {
00486 int first = 1;
00487 char *buf, *pos, *end;
00488
00489 pos = buf = malloc(50);
00490 if (buf == NULL)
00491 return NULL;
00492 memset(buf, 0, 50);
00493 end = buf + 50;
00494
00495 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
00496 pos += snprintf(pos, end - pos, "%sWPA-PSK", first ? "" : " ");
00497 first = 0;
00498 }
00499
00500 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
00501 pos += snprintf(pos, end - pos, "%sWPA-EAP", first ? "" : " ");
00502 first = 0;
00503 }
00504
00505 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
00506 pos += snprintf(pos, end - pos, "%sIEEE8021X",
00507 first ? "" : " ");
00508 first = 0;
00509 }
00510
00511 if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
00512 pos += snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
00513 first = 0;
00514 }
00515
00516 if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
00517 pos += snprintf(pos, end - pos, "%sWPA-NONE",
00518 first ? "" : " ");
00519 first = 0;
00520 }
00521
00522 return buf;
00523 }
00524
00525
00526 static int wpa_config_parse_cipher(int line, const char *value)
00527 {
00528 int val = 0, last;
00529 char *start, *end, *buf;
00530
00531 buf = strdup(value);
00532 if (buf == NULL)
00533 return -1;
00534 start = buf;
00535
00536 while (*start != '\0') {
00537 while (*start == ' ' || *start == '\t')
00538 start++;
00539 if (*start == '\0')
00540 break;
00541 end = start;
00542 while (*end != ' ' && *end != '\t' && *end != '\0')
00543 end++;
00544 last = *end == '\0';
00545 *end = '\0';
00546 if (strcmp(start, "CCMP") == 0)
00547 val |= WPA_CIPHER_CCMP;
00548 else if (strcmp(start, "TKIP") == 0)
00549 val |= WPA_CIPHER_TKIP;
00550 else if (strcmp(start, "WEP104") == 0)
00551 val |= WPA_CIPHER_WEP104;
00552 else if (strcmp(start, "WEP40") == 0)
00553 val |= WPA_CIPHER_WEP40;
00554 else if (strcmp(start, "NONE") == 0)
00555 val |= WPA_CIPHER_NONE;
00556 else {
00557 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
00558 line, start);
00559 free(buf);
00560 return -1;
00561 }
00562
00563 if (last)
00564 break;
00565 start = end + 1;
00566 }
00567 free(buf);
00568
00569 if (val == 0) {
00570 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
00571 line);
00572 return -1;
00573 }
00574 return val;
00575 }
00576
00577
00578 static char * wpa_config_write_cipher(int cipher)
00579 {
00580 int first = 1;
00581 char *buf, *pos, *end;
00582
00583 pos = buf = malloc(50);
00584 if (buf == NULL)
00585 return NULL;
00586 memset(buf, 0, 50);
00587 end = buf + 50;
00588
00589 if (cipher & WPA_CIPHER_CCMP) {
00590 pos += snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
00591 first = 0;
00592 }
00593
00594 if (cipher & WPA_CIPHER_TKIP) {
00595 pos += snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
00596 first = 0;
00597 }
00598
00599 if (cipher & WPA_CIPHER_WEP104) {
00600 pos += snprintf(pos, end - pos, "%sWEP104", first ? "" : " ");
00601 first = 0;
00602 }
00603
00604 if (cipher & WPA_CIPHER_WEP40) {
00605 pos += snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
00606 first = 0;
00607 }
00608
00609 if (cipher & WPA_CIPHER_NONE) {
00610 pos += snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
00611 first = 0;
00612 }
00613
00614 return buf;
00615 }
00616
00617
00618 static int wpa_config_parse_pairwise(const struct parse_data *data,
00619 struct wpa_ssid *ssid, int line,
00620 const char *value)
00621 {
00622 int val;
00623 val = wpa_config_parse_cipher(line, value);
00624 if (val == -1)
00625 return -1;
00626 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) {
00627 wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
00628 "(0x%x).", line, val);
00629 return -1;
00630 }
00631
00632 wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
00633 ssid->pairwise_cipher = val;
00634 return 0;
00635 }
00636
00637
00638 static char * wpa_config_write_pairwise(const struct parse_data *data,
00639 struct wpa_ssid *ssid)
00640 {
00641 return wpa_config_write_cipher(ssid->pairwise_cipher);
00642 }
00643
00644
00645 static int wpa_config_parse_group(const struct parse_data *data,
00646 struct wpa_ssid *ssid, int line,
00647 const char *value)
00648 {
00649 int val;
00650 val = wpa_config_parse_cipher(line, value);
00651 if (val == -1)
00652 return -1;
00653 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 |
00654 WPA_CIPHER_WEP40)) {
00655 wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
00656 "(0x%x).", line, val);
00657 return -1;
00658 }
00659
00660 wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
00661 ssid->group_cipher = val;
00662 return 0;
00663 }
00664
00665
00666 static char * wpa_config_write_group(const struct parse_data *data,
00667 struct wpa_ssid *ssid)
00668 {
00669 return wpa_config_write_cipher(ssid->group_cipher);
00670 }
00671
00672
00673 static int wpa_config_parse_auth_alg(const struct parse_data *data,
00674 struct wpa_ssid *ssid, int line,
00675 const char *value)
00676 {
00677 int val = 0, last, errors = 0;
00678 char *start, *end, *buf;
00679
00680 buf = strdup(value);
00681 if (buf == NULL)
00682 return -1;
00683 start = buf;
00684
00685 while (*start != '\0') {
00686 while (*start == ' ' || *start == '\t')
00687 start++;
00688 if (*start == '\0')
00689 break;
00690 end = start;
00691 while (*end != ' ' && *end != '\t' && *end != '\0')
00692 end++;
00693 last = *end == '\0';
00694 *end = '\0';
00695 if (strcmp(start, "OPEN") == 0)
00696 val |= WPA_AUTH_ALG_OPEN;
00697 else if (strcmp(start, "SHARED") == 0)
00698 val |= WPA_AUTH_ALG_SHARED;
00699 else if (strcmp(start, "LEAP") == 0)
00700 val |= WPA_AUTH_ALG_LEAP;
00701 else {
00702 wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
00703 line, start);
00704 errors++;
00705 }
00706
00707 if (last)
00708 break;
00709 start = end + 1;
00710 }
00711 free(buf);
00712
00713 if (val == 0) {
00714 wpa_printf(MSG_ERROR,
00715 "Line %d: no auth_alg values configured.", line);
00716 errors++;
00717 }
00718
00719 wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
00720 ssid->auth_alg = val;
00721 return errors ? -1 : 0;
00722 }
00723
00724
00725 static char * wpa_config_write_auth_alg(const struct parse_data *data,
00726 struct wpa_ssid *ssid)
00727 {
00728 int first = 1;
00729 char *buf, *pos, *end;
00730
00731 pos = buf = malloc(30);
00732 if (buf == NULL)
00733 return NULL;
00734 memset(buf, 0, 30);
00735 end = buf + 30;
00736
00737 if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
00738 pos += snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
00739 first = 0;
00740 }
00741
00742 if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
00743 pos += snprintf(pos, end - pos, "%sSHARED", first ? "" : " ");
00744 first = 0;
00745 }
00746
00747 if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
00748 pos += snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
00749 first = 0;
00750 }
00751
00752 return buf;
00753 }
00754
00755
00756 static int wpa_config_parse_eap(const struct parse_data *data,
00757 struct wpa_ssid *ssid, int line,
00758 const char *value)
00759 {
00760 int last, errors = 0;
00761 char *start, *end, *buf;
00762 u8 *methods = NULL, *tmp;
00763 size_t num_methods = 0;
00764
00765 buf = strdup(value);
00766 if (buf == NULL)
00767 return -1;
00768 start = buf;
00769
00770 while (*start != '\0') {
00771 while (*start == ' ' || *start == '\t')
00772 start++;
00773 if (*start == '\0')
00774 break;
00775 end = start;
00776 while (*end != ' ' && *end != '\t' && *end != '\0')
00777 end++;
00778 last = *end == '\0';
00779 *end = '\0';
00780 tmp = methods;
00781 methods = realloc(methods, num_methods + 1);
00782 if (methods == NULL) {
00783 free(tmp);
00784 free(buf);
00785 return -1;
00786 }
00787 methods[num_methods] = eap_get_type(start);
00788 if (methods[num_methods] == EAP_TYPE_NONE) {
00789 wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
00790 "'%s'", line, start);
00791 wpa_printf(MSG_ERROR, "You may need to add support for"
00792 " this EAP method during wpa_supplicant\n"
00793 "build time configuration.\n"
00794 "See README for more information.");
00795 errors++;
00796 } else if (methods[num_methods] == EAP_TYPE_LEAP)
00797 ssid->leap++;
00798 else
00799 ssid->non_leap++;
00800 num_methods++;
00801 if (last)
00802 break;
00803 start = end + 1;
00804 }
00805 free(buf);
00806
00807 tmp = methods;
00808 methods = realloc(methods, num_methods + 1);
00809 if (methods == NULL) {
00810 free(tmp);
00811 return -1;
00812 }
00813 methods[num_methods] = EAP_TYPE_NONE;
00814 num_methods++;
00815
00816 wpa_hexdump(MSG_MSGDUMP, "eap methods", methods, num_methods);
00817 ssid->eap_methods = methods;
00818 return errors ? -1 : 0;
00819 }
00820
00821
00822 static char * wpa_config_write_eap(const struct parse_data *data,
00823 struct wpa_ssid *ssid)
00824 {
00825 int first = 1;
00826 char *buf, *pos, *end;
00827 const u8 *eap_methods = ssid->eap_methods;
00828 const char *name;
00829
00830 if (eap_methods == NULL)
00831 return NULL;
00832
00833 pos = buf = malloc(100);
00834 if (buf == NULL)
00835 return NULL;
00836 memset(buf, 0, 100);
00837 end = buf + 100;
00838
00839 while (*eap_methods != EAP_TYPE_NONE) {
00840 name = eap_get_name(*eap_methods);
00841 if (name)
00842 pos += snprintf(pos, end - pos, "%s%s",
00843 first ? "" : " ", name);
00844 first = 0;
00845 eap_methods++;
00846 }
00847
00848 return buf;
00849 }
00850
00851
00852 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
00853 const char *value, int idx)
00854 {
00855 char *buf, title[20];
00856
00857 buf = wpa_config_parse_string(value, len);
00858 if (buf == NULL) {
00859 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
00860 line, idx, value);
00861 return -1;
00862 }
00863 if (*len > MAX_WEP_KEY_LEN) {
00864 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
00865 line, idx, value);
00866 free(buf);
00867 return -1;
00868 }
00869 memcpy(key, buf, *len);
00870 free(buf);
00871 snprintf(title, sizeof(title), "wep_key%d", idx);
00872 wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
00873 return 0;
00874 }
00875
00876
00877 static int wpa_config_parse_wep_key0(const struct parse_data *data,
00878 struct wpa_ssid *ssid, int line,
00879 const char *value)
00880 {
00881 return wpa_config_parse_wep_key(ssid->wep_key[0],
00882 &ssid->wep_key_len[0], line,
00883 value, 0);
00884 }
00885
00886
00887 static int wpa_config_parse_wep_key1(const struct parse_data *data,
00888 struct wpa_ssid *ssid, int line,
00889 const char *value)
00890 {
00891 return wpa_config_parse_wep_key(ssid->wep_key[1],
00892 &ssid->wep_key_len[1], line,
00893 value, 1);
00894 }
00895
00896
00897 static int wpa_config_parse_wep_key2(const struct parse_data *data,
00898 struct wpa_ssid *ssid, int line,
00899 const char *value)
00900 {
00901 return wpa_config_parse_wep_key(ssid->wep_key[2],
00902 &ssid->wep_key_len[2], line,
00903 value, 2);
00904 }
00905
00906
00907 static int wpa_config_parse_wep_key3(const struct parse_data *data,
00908 struct wpa_ssid *ssid, int line,
00909 const char *value)
00910 {
00911 return wpa_config_parse_wep_key(ssid->wep_key[3],
00912 &ssid->wep_key_len[3], line,
00913 value, 3);
00914 }
00915
00916
00917 static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
00918 {
00919 if (ssid->wep_key_len[idx] == 0)
00920 return NULL;
00921 return wpa_config_write_string(ssid->wep_key[idx],
00922 ssid->wep_key_len[idx]);
00923 }
00924
00925
00926 static char * wpa_config_write_wep_key0(const struct parse_data *data,
00927 struct wpa_ssid *ssid)
00928 {
00929 return wpa_config_write_wep_key(ssid, 0);
00930 }
00931
00932
00933 static char * wpa_config_write_wep_key1(const struct parse_data *data,
00934 struct wpa_ssid *ssid)
00935 {
00936 return wpa_config_write_wep_key(ssid, 1);
00937 }
00938
00939
00940 static char * wpa_config_write_wep_key2(const struct parse_data *data,
00941 struct wpa_ssid *ssid)
00942 {
00943 return wpa_config_write_wep_key(ssid, 2);
00944 }
00945
00946
00947 static char * wpa_config_write_wep_key3(const struct parse_data *data,
00948 struct wpa_ssid *ssid)
00949 {
00950 return wpa_config_write_wep_key(ssid, 3);
00951 }
00952
00953
00954
00955
00956
00957 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
00958
00959
00960 #define STR(f) .name = #f, .parser = wpa_config_parse_str, \
00961 .writer = wpa_config_write_str, .param1 = OFFSET(f)
00962
00963
00964
00965
00966 #define STR_LEN(f) STR(f), .param2 = OFFSET(f ## _len)
00967
00968
00969
00970 #define STR_RANGE(f, min, max) STR_LEN(f), .param3 = (void *) (min), \
00971 .param4 = (void *) (max)
00972
00973
00974
00975 #define INT(f) .name = #f, .parser = wpa_config_parse_int, \
00976 .writer = wpa_config_write_int, \
00977 .param1 = OFFSET(f), .param2 = (void *) 0
00978
00979
00980 #define INT_RANGE(f, min, max) INT(f), .param3 = (void *) (min), \
00981 .param4 = (void *) (max)
00982
00983
00984
00985 #define FUNC(f) .name = #f, .parser = wpa_config_parse_ ## f, \
00986 .writer = wpa_config_write_ ## f
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011 static const struct parse_data ssid_fields[] = {
01012 { STR_RANGE(ssid, 0, MAX_SSID_LEN) },
01013 { INT_RANGE(scan_ssid, 0, 1) },
01014 { FUNC(bssid) },
01015 { FUNC(psk), .key_data = 1 },
01016 { FUNC(proto) },
01017 { FUNC(key_mgmt) },
01018 { FUNC(pairwise) },
01019 { FUNC(group) },
01020 { FUNC(auth_alg) },
01021 { FUNC(eap) },
01022 { STR_LEN(identity) },
01023 { STR_LEN(anonymous_identity) },
01024 { STR_RANGE(eappsk, EAP_PSK_LEN, EAP_PSK_LEN), .key_data = 1 },
01025 { STR_LEN(nai) },
01026 { STR_LEN(password), .key_data = 1 },
01027 { STR(ca_cert) },
01028 { STR(ca_path) },
01029 { STR(client_cert) },
01030 { STR(private_key) },
01031 { STR(private_key_passwd), .key_data = 1 },
01032 { STR(dh_file) },
01033 { STR(subject_match) },
01034 { STR(altsubject_match) },
01035 { STR(ca_cert2) },
01036 { STR(ca_path2) },
01037 { STR(client_cert2) },
01038 { STR(private_key2) },
01039 { STR(private_key2_passwd), .key_data = 1 },
01040 { STR(dh_file2) },
01041 { STR(subject_match2) },
01042 { STR(altsubject_match2) },
01043 { STR(phase1) },
01044 { STR(phase2) },
01045 { STR(pcsc) },
01046 { STR(pin), .key_data = 1 },
01047 { STR(engine_id) },
01048 { STR(key_id) },
01049 { INT(engine) },
01050 { INT(eapol_flags) },
01051 { FUNC(wep_key0), .key_data = 1 },
01052 { FUNC(wep_key1), .key_data = 1 },
01053 { FUNC(wep_key2), .key_data = 1 },
01054 { FUNC(wep_key3), .key_data = 1 },
01055 { INT(wep_tx_keyidx) },
01056 { INT(priority) },
01057 { INT(eap_workaround) },
01058 { STR(pac_file) },
01059 { INT_RANGE(mode, 0, 1) },
01060 { INT_RANGE(proactive_key_caching, 0, 1) },
01061 { INT_RANGE(disabled, 0, 1) },
01062 };
01063
01064 #undef OFFSET
01065 #undef STR
01066 #undef STR_LEN
01067 #undef STR_RANGE
01068 #undef INT
01069 #undef INT_RANGE
01070 #undef FUNC
01071 #define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
01072
01073
01086 int wpa_config_add_prio_network(struct wpa_config *config,
01087 struct wpa_ssid *ssid)
01088 {
01089 int prio;
01090 struct wpa_ssid *prev, **nlist;
01091
01092
01093
01094
01095
01096 for (prio = 0; prio < config->num_prio; prio++) {
01097 prev = config->pssid[prio];
01098 if (prev->priority == ssid->priority) {
01099 while (prev->pnext)
01100 prev = prev->pnext;
01101 prev->pnext = ssid;
01102 return 0;
01103 }
01104 }
01105
01106
01107 nlist = realloc(config->pssid,
01108 (config->num_prio + 1) * sizeof(struct wpa_ssid *));
01109 if (nlist == NULL)
01110 return -1;
01111
01112 for (prio = 0; prio < config->num_prio; prio++) {
01113 if (nlist[prio]->priority < ssid->priority)
01114 break;
01115 }
01116
01117 memmove(&nlist[prio + 1], &nlist[prio],
01118 (config->num_prio - prio) * sizeof(struct wpa_ssid *));
01119
01120 nlist[prio] = ssid;
01121 config->num_prio++;
01122 config->pssid = nlist;
01123
01124 return 0;
01125 }
01126
01127
01138 static int wpa_config_update_prio_list(struct wpa_config *config)
01139 {
01140 struct wpa_ssid *ssid;
01141 int ret = 0;
01142
01143 free(config->pssid);
01144 config->pssid = NULL;
01145 config->num_prio = 0;
01146
01147 ssid = config->ssid;
01148 while (ssid) {
01149 ssid->pnext = NULL;
01150 if (wpa_config_add_prio_network(config, ssid) < 0)
01151 ret = -1;
01152 ssid = ssid->next;
01153 }
01154
01155 return ret;
01156 }
01157
01158
01167 void wpa_config_free_ssid(struct wpa_ssid *ssid)
01168 {
01169 free(ssid->ssid);
01170 free(ssid->passphrase);
01171 free(ssid->eap_methods);
01172 free(ssid->identity);
01173 free(ssid->anonymous_identity);
01174 free(ssid->eappsk);
01175 free(ssid->nai);
01176 free(ssid->password);
01177 free(ssid->ca_cert);
01178 free(ssid->ca_path);
01179 free(ssid->client_cert);
01180 free(ssid->private_key);
01181 free(ssid->private_key_passwd);
01182 free(ssid->dh_file);
01183 free(ssid->subject_match);
01184 free(ssid->altsubject_match);
01185 free(ssid->ca_cert2);
01186 free(ssid->ca_path2);
01187 free(ssid->client_cert2);
01188 free(ssid->private_key2);
01189 free(ssid->private_key2_passwd);
01190 free(ssid->dh_file2);
01191 free(ssid->subject_match2);
01192 free(ssid->altsubject_match2);
01193 free(ssid->phase1);
01194 free(ssid->phase2);
01195 free(ssid->pcsc);
01196 free(ssid->pin);
01197 free(ssid->engine_id);
01198 free(ssid->key_id);
01199 free(ssid->otp);
01200 free(ssid->pending_req_otp);
01201 free(ssid->pac_file);
01202 free(ssid->new_password);
01203 free(ssid);
01204 }
01205
01206
01215 void wpa_config_free(struct wpa_config *config)
01216 {
01217 struct wpa_config_blob *blob, *prevblob;
01218 struct wpa_ssid *ssid, *prev = NULL;
01219 ssid = config->ssid;
01220 while (ssid) {
01221 prev = ssid;
01222 ssid = ssid->next;
01223 wpa_config_free_ssid(prev);
01224 }
01225
01226 blob = config->blobs;
01227 prevblob = NULL;
01228 while (blob) {
01229 prevblob = blob;
01230 blob = blob->next;
01231 wpa_config_free_blob(prevblob);
01232 }
01233
01234 free(config->ctrl_interface);
01235 free(config->opensc_engine_path);
01236 free(config->pkcs11_engine_path);
01237 free(config->pkcs11_module_path);
01238 free(config->driver_param);
01239 free(config->pssid);
01240 free(config);
01241 }
01242
01243
01251 int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int method)
01252 {
01253 u8 *pos;
01254
01255 if (ssid == NULL || ssid->eap_methods == NULL)
01256 return 1;
01257
01258 pos = ssid->eap_methods;
01259 while (*pos != EAP_TYPE_NONE) {
01260 if (*pos == method)
01261 return 1;
01262 pos++;
01263 }
01264 return 0;
01265 }
01266
01267
01275 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
01276 {
01277 struct wpa_ssid *ssid;
01278
01279 ssid = config->ssid;
01280 while (ssid) {
01281 if (id == ssid->id)
01282 break;
01283 ssid = ssid->next;
01284 }
01285
01286 return ssid;
01287 }
01288
01289
01296 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
01297 {
01298 int id;
01299 struct wpa_ssid *ssid, *last = NULL;
01300
01301 id = -1;
01302 ssid = config->ssid;
01303 while (ssid) {
01304 if (ssid->id > id)
01305 id = ssid->id;
01306 last = ssid;
01307 ssid = ssid->next;
01308 }
01309 id++;
01310
01311 ssid = malloc(sizeof(*ssid));
01312 if (ssid == NULL)
01313 return NULL;
01314 memset(ssid, 0, sizeof(*ssid));
01315 ssid->id = id;
01316 if (last)
01317 last->next = ssid;
01318 else
01319 config->ssid = ssid;
01320
01321 wpa_config_update_prio_list(config);
01322
01323 return ssid;
01324 }
01325
01326
01334 int wpa_config_remove_network(struct wpa_config *config, int id)
01335 {
01336 struct wpa_ssid *ssid, *prev = NULL;
01337
01338 ssid = config->ssid;
01339 while (ssid) {
01340 if (id == ssid->id)
01341 break;
01342 prev = ssid;
01343 ssid = ssid->next;
01344 }
01345
01346 if (ssid == NULL)
01347 return -1;
01348
01349 if (prev)
01350 prev->next = ssid->next;
01351 else
01352 config->ssid = ssid->next;
01353
01354 wpa_config_update_prio_list(config);
01355 wpa_config_free_ssid(ssid);
01356 return 0;
01357 }
01358
01359
01365 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
01366 {
01367 ssid->proto = DEFAULT_PROTO;
01368 ssid->pairwise_cipher = DEFAULT_PAIRWISE;
01369 ssid->group_cipher = DEFAULT_GROUP;
01370 ssid->key_mgmt = DEFAULT_KEY_MGMT;
01371 ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
01372 ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
01373 }
01374
01375
01390 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
01391 int line)
01392 {
01393 int i, ret = 0;
01394
01395 if (ssid == NULL || var == NULL || value == NULL)
01396 return -1;
01397
01398 for (i = 0; i < NUM_SSID_FIELDS; i++) {
01399 const struct parse_data *field = &ssid_fields[i];
01400 if (strcmp(var, field->name) != 0)
01401 continue;
01402
01403 if (field->parser(field, ssid, line, value)) {
01404 if (line) {
01405 wpa_printf(MSG_ERROR, "Line %d: failed to "
01406 "parse %s '%s'.", line, var, value);
01407 }
01408 ret = -1;
01409 }
01410 break;
01411 }
01412 if (i == NUM_SSID_FIELDS) {
01413 if (line) {
01414 wpa_printf(MSG_ERROR, "Line %d: unknown network field "
01415 "'%s'.", line, var);
01416 }
01417 ret = -1;
01418 }
01419
01420 return ret;
01421 }
01422
01423
01437 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
01438 {
01439 int i;
01440
01441 if (ssid == NULL || var == NULL)
01442 return NULL;
01443
01444 for (i = 0; i < NUM_SSID_FIELDS; i++) {
01445 const struct parse_data *field = &ssid_fields[i];
01446 if (strcmp(var, field->name) == 0)
01447 return field->writer(field, ssid);
01448 }
01449
01450 return NULL;
01451 }
01452
01453
01462 void wpa_config_update_psk(struct wpa_ssid *ssid)
01463 {
01464 pbkdf2_sha1(ssid->passphrase,
01465 (char *) ssid->ssid, ssid->ssid_len, 4096,
01466 ssid->psk, PMK_LEN);
01467 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
01468 ssid->psk, PMK_LEN);
01469 ssid->psk_set = 1;
01470 }
01471
01472
01480 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
01481 const char *name)
01482 {
01483 struct wpa_config_blob *blob = config->blobs;
01484
01485 while (blob) {
01486 if (strcmp(blob->name, name) == 0)
01487 return blob;
01488 blob = blob->next;
01489 }
01490 return NULL;
01491 }
01492
01493
01503 void wpa_config_set_blob(struct wpa_config *config,
01504 struct wpa_config_blob *blob)
01505 {
01506 wpa_config_remove_blob(config, blob->name);
01507 blob->next = config->blobs;
01508 config->blobs = blob;
01509 }
01510
01511
01517 void wpa_config_free_blob(struct wpa_config_blob *blob)
01518 {
01519 if (blob) {
01520 free(blob->name);
01521 free(blob->data);
01522 free(blob);
01523 }
01524 }
01525
01526
01534 int wpa_config_remove_blob(struct wpa_config *config, const char *name)
01535 {
01536 struct wpa_config_blob *pos = config->blobs, *prev = NULL;
01537
01538 while (pos) {
01539 if (strcmp(pos->name, name) == 0) {
01540 if (prev)
01541 prev->next = pos->next;
01542 else
01543 config->blobs = pos->next;
01544 wpa_config_free_blob(pos);
01545 return 0;
01546 }
01547 prev = pos;
01548 pos = pos->next;
01549 }
01550
01551 return -1;
01552 }
01553
01554
01563 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
01564 const char *driver_param)
01565 {
01566 struct wpa_config *config;
01567
01568 config = malloc(sizeof(*config));
01569 if (config == NULL)
01570 return NULL;
01571 memset(config, 0, sizeof(*config));
01572 config->eapol_version = DEFAULT_EAPOL_VERSION;
01573 config->ap_scan = DEFAULT_AP_SCAN;
01574 config->fast_reauth = DEFAULT_FAST_REAUTH;
01575
01576 if (ctrl_interface)
01577 config->ctrl_interface = strdup(ctrl_interface);
01578 if (driver_param)
01579 config->driver_param = strdup(driver_param);
01580
01581 return config;
01582 }
01583