2049353
From 9255c9b05b0a04b8d89739b3efcb9f393a617fe9 Mon Sep 17 00:00:00 2001
2049353
From: Guy Harris <guy@alum.mit.edu>
2049353
Date: Tue, 11 Nov 2014 15:51:54 -0800
2049353
Subject: [PATCH] Do bounds checking and length checking.
2049353
2049353
Don't run past the end of the captured data, and don't run past the end
2049353
of the packet (i.e., don't make the length variable go negative).
2049353
---
2049353
 print-geonet.c | 270 ++++++++++++++++++++++++++++++++-------------------------
2049353
 1 file changed, 151 insertions(+), 119 deletions(-)
2049353
2049353
diff --git a/print-geonet.c b/print-geonet.c
2049353
index d902066..edfb7f2 100644
2049353
--- a/print-geonet.c
2049353
+++ b/print-geonet.c
2049353
@@ -56,16 +56,12 @@ static const struct tok msg_type_values[] = {
2049353
 
2049353
 static void
2049353
 print_btp_body(netdissect_options *ndo,
2049353
-               const u_char *bp, u_int length)
2049353
+               const u_char *bp)
2049353
 {
2049353
 	int version;
2049353
 	int msg_type;
2049353
 	const char *msg_type_str;
2049353
 
2049353
-	if (length <= 2) {
2049353
-		return;
2049353
-	}
2049353
-
2049353
 	/* Assuming ItsDpuHeader */
2049353
 	version = bp[0];
2049353
 	msg_type = bp[1];
2049353
@@ -83,7 +79,7 @@ print_btp(netdissect_options *ndo,
2049353
 	ND_PRINT((ndo, "; BTP Dst:%u Src:%u", dest, src));
2049353
 }
2049353
 
2049353
-static void
2049353
+static int
2049353
 print_long_pos_vector(netdissect_options *ndo,
2049353
                       const u_char *bp)
2049353
 {
2049353
@@ -91,10 +87,13 @@ print_long_pos_vector(netdissect_options *ndo,
2049353
 
2049353
 	ND_PRINT((ndo, "GN_ADDR:%s ", linkaddr_string (ndo, bp, 0, GEONET_ADDR_LEN)));
2049353
 
2049353
+	if (!ND_TTEST2(*(bp+12), 8))
2049353
+		return (-1);
2049353
 	lat = EXTRACT_32BITS(bp+12);
2049353
 	ND_PRINT((ndo, "lat:%d ", lat));
2049353
 	lon = EXTRACT_32BITS(bp+16);
2049353
 	ND_PRINT((ndo, "lon:%d", lon));
2049353
+	return (0);
2049353
 }
2049353
 
2049353
 
2049353
@@ -105,137 +104,170 @@ print_long_pos_vector(netdissect_options *ndo,
2049353
 void
2049353
 geonet_print(netdissect_options *ndo, const u_char *eth, const u_char *bp, u_int length)
2049353
 {
2049353
+	int version;
2049353
+	int next_hdr;
2049353
+	int hdr_type;
2049353
+	int hdr_subtype;
2049353
+	uint16_t payload_length;
2049353
+	int hop_limit;
2049353
+	const char *next_hdr_txt = "Unknown";
2049353
+	const char *hdr_type_txt = "Unknown";
2049353
+	int hdr_size = -1;
2049353
+
2049353
 	ND_PRINT((ndo, "GeoNet src:%s; ", etheraddr_string(ndo, eth+6)));
2049353
 
2049353
-	if (length >= 36) {
2049353
-		/* Process Common Header */
2049353
-		int version = bp[0] >> 4;
2049353
-		int next_hdr = bp[0] & 0x0f;
2049353
-		int hdr_type = bp[1] >> 4;
2049353
-		int hdr_subtype = bp[1] & 0x0f;
2049353
-		uint16_t payload_length = EXTRACT_16BITS(bp+4);
2049353
-		int hop_limit = bp[7];
2049353
-		const char *next_hdr_txt = "Unknown";
2049353
-		const char *hdr_type_txt = "Unknown";
2049353
-		int hdr_size = -1;
2049353
+	/* Process Common Header */
2049353
+	if (length < 36)
2049353
+		goto malformed;
2049353
+		
2049353
+	ND_TCHECK2(*bp, 7);
2049353
+	version = bp[0] >> 4;
2049353
+	next_hdr = bp[0] & 0x0f;
2049353
+	hdr_type = bp[1] >> 4;
2049353
+	hdr_subtype = bp[1] & 0x0f;
2049353
+	payload_length = EXTRACT_16BITS(bp+4);
2049353
+	hop_limit = bp[7];
2049353
 
2049353
-		switch (next_hdr) {
2049353
-			case 0: next_hdr_txt = "Any"; break;
2049353
-			case 1: next_hdr_txt = "BTP-A"; break;
2049353
-			case 2: next_hdr_txt = "BTP-B"; break;
2049353
-			case 3: next_hdr_txt = "IPv6"; break;
2049353
-		}
2049353
+	switch (next_hdr) {
2049353
+		case 0: next_hdr_txt = "Any"; break;
2049353
+		case 1: next_hdr_txt = "BTP-A"; break;
2049353
+		case 2: next_hdr_txt = "BTP-B"; break;
2049353
+		case 3: next_hdr_txt = "IPv6"; break;
2049353
+	}
2049353
 
2049353
-		switch (hdr_type) {
2049353
-			case 0: hdr_type_txt = "Any"; break;
2049353
-			case 1: hdr_type_txt = "Beacon"; break;
2049353
-			case 2: hdr_type_txt = "GeoUnicast"; break;
2049353
-			case 3: switch (hdr_subtype) {
2049353
-					case 0: hdr_type_txt = "GeoAnycastCircle"; break;
2049353
-					case 1: hdr_type_txt = "GeoAnycastRect"; break;
2049353
-					case 2: hdr_type_txt = "GeoAnycastElipse"; break;
2049353
-				}
2049353
-				break;
2049353
-			case 4: switch (hdr_subtype) {
2049353
-					case 0: hdr_type_txt = "GeoBroadcastCircle"; break;
2049353
-					case 1: hdr_type_txt = "GeoBroadcastRect"; break;
2049353
-					case 2: hdr_type_txt = "GeoBroadcastElipse"; break;
2049353
-				}
2049353
-				break;
2049353
-			case 5: switch (hdr_subtype) {
2049353
-					case 0: hdr_type_txt = "TopoScopeBcast-SH"; break;
2049353
-					case 1: hdr_type_txt = "TopoScopeBcast-MH"; break;
2049353
-				}
2049353
-				break;
2049353
-			case 6: switch (hdr_subtype) {
2049353
-					case 0: hdr_type_txt = "LocService-Request"; break;
2049353
-					case 1: hdr_type_txt = "LocService-Reply"; break;
2049353
-				}
2049353
-				break;
2049353
-		}
2049353
+	switch (hdr_type) {
2049353
+		case 0: hdr_type_txt = "Any"; break;
2049353
+		case 1: hdr_type_txt = "Beacon"; break;
2049353
+		case 2: hdr_type_txt = "GeoUnicast"; break;
2049353
+		case 3: switch (hdr_subtype) {
2049353
+				case 0: hdr_type_txt = "GeoAnycastCircle"; break;
2049353
+				case 1: hdr_type_txt = "GeoAnycastRect"; break;
2049353
+				case 2: hdr_type_txt = "GeoAnycastElipse"; break;
2049353
+			}
2049353
+			break;
2049353
+		case 4: switch (hdr_subtype) {
2049353
+				case 0: hdr_type_txt = "GeoBroadcastCircle"; break;
2049353
+				case 1: hdr_type_txt = "GeoBroadcastRect"; break;
2049353
+				case 2: hdr_type_txt = "GeoBroadcastElipse"; break;
2049353
+			}
2049353
+			break;
2049353
+		case 5: switch (hdr_subtype) {
2049353
+				case 0: hdr_type_txt = "TopoScopeBcast-SH"; break;
2049353
+				case 1: hdr_type_txt = "TopoScopeBcast-MH"; break;
2049353
+			}
2049353
+			break;
2049353
+		case 6: switch (hdr_subtype) {
2049353
+				case 0: hdr_type_txt = "LocService-Request"; break;
2049353
+				case 1: hdr_type_txt = "LocService-Reply"; break;
2049353
+			}
2049353
+			break;
2049353
+	}
2049353
+
2049353
+	ND_PRINT((ndo, "v:%d ", version));
2049353
+	ND_PRINT((ndo, "NH:%d-%s ", next_hdr, next_hdr_txt));
2049353
+	ND_PRINT((ndo, "HT:%d-%d-%s ", hdr_type, hdr_subtype, hdr_type_txt));
2049353
+	ND_PRINT((ndo, "HopLim:%d ", hop_limit));
2049353
+	ND_PRINT((ndo, "Payload:%d ", payload_length));
2049353
+	if (print_long_pos_vector(ndo, bp + 8) == -1)
2049353
+		goto trunc;
2049353
 
2049353
-		ND_PRINT((ndo, "v:%d ", version));
2049353
-		ND_PRINT((ndo, "NH:%d-%s ", next_hdr, next_hdr_txt));
2049353
-		ND_PRINT((ndo, "HT:%d-%d-%s ", hdr_type, hdr_subtype, hdr_type_txt));
2049353
-		ND_PRINT((ndo, "HopLim:%d ", hop_limit));
2049353
-		ND_PRINT((ndo, "Payload:%d ", payload_length));
2049353
-		print_long_pos_vector(ndo, bp + 8);
2049353
+	/* Skip Common Header */
2049353
+	length -= 36;
2049353
+	bp += 36;
2049353
 
2049353
-		/* Skip Common Header */
2049353
-		length -= 36;
2049353
-		bp += 36;
2049353
+	/* Process Extended Headers */
2049353
+	switch (hdr_type) {
2049353
+		case 0: /* Any */
2049353
+			hdr_size = 0;
2049353
+			break;
2049353
+		case 1: /* Beacon */
2049353
+			hdr_size = 0;
2049353
+			break;
2049353
+		case 2: /* GeoUnicast */
2049353
+			break;
2049353
+		case 3: switch (hdr_subtype) {
2049353
+				case 0: /* GeoAnycastCircle */
2049353
+					break;
2049353
+				case 1: /* GeoAnycastRect */
2049353
+					break;
2049353
+				case 2: /* GeoAnycastElipse */
2049353
+					break;
2049353
+			}
2049353
+			break;
2049353
+		case 4: switch (hdr_subtype) {
2049353
+				case 0: /* GeoBroadcastCircle */
2049353
+					break;
2049353
+				case 1: /* GeoBroadcastRect */
2049353
+					break;
2049353
+				case 2: /* GeoBroadcastElipse */
2049353
+					break;
2049353
+			}
2049353
+			break;
2049353
+		case 5: switch (hdr_subtype) {
2049353
+				case 0: /* TopoScopeBcast-SH */
2049353
+					hdr_size = 0;
2049353
+					break;
2049353
+				case 1: /* TopoScopeBcast-MH */
2049353
+					hdr_size = 68 - 36;
2049353
+					break;
2049353
+			}
2049353
+			break;
2049353
+		case 6: switch (hdr_subtype) {
2049353
+				case 0: /* LocService-Request */
2049353
+					break;
2049353
+				case 1: /* LocService-Reply */
2049353
+					break;
2049353
+			}
2049353
+			break;
2049353
+	}
2049353
 
2049353
-		/* Process Extended Headers */
2049353
-		switch (hdr_type) {
2049353
+	/* Skip Extended headers */
2049353
+	if (hdr_size >= 0) {
2049353
+		if (length < (u_int)hdr_size)
2049353
+			goto malformed;
2049353
+		ND_TCHECK2(*bp, hdr_size);
2049353
+		length -= hdr_size;
2049353
+		bp += hdr_size;
2049353
+		switch (next_hdr) {
2049353
 			case 0: /* Any */
2049353
-				hdr_size = 0;
2049353
-				break;
2049353
-			case 1: /* Beacon */
2049353
-				hdr_size = 0;
2049353
-				break;
2049353
-			case 2: /* GeoUnicast */
2049353
 				break;
2049353
-			case 3: switch (hdr_subtype) {
2049353
-					case 0: /* GeoAnycastCircle */
2049353
-						break;
2049353
-					case 1: /* GeoAnycastRect */
2049353
-						break;
2049353
-					case 2: /* GeoAnycastElipse */
2049353
-						break;
2049353
+			case 1:
2049353
+			case 2: /* BTP A/B */
2049353
+				if (length < 4)
2049353
+					goto malformed;
2049353
+				ND_TCHECK2(*bp, 4);
2049353
+				print_btp(ndo, bp);
2049353
+				length -= 4;
2049353
+				bp += 4;
2049353
+				if (length >= 2) {
2049353
+					/*
2049353
+					 * XXX - did print_btp_body()
2049353
+					 * return if length < 2
2049353
+					 * because this is optional,
2049353
+					 * or was that just not
2049353
+					 * reporting genuine errors?
2049353
+					 */
2049353
+					ND_TCHECK2(*bp, 2);
2049353
+					print_btp_body(ndo, bp);
2049353
 				}
2049353
 				break;
2049353
-			case 4: switch (hdr_subtype) {
2049353
-					case 0: /* GeoBroadcastCircle */
2049353
-						break;
2049353
-					case 1: /* GeoBroadcastRect */
2049353
-						break;
2049353
-					case 2: /* GeoBroadcastElipse */
2049353
-						break;
2049353
-				}
2049353
-				break;
2049353
-			case 5: switch (hdr_subtype) {
2049353
-					case 0: /* TopoScopeBcast-SH */
2049353
-						hdr_size = 0;
2049353
-						break;
2049353
-					case 1: /* TopoScopeBcast-MH */
2049353
-						hdr_size = 68 - 36;
2049353
-						break;
2049353
-				}
2049353
-				break;
2049353
-			case 6: switch (hdr_subtype) {
2049353
-					case 0: /* LocService-Request */
2049353
-						break;
2049353
-					case 1: /* LocService-Reply */
2049353
-						break;
2049353
-				}
2049353
+			case 3: /* IPv6 */
2049353
 				break;
2049353
 		}
2049353
-
2049353
-		/* Skip Extended headers */
2049353
-		if (hdr_size >= 0) {
2049353
-			length -= hdr_size;
2049353
-			bp += hdr_size;
2049353
-			switch (next_hdr) {
2049353
-				case 0: /* Any */
2049353
-					break;
2049353
-				case 1:
2049353
-				case 2: /* BTP A/B */
2049353
-					print_btp(ndo, bp);
2049353
-					length -= 4;
2049353
-					bp += 4;
2049353
-					print_btp_body(ndo, bp, length);
2049353
-					break;
2049353
-				case 3: /* IPv6 */
2049353
-					break;
2049353
-			}
2049353
-		}
2049353
-	} else {
2049353
-		ND_PRINT((ndo, "Malformed (small) "));
2049353
 	}
2049353
 
2049353
 	/* Print user data part */
2049353
 	if (ndo->ndo_vflag)
2049353
 		ND_DEFAULTPRINT(bp, length);
2049353
+	return;
2049353
+
2049353
+malformed:
2049353
+	ND_PRINT((ndo, " Malformed (small) "));
2049353
+	/* XXX - print the remaining data as hex? */
2049353
+	return;
2049353
+
2049353
+trunc:
2049353
+	ND_PRINT((ndo, "[|geonet]"));
2049353
 }
2049353
 
2049353
 
2049353
-- 
2049353
1.8.3.1
2049353