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

Generated on Sat May 6 21:13:30 2006 for wpa_supplicant by  doxygen 1.4.2