1 /*
2  * hostapd - Management frame fuzzer
3  * Copyright (c) 2015-2019, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "ap/hostapd.h"
14 #include "ap/hw_features.h"
15 #include "ap/ieee802_11.h"
16 #include "ap/sta_info.h"
17 #include "ap/ap_list.h"
18 #include "../fuzzer-common.h"
19 
20 
21 const struct wpa_driver_ops *const wpa_drivers[] =
22 {
23 	NULL
24 };
25 
26 
27 struct arg_ctx {
28 	const u8 *data;
29 	size_t data_len;
30 	struct hostapd_iface iface;
31 	struct hostapd_data hapd;
32 	struct wpa_driver_ops driver;
33 	struct hostapd_config iconf;
34 	struct hostapd_bss_config conf;
35 };
36 
37 
test_send_mgmt(void * eloop_data,void * user_ctx)38 static void test_send_mgmt(void *eloop_data, void *user_ctx)
39 {
40 	struct arg_ctx *ctx = eloop_data;
41 	struct hostapd_frame_info fi;
42 	const u8 *pos, *end;
43 
44 	os_memset(&fi, 0, sizeof(fi));
45 
46 	pos = ctx->data;
47 	end = pos + ctx->data_len;
48 
49 	while (end - pos > 2) {
50 		u16 flen;
51 
52 		flen = WPA_GET_BE16(pos);
53 		pos += 2;
54 		if (end - pos < flen)
55 			break;
56 		wpa_hexdump(MSG_MSGDUMP, "fuzzer - frame", pos, flen);
57 		ieee802_11_mgmt(&ctx->hapd, pos, flen, &fi);
58 		pos += flen;
59 	}
60 
61 	eloop_terminate();
62 }
63 
64 
gen_modes(void)65 static struct hostapd_hw_modes * gen_modes(void)
66 {
67 	struct hostapd_hw_modes *mode;
68 	struct hostapd_channel_data *chan;
69 
70 	mode = os_zalloc(sizeof(struct hostapd_hw_modes));
71 	if (!mode)
72 		return NULL;
73 
74 	mode->mode = HOSTAPD_MODE_IEEE80211G;
75 	chan = os_zalloc(sizeof(struct hostapd_channel_data));
76 	if (!chan) {
77 		os_free(mode);
78 		return NULL;
79 	}
80 	chan->chan = 1;
81 	chan->freq = 2412;
82 	mode->channels = chan;
83 	mode->num_channels = 1;
84 
85 	mode->rates = os_zalloc(sizeof(int));
86 	if (!mode->rates) {
87 		os_free(chan);
88 		os_free(mode);
89 		return NULL;
90 	}
91 	mode->rates[0] = 10;
92 	mode->num_rates = 1;
93 
94 	return mode;
95 }
96 
97 
init_hapd(struct arg_ctx * ctx)98 static int init_hapd(struct arg_ctx *ctx)
99 {
100 	struct hostapd_data *hapd = &ctx->hapd;
101 	struct sta_info *sta;
102 	struct hostapd_bss_config *bss;
103 
104 	hapd->driver = &ctx->driver;
105 	os_memcpy(hapd->own_addr, "\x02\x00\x00\x00\x03\x00", ETH_ALEN);
106 	hapd->iface = &ctx->iface;
107 	hapd->iface->conf = hostapd_config_defaults();
108 	if (!hapd->iface->conf)
109 		return -1;
110 	hapd->iface->hw_features = gen_modes();
111 	hapd->iface->num_hw_features = 1;
112 	hapd->iface->current_mode = hapd->iface->hw_features;
113 	hapd->iconf = hapd->iface->conf;
114 	hapd->iconf->hw_mode = HOSTAPD_MODE_IEEE80211G;
115 	hapd->iconf->channel = 1;
116 	bss = hapd->conf = hapd->iconf->bss[0];
117 	hostapd_config_defaults_bss(hapd->conf);
118 	os_memcpy(bss->ssid.ssid, "test", 4);
119 	bss->ssid.ssid_len = 4;
120 	bss->ssid.ssid_set = 1;
121 
122 	sta = ap_sta_add(hapd, (u8 *) "\x02\x00\x00\x00\x00\x00");
123 	if (sta)
124 		sta->flags |= WLAN_STA_ASSOC | WLAN_STA_WMM;
125 
126 	return 0;
127 }
128 
129 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)130 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
131 {
132 	struct arg_ctx ctx;
133 
134 	wpa_fuzzer_set_debug_level();
135 
136 	if (os_program_init())
137 		return 0;
138 
139 	if (eloop_init()) {
140 		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
141 		return 0;
142 	}
143 
144 	os_memset(&ctx, 0, sizeof(ctx));
145 	ctx.data = data;
146 	ctx.data_len = size;
147 
148 	if (init_hapd(&ctx))
149 		goto fail;
150 
151 	eloop_register_timeout(0, 0, test_send_mgmt, &ctx, NULL);
152 
153 	wpa_printf(MSG_DEBUG, "Starting eloop");
154 	eloop_run();
155 	wpa_printf(MSG_DEBUG, "eloop done");
156 	hostapd_free_stas(&ctx.hapd);
157 	hostapd_free_hw_features(ctx.hapd.iface->hw_features,
158 				 ctx.hapd.iface->num_hw_features);
159 
160 fail:
161 	hostapd_config_free(ctx.hapd.iconf);
162 	ap_list_deinit(&ctx.iface);
163 	eloop_destroy();
164 	os_program_deinit();
165 
166 	return 0;
167 }
168