1 /* 2 * Wi-Fi Protected Setup - device attributes 3 * Copyright (c) 2008, Jouni Malinen <j@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 static int wps_build_manufacturer(struct wps_device_data *dev, 23 struct wpabuf *msg) 24 { 25 size_t len; 26 wpa_printf(MSG_DEBUG, "WPS: * Manufacturer"); 27 wpabuf_put_be16(msg, ATTR_MANUFACTURER); 28 len = dev->manufacturer ? os_strlen(dev->manufacturer) : 0; 29 if (len == 0) { 30 /* 31 * Some deployed WPS implementations fail to parse zero-length 32 * attributes. As a workaround, send a null character if the 33 * device attribute string is empty. 34 */ 35 wpabuf_put_be16(msg, 1); 36 wpabuf_put_u8(msg, '\0'); 37 } else { 38 wpabuf_put_be16(msg, len); 39 wpabuf_put_data(msg, dev->manufacturer, len); 40 } 41 return 0; 42 } 43 44 45 static int wps_build_model_name(struct wps_device_data *dev, 46 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 if (len == 0) { 53 /* 54 * Some deployed WPS implementations fail to parse zero-length 55 * attributes. As a workaround, send a null character if the 56 * device attribute string is empty. 57 */ 58 wpabuf_put_be16(msg, 1); 59 wpabuf_put_u8(msg, '\0'); 60 } else { 61 wpabuf_put_be16(msg, len); 62 wpabuf_put_data(msg, dev->model_name, len); 63 } 64 return 0; 65 } 66 67 68 static int wps_build_model_number(struct wps_device_data *dev, 69 struct wpabuf *msg) 70 { 71 size_t len; 72 wpa_printf(MSG_DEBUG, "WPS: * Model Number"); 73 wpabuf_put_be16(msg, ATTR_MODEL_NUMBER); 74 len = dev->model_number ? os_strlen(dev->model_number) : 0; 75 if (len == 0) { 76 /* 77 * Some deployed WPS implementations fail to parse zero-length 78 * attributes. As a workaround, send a null character if the 79 * device attribute string is empty. 80 */ 81 wpabuf_put_be16(msg, 1); 82 wpabuf_put_u8(msg, '\0'); 83 } else { 84 wpabuf_put_be16(msg, len); 85 wpabuf_put_data(msg, dev->model_number, len); 86 } 87 return 0; 88 } 89 90 91 static int wps_build_serial_number(struct wps_device_data *dev, 92 struct wpabuf *msg) 93 { 94 size_t len; 95 wpa_printf(MSG_DEBUG, "WPS: * Serial Number"); 96 wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER); 97 len = dev->serial_number ? os_strlen(dev->serial_number) : 0; 98 if (len == 0) { 99 /* 100 * Some deployed WPS implementations fail to parse zero-length 101 * attributes. As a workaround, send a null character if the 102 * device attribute string is empty. 103 */ 104 wpabuf_put_be16(msg, 1); 105 wpabuf_put_u8(msg, '\0'); 106 } else { 107 wpabuf_put_be16(msg, len); 108 wpabuf_put_data(msg, dev->serial_number, len); 109 } 110 return 0; 111 } 112 113 114 int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg) 115 { 116 struct wps_dev_type *d; 117 wpa_printf(MSG_DEBUG, "WPS: * Primary Device Type"); 118 wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE); 119 wpabuf_put_be16(msg, sizeof(*d)); 120 d = wpabuf_put(msg, sizeof(*d)); 121 WPA_PUT_BE16(d->categ_id, dev->categ); 122 WPA_PUT_BE32(d->oui, dev->oui); 123 WPA_PUT_BE16(d->sub_categ_id, dev->sub_categ); 124 return 0; 125 } 126 127 128 static int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg) 129 { 130 size_t len; 131 wpa_printf(MSG_DEBUG, "WPS: * Device Name"); 132 wpabuf_put_be16(msg, ATTR_DEV_NAME); 133 len = dev->device_name ? os_strlen(dev->device_name) : 0; 134 if (len == 0) { 135 /* 136 * Some deployed WPS implementations fail to parse zero-length 137 * attributes. As a workaround, send a null character if the 138 * device attribute string is empty. 139 */ 140 wpabuf_put_be16(msg, 1); 141 wpabuf_put_u8(msg, '\0'); 142 } else { 143 wpabuf_put_be16(msg, len); 144 wpabuf_put_data(msg, dev->device_name, len); 145 } 146 return 0; 147 } 148 149 150 int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg) 151 { 152 if (wps_build_manufacturer(dev, msg) || 153 wps_build_model_name(dev, msg) || 154 wps_build_model_number(dev, msg) || 155 wps_build_serial_number(dev, msg) || 156 wps_build_primary_dev_type(dev, msg) || 157 wps_build_dev_name(dev, msg)) 158 return -1; 159 return 0; 160 } 161 162 163 int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg) 164 { 165 wpa_printf(MSG_DEBUG, "WPS: * OS Version"); 166 wpabuf_put_be16(msg, ATTR_OS_VERSION); 167 wpabuf_put_be16(msg, 4); 168 wpabuf_put_be32(msg, 0x80000000 | dev->os_version); 169 return 0; 170 } 171 172 173 int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg) 174 { 175 wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", dev->rf_bands); 176 wpabuf_put_be16(msg, ATTR_RF_BANDS); 177 wpabuf_put_be16(msg, 1); 178 wpabuf_put_u8(msg, dev->rf_bands); 179 return 0; 180 } 181 182 183 static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str, 184 size_t str_len) 185 { 186 if (str == NULL) { 187 wpa_printf(MSG_DEBUG, "WPS: No Manufacturer received"); 188 return -1; 189 } 190 191 wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len); 192 193 os_free(dev->manufacturer); 194 dev->manufacturer = os_malloc(str_len + 1); 195 if (dev->manufacturer == NULL) 196 return -1; 197 os_memcpy(dev->manufacturer, str, str_len); 198 dev->manufacturer[str_len] = '\0'; 199 200 return 0; 201 } 202 203 204 static int wps_process_model_name(struct wps_device_data *dev, const u8 *str, 205 size_t str_len) 206 { 207 if (str == NULL) { 208 wpa_printf(MSG_DEBUG, "WPS: No Model Name received"); 209 return -1; 210 } 211 212 wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len); 213 214 os_free(dev->model_name); 215 dev->model_name = os_malloc(str_len + 1); 216 if (dev->model_name == NULL) 217 return -1; 218 os_memcpy(dev->model_name, str, str_len); 219 dev->model_name[str_len] = '\0'; 220 221 return 0; 222 } 223 224 225 static int wps_process_model_number(struct wps_device_data *dev, const u8 *str, 226 size_t str_len) 227 { 228 if (str == NULL) { 229 wpa_printf(MSG_DEBUG, "WPS: No Model Number received"); 230 return -1; 231 } 232 233 wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len); 234 235 os_free(dev->model_number); 236 dev->model_number = os_malloc(str_len + 1); 237 if (dev->model_number == NULL) 238 return -1; 239 os_memcpy(dev->model_number, str, str_len); 240 dev->model_number[str_len] = '\0'; 241 242 return 0; 243 } 244 245 246 static int wps_process_serial_number(struct wps_device_data *dev, 247 const u8 *str, size_t str_len) 248 { 249 if (str == NULL) { 250 wpa_printf(MSG_DEBUG, "WPS: No Serial Number received"); 251 return -1; 252 } 253 254 wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len); 255 256 os_free(dev->serial_number); 257 dev->serial_number = os_malloc(str_len + 1); 258 if (dev->serial_number == NULL) 259 return -1; 260 os_memcpy(dev->serial_number, str, str_len); 261 dev->serial_number[str_len] = '\0'; 262 263 return 0; 264 } 265 266 267 static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str, 268 size_t str_len) 269 { 270 if (str == NULL) { 271 wpa_printf(MSG_DEBUG, "WPS: No Device Name received"); 272 return -1; 273 } 274 275 wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len); 276 277 os_free(dev->device_name); 278 dev->device_name = os_malloc(str_len + 1); 279 if (dev->device_name == NULL) 280 return -1; 281 os_memcpy(dev->device_name, str, str_len); 282 dev->device_name[str_len] = '\0'; 283 284 return 0; 285 } 286 287 288 static int wps_process_primary_dev_type(struct wps_device_data *dev, 289 const u8 *dev_type) 290 { 291 struct wps_dev_type *d; 292 293 if (dev_type == NULL) { 294 wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received"); 295 return -1; 296 } 297 298 d = (struct wps_dev_type *) dev_type; 299 dev->categ = WPA_GET_BE16(d->categ_id); 300 dev->oui = WPA_GET_BE32(d->oui); 301 dev->sub_categ = WPA_GET_BE16(d->sub_categ_id); 302 303 wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: category %d " 304 "OUI %08x sub-category %d", 305 dev->categ, dev->oui, dev->sub_categ); 306 307 return 0; 308 } 309 310 311 int wps_process_device_attrs(struct wps_device_data *dev, 312 struct wps_parse_attr *attr) 313 { 314 if (wps_process_manufacturer(dev, attr->manufacturer, 315 attr->manufacturer_len) || 316 wps_process_model_name(dev, attr->model_name, 317 attr->model_name_len) || 318 wps_process_model_number(dev, attr->model_number, 319 attr->model_number_len) || 320 wps_process_serial_number(dev, attr->serial_number, 321 attr->serial_number_len) || 322 wps_process_primary_dev_type(dev, attr->primary_dev_type) || 323 wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len)) 324 return -1; 325 return 0; 326 } 327 328 329 int wps_process_os_version(struct wps_device_data *dev, const u8 *ver) 330 { 331 if (ver == NULL) { 332 wpa_printf(MSG_DEBUG, "WPS: No OS Version received"); 333 return -1; 334 } 335 336 dev->os_version = WPA_GET_BE32(ver); 337 wpa_printf(MSG_DEBUG, "WPS: OS Version %08x", dev->os_version); 338 339 return 0; 340 } 341 342 343 int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands) 344 { 345 if (bands == NULL) { 346 wpa_printf(MSG_DEBUG, "WPS: No RF Bands received"); 347 return -1; 348 } 349 350 dev->rf_bands = *bands; 351 wpa_printf(MSG_DEBUG, "WPS: Enrollee RF Bands 0x%x", dev->rf_bands); 352 353 return 0; 354 } 355 356 357 void wps_device_data_dup(struct wps_device_data *dst, 358 const struct wps_device_data *src) 359 { 360 if (src->device_name) 361 dst->device_name = os_strdup(src->device_name); 362 if (src->manufacturer) 363 dst->manufacturer = os_strdup(src->manufacturer); 364 if (src->model_name) 365 dst->model_name = os_strdup(src->model_name); 366 if (src->model_number) 367 dst->model_number = os_strdup(src->model_number); 368 if (src->serial_number) 369 dst->serial_number = os_strdup(src->serial_number); 370 dst->categ = src->categ; 371 dst->oui = src->oui; 372 dst->sub_categ = src->sub_categ; 373 dst->os_version = src->os_version; 374 dst->rf_bands = src->rf_bands; 375 } 376 377 378 void wps_device_data_free(struct wps_device_data *dev) 379 { 380 os_free(dev->device_name); 381 dev->device_name = NULL; 382 os_free(dev->manufacturer); 383 dev->manufacturer = NULL; 384 os_free(dev->model_name); 385 dev->model_name = NULL; 386 os_free(dev->model_number); 387 dev->model_number = NULL; 388 os_free(dev->serial_number); 389 dev->serial_number = NULL; 390 } 391