config.c

Go to the documentation of this file.
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         /* First network for this priority - add new priority list */
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 

Generated on Mon Nov 21 20:50:40 2005 for wpa_supplicant by  doxygen 1.4.2