ap_config.c
Go to the documentation of this file.
00001 /*
00002  * hostapd / Configuration helper functions
00003  * Copyright (c) 2003-2009, 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 "utils/includes.h"
00016 
00017 #include "utils/common.h"
00018 #include "crypto/sha1.h"
00019 #include "radius/radius_client.h"
00020 #include "common/ieee802_11_defs.h"
00021 #include "common/eapol_common.h"
00022 #include "eap_common/eap_wsc_common.h"
00023 #include "eap_server/eap.h"
00024 #include "wpa_auth.h"
00025 #include "sta_info.h"
00026 #include "ap_config.h"
00027 
00028 
00029 static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
00030 {
00031         struct hostapd_vlan *vlan, *prev;
00032 
00033         vlan = bss->vlan;
00034         prev = NULL;
00035         while (vlan) {
00036                 prev = vlan;
00037                 vlan = vlan->next;
00038                 os_free(prev);
00039         }
00040 
00041         bss->vlan = NULL;
00042 }
00043 
00044 
00045 void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
00046 {
00047         bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
00048         bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
00049         bss->logger_syslog = (unsigned int) -1;
00050         bss->logger_stdout = (unsigned int) -1;
00051 
00052         bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
00053 
00054         bss->wep_rekeying_period = 300;
00055         /* use key0 in individual key and key1 in broadcast key */
00056         bss->broadcast_key_idx_min = 1;
00057         bss->broadcast_key_idx_max = 2;
00058         bss->eap_reauth_period = 3600;
00059 
00060         bss->wpa_group_rekey = 600;
00061         bss->wpa_gmk_rekey = 86400;
00062         bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
00063         bss->wpa_pairwise = WPA_CIPHER_TKIP;
00064         bss->wpa_group = WPA_CIPHER_TKIP;
00065         bss->rsn_pairwise = 0;
00066 
00067         bss->max_num_sta = MAX_STA_COUNT;
00068 
00069         bss->dtim_period = 2;
00070 
00071         bss->radius_server_auth_port = 1812;
00072         bss->ap_max_inactivity = AP_MAX_INACTIVITY;
00073         bss->eapol_version = EAPOL_VERSION;
00074 
00075         bss->max_listen_interval = 65535;
00076 
00077 #ifdef CONFIG_IEEE80211W
00078         bss->assoc_sa_query_max_timeout = 1000;
00079         bss->assoc_sa_query_retry_timeout = 201;
00080 #endif /* CONFIG_IEEE80211W */
00081 #ifdef EAP_SERVER_FAST
00082          /* both anonymous and authenticated provisioning */
00083         bss->eap_fast_prov = 3;
00084         bss->pac_key_lifetime = 7 * 24 * 60 * 60;
00085         bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
00086 #endif /* EAP_SERVER_FAST */
00087 }
00088 
00089 
00090 struct hostapd_config * hostapd_config_defaults(void)
00091 {
00092         struct hostapd_config *conf;
00093         struct hostapd_bss_config *bss;
00094         int i;
00095         const int aCWmin = 4, aCWmax = 10;
00096         const struct hostapd_wmm_ac_params ac_bk =
00097                 { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
00098         const struct hostapd_wmm_ac_params ac_be =
00099                 { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
00100         const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
00101                 { aCWmin - 1, aCWmin, 2, 3000 / 32, 1 };
00102         const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
00103                 { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 };
00104 
00105         conf = os_zalloc(sizeof(*conf));
00106         bss = os_zalloc(sizeof(*bss));
00107         if (conf == NULL || bss == NULL) {
00108                 wpa_printf(MSG_ERROR, "Failed to allocate memory for "
00109                            "configuration data.");
00110                 os_free(conf);
00111                 os_free(bss);
00112                 return NULL;
00113         }
00114 
00115         bss->radius = os_zalloc(sizeof(*bss->radius));
00116         if (bss->radius == NULL) {
00117                 os_free(conf);
00118                 os_free(bss);
00119                 return NULL;
00120         }
00121 
00122         hostapd_config_defaults_bss(bss);
00123 
00124         conf->num_bss = 1;
00125         conf->bss = bss;
00126 
00127         conf->beacon_int = 100;
00128         conf->rts_threshold = -1; /* use driver default: 2347 */
00129         conf->fragm_threshold = -1; /* user driver default: 2346 */
00130         conf->send_probe_response = 1;
00131 
00132         for (i = 0; i < NUM_TX_QUEUES; i++)
00133                 conf->tx_queue[i].aifs = -1; /* use hw default */
00134 
00135         conf->wmm_ac_params[0] = ac_be;
00136         conf->wmm_ac_params[1] = ac_bk;
00137         conf->wmm_ac_params[2] = ac_vi;
00138         conf->wmm_ac_params[3] = ac_vo;
00139 
00140         conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
00141 
00142         return conf;
00143 }
00144 
00145 
00146 int hostapd_mac_comp(const void *a, const void *b)
00147 {
00148         return os_memcmp(a, b, sizeof(macaddr));
00149 }
00150 
00151 
00152 int hostapd_mac_comp_empty(const void *a)
00153 {
00154         macaddr empty = { 0 };
00155         return os_memcmp(a, empty, sizeof(macaddr));
00156 }
00157 
00158 
00159 static int hostapd_config_read_wpa_psk(const char *fname,
00160                                        struct hostapd_ssid *ssid)
00161 {
00162         FILE *f;
00163         char buf[128], *pos;
00164         int line = 0, ret = 0, len, ok;
00165         u8 addr[ETH_ALEN];
00166         struct hostapd_wpa_psk *psk;
00167 
00168         if (!fname)
00169                 return 0;
00170 
00171         f = fopen(fname, "r");
00172         if (!f) {
00173                 wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname);
00174                 return -1;
00175         }
00176 
00177         while (fgets(buf, sizeof(buf), f)) {
00178                 line++;
00179 
00180                 if (buf[0] == '#')
00181                         continue;
00182                 pos = buf;
00183                 while (*pos != '\0') {
00184                         if (*pos == '\n') {
00185                                 *pos = '\0';
00186                                 break;
00187                         }
00188                         pos++;
00189                 }
00190                 if (buf[0] == '\0')
00191                         continue;
00192 
00193                 if (hwaddr_aton(buf, addr)) {
00194                         wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
00195                                    "line %d in '%s'", buf, line, fname);
00196                         ret = -1;
00197                         break;
00198                 }
00199 
00200                 psk = os_zalloc(sizeof(*psk));
00201                 if (psk == NULL) {
00202                         wpa_printf(MSG_ERROR, "WPA PSK allocation failed");
00203                         ret = -1;
00204                         break;
00205                 }
00206                 if (is_zero_ether_addr(addr))
00207                         psk->group = 1;
00208                 else
00209                         os_memcpy(psk->addr, addr, ETH_ALEN);
00210 
00211                 pos = buf + 17;
00212                 if (*pos == '\0') {
00213                         wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
00214                                    line, fname);
00215                         os_free(psk);
00216                         ret = -1;
00217                         break;
00218                 }
00219                 pos++;
00220 
00221                 ok = 0;
00222                 len = os_strlen(pos);
00223                 if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
00224                         ok = 1;
00225                 else if (len >= 8 && len < 64) {
00226                         pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
00227                                     4096, psk->psk, PMK_LEN);
00228                         ok = 1;
00229                 }
00230                 if (!ok) {
00231                         wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
00232                                    "'%s'", pos, line, fname);
00233                         os_free(psk);
00234                         ret = -1;
00235                         break;
00236                 }
00237 
00238                 psk->next = ssid->wpa_psk;
00239                 ssid->wpa_psk = psk;
00240         }
00241 
00242         fclose(f);
00243 
00244         return ret;
00245 }
00246 
00247 
00248 static int hostapd_derive_psk(struct hostapd_ssid *ssid)
00249 {
00250         ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
00251         if (ssid->wpa_psk == NULL) {
00252                 wpa_printf(MSG_ERROR, "Unable to alloc space for PSK");
00253                 return -1;
00254         }
00255         wpa_hexdump_ascii(MSG_DEBUG, "SSID",
00256                           (u8 *) ssid->ssid, ssid->ssid_len);
00257         wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)",
00258                               (u8 *) ssid->wpa_passphrase,
00259                               os_strlen(ssid->wpa_passphrase));
00260         pbkdf2_sha1(ssid->wpa_passphrase,
00261                     ssid->ssid, ssid->ssid_len,
00262                     4096, ssid->wpa_psk->psk, PMK_LEN);
00263         wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)",
00264                         ssid->wpa_psk->psk, PMK_LEN);
00265         return 0;
00266 }
00267 
00268 
00269 int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
00270 {
00271         struct hostapd_ssid *ssid = &conf->ssid;
00272 
00273         if (ssid->wpa_passphrase != NULL) {
00274                 if (ssid->wpa_psk != NULL) {
00275                         wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
00276                                    "instead of passphrase");
00277                 } else {
00278                         wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on "
00279                                    "passphrase");
00280                         if (hostapd_derive_psk(ssid) < 0)
00281                                 return -1;
00282                 }
00283                 ssid->wpa_psk->group = 1;
00284         }
00285 
00286         if (ssid->wpa_psk_file) {
00287                 if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file,
00288                                                 &conf->ssid))
00289                         return -1;
00290         }
00291 
00292         return 0;
00293 }
00294 
00295 
00296 int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b)
00297 {
00298         int i;
00299 
00300         if (a->idx != b->idx || a->default_len != b->default_len)
00301                 return 1;
00302         for (i = 0; i < NUM_WEP_KEYS; i++)
00303                 if (a->len[i] != b->len[i] ||
00304                     os_memcmp(a->key[i], b->key[i], a->len[i]) != 0)
00305                         return 1;
00306         return 0;
00307 }
00308 
00309 
00310 static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
00311                                        int num_servers)
00312 {
00313         int i;
00314 
00315         for (i = 0; i < num_servers; i++) {
00316                 os_free(servers[i].shared_secret);
00317         }
00318         os_free(servers);
00319 }
00320 
00321 
00322 static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
00323 {
00324         os_free(user->identity);
00325         os_free(user->password);
00326         os_free(user);
00327 }
00328 
00329 
00330 static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
00331 {
00332         int i;
00333         for (i = 0; i < NUM_WEP_KEYS; i++) {
00334                 os_free(keys->key[i]);
00335                 keys->key[i] = NULL;
00336         }
00337 }
00338 
00339 
00340 static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
00341 {
00342         struct hostapd_wpa_psk *psk, *prev;
00343         struct hostapd_eap_user *user, *prev_user;
00344 
00345         if (conf == NULL)
00346                 return;
00347 
00348         psk = conf->ssid.wpa_psk;
00349         while (psk) {
00350                 prev = psk;
00351                 psk = psk->next;
00352                 os_free(prev);
00353         }
00354 
00355         os_free(conf->ssid.wpa_passphrase);
00356         os_free(conf->ssid.wpa_psk_file);
00357 #ifdef CONFIG_FULL_DYNAMIC_VLAN
00358         os_free(conf->ssid.vlan_tagged_interface);
00359 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
00360 
00361         user = conf->eap_user;
00362         while (user) {
00363                 prev_user = user;
00364                 user = user->next;
00365                 hostapd_config_free_eap_user(prev_user);
00366         }
00367 
00368         os_free(conf->dump_log_name);
00369         os_free(conf->eap_req_id_text);
00370         os_free(conf->accept_mac);
00371         os_free(conf->deny_mac);
00372         os_free(conf->nas_identifier);
00373         hostapd_config_free_radius(conf->radius->auth_servers,
00374                                    conf->radius->num_auth_servers);
00375         hostapd_config_free_radius(conf->radius->acct_servers,
00376                                    conf->radius->num_acct_servers);
00377         os_free(conf->rsn_preauth_interfaces);
00378         os_free(conf->ctrl_interface);
00379         os_free(conf->ca_cert);
00380         os_free(conf->server_cert);
00381         os_free(conf->private_key);
00382         os_free(conf->private_key_passwd);
00383         os_free(conf->dh_file);
00384         os_free(conf->pac_opaque_encr_key);
00385         os_free(conf->eap_fast_a_id);
00386         os_free(conf->eap_fast_a_id_info);
00387         os_free(conf->eap_sim_db);
00388         os_free(conf->radius_server_clients);
00389         os_free(conf->test_socket);
00390         os_free(conf->radius);
00391         hostapd_config_free_vlan(conf);
00392         if (conf->ssid.dyn_vlan_keys) {
00393                 struct hostapd_ssid *ssid = &conf->ssid;
00394                 size_t i;
00395                 for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
00396                         if (ssid->dyn_vlan_keys[i] == NULL)
00397                                 continue;
00398                         hostapd_config_free_wep(ssid->dyn_vlan_keys[i]);
00399                         os_free(ssid->dyn_vlan_keys[i]);
00400                 }
00401                 os_free(ssid->dyn_vlan_keys);
00402                 ssid->dyn_vlan_keys = NULL;
00403         }
00404 
00405 #ifdef CONFIG_IEEE80211R
00406         {
00407                 struct ft_remote_r0kh *r0kh, *r0kh_prev;
00408                 struct ft_remote_r1kh *r1kh, *r1kh_prev;
00409 
00410                 r0kh = conf->r0kh_list;
00411                 conf->r0kh_list = NULL;
00412                 while (r0kh) {
00413                         r0kh_prev = r0kh;
00414                         r0kh = r0kh->next;
00415                         os_free(r0kh_prev);
00416                 }
00417 
00418                 r1kh = conf->r1kh_list;
00419                 conf->r1kh_list = NULL;
00420                 while (r1kh) {
00421                         r1kh_prev = r1kh;
00422                         r1kh = r1kh->next;
00423                         os_free(r1kh_prev);
00424                 }
00425         }
00426 #endif /* CONFIG_IEEE80211R */
00427 
00428 #ifdef CONFIG_WPS
00429         os_free(conf->wps_pin_requests);
00430         os_free(conf->device_name);
00431         os_free(conf->manufacturer);
00432         os_free(conf->model_name);
00433         os_free(conf->model_number);
00434         os_free(conf->serial_number);
00435         os_free(conf->device_type);
00436         os_free(conf->config_methods);
00437         os_free(conf->ap_pin);
00438         os_free(conf->extra_cred);
00439         os_free(conf->ap_settings);
00440         os_free(conf->upnp_iface);
00441         os_free(conf->friendly_name);
00442         os_free(conf->manufacturer_url);
00443         os_free(conf->model_description);
00444         os_free(conf->model_url);
00445         os_free(conf->upc);
00446 #endif /* CONFIG_WPS */
00447 }
00448 
00449 
00454 void hostapd_config_free(struct hostapd_config *conf)
00455 {
00456         size_t i;
00457 
00458         if (conf == NULL)
00459                 return;
00460 
00461         for (i = 0; i < conf->num_bss; i++)
00462                 hostapd_config_free_bss(&conf->bss[i]);
00463         os_free(conf->bss);
00464         os_free(conf->supported_rates);
00465         os_free(conf->basic_rates);
00466 
00467         os_free(conf);
00468 }
00469 
00470 
00481 int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
00482                           const u8 *addr, int *vlan_id)
00483 {
00484         int start, end, middle, res;
00485 
00486         start = 0;
00487         end = num_entries - 1;
00488 
00489         while (start <= end) {
00490                 middle = (start + end) / 2;
00491                 res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
00492                 if (res == 0) {
00493                         if (vlan_id)
00494                                 *vlan_id = list[middle].vlan_id;
00495                         return 1;
00496                 }
00497                 if (res < 0)
00498                         start = middle + 1;
00499                 else
00500                         end = middle - 1;
00501         }
00502 
00503         return 0;
00504 }
00505 
00506 
00507 int hostapd_rate_found(int *list, int rate)
00508 {
00509         int i;
00510 
00511         if (list == NULL)
00512                 return 0;
00513 
00514         for (i = 0; list[i] >= 0; i++)
00515                 if (list[i] == rate)
00516                         return 1;
00517 
00518         return 0;
00519 }
00520 
00521 
00522 const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
00523 {
00524         struct hostapd_vlan *v = vlan;
00525         while (v) {
00526                 if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD)
00527                         return v->ifname;
00528                 v = v->next;
00529         }
00530         return NULL;
00531 }
00532 
00533 
00534 const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
00535                            const u8 *addr, const u8 *prev_psk)
00536 {
00537         struct hostapd_wpa_psk *psk;
00538         int next_ok = prev_psk == NULL;
00539 
00540         for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
00541                 if (next_ok &&
00542                     (psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0))
00543                         return psk->psk;
00544 
00545                 if (psk->psk == prev_psk)
00546                         next_ok = 1;
00547         }
00548 
00549         return NULL;
00550 }
00551 
00552 
00553 const struct hostapd_eap_user *
00554 hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
00555                      size_t identity_len, int phase2)
00556 {
00557         struct hostapd_eap_user *user = conf->eap_user;
00558 
00559 #ifdef CONFIG_WPS
00560         if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
00561             os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
00562                 static struct hostapd_eap_user wsc_enrollee;
00563                 os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
00564                 wsc_enrollee.methods[0].method = eap_server_get_type(
00565                         "WSC", &wsc_enrollee.methods[0].vendor);
00566                 return &wsc_enrollee;
00567         }
00568 
00569         if (conf->wps_state && conf->ap_pin &&
00570             identity_len == WSC_ID_REGISTRAR_LEN &&
00571             os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
00572                 static struct hostapd_eap_user wsc_registrar;
00573                 os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
00574                 wsc_registrar.methods[0].method = eap_server_get_type(
00575                         "WSC", &wsc_registrar.methods[0].vendor);
00576                 wsc_registrar.password = (u8 *) conf->ap_pin;
00577                 wsc_registrar.password_len = os_strlen(conf->ap_pin);
00578                 return &wsc_registrar;
00579         }
00580 #endif /* CONFIG_WPS */
00581 
00582         while (user) {
00583                 if (!phase2 && user->identity == NULL) {
00584                         /* Wildcard match */
00585                         break;
00586                 }
00587 
00588                 if (user->phase2 == !!phase2 && user->wildcard_prefix &&
00589                     identity_len >= user->identity_len &&
00590                     os_memcmp(user->identity, identity, user->identity_len) ==
00591                     0) {
00592                         /* Wildcard prefix match */
00593                         break;
00594                 }
00595 
00596                 if (user->phase2 == !!phase2 &&
00597                     user->identity_len == identity_len &&
00598                     os_memcmp(user->identity, identity, identity_len) == 0)
00599                         break;
00600                 user = user->next;
00601         }
00602 
00603         return user;
00604 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:33