ap_config.c revision 214501
1/*
2 * hostapd / Configuration helper functions
3 * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "utils/includes.h"
16
17#include "utils/common.h"
18#include "crypto/sha1.h"
19#include "radius/radius_client.h"
20#include "common/ieee802_11_defs.h"
21#include "common/eapol_common.h"
22#include "eap_common/eap_wsc_common.h"
23#include "eap_server/eap.h"
24#include "wpa_auth.h"
25#include "sta_info.h"
26#include "ap_config.h"
27
28
29static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
30{
31	struct hostapd_vlan *vlan, *prev;
32
33	vlan = bss->vlan;
34	prev = NULL;
35	while (vlan) {
36		prev = vlan;
37		vlan = vlan->next;
38		os_free(prev);
39	}
40
41	bss->vlan = NULL;
42}
43
44
45void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
46{
47	bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
48	bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
49	bss->logger_syslog = (unsigned int) -1;
50	bss->logger_stdout = (unsigned int) -1;
51
52	bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
53
54	bss->wep_rekeying_period = 300;
55	/* use key0 in individual key and key1 in broadcast key */
56	bss->broadcast_key_idx_min = 1;
57	bss->broadcast_key_idx_max = 2;
58	bss->eap_reauth_period = 3600;
59
60	bss->wpa_group_rekey = 600;
61	bss->wpa_gmk_rekey = 86400;
62	bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
63	bss->wpa_pairwise = WPA_CIPHER_TKIP;
64	bss->wpa_group = WPA_CIPHER_TKIP;
65	bss->rsn_pairwise = 0;
66
67	bss->max_num_sta = MAX_STA_COUNT;
68
69	bss->dtim_period = 2;
70
71	bss->radius_server_auth_port = 1812;
72	bss->ap_max_inactivity = AP_MAX_INACTIVITY;
73	bss->eapol_version = EAPOL_VERSION;
74
75	bss->max_listen_interval = 65535;
76
77#ifdef CONFIG_IEEE80211W
78	bss->assoc_sa_query_max_timeout = 1000;
79	bss->assoc_sa_query_retry_timeout = 201;
80#endif /* CONFIG_IEEE80211W */
81#ifdef EAP_SERVER_FAST
82	 /* both anonymous and authenticated provisioning */
83	bss->eap_fast_prov = 3;
84	bss->pac_key_lifetime = 7 * 24 * 60 * 60;
85	bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
86#endif /* EAP_SERVER_FAST */
87}
88
89
90struct hostapd_config * hostapd_config_defaults(void)
91{
92	struct hostapd_config *conf;
93	struct hostapd_bss_config *bss;
94	int i;
95	const int aCWmin = 4, aCWmax = 10;
96	const struct hostapd_wmm_ac_params ac_bk =
97		{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
98	const struct hostapd_wmm_ac_params ac_be =
99		{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
100	const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
101		{ aCWmin - 1, aCWmin, 2, 3000 / 32, 1 };
102	const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
103		{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 };
104
105	conf = os_zalloc(sizeof(*conf));
106	bss = os_zalloc(sizeof(*bss));
107	if (conf == NULL || bss == NULL) {
108		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
109			   "configuration data.");
110		os_free(conf);
111		os_free(bss);
112		return NULL;
113	}
114
115	bss->radius = os_zalloc(sizeof(*bss->radius));
116	if (bss->radius == NULL) {
117		os_free(conf);
118		os_free(bss);
119		return NULL;
120	}
121
122	hostapd_config_defaults_bss(bss);
123
124	conf->num_bss = 1;
125	conf->bss = bss;
126
127	conf->beacon_int = 100;
128	conf->rts_threshold = -1; /* use driver default: 2347 */
129	conf->fragm_threshold = -1; /* user driver default: 2346 */
130	conf->send_probe_response = 1;
131
132	for (i = 0; i < NUM_TX_QUEUES; i++)
133		conf->tx_queue[i].aifs = -1; /* use hw default */
134
135	conf->wmm_ac_params[0] = ac_be;
136	conf->wmm_ac_params[1] = ac_bk;
137	conf->wmm_ac_params[2] = ac_vi;
138	conf->wmm_ac_params[3] = ac_vo;
139
140	conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
141
142	return conf;
143}
144
145
146int hostapd_mac_comp(const void *a, const void *b)
147{
148	return os_memcmp(a, b, sizeof(macaddr));
149}
150
151
152int hostapd_mac_comp_empty(const void *a)
153{
154	macaddr empty = { 0 };
155	return os_memcmp(a, empty, sizeof(macaddr));
156}
157
158
159static int hostapd_config_read_wpa_psk(const char *fname,
160				       struct hostapd_ssid *ssid)
161{
162	FILE *f;
163	char buf[128], *pos;
164	int line = 0, ret = 0, len, ok;
165	u8 addr[ETH_ALEN];
166	struct hostapd_wpa_psk *psk;
167
168	if (!fname)
169		return 0;
170
171	f = fopen(fname, "r");
172	if (!f) {
173		wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname);
174		return -1;
175	}
176
177	while (fgets(buf, sizeof(buf), f)) {
178		line++;
179
180		if (buf[0] == '#')
181			continue;
182		pos = buf;
183		while (*pos != '\0') {
184			if (*pos == '\n') {
185				*pos = '\0';
186				break;
187			}
188			pos++;
189		}
190		if (buf[0] == '\0')
191			continue;
192
193		if (hwaddr_aton(buf, addr)) {
194			wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
195				   "line %d in '%s'", buf, line, fname);
196			ret = -1;
197			break;
198		}
199
200		psk = os_zalloc(sizeof(*psk));
201		if (psk == NULL) {
202			wpa_printf(MSG_ERROR, "WPA PSK allocation failed");
203			ret = -1;
204			break;
205		}
206		if (is_zero_ether_addr(addr))
207			psk->group = 1;
208		else
209			os_memcpy(psk->addr, addr, ETH_ALEN);
210
211		pos = buf + 17;
212		if (*pos == '\0') {
213			wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
214				   line, fname);
215			os_free(psk);
216			ret = -1;
217			break;
218		}
219		pos++;
220
221		ok = 0;
222		len = os_strlen(pos);
223		if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
224			ok = 1;
225		else if (len >= 8 && len < 64) {
226			pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
227				    4096, psk->psk, PMK_LEN);
228			ok = 1;
229		}
230		if (!ok) {
231			wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
232				   "'%s'", pos, line, fname);
233			os_free(psk);
234			ret = -1;
235			break;
236		}
237
238		psk->next = ssid->wpa_psk;
239		ssid->wpa_psk = psk;
240	}
241
242	fclose(f);
243
244	return ret;
245}
246
247
248static int hostapd_derive_psk(struct hostapd_ssid *ssid)
249{
250	ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
251	if (ssid->wpa_psk == NULL) {
252		wpa_printf(MSG_ERROR, "Unable to alloc space for PSK");
253		return -1;
254	}
255	wpa_hexdump_ascii(MSG_DEBUG, "SSID",
256			  (u8 *) ssid->ssid, ssid->ssid_len);
257	wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)",
258			      (u8 *) ssid->wpa_passphrase,
259			      os_strlen(ssid->wpa_passphrase));
260	pbkdf2_sha1(ssid->wpa_passphrase,
261		    ssid->ssid, ssid->ssid_len,
262		    4096, ssid->wpa_psk->psk, PMK_LEN);
263	wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)",
264			ssid->wpa_psk->psk, PMK_LEN);
265	return 0;
266}
267
268
269int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
270{
271	struct hostapd_ssid *ssid = &conf->ssid;
272
273	if (ssid->wpa_passphrase != NULL) {
274		if (ssid->wpa_psk != NULL) {
275			wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
276				   "instead of passphrase");
277		} else {
278			wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on "
279				   "passphrase");
280			if (hostapd_derive_psk(ssid) < 0)
281				return -1;
282		}
283		ssid->wpa_psk->group = 1;
284	}
285
286	if (ssid->wpa_psk_file) {
287		if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file,
288						&conf->ssid))
289			return -1;
290	}
291
292	return 0;
293}
294
295
296int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b)
297{
298	int i;
299
300	if (a->idx != b->idx || a->default_len != b->default_len)
301		return 1;
302	for (i = 0; i < NUM_WEP_KEYS; i++)
303		if (a->len[i] != b->len[i] ||
304		    os_memcmp(a->key[i], b->key[i], a->len[i]) != 0)
305			return 1;
306	return 0;
307}
308
309
310static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
311				       int num_servers)
312{
313	int i;
314
315	for (i = 0; i < num_servers; i++) {
316		os_free(servers[i].shared_secret);
317	}
318	os_free(servers);
319}
320
321
322static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
323{
324	os_free(user->identity);
325	os_free(user->password);
326	os_free(user);
327}
328
329
330static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
331{
332	int i;
333	for (i = 0; i < NUM_WEP_KEYS; i++) {
334		os_free(keys->key[i]);
335		keys->key[i] = NULL;
336	}
337}
338
339
340static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
341{
342	struct hostapd_wpa_psk *psk, *prev;
343	struct hostapd_eap_user *user, *prev_user;
344
345	if (conf == NULL)
346		return;
347
348	psk = conf->ssid.wpa_psk;
349	while (psk) {
350		prev = psk;
351		psk = psk->next;
352		os_free(prev);
353	}
354
355	os_free(conf->ssid.wpa_passphrase);
356	os_free(conf->ssid.wpa_psk_file);
357	hostapd_config_free_wep(&conf->ssid.wep);
358#ifdef CONFIG_FULL_DYNAMIC_VLAN
359	os_free(conf->ssid.vlan_tagged_interface);
360#endif /* CONFIG_FULL_DYNAMIC_VLAN */
361
362	user = conf->eap_user;
363	while (user) {
364		prev_user = user;
365		user = user->next;
366		hostapd_config_free_eap_user(prev_user);
367	}
368
369	os_free(conf->dump_log_name);
370	os_free(conf->eap_req_id_text);
371	os_free(conf->accept_mac);
372	os_free(conf->deny_mac);
373	os_free(conf->nas_identifier);
374	hostapd_config_free_radius(conf->radius->auth_servers,
375				   conf->radius->num_auth_servers);
376	hostapd_config_free_radius(conf->radius->acct_servers,
377				   conf->radius->num_acct_servers);
378	os_free(conf->rsn_preauth_interfaces);
379	os_free(conf->ctrl_interface);
380	os_free(conf->ca_cert);
381	os_free(conf->server_cert);
382	os_free(conf->private_key);
383	os_free(conf->private_key_passwd);
384	os_free(conf->dh_file);
385	os_free(conf->pac_opaque_encr_key);
386	os_free(conf->eap_fast_a_id);
387	os_free(conf->eap_fast_a_id_info);
388	os_free(conf->eap_sim_db);
389	os_free(conf->radius_server_clients);
390	os_free(conf->test_socket);
391	os_free(conf->radius);
392	hostapd_config_free_vlan(conf);
393	if (conf->ssid.dyn_vlan_keys) {
394		struct hostapd_ssid *ssid = &conf->ssid;
395		size_t i;
396		for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
397			if (ssid->dyn_vlan_keys[i] == NULL)
398				continue;
399			hostapd_config_free_wep(ssid->dyn_vlan_keys[i]);
400			os_free(ssid->dyn_vlan_keys[i]);
401		}
402		os_free(ssid->dyn_vlan_keys);
403		ssid->dyn_vlan_keys = NULL;
404	}
405
406#ifdef CONFIG_IEEE80211R
407	{
408		struct ft_remote_r0kh *r0kh, *r0kh_prev;
409		struct ft_remote_r1kh *r1kh, *r1kh_prev;
410
411		r0kh = conf->r0kh_list;
412		conf->r0kh_list = NULL;
413		while (r0kh) {
414			r0kh_prev = r0kh;
415			r0kh = r0kh->next;
416			os_free(r0kh_prev);
417		}
418
419		r1kh = conf->r1kh_list;
420		conf->r1kh_list = NULL;
421		while (r1kh) {
422			r1kh_prev = r1kh;
423			r1kh = r1kh->next;
424			os_free(r1kh_prev);
425		}
426	}
427#endif /* CONFIG_IEEE80211R */
428
429#ifdef CONFIG_WPS
430	os_free(conf->wps_pin_requests);
431	os_free(conf->device_name);
432	os_free(conf->manufacturer);
433	os_free(conf->model_name);
434	os_free(conf->model_number);
435	os_free(conf->serial_number);
436	os_free(conf->device_type);
437	os_free(conf->config_methods);
438	os_free(conf->ap_pin);
439	os_free(conf->extra_cred);
440	os_free(conf->ap_settings);
441	os_free(conf->upnp_iface);
442	os_free(conf->friendly_name);
443	os_free(conf->manufacturer_url);
444	os_free(conf->model_description);
445	os_free(conf->model_url);
446	os_free(conf->upc);
447#endif /* CONFIG_WPS */
448}
449
450
451/**
452 * hostapd_config_free - Free hostapd configuration
453 * @conf: Configuration data from hostapd_config_read().
454 */
455void hostapd_config_free(struct hostapd_config *conf)
456{
457	size_t i;
458
459	if (conf == NULL)
460		return;
461
462	for (i = 0; i < conf->num_bss; i++)
463		hostapd_config_free_bss(&conf->bss[i]);
464	os_free(conf->bss);
465	os_free(conf->supported_rates);
466	os_free(conf->basic_rates);
467
468	os_free(conf);
469}
470
471
472/**
473 * hostapd_maclist_found - Find a MAC address from a list
474 * @list: MAC address list
475 * @num_entries: Number of addresses in the list
476 * @addr: Address to search for
477 * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed
478 * Returns: 1 if address is in the list or 0 if not.
479 *
480 * Perform a binary search for given MAC address from a pre-sorted list.
481 */
482int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
483			  const u8 *addr, int *vlan_id)
484{
485	int start, end, middle, res;
486
487	start = 0;
488	end = num_entries - 1;
489
490	while (start <= end) {
491		middle = (start + end) / 2;
492		res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
493		if (res == 0) {
494			if (vlan_id)
495				*vlan_id = list[middle].vlan_id;
496			return 1;
497		}
498		if (res < 0)
499			start = middle + 1;
500		else
501			end = middle - 1;
502	}
503
504	return 0;
505}
506
507
508int hostapd_rate_found(int *list, int rate)
509{
510	int i;
511
512	if (list == NULL)
513		return 0;
514
515	for (i = 0; list[i] >= 0; i++)
516		if (list[i] == rate)
517			return 1;
518
519	return 0;
520}
521
522
523const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
524{
525	struct hostapd_vlan *v = vlan;
526	while (v) {
527		if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD)
528			return v->ifname;
529		v = v->next;
530	}
531	return NULL;
532}
533
534
535const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
536			   const u8 *addr, const u8 *prev_psk)
537{
538	struct hostapd_wpa_psk *psk;
539	int next_ok = prev_psk == NULL;
540
541	for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
542		if (next_ok &&
543		    (psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0))
544			return psk->psk;
545
546		if (psk->psk == prev_psk)
547			next_ok = 1;
548	}
549
550	return NULL;
551}
552
553
554const struct hostapd_eap_user *
555hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
556		     size_t identity_len, int phase2)
557{
558	struct hostapd_eap_user *user = conf->eap_user;
559
560#ifdef CONFIG_WPS
561	if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
562	    os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
563		static struct hostapd_eap_user wsc_enrollee;
564		os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
565		wsc_enrollee.methods[0].method = eap_server_get_type(
566			"WSC", &wsc_enrollee.methods[0].vendor);
567		return &wsc_enrollee;
568	}
569
570	if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
571	    os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
572		static struct hostapd_eap_user wsc_registrar;
573		os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
574		wsc_registrar.methods[0].method = eap_server_get_type(
575			"WSC", &wsc_registrar.methods[0].vendor);
576		wsc_registrar.password = (u8 *) conf->ap_pin;
577		wsc_registrar.password_len = conf->ap_pin ?
578			os_strlen(conf->ap_pin) : 0;
579		return &wsc_registrar;
580	}
581#endif /* CONFIG_WPS */
582
583	while (user) {
584		if (!phase2 && user->identity == NULL) {
585			/* Wildcard match */
586			break;
587		}
588
589		if (user->phase2 == !!phase2 && user->wildcard_prefix &&
590		    identity_len >= user->identity_len &&
591		    os_memcmp(user->identity, identity, user->identity_len) ==
592		    0) {
593			/* Wildcard prefix match */
594			break;
595		}
596
597		if (user->phase2 == !!phase2 &&
598		    user->identity_len == identity_len &&
599		    os_memcmp(user->identity, identity, identity_len) == 0)
600			break;
601		user = user->next;
602	}
603
604	return user;
605}
606