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