Branch data Line data Source code
1 : : /*
2 : : * Wi-Fi Protected Setup - device attributes
3 : : * Copyright (c) 2008, 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 "includes.h"
10 : :
11 : : #include "common.h"
12 : : #include "wps_i.h"
13 : : #include "wps_dev_attr.h"
14 : :
15 : :
16 : 2174 : int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg)
17 : : {
18 : : size_t len;
19 : 2174 : wpa_printf(MSG_DEBUG, "WPS: * Manufacturer");
20 : 2174 : wpabuf_put_be16(msg, ATTR_MANUFACTURER);
21 [ + + ]: 2174 : len = dev->manufacturer ? os_strlen(dev->manufacturer) : 0;
22 : : #ifndef CONFIG_WPS_STRICT
23 [ + + ]: 2174 : if (len == 0) {
24 : : /*
25 : : * Some deployed WPS implementations fail to parse zero-length
26 : : * attributes. As a workaround, send a space character if the
27 : : * device attribute string is empty.
28 : : */
29 : 2091 : wpabuf_put_be16(msg, 1);
30 : 2091 : wpabuf_put_u8(msg, ' ');
31 : 2091 : return 0;
32 : : }
33 : : #endif /* CONFIG_WPS_STRICT */
34 : 83 : wpabuf_put_be16(msg, len);
35 : 83 : wpabuf_put_data(msg, dev->manufacturer, len);
36 : 2174 : return 0;
37 : : }
38 : :
39 : :
40 : 2174 : int wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg)
41 : : {
42 : : size_t len;
43 : 2174 : wpa_printf(MSG_DEBUG, "WPS: * Model Name");
44 : 2174 : wpabuf_put_be16(msg, ATTR_MODEL_NAME);
45 [ + + ]: 2174 : len = dev->model_name ? os_strlen(dev->model_name) : 0;
46 : : #ifndef CONFIG_WPS_STRICT
47 [ + + ]: 2174 : if (len == 0) {
48 : : /*
49 : : * Some deployed WPS implementations fail to parse zero-length
50 : : * attributes. As a workaround, send a space character if the
51 : : * device attribute string is empty.
52 : : */
53 : 2091 : wpabuf_put_be16(msg, 1);
54 : 2091 : wpabuf_put_u8(msg, ' ');
55 : 2091 : return 0;
56 : : }
57 : : #endif /* CONFIG_WPS_STRICT */
58 : 83 : wpabuf_put_be16(msg, len);
59 : 83 : wpabuf_put_data(msg, dev->model_name, len);
60 : 2174 : return 0;
61 : : }
62 : :
63 : :
64 : 2174 : int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg)
65 : : {
66 : : size_t len;
67 : 2174 : wpa_printf(MSG_DEBUG, "WPS: * Model Number");
68 : 2174 : wpabuf_put_be16(msg, ATTR_MODEL_NUMBER);
69 [ + + ]: 2174 : len = dev->model_number ? os_strlen(dev->model_number) : 0;
70 : : #ifndef CONFIG_WPS_STRICT
71 [ + + ]: 2174 : if (len == 0) {
72 : : /*
73 : : * Some deployed WPS implementations fail to parse zero-length
74 : : * attributes. As a workaround, send a space character if the
75 : : * device attribute string is empty.
76 : : */
77 : 2091 : wpabuf_put_be16(msg, 1);
78 : 2091 : wpabuf_put_u8(msg, ' ');
79 : 2091 : return 0;
80 : : }
81 : : #endif /* CONFIG_WPS_STRICT */
82 : 83 : wpabuf_put_be16(msg, len);
83 : 83 : wpabuf_put_data(msg, dev->model_number, len);
84 : 2174 : return 0;
85 : : }
86 : :
87 : :
88 : 819 : int wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg)
89 : : {
90 : : size_t len;
91 : 819 : wpa_printf(MSG_DEBUG, "WPS: * Serial Number");
92 : 819 : wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER);
93 [ + + ]: 819 : len = dev->serial_number ? os_strlen(dev->serial_number) : 0;
94 : : #ifndef CONFIG_WPS_STRICT
95 [ + + ]: 819 : if (len == 0) {
96 : : /*
97 : : * Some deployed WPS implementations fail to parse zero-length
98 : : * attributes. As a workaround, send a space character if the
99 : : * device attribute string is empty.
100 : : */
101 : 736 : wpabuf_put_be16(msg, 1);
102 : 736 : wpabuf_put_u8(msg, ' ');
103 : 736 : return 0;
104 : : }
105 : : #endif /* CONFIG_WPS_STRICT */
106 : 83 : wpabuf_put_be16(msg, len);
107 : 83 : wpabuf_put_data(msg, dev->serial_number, len);
108 : 819 : return 0;
109 : : }
110 : :
111 : :
112 : 2477 : int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg)
113 : : {
114 : 2477 : wpa_printf(MSG_DEBUG, "WPS: * Primary Device Type");
115 : 2477 : wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE);
116 : 2477 : wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN);
117 : 2477 : wpabuf_put_data(msg, dev->pri_dev_type, WPS_DEV_TYPE_LEN);
118 : 2477 : return 0;
119 : : }
120 : :
121 : :
122 : 1355 : int wps_build_secondary_dev_type(struct wps_device_data *dev,
123 : : struct wpabuf *msg)
124 : : {
125 [ + + ]: 1355 : if (!dev->num_sec_dev_types)
126 : 1311 : return 0;
127 : :
128 : 44 : wpa_printf(MSG_DEBUG, "WPS: * Secondary Device Type");
129 : 44 : wpabuf_put_be16(msg, ATTR_SECONDARY_DEV_TYPE_LIST);
130 : 44 : wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN * dev->num_sec_dev_types);
131 : 44 : wpabuf_put_data(msg, dev->sec_dev_type,
132 : 44 : WPS_DEV_TYPE_LEN * dev->num_sec_dev_types);
133 : :
134 : 1355 : return 0;
135 : : }
136 : :
137 : :
138 : 1355 : int wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg,
139 : : unsigned int num_req_dev_types,
140 : : const u8 *req_dev_types)
141 : : {
142 : : unsigned int i;
143 : :
144 [ + + ]: 1363 : for (i = 0; i < num_req_dev_types; i++) {
145 : 8 : wpa_hexdump(MSG_DEBUG, "WPS: * Requested Device Type",
146 : 8 : req_dev_types + i * WPS_DEV_TYPE_LEN,
147 : : WPS_DEV_TYPE_LEN);
148 : 8 : wpabuf_put_be16(msg, ATTR_REQUESTED_DEV_TYPE);
149 : 8 : wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN);
150 : 8 : wpabuf_put_data(msg, req_dev_types + i * WPS_DEV_TYPE_LEN,
151 : : WPS_DEV_TYPE_LEN);
152 : : }
153 : :
154 : 1355 : return 0;
155 : : }
156 : :
157 : :
158 : 2477 : int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg)
159 : : {
160 : : size_t len;
161 : 2477 : wpa_printf(MSG_DEBUG, "WPS: * Device Name");
162 : 2477 : wpabuf_put_be16(msg, ATTR_DEV_NAME);
163 [ + + ]: 2477 : len = dev->device_name ? os_strlen(dev->device_name) : 0;
164 : : #ifndef CONFIG_WPS_STRICT
165 [ + + ]: 2477 : if (len == 0) {
166 : : /*
167 : : * Some deployed WPS implementations fail to parse zero-length
168 : : * attributes. As a workaround, send a space character if the
169 : : * device attribute string is empty.
170 : : */
171 : 238 : wpabuf_put_be16(msg, 1);
172 : 238 : wpabuf_put_u8(msg, ' ');
173 : 238 : return 0;
174 : : }
175 : : #endif /* CONFIG_WPS_STRICT */
176 : 2239 : wpabuf_put_be16(msg, len);
177 : 2239 : wpabuf_put_data(msg, dev->device_name, len);
178 : 2477 : return 0;
179 : : }
180 : :
181 : :
182 : 799 : int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg)
183 : : {
184 [ + - + - ]: 1598 : if (wps_build_manufacturer(dev, msg) ||
185 [ + - ]: 1598 : wps_build_model_name(dev, msg) ||
186 [ + - ]: 1598 : wps_build_model_number(dev, msg) ||
187 [ + - ]: 1598 : wps_build_serial_number(dev, msg) ||
188 [ - + ]: 1598 : wps_build_primary_dev_type(dev, msg) ||
189 : 799 : wps_build_dev_name(dev, msg))
190 : 0 : return -1;
191 : 799 : return 0;
192 : : }
193 : :
194 : :
195 : 310 : int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg)
196 : : {
197 : 310 : wpa_printf(MSG_DEBUG, "WPS: * OS Version");
198 : 310 : wpabuf_put_be16(msg, ATTR_OS_VERSION);
199 : 310 : wpabuf_put_be16(msg, 4);
200 : 310 : wpabuf_put_be32(msg, 0x80000000 | dev->os_version);
201 : 310 : return 0;
202 : : }
203 : :
204 : :
205 : 156 : int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg)
206 : : {
207 [ + + ]: 156 : if (dev->vendor_ext_m1 != NULL) {
208 : 12 : wpa_hexdump(MSG_DEBUG, "WPS: * Vendor Extension M1",
209 : 6 : wpabuf_head_u8(dev->vendor_ext_m1),
210 : 6 : wpabuf_len(dev->vendor_ext_m1));
211 : 6 : wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
212 : 6 : wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext_m1));
213 : 6 : wpabuf_put_buf(msg, dev->vendor_ext_m1);
214 : : }
215 : 156 : return 0;
216 : : }
217 : :
218 : :
219 : 1707 : int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg,
220 : : u8 rf_band)
221 : : {
222 [ + + ]: 1707 : return wps_build_rf_bands_attr(msg, rf_band ? rf_band : dev->rf_bands);
223 : : }
224 : :
225 : :
226 : 978 : int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg)
227 : : {
228 : : int i;
229 : :
230 [ + + ]: 10758 : for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
231 [ + - ]: 9780 : if (dev->vendor_ext[i] == NULL)
232 : 9780 : continue;
233 : 0 : wpa_hexdump(MSG_DEBUG, "WPS: * Vendor Extension",
234 : 0 : wpabuf_head_u8(dev->vendor_ext[i]),
235 : 0 : wpabuf_len(dev->vendor_ext[i]));
236 : 0 : wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
237 : 0 : wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext[i]));
238 : 0 : wpabuf_put_buf(msg, dev->vendor_ext[i]);
239 : : }
240 : :
241 : 978 : return 0;
242 : : }
243 : :
244 : :
245 : 287 : static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str,
246 : : size_t str_len)
247 : : {
248 [ - + ]: 287 : if (str == NULL) {
249 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Manufacturer received");
250 : 0 : return -1;
251 : : }
252 : :
253 : 287 : wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len);
254 : :
255 : 287 : os_free(dev->manufacturer);
256 : 287 : dev->manufacturer = dup_binstr(str, str_len);
257 [ - + ]: 287 : if (dev->manufacturer == NULL)
258 : 0 : return -1;
259 : :
260 : 287 : return 0;
261 : : }
262 : :
263 : :
264 : 287 : static int wps_process_model_name(struct wps_device_data *dev, const u8 *str,
265 : : size_t str_len)
266 : : {
267 [ - + ]: 287 : if (str == NULL) {
268 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Model Name received");
269 : 0 : return -1;
270 : : }
271 : :
272 : 287 : wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len);
273 : :
274 : 287 : os_free(dev->model_name);
275 : 287 : dev->model_name = dup_binstr(str, str_len);
276 [ - + ]: 287 : if (dev->model_name == NULL)
277 : 0 : return -1;
278 : :
279 : 287 : return 0;
280 : : }
281 : :
282 : :
283 : 287 : static int wps_process_model_number(struct wps_device_data *dev, const u8 *str,
284 : : size_t str_len)
285 : : {
286 [ - + ]: 287 : if (str == NULL) {
287 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Model Number received");
288 : 0 : return -1;
289 : : }
290 : :
291 : 287 : wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len);
292 : :
293 : 287 : os_free(dev->model_number);
294 : 287 : dev->model_number = dup_binstr(str, str_len);
295 [ - + ]: 287 : if (dev->model_number == NULL)
296 : 0 : return -1;
297 : :
298 : 287 : return 0;
299 : : }
300 : :
301 : :
302 : 287 : static int wps_process_serial_number(struct wps_device_data *dev,
303 : : const u8 *str, size_t str_len)
304 : : {
305 [ - + ]: 287 : if (str == NULL) {
306 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Serial Number received");
307 : 0 : return -1;
308 : : }
309 : :
310 : 287 : wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len);
311 : :
312 : 287 : os_free(dev->serial_number);
313 : 287 : dev->serial_number = dup_binstr(str, str_len);
314 [ - + ]: 287 : if (dev->serial_number == NULL)
315 : 0 : return -1;
316 : :
317 : 287 : return 0;
318 : : }
319 : :
320 : :
321 : 287 : static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str,
322 : : size_t str_len)
323 : : {
324 [ - + ]: 287 : if (str == NULL) {
325 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Device Name received");
326 : 0 : return -1;
327 : : }
328 : :
329 : 287 : wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len);
330 : :
331 : 287 : os_free(dev->device_name);
332 : 287 : dev->device_name = dup_binstr(str, str_len);
333 [ - + ]: 287 : if (dev->device_name == NULL)
334 : 0 : return -1;
335 : :
336 : 287 : return 0;
337 : : }
338 : :
339 : :
340 : 287 : static int wps_process_primary_dev_type(struct wps_device_data *dev,
341 : : const u8 *dev_type)
342 : : {
343 : : #ifndef CONFIG_NO_STDOUT_DEBUG
344 : : char devtype[WPS_DEV_TYPE_BUFSIZE];
345 : : #endif /* CONFIG_NO_STDOUT_DEBUG */
346 : :
347 [ - + ]: 287 : if (dev_type == NULL) {
348 : 0 : wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received");
349 : 0 : return -1;
350 : : }
351 : :
352 : 287 : os_memcpy(dev->pri_dev_type, dev_type, WPS_DEV_TYPE_LEN);
353 : 287 : wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: %s",
354 : 287 : wps_dev_type_bin2str(dev->pri_dev_type, devtype,
355 : : sizeof(devtype)));
356 : :
357 : 287 : return 0;
358 : : }
359 : :
360 : :
361 : 287 : int wps_process_device_attrs(struct wps_device_data *dev,
362 : : struct wps_parse_attr *attr)
363 : : {
364 [ + - ]: 287 : if (wps_process_manufacturer(dev, attr->manufacturer,
365 [ + - ]: 287 : attr->manufacturer_len) ||
366 : 287 : wps_process_model_name(dev, attr->model_name,
367 [ + - ]: 287 : attr->model_name_len) ||
368 : 287 : wps_process_model_number(dev, attr->model_number,
369 [ + - ]: 287 : attr->model_number_len) ||
370 : 287 : wps_process_serial_number(dev, attr->serial_number,
371 [ + - ]: 287 : attr->serial_number_len) ||
372 [ - + ]: 574 : wps_process_primary_dev_type(dev, attr->primary_dev_type) ||
373 : 287 : wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len))
374 : 0 : return -1;
375 : 287 : return 0;
376 : : }
377 : :
378 : :
379 : 154 : int wps_process_os_version(struct wps_device_data *dev, const u8 *ver)
380 : : {
381 [ - + ]: 154 : if (ver == NULL) {
382 : 0 : wpa_printf(MSG_DEBUG, "WPS: No OS Version received");
383 : 0 : return -1;
384 : : }
385 : :
386 : 154 : dev->os_version = WPA_GET_BE32(ver);
387 : 154 : wpa_printf(MSG_DEBUG, "WPS: OS Version %08x", dev->os_version);
388 : :
389 : 154 : return 0;
390 : : }
391 : :
392 : :
393 : 154 : int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
394 : : {
395 [ - + ]: 154 : if (bands == NULL) {
396 : 0 : wpa_printf(MSG_DEBUG, "WPS: No RF Bands received");
397 : 0 : return -1;
398 : : }
399 : :
400 : 154 : dev->rf_bands = *bands;
401 : 154 : wpa_printf(MSG_DEBUG, "WPS: Enrollee RF Bands 0x%x", dev->rf_bands);
402 : :
403 : 154 : return 0;
404 : : }
405 : :
406 : :
407 : 571 : void wps_device_data_free(struct wps_device_data *dev)
408 : : {
409 : 571 : os_free(dev->device_name);
410 : 571 : dev->device_name = NULL;
411 : 571 : os_free(dev->manufacturer);
412 : 571 : dev->manufacturer = NULL;
413 : 571 : os_free(dev->model_name);
414 : 571 : dev->model_name = NULL;
415 : 571 : os_free(dev->model_number);
416 : 571 : dev->model_number = NULL;
417 : 571 : os_free(dev->serial_number);
418 : 571 : dev->serial_number = NULL;
419 : 571 : }
|