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