changeset 2170:6787ee3545b5 draft

get_option should not perform length validation based on the option number
author Roy Marples <roy@marples.name>
date Fri, 29 Nov 2013 12:02:45 +0000
parents 97267d7f1321
children 8a1a9d940b2c
files dhcp.c
diffstat 1 files changed, 6 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/dhcp.c	Fri Nov 29 12:02:17 2013 +0000
+++ b/dhcp.c	Fri Nov 29 12:02:45 2013 +0000
@@ -244,49 +244,6 @@
 			printf("%03d %s\n", opt->option, opt->v.var);
 }
 
-static int
-validate_length(uint8_t option, int dl, int *type)
-{
-	const struct dhcp_opt *opt;
-	ssize_t sz;
-
-	if (dl == 0)
-		return -1;
-
-	for (opt = dhcp_opts; opt->option; opt++) {
-		if (opt->option != option)
-			continue;
-
-		if (type)
-			*type = opt->type;
-
-		if (opt->type == 0 ||
-		    opt->type & (STRING | RFC3442 | RFC5969))
-			return dl;
-
-		if (opt->type & ADDRIPV4 && opt->type & ARRAY) {
-			if (dl < (int)sizeof(uint32_t))
-				return -1;
-			return dl - (dl % sizeof(uint32_t));
-		}
-
-		sz = 0;
-		if (opt->type & (UINT32 | ADDRIPV4))
-			sz = sizeof(uint32_t);
-		if (opt->type & UINT16)
-			sz = sizeof(uint16_t);
-		if (opt->type & UINT8)
-			sz = sizeof(uint8_t);
-		/* If we don't know the size, assume it's valid */
-		if (sz == 0)
-			return dl;
-		return (dl < sz ? -1 : sz);
-	}
-
-	/* unknown option, so let it pass */
-	return dl;
-}
-
 #ifdef DEBUG_MEMORY
 static void
 dhcp_cleanup(void)
@@ -297,9 +254,9 @@
 }
 #endif
 
-#define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL, NULL)
+#define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL)
 static const uint8_t *
-get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type)
+get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len)
 {
 	const uint8_t *p = dhcp->options;
 	const uint8_t *e = p + sizeof(dhcp->options);
@@ -325,6 +282,10 @@
 				bp += ol;
 			}
 			ol = *p;
+			if (p + ol > e) {
+				errno = EINVAL;
+				return NULL;
+			}
 			op = p + 1;
 			bl += ol;
 		}
@@ -356,12 +317,6 @@
 	}
 
 exit:
-
-	bl = validate_length(opt, bl, type);
-	if (bl == -1) {
-		errno = EINVAL;
-		return NULL;
-	}
 	if (len)
 		*len = bl;
 	if (bp) {