• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_build_application_ext(struct wps_device_data * dev,struct wpabuf * msg)245  int wps_build_application_ext(struct wps_device_data *dev, struct wpabuf *msg)
246  {
247  	if (!dev->application_ext)
248  		return 0;
249  
250  	wpa_hexdump_buf(MSG_DEBUG, "WPS:  * Application Extension",
251  			dev->application_ext);
252  	wpabuf_put_be16(msg, ATTR_APPLICATION_EXT);
253  	wpabuf_put_be16(msg, wpabuf_len(dev->application_ext));
254  	wpabuf_put_buf(msg, dev->application_ext);
255  
256  	return 0;
257  }
258  
259  
wps_process_manufacturer(struct wps_device_data * dev,const u8 * str,size_t str_len)260  static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str,
261  				    size_t str_len)
262  {
263  	if (str == NULL) {
264  		wpa_printf(MSG_DEBUG, "WPS: No Manufacturer received");
265  		return -1;
266  	}
267  
268  	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len);
269  
270  	os_free(dev->manufacturer);
271  	dev->manufacturer = dup_binstr(str, str_len);
272  	if (dev->manufacturer == NULL)
273  		return -1;
274  
275  	return 0;
276  }
277  
278  
wps_process_model_name(struct wps_device_data * dev,const u8 * str,size_t str_len)279  static int wps_process_model_name(struct wps_device_data *dev, const u8 *str,
280  				  size_t str_len)
281  {
282  	if (str == NULL) {
283  		wpa_printf(MSG_DEBUG, "WPS: No Model Name received");
284  		return -1;
285  	}
286  
287  	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len);
288  
289  	os_free(dev->model_name);
290  	dev->model_name = dup_binstr(str, str_len);
291  	if (dev->model_name == NULL)
292  		return -1;
293  
294  	return 0;
295  }
296  
297  
wps_process_model_number(struct wps_device_data * dev,const u8 * str,size_t str_len)298  static int wps_process_model_number(struct wps_device_data *dev, const u8 *str,
299  				    size_t str_len)
300  {
301  	if (str == NULL) {
302  		wpa_printf(MSG_DEBUG, "WPS: No Model Number received");
303  		return -1;
304  	}
305  
306  	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len);
307  
308  	os_free(dev->model_number);
309  	dev->model_number = dup_binstr(str, str_len);
310  	if (dev->model_number == NULL)
311  		return -1;
312  
313  	return 0;
314  }
315  
316  
wps_process_serial_number(struct wps_device_data * dev,const u8 * str,size_t str_len)317  static int wps_process_serial_number(struct wps_device_data *dev,
318  				     const u8 *str, size_t str_len)
319  {
320  	if (str == NULL) {
321  		wpa_printf(MSG_DEBUG, "WPS: No Serial Number received");
322  		return -1;
323  	}
324  
325  	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len);
326  
327  	os_free(dev->serial_number);
328  	dev->serial_number = dup_binstr(str, str_len);
329  	if (dev->serial_number == NULL)
330  		return -1;
331  
332  	return 0;
333  }
334  
335  
wps_process_dev_name(struct wps_device_data * dev,const u8 * str,size_t str_len)336  static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str,
337  				size_t str_len)
338  {
339  	if (str == NULL) {
340  		wpa_printf(MSG_DEBUG, "WPS: No Device Name received");
341  		return -1;
342  	}
343  
344  	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len);
345  
346  	os_free(dev->device_name);
347  	dev->device_name = dup_binstr(str, str_len);
348  	if (dev->device_name == NULL)
349  		return -1;
350  
351  	return 0;
352  }
353  
354  
wps_process_primary_dev_type(struct wps_device_data * dev,const u8 * dev_type)355  static int wps_process_primary_dev_type(struct wps_device_data *dev,
356  					const u8 *dev_type)
357  {
358  #ifndef CONFIG_NO_STDOUT_DEBUG
359  	char devtype[WPS_DEV_TYPE_BUFSIZE];
360  #endif /* CONFIG_NO_STDOUT_DEBUG */
361  
362  	if (dev_type == NULL) {
363  		wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received");
364  		return -1;
365  	}
366  
367  	os_memcpy(dev->pri_dev_type, dev_type, WPS_DEV_TYPE_LEN);
368  	wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: %s",
369  		   wps_dev_type_bin2str(dev->pri_dev_type, devtype,
370  					sizeof(devtype)));
371  
372  	return 0;
373  }
374  
375  
wps_process_device_attrs(struct wps_device_data * dev,struct wps_parse_attr * attr)376  int wps_process_device_attrs(struct wps_device_data *dev,
377  			     struct wps_parse_attr *attr)
378  {
379  	if (wps_process_manufacturer(dev, attr->manufacturer,
380  				     attr->manufacturer_len) ||
381  	    wps_process_model_name(dev, attr->model_name,
382  				   attr->model_name_len) ||
383  	    wps_process_model_number(dev, attr->model_number,
384  				     attr->model_number_len) ||
385  	    wps_process_serial_number(dev, attr->serial_number,
386  				      attr->serial_number_len) ||
387  	    wps_process_primary_dev_type(dev, attr->primary_dev_type) ||
388  	    wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len))
389  		return -1;
390  	return 0;
391  }
392  
393  
wps_process_os_version(struct wps_device_data * dev,const u8 * ver)394  int wps_process_os_version(struct wps_device_data *dev, const u8 *ver)
395  {
396  	if (ver == NULL) {
397  		wpa_printf(MSG_DEBUG, "WPS: No OS Version received");
398  		return -1;
399  	}
400  
401  	dev->os_version = WPA_GET_BE32(ver);
402  	wpa_printf(MSG_DEBUG, "WPS: OS Version %08x", dev->os_version);
403  
404  	return 0;
405  }
406  
407  
wps_process_vendor_ext_m1(struct wps_device_data * dev,const u8 ext)408  void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext)
409  {
410  	dev->multi_ap_ext = ext;
411  	wpa_printf(MSG_DEBUG, "WPS: Multi-AP extension value %02x",
412  		   dev->multi_ap_ext);
413  }
414  
415  
wps_process_rf_bands(struct wps_device_data * dev,const u8 * bands)416  int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
417  {
418  	if (bands == NULL) {
419  		wpa_printf(MSG_DEBUG, "WPS: No RF Bands received");
420  		return -1;
421  	}
422  
423  	dev->rf_bands = *bands;
424  	wpa_printf(MSG_DEBUG, "WPS: Enrollee RF Bands 0x%x", dev->rf_bands);
425  
426  	return 0;
427  }
428  
429  
wps_device_data_free(struct wps_device_data * dev)430  void wps_device_data_free(struct wps_device_data *dev)
431  {
432  	os_free(dev->device_name);
433  	dev->device_name = NULL;
434  	os_free(dev->manufacturer);
435  	dev->manufacturer = NULL;
436  	os_free(dev->model_name);
437  	dev->model_name = NULL;
438  	os_free(dev->model_number);
439  	dev->model_number = NULL;
440  	os_free(dev->serial_number);
441  	dev->serial_number = NULL;
442  	wpabuf_free(dev->application_ext);
443  	dev->application_ext = NULL;
444  }
445