dhclient - Add some more paranoia and make code clearer.
authorAntonio Huete Jimenez <tuxillo@quantumachine.net>
Tue, 14 Aug 2012 23:06:26 +0000 (01:06 +0200)
committerAntonio Huete Jimenez <tuxillo@quantumachine.net>
Wed, 15 Aug 2012 01:22:20 +0000 (03:22 +0200)
- Check that the required length field for the option
  is present before using it. Reject lease if no length
  field is present.

Taken-from: OpenBSD

sbin/dhclient/options.c

index 3022dd0..b6edda6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: src/sbin/dhclient/options.c,v 1.40 2012/06/26 14:36:11 krw Exp $      */
+/*     $OpenBSD: src/sbin/dhclient/options.c,v 1.41 2012/06/26 14:46:42 krw Exp $      */
 
 /* DHCP options parsing and reassembly. */
 
@@ -68,21 +68,23 @@ parse_option_buffer(struct option_data *options, unsigned char *buffer,
                }
 
                /*
-                * All options other than DHO_PAD and DHO_END have a
-                * one-byte length field.
+                * All options other than DHO_PAD and DHO_END have a one-byte
+                * length field. It could be 0! Make sure that the length byte
+                * is present, and all the data is available.
                 */
-               if (s + 2 > end)
-                       len = 0;
-               else
+               if (s + 1 < end) {
                        len = s[1];
-
-               /*
-                * If the option claims to extend beyond the end of the buffer
-                * then mark the options buffer bad.
-                */
-               if (s + len + 2 > end) {
-                       warning("option %s (%d) larger than buffer.",
-                           dhcp_options[code].name, len);
+                       if (s + 1 + len < end) {
+                               ; /* option data is all there. */
+                       } else {
+                               warning("option %s (%d) larger than buffer.",
+                                   dhcp_options[code].name, len);
+                               warning("rejecting bogus offer.");
+                               return (0);
+                       }
+               } else {
+                       warning("option %s has no length field.",
+                           dhcp_options[code].name);
                        warning("rejecting bogus offer.");
                        return (0);
                }
@@ -95,8 +97,8 @@ parse_option_buffer(struct option_data *options, unsigned char *buffer,
                 * MUST be prepared to delete trailing nulls if they exist."
                 */
                if (dhcp_options[code].format[0] == 't') {
-                       for (len = s[1]; len > 0 && s[len + 1] == '\0'; len--)
-                               ;
+                       while (len > 0 && s[len + 1] == '\0')
+                               len--;
                }
 
                /*