diff --git a/src/cmdu_validate.c b/src/cmdu_validate.c index db88f3d5342268bdf7b5188014a97befb769bca9..13ba37367fe6e3fb814109f028f15f2d19dde9ae 100644 --- a/src/cmdu_validate.c +++ b/src/cmdu_validate.c @@ -208,7 +208,7 @@ static int validate_wsc_m2(uint8_t *m2, uint16_t m2_size) { uint8_t *data; uint8_t *m2_end; - bool ret = false; + bool ret = -1; if (!m2 || !m2_size) return -1; @@ -227,17 +227,17 @@ static int validate_wsc_m2(uint8_t *m2, uint16_t m2_size) if (data + attr_len > m2_end) { dbg("%s: parse_wsc_m2 failed\n", __func__); - ret = false; + ret = -1; break; } if (attr_type == ATTR_MSG_TYPE) { if (attr_len != 1) { - ret = false; + ret = -1; break; } if (*data == MSG_TYPE_M2) - ret = true; + ret = 0; } data += attr_len; @@ -247,6 +247,304 @@ static int validate_wsc_m2(uint8_t *m2, uint16_t m2_size) return ret; } +/* Check WSC TLV (containing M2) */ +static int check_wsc_tlv(struct tlv *t) +{ + uint8_t *tv_data; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + if (!tlv_len) + return -1; + + tv_data = (uint8_t *)t->data; + if (!tv_data) + return -1; + + return validate_wsc_m2(tv_data, tlv_len); +} + +/* Check 1905.1 AL MAC address type TLV */ +static int check_al_mac_addr_type_tlv(struct tlv *t) +{ + uint8_t *tv_data; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + + /* macaddr (6 bytes) */ + if (tlv_len != 6) + return -1; + + tv_data = (uint8_t *)t->data; + if (!tv_data) + return -1; + + return 0; +} + +/* Check AP Radio Indentifier TLV */ +static int check_ap_radio_dentifier_tlv(struct tlv *t) +{ + uint8_t *tv_data; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + + /* bssid (6 bytes) */ + if (tlv_len != 6) + return -1; + + tv_data = (uint8_t *)t->data; + if (!tv_data) + return -1; + + return 0; +} + +/* Check Default 802.1Q Settings TLV */ +static int check_default_11q_settings_tlv(struct tlv *t) +{ + struct tlv_default_8021q_settings *tlv; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + + /* pvid + pcp (3 bytes) */ + if (tlv_len != sizeof(struct tlv_default_8021q_settings)) + return -1; + + tlv = (struct tlv_default_8021q_settings *)t->data; + if (!tlv) + return -1; + + return 0; +} + +/* Check SupportedFreqBand TLV */ +static int check_supported_band_tlv(struct tlv *t) +{ + struct tlv_supported_band *tlv; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + + /* band (1 byte) */ + if (tlv_len != sizeof(struct tlv_supported_band)) + return -1; + + tlv = (struct tlv_supported_band *)t->data; + if (!tlv) + return -1; + + return 0; +} + +/* Check SupportedRole TLV */ +static int check_supported_role_tlv(struct tlv *t) +{ + struct tlv_supported_role *tlv; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + + /* role (1 byte) */ + if (tlv_len != sizeof(struct tlv_supported_role)) + return -1; + + tlv = (struct tlv_supported_role *)t->data; + if (!tlv) + return -1; + + return 0; +} + +/* Check MultiAP Profile TLV */ +static int check_map_profile_tlv(struct tlv *t) +{ + struct tlv_map_profile *tlv; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + + /* profile (1 byte) */ + if (tlv_len != sizeof(struct tlv_map_profile)) + return -1; + + tlv = (struct tlv_map_profile *)t->data; + if (!tlv) + return -1; + + return 0; +} + +/* Check SearchedRole TLV */ +static int check_searched_role_tlv(struct tlv *t) +{ + struct tlv_searched_role *tlv; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + + /* role (1 byte) */ + if (tlv_len != sizeof(struct tlv_searched_role)) + return -1; + + tlv = (struct tlv_searched_role *)t->data; + if (!tlv) + return -1; + + return 0; +} + +/* Check AutoconfigFreqBand TLV */ +static int check_autoconfig_freq_band_tlv(struct tlv *t) +{ + struct tlv_autoconfig_band *tlv; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + + /* band (1 byte) */ + if (tlv_len != sizeof(struct tlv_autoconfig_band)) + return -1; + + tlv = (struct tlv_autoconfig_band *)t->data; + if (!tlv) + return -1; + + return 0; +} + +/* Check Traffic Separation Policy TLV */ +static int check_traffic_separation_policy_tlv(struct tlv *t) +{ + int i, offset = 0; + uint8_t num_ssid; + uint8_t *tv_data; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + /* at least 1 byte: num_ssid */ + if (tlv_len < 1) + return -1; + + tv_data = (uint8_t *)t->data; + if (!tv_data) + return -1; + + num_ssid = tv_data[offset++]; + + for (i = 0; i < num_ssid; i++) { + int ssid_len; + + /* ssid_len (1 byte) */ + if (offset + 1 > tlv_len) + return -1; + ssid_len = tv_data[offset++]; + + /* ssid (ssid_len bytes) */ + if (offset + ssid_len > tlv_len) + return -1; + offset += ssid_len; + + /* vid (2 bytes) */ + if (offset + 2 > tlv_len) + return -1; + offset += 2; + } + + return 0; +} + +/* Check SupportedService TLV */ +static int check_supported_service_tlv(struct tlv *t) +{ + int offset = 0; + uint8_t num_services; + uint8_t *tv_data; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + /* at least 1 byte: num_services */ + if (tlv_len < 1) + return -1; + + tv_data = (uint8_t *)t->data; + if (!tv_data) + return -1; + + num_services = tv_data[offset++]; + + /* services (num_services bytes) */ + if (offset + num_services > tlv_len) + return -1; + + return 0; +} + +/* Check SearchedService TLV */ +static int check_searched_service_tlv(struct tlv *t) +{ + int offset = 0; + uint8_t num_services; + uint8_t *tv_data; + uint16_t tlv_len; + + if (!t) + return -1; + + tlv_len = tlv_length(t); + /* at least 1 byte: num_services */ + if (tlv_len < 1) + return -1; + + tv_data = (uint8_t *)t->data; + if (!tv_data) + return -1; + + num_services = tv_data[offset++]; + + /* services (num_services bytes) */ + if (offset + num_services > tlv_len) + return -1; + + return 0; +} + bool validate_ap_autoconfig_wsc(struct cmdu_buff *cmdu, struct tlv *tv[][16]) { struct tlv_policy a_policy[] = { @@ -285,90 +583,21 @@ bool validate_ap_autoconfig_wsc(struct cmdu_buff *cmdu, struct tlv *tv[][16]) } /* Parse Default 802.1Q Settings TLV */ - if (tv[0][0]) { - struct tlv_default_8021q_settings *tlv; - uint16_t tlv_len = tlv_length(tv[0][0]); - - if (tlv_len != sizeof(struct tlv_default_8021q_settings)) - return false; - - tlv = (struct tlv_default_8021q_settings *)tv[0][0]->data; - if (!tlv) - return false; - } + if (check_default_11q_settings_tlv(tv[0][0])) + return false; /* Parse Traffic Separation Policy TLV */ - if (tv[1][0]) { - int i, offset = 0; - uint8_t *tv_data; - uint8_t num_ssid; - uint16_t tlv_len = tlv_length(tv[1][0]); - - if (!tlv_len) - return false; - - tv_data = (uint8_t *)tv[1][0]->data; - if (!tv_data) - return false; - - /* num_ssid (1 byte) */ - if (offset + 1 > tlv_len) - return false; - - num_ssid = tv_data[offset++]; - - for (i = 0; i < num_ssid; i++) { - int ssid_len; - - /* ssid_len (1 byte) */ - if (offset + 1 > tlv_len) - return false; - - ssid_len = tv_data[offset++]; - - /* ssid (ssid_len bytes) */ - if (offset + ssid_len > tlv_len) - return false; - - offset += ssid_len; - - /* vid (2 bytes) */ - if (offset + 2 > tlv_len) - return false; - - offset += 2; - } - } + if (check_traffic_separation_policy_tlv(tv[1][0])) + return false; /* Parse AP Radio Identifier TLV */ - if (tv[2][0]) { - uint8_t *tv_data; - uint16_t tlv_len = tlv_length(tv[2][0]); - - /* bssid (6 bytes) */ - if (tlv_len != 6) - return false; - - tv_data = (uint8_t *) tv[2][0]->data; - if (!tv_data) - return false; - } + if (check_ap_radio_dentifier_tlv(tv[2][0])) + return false; /* Parse WSC TLVs (containing M2) */ while (tv[3][num]) { - uint8_t *tv_data; - uint16_t tlv_len = tlv_length(tv[3][num]); - - if (!tlv_len) + if (check_wsc_tlv(tv[3][num])) return false; - - tv_data = (uint8_t *) tv[3][num]->data; - if (!tv_data) - return false; - - if (!validate_wsc_m2(tv_data, tlv_len)) - return false; - num++; } @@ -424,114 +653,28 @@ bool validate_ap_autoconfig_search(struct cmdu_buff *cmdu, struct tlv *tv[][16]) } /* Parse 1905.1 AL MAC address type TLV */ - if (tv[0][0]) { - uint8_t *tv_data; - uint16_t tlv_len = tlv_length(tv[0][0]); - - /* macaddr (6 bytes) */ - if (tlv_len != 6) - return false; - - tv_data = (uint8_t *) tv[0][0]->data; - if (!tv_data) - return false; - } + if (check_al_mac_addr_type_tlv(tv[0][0])) + return false; /* Parse SearchedRole TLV */ - if (tv[1][0]) { - struct tlv_searched_role *tlv; - uint16_t tlv_len = tlv_length(tv[1][0]); - - /* role (1 byte) */ - if (tlv_len != sizeof(struct tlv_searched_role)) - return false; - - tlv = (struct tlv_searched_role *)tv[1][0]->data; - if (!tlv) - return false; - } + if (check_searched_role_tlv(tv[1][0])) + return false; /* Parse AutoconfigFreqBand TLV */ - if (tv[2][0]) { - struct tlv_autoconfig_band *tlv; - uint16_t tlv_len = tlv_length(tv[2][0]); - - /* band (1 byte) */ - if (tlv_len != sizeof(struct tlv_autoconfig_band)) - return false; - - tlv = (struct tlv_autoconfig_band *)tv[2][0]->data; - if (!tlv) - return false; - } + if (check_autoconfig_freq_band_tlv(tv[2][0])) + return false; /* Parse SupportedService TLV */ - if (tv[3][0]) { - uint8_t *tv_data; - uint8_t num_services; - int offset = 0; - uint16_t tlv_len = tlv_length(tv[3][0]); - - if (tlv_len < 1) - return false; - - tv_data = (uint8_t *) tv[3][0]->data; - if (!tv_data) - return false; - - /* num_services (1 byte) */ - if (offset + 1 > tlv_len) - return false; - - num_services = tv_data[offset]; - - offset += 1; - - /* services (num_services bytes) */ - if (offset + num_services > tlv_len) - return false; - } + if (check_supported_service_tlv(tv[3][0])) + return false; /* Parse SearchedService TLV */ - if (tv[4][0]) { - uint8_t *tv_data; - uint8_t num_services; - int offset = 0; - uint16_t tlv_len = tlv_length(tv[4][0]); - - if (tlv_len < 1) - return false; - - tv_data = (uint8_t *) tv[4][0]->data; - if (!tv_data) - return false; - - /* num_services (1 byte) */ - if (offset + 1 > tlv_len) - return false; - - num_services = tv_data[offset]; - - offset += 1; - - /* services (num_services bytes) */ - if (offset + num_services > tlv_len) - return false; - } + if (check_searched_service_tlv(tv[4][0])) + return false; /* Parse MultiAP Profile TLV */ - if (tv[5][0]) { - struct tlv_map_profile *tlv; - uint16_t tlv_len = tlv_length(tv[5][0]); - - /* profile (1 byte) */ - if (tlv_len != sizeof(struct tlv_map_profile)) - return false; - - tlv = (struct tlv_map_profile *)tv[5][0]->data; - if (!tlv) - return false; - } + if (check_map_profile_tlv(tv[5][0])) + return false; return true; } @@ -576,73 +719,20 @@ bool validate_ap_autoconfig_response(struct cmdu_buff *cmdu, struct tlv *tv[][16 } /* Parse SupportedRole TLV */ - if (tv[0][0]) { - struct tlv_supported_role *tlv; - uint16_t tlv_len = tlv_length(tv[0][0]); - - /* role (1 byte) */ - if (tlv_len != sizeof(struct tlv_supported_role)) - return false; - - tlv = (struct tlv_supported_role *)tv[0][0]->data; - if (!tlv) - return false; - } + if (check_supported_role_tlv(tv[0][0])) + return false; /* Parse SupportedService TLV */ - if (tv[1][0]) { - uint8_t *tv_data; - uint8_t num_services; - int offset = 0; - uint16_t tlv_len = tlv_length(tv[1][0]); - - if (tlv_len < 1) - return false; - - tv_data = (uint8_t *) tv[1][0]->data; - if (!tv_data) - return false; - - /* num_services (1 byte) */ - if (offset + 1 > tlv_len) - return false; - - num_services = tv_data[offset]; - - offset += 1; - - /* services (num_services bytes) */ - if (offset + num_services > tlv_len) - return false; - } + if (check_supported_service_tlv(tv[1][0])) + return false; /* Parse MultiAP Profile TLV */ - if (tv[2][0]) { - struct tlv_map_profile *tlv; - uint16_t tlv_len = tlv_length(tv[2][0]); - - /* profile (1 byte) */ - if (tlv_len != sizeof(struct tlv_map_profile)) - return false; - - tlv = (struct tlv_map_profile *)tv[2][0]->data; - if (!tlv) - return false; - } + if (check_map_profile_tlv(tv[2][0])) + return false; /* Parse SupportedFreqBand TLV */ - if (tv[3][0]) { - struct tlv_supported_band *tlv; - uint16_t tlv_len = tlv_length(tv[3][0]); - - /* band (1 byte) */ - if (tlv_len != sizeof(struct tlv_supported_band)) - return false; - - tlv = (struct tlv_supported_band *)tv[3][0]->data; - if (!tlv) - return false; - } + if (check_supported_band_tlv(tv[3][0])) + return false; return true; } @@ -684,46 +774,16 @@ bool validate_ap_autoconfig_renew(struct cmdu_buff *cmdu, struct tlv *tv[][16]) } /* Parse 1905.1 AL MAC address type TLV */ - if (tv[0][0]) { - uint8_t *tv_data; - uint16_t tlv_len = tlv_length(tv[0][0]); - - /* macaddr (6 bytes) */ - if (tlv_len != 6) - return false; - - tv_data = (uint8_t *) tv[0][0]->data; - if (!tv_data) - return false; - } + if (check_al_mac_addr_type_tlv(tv[0][0])) + return false; /* Parse SupportedFreqBand TLV */ - if (tv[1][0]) { - struct tlv_supported_band *tlv; - uint16_t tlv_len = tlv_length(tv[1][0]); - - /* band (1 byte) */ - if (tlv_len != sizeof(struct tlv_supported_band)) - return false; - - tlv = (struct tlv_supported_band *)tv[1][0]->data; - if (!tlv) - return false; - } + if (check_supported_band_tlv(tv[1][0])) + return false; /* Parse SupportedRole TLV */ - if (tv[2][0]) { - struct tlv_supported_role *tlv; - uint16_t tlv_len = tlv_length(tv[2][0]); - - /* role (1 byte) */ - if (tlv_len != sizeof(struct tlv_supported_role)) - return false; - - tlv = (struct tlv_supported_role *)tv[2][0]->data; - if (!tlv) - return false; - } + if (check_supported_role_tlv(tv[2][0])) + return false; return true; }