]> git.decadent.org.uk Git - odhcp6c.git/blobdiff - src/dhcpv6.c
Merge pull request #41 from bwhacks/security-fixes
[odhcp6c.git] / src / dhcpv6.c
index cfa3f29e17f5ec39415572cc89207b88730d2dcd..e27d8995a40102a5446816334fb3e3843819e311 100644 (file)
@@ -23,6 +23,7 @@
 #include <unistd.h>
 #include <syslog.h>
 #include <stdbool.h>
+#include <ctype.h>
 #include <sys/time.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
@@ -812,7 +813,8 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc,
                        if (inf_max_rt >= DHCPV6_INF_MAX_RT_MIN &&
                                        inf_max_rt <= DHCPV6_INF_MAX_RT_MAX)
                                cand.inf_max_rt = inf_max_rt;
-               } else if (otype == DHCPV6_OPT_IA_PD && request_prefix) {
+               } else if (otype == DHCPV6_OPT_IA_PD && request_prefix &&
+                                       olen >= -4 + sizeof(struct dhcpv6_ia_hdr)) {
                        struct dhcpv6_ia_hdr *h = (struct dhcpv6_ia_hdr*)&odata[-4];
                        uint8_t *oend = odata + olen, *d;
                        dhcpv6_for_each_option(&h[1], oend, otype, olen, d) {
@@ -822,7 +824,8 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc,
                                        have_pd = p->prefix;
                                }
                        }
-               } else if (otype == DHCPV6_OPT_IA_NA) {
+               } else if (otype == DHCPV6_OPT_IA_NA &&
+                                       olen >= -4 + sizeof(struct dhcpv6_ia_hdr)) {
                        struct dhcpv6_ia_hdr *h = (struct dhcpv6_ia_hdr*)&odata[-4];
                        uint8_t *oend = odata + olen, *d;
                        dhcpv6_for_each_option(&h[1], oend, otype, olen, d)
@@ -1185,7 +1188,7 @@ static int dhcpv6_parse_ia(void *opt, void *end)
                                if (elen > 64)
                                        elen = 64;
 
-                               if (elen <= 32 || elen <= entry.length) {
+                               if (entry.length < 32 || elen <= entry.length) {
                                        ok = false;
                                        continue;
                                }
@@ -1290,16 +1293,22 @@ static int dhcpv6_calc_refresh_timers(void)
 
 
 static void dhcpv6_log_status_code(const uint16_t code, const char *scope,
-               const void *status_msg, const int len)
+               const void *status_msg, int len)
 {
-       uint8_t buf[len + 3];
+       const char *src = status_msg;
+       char buf[len + 3];
+       char *dst = buf;
 
-       memset(buf, 0, sizeof(buf));
        if (len) {
-               buf[0] = '(';
-               memcpy(&buf[1], status_msg, len);
-               buf[len + 1] = ')';
+               *dst++ = '(';
+               while (len--) {
+                       *dst = isprint((unsigned char)*src) ? *src : '?';
+                       src++;
+                       dst++;
+               }
+               *dst++ = ')';
        }
+       *dst = 0;
 
        syslog(LOG_WARNING, "Server returned %s status %i %s",
                scope, code, buf);
@@ -1362,6 +1371,7 @@ static void dhcpv6_handle_ia_status_code(const enum dhcpv6_msg orig,
        }
 }
 
+// Note this always takes ownership of cand->ia_na and cand->ia_pd
 static void dhcpv6_add_server_cand(const struct dhcpv6_server_cand *cand)
 {
        size_t cand_len, i;
@@ -1384,7 +1394,10 @@ static void dhcpv6_add_server_cand(const struct dhcpv6_server_cand *cand)
                        break;
        }
 
-       odhcp6c_insert_state(STATE_SERVER_CAND, i * sizeof(*c), cand, sizeof(*cand));
+       if (odhcp6c_insert_state(STATE_SERVER_CAND, i * sizeof(*c), cand, sizeof(*cand))) {
+               free(cand->ia_na);
+               free(cand->ia_pd);
+       }
 }
 
 static void dhcpv6_clear_all_server_cand(void)