$search
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 }