]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - src/wps/wps_attr_parse.c
hostapd: Support Multi-AP backhaul STA onboarding with WPS
[thirdparty/hostap.git] / src / wps / wps_attr_parse.c
index b04c222194c905129fa122e18616e2a6341928a5..fd51635158ac5c646bf8772e0d83200972e9c595 100644 (file)
@@ -59,6 +59,25 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
                }
                attr->settings_delay_time = pos;
                break;
+       case WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS:
+               if (len != 2) {
+                       wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Configuration Methods length %u",
+                                  len);
+                       return -1;
+               }
+               attr->registrar_configuration_methods = pos;
+               break;
+       case WFA_ELEM_MULTI_AP:
+               if (len != 1) {
+                       wpa_printf(MSG_DEBUG,
+                                  "WPS: Invalid Multi-AP Extension length %u",
+                                  len);
+                       return -1;
+               }
+               attr->multi_ap_ext = *pos;
+               wpa_printf(MSG_DEBUG, "WPS: Multi-AP Extension 0x%02x",
+                          attr->multi_ap_ext);
+               break;
        default:
                wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
                           "Extension subelement %u", id);
@@ -75,10 +94,10 @@ static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
        const u8 *end = pos + len;
        u8 id, elen;
 
-       while (pos + 2 < end) {
+       while (end - pos >= 2) {
                id = *pos++;
                elen = *pos++;
-               if (pos + elen > end)
+               if (elen > end - pos)
                        break;
                if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
                        return -1;
@@ -439,25 +458,55 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
                break;
        case ATTR_MANUFACTURER:
                attr->manufacturer = pos;
-               attr->manufacturer_len = len;
+               if (len > WPS_MANUFACTURER_MAX_LEN)
+                       attr->manufacturer_len = WPS_MANUFACTURER_MAX_LEN;
+               else
+                       attr->manufacturer_len = len;
                break;
        case ATTR_MODEL_NAME:
                attr->model_name = pos;
-               attr->model_name_len = len;
+               if (len > WPS_MODEL_NAME_MAX_LEN)
+                       attr->model_name_len = WPS_MODEL_NAME_MAX_LEN;
+               else
+                       attr->model_name_len = len;
                break;
        case ATTR_MODEL_NUMBER:
                attr->model_number = pos;
-               attr->model_number_len = len;
+               if (len > WPS_MODEL_NUMBER_MAX_LEN)
+                       attr->model_number_len = WPS_MODEL_NUMBER_MAX_LEN;
+               else
+                       attr->model_number_len = len;
                break;
        case ATTR_SERIAL_NUMBER:
                attr->serial_number = pos;
-               attr->serial_number_len = len;
+               if (len > WPS_SERIAL_NUMBER_MAX_LEN)
+                       attr->serial_number_len = WPS_SERIAL_NUMBER_MAX_LEN;
+               else
+                       attr->serial_number_len = len;
                break;
        case ATTR_DEV_NAME:
+               if (len > WPS_DEV_NAME_MAX_LEN) {
+                       wpa_printf(MSG_DEBUG,
+                                  "WPS: Ignore too long Device Name (len=%u)",
+                                  len);
+                       break;
+               }
                attr->dev_name = pos;
                attr->dev_name_len = len;
                break;
        case ATTR_PUBLIC_KEY:
+               /*
+                * The Public Key attribute is supposed to be exactly 192 bytes
+                * in length. Allow couple of bytes shorter one to try to
+                * interoperate with implementations that do not use proper
+                * zero-padding.
+                */
+               if (len < 190 || len > 192) {
+                       wpa_printf(MSG_DEBUG,
+                                  "WPS: Ignore Public Key with unexpected length %u",
+                                  len);
+                       break;
+               }
                attr->public_key = pos;
                attr->public_key_len = len;
                break;
@@ -477,6 +526,11 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
                attr->num_cred++;
                break;
        case ATTR_SSID:
+               if (len > SSID_MAX_LEN) {
+                       wpa_printf(MSG_DEBUG,
+                                  "WPS: Ignore too long SSID (len=%u)", len);
+                       break;
+               }
                attr->ssid = pos;
                attr->ssid_len = len;
                break;