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


wpa_supplicant_node
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:25:12