diff --git a/common/options.c b/common/options.c index 25450e1df..f55daac5e 100644 --- a/common/options.c +++ b/common/options.c @@ -2735,6 +2735,9 @@ build_server_oro(struct data_string *server_oro, * Allocate space. */ memset(server_oro, 0, sizeof(*server_oro)); + if (num_opts > INT_MAX / 2) { + log_fatal("server ORO option count overflow"); + } if (!buffer_allocate(&server_oro->buffer, num_opts * 2, MDL)) { log_fatal("no memory to build server ORO"); } @@ -3661,7 +3664,12 @@ fqdn6_universe_decode(struct option_state *options, * first to calculate the precise size or reallocate to a smaller * buffer later, either of which is a bigger performance hit than * just doing a generous allocation. */ - unsigned bp_size = 3 + (length * 4); + unsigned bp_size; + if (length > (UINT_MAX - 3) / 4) { + log_error("dhcp6.fqdn option length overflow."); + return 0; + } + bp_size = 3 + (length * 4); if (!buffer_allocate(&bp, bp_size, MDL)) { log_error("No memory for dhcp6.fqdn option buffer."); diff --git a/common/parse.c b/common/parse.c index b123a6c7e..924415442 100644 --- a/common/parse.c +++ b/common/parse.c @@ -1481,6 +1481,8 @@ void parse_option_space_decl (cfile) } nu -> index = universe_count++; if (nu -> index >= universe_max) { + if (universe_max > INT_MAX / 2) + log_fatal ("Option space array too large."); ua = dmalloc (universe_max * 2 * sizeof *ua, MDL); if (!ua) log_fatal ("No memory to expand option space array."); diff --git a/common/tree.c b/common/tree.c index 681733542..6657f6088 100644 --- a/common/tree.c +++ b/common/tree.c @@ -58,7 +58,7 @@ data_string_sprintfa(struct data_string *ds, const char *fmt, ...) { int cur_strlen; int max; int vsnprintf_ret; - int new_len; + unsigned int new_len; struct buffer *tmp_buffer; /* @@ -97,10 +97,13 @@ data_string_sprintfa(struct data_string *ds, const char *fmt, ...) { /* * Figure out a size big enough. */ - new_len = ds->len * 2; - while (new_len <= cur_strlen + vsnprintf_ret) { + new_len = ds->len; + do { + if (new_len > UINT_MAX / 2) { + return 0; + } new_len *= 2; - } + } while (new_len <= (unsigned int)(cur_strlen + vsnprintf_ret)); /* * Create a new buffer and fill it. diff --git a/omapip/alloc.c b/omapip/alloc.c index d13d3d7eb..0f458a6cb 100644 --- a/omapip/alloc.c +++ b/omapip/alloc.c @@ -1106,6 +1106,8 @@ isc_result_t omapi_addr_list_new (omapi_addr_list_t **d, unsigned count, { omapi_addr_list_t *new; + if (count > (SIZE_MAX - sizeof (omapi_addr_list_t)) / sizeof (omapi_addr_t)) + return ISC_R_NOMEMORY; new = dmalloc ((count * sizeof (omapi_addr_t)) + sizeof (omapi_addr_list_t), file, line); if (!new) diff --git a/omapip/array.c b/omapip/array.c index 600d78350..593b8f5df 100644 --- a/omapip/array.c +++ b/omapip/array.c @@ -102,6 +102,9 @@ isc_result_t omapi_array_set (omapi_array_t *array, void *ptr, int index, space in the array, make more space in the array. */ if (array -> max <= index) { delta = index - array -> max + 10; + if ((unsigned)delta > SIZE_MAX / sizeof (char *) || + (unsigned)(array -> max + delta) > SIZE_MAX / sizeof (char *)) + return ISC_R_NOMEMORY; newbuf = dmalloc ((array -> max + delta) * sizeof (char *), file, line); if (!newbuf) diff --git a/omapip/protocol.c b/omapip/protocol.c index 38db66ea0..82b7c5692 100644 --- a/omapip/protocol.c +++ b/omapip/protocol.c @@ -709,15 +709,23 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, (p -> message -> authenticator -> u.buffer.value, c, p -> message -> authlen); - /* Verify the signature. */ - if (p -> message -> id_object && - ((signature -> value -> u.buffer.len != - p -> message -> authlen) || - (memcmp (signature -> value -> u.buffer.value, - p -> message -> authenticator -> u.buffer.value, - p -> message -> authlen) != 0))) { - /* Invalid signature. */ - p->verify_result = DHCP_R_INVALIDKEY; + /* Verify the signature using constant-time comparison + * to prevent timing side-channel attacks. */ + if (p -> message -> id_object) { + int sig_mismatch = (signature -> value -> u.buffer.len != + p -> message -> authlen); + if (!sig_mismatch) { + volatile unsigned char diff = 0; + unsigned i; + for (i = 0; i < p -> message -> authlen; i++) + diff |= signature -> value -> u.buffer.value[i] + ^ p -> message -> authenticator -> u.buffer.value[i]; + sig_mismatch = (diff != 0); + } + if (sig_mismatch) { + /* Invalid signature. */ + p->verify_result = DHCP_R_INVALIDKEY; + } } if (signature != NULL) {