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