summaryrefslogtreecommitdiff
path: root/src/trunnel
diff options
context:
space:
mode:
authorrl1987 <rl1987@sdf.lonestar.org>2018-12-18 11:58:40 +0200
committerrl1987 <rl1987@sdf.lonestar.org>2018-12-18 12:10:08 +0200
commitc92c0cbc9f7a1ad889cfdda6943ca484d110438e (patch)
treef939757e31abec3490371f5d37460b1defa4dd70 /src/trunnel
parent5b2acbec0e50a1858c43d0cafe9c4696152cde27 (diff)
downloadtor-c92c0cbc9f7a1ad889cfdda6943ca484d110438e.tar.gz
tor-c92c0cbc9f7a1ad889cfdda6943ca484d110438e.zip
Actually allow unrecognized address types in NETINFO cell
Ignore the address value instead of failing with error condition in case unrecognized address type is found.
Diffstat (limited to 'src/trunnel')
-rw-r--r--src/trunnel/netinfo.c124
-rw-r--r--src/trunnel/netinfo.trunnel4
2 files changed, 74 insertions, 54 deletions
diff --git a/src/trunnel/netinfo.c b/src/trunnel/netinfo.c
index de389eb13f..5d815b9b12 100644
--- a/src/trunnel/netinfo.c
+++ b/src/trunnel/netinfo.c
@@ -140,7 +140,6 @@ netinfo_addr_check(const netinfo_addr_t *obj)
break;
default:
- return "Bad tag for union";
break;
}
return NULL;
@@ -175,7 +174,6 @@ netinfo_addr_encoded_len(const netinfo_addr_t *obj)
break;
default:
- trunnel_assert(0);
break;
}
return result;
@@ -198,6 +196,8 @@ netinfo_addr_encode(uint8_t *output, const size_t avail, const netinfo_addr_t *o
const ssize_t encoded_len = netinfo_addr_encoded_len(obj);
#endif
+ uint8_t *backptr_len = NULL;
+
if (NULL != (msg = netinfo_addr_check(obj)))
goto check_failed;
@@ -213,39 +213,49 @@ netinfo_addr_encode(uint8_t *output, const size_t avail, const netinfo_addr_t *o
written += 1; ptr += 1;
/* Encode u8 len */
+ backptr_len = ptr;
trunnel_assert(written <= avail);
if (avail - written < 1)
goto truncated;
trunnel_set_uint8(ptr, (obj->len));
written += 1; ptr += 1;
-
- /* Encode union addr[addr_type] */
- trunnel_assert(written <= avail);
- switch (obj->addr_type) {
-
- case NETINFO_ADDR_TYPE_IPV4:
-
- /* Encode u32 addr_ipv4 */
- trunnel_assert(written <= avail);
- if (avail - written < 4)
- goto truncated;
- trunnel_set_uint32(ptr, trunnel_htonl(obj->addr_ipv4));
- written += 4; ptr += 4;
- break;
-
- case NETINFO_ADDR_TYPE_IPV6:
-
- /* Encode u8 addr_ipv6[16] */
- trunnel_assert(written <= avail);
- if (avail - written < 16)
- goto truncated;
- memcpy(ptr, obj->addr_ipv6, 16);
- written += 16; ptr += 16;
- break;
-
- default:
- trunnel_assert(0);
- break;
+ {
+ size_t written_before_union = written;
+
+ /* Encode union addr[addr_type] */
+ trunnel_assert(written <= avail);
+ switch (obj->addr_type) {
+
+ case NETINFO_ADDR_TYPE_IPV4:
+
+ /* Encode u32 addr_ipv4 */
+ trunnel_assert(written <= avail);
+ if (avail - written < 4)
+ goto truncated;
+ trunnel_set_uint32(ptr, trunnel_htonl(obj->addr_ipv4));
+ written += 4; ptr += 4;
+ break;
+
+ case NETINFO_ADDR_TYPE_IPV6:
+
+ /* Encode u8 addr_ipv6[16] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 16)
+ goto truncated;
+ memcpy(ptr, obj->addr_ipv6, 16);
+ written += 16; ptr += 16;
+ break;
+
+ default:
+ break;
+ }
+ /* Write the length field back to len */
+ trunnel_assert(written >= written_before_union);
+#if UINT8_MAX < SIZE_MAX
+ if (written - written_before_union > UINT8_MAX)
+ goto check_failed;
+#endif
+ trunnel_set_uint8(backptr_len, (written - written_before_union));
}
@@ -291,29 +301,39 @@ netinfo_addr_parse_into(netinfo_addr_t *obj, const uint8_t *input, const size_t
CHECK_REMAINING(1, truncated);
obj->len = (trunnel_get_uint8(ptr));
remaining -= 1; ptr += 1;
-
- /* Parse union addr[addr_type] */
- switch (obj->addr_type) {
-
- case NETINFO_ADDR_TYPE_IPV4:
-
- /* Parse u32 addr_ipv4 */
- CHECK_REMAINING(4, truncated);
- obj->addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
- remaining -= 4; ptr += 4;
- break;
-
- case NETINFO_ADDR_TYPE_IPV6:
-
- /* Parse u8 addr_ipv6[16] */
- CHECK_REMAINING(16, truncated);
- memcpy(obj->addr_ipv6, ptr, 16);
- remaining -= 16; ptr += 16;
- break;
-
- default:
+ {
+ size_t remaining_after;
+ CHECK_REMAINING(obj->len, truncated);
+ remaining_after = remaining - obj->len;
+ remaining = obj->len;
+
+ /* Parse union addr[addr_type] */
+ switch (obj->addr_type) {
+
+ case NETINFO_ADDR_TYPE_IPV4:
+
+ /* Parse u32 addr_ipv4 */
+ CHECK_REMAINING(4, fail);
+ obj->addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
+ remaining -= 4; ptr += 4;
+ break;
+
+ case NETINFO_ADDR_TYPE_IPV6:
+
+ /* Parse u8 addr_ipv6[16] */
+ CHECK_REMAINING(16, fail);
+ memcpy(obj->addr_ipv6, ptr, 16);
+ remaining -= 16; ptr += 16;
+ break;
+
+ default:
+ /* Skip to end of union */
+ ptr += remaining; remaining = 0;
+ break;
+ }
+ if (remaining != 0)
goto fail;
- break;
+ remaining = remaining_after;
}
trunnel_assert(ptr + remaining == input + len_in);
return len_in - remaining;
diff --git a/src/trunnel/netinfo.trunnel b/src/trunnel/netinfo.trunnel
index 83c3a9e40f..2c4b7a7591 100644
--- a/src/trunnel/netinfo.trunnel
+++ b/src/trunnel/netinfo.trunnel
@@ -7,10 +7,10 @@ const NETINFO_ADDR_TYPE_IPV6 = 6;
struct netinfo_addr {
u8 addr_type;
u8 len;
- union addr[addr_type] {
+ union addr[addr_type] with length len {
NETINFO_ADDR_TYPE_IPV4: u32 ipv4;
NETINFO_ADDR_TYPE_IPV6: u8 ipv6[16];
- default: fail;
+ default: ignore;
};
}