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