Fix CVS-2011-2748, malformed packets can cause server to crash causing a DoS.

This commit is contained in:
christos 2011-08-15 21:12:43 +00:00
parent b4f44e540e
commit 4dff6c909f
3 changed files with 36 additions and 14 deletions

View File

@ -34,7 +34,7 @@
#ifndef lint
static char copyright[] =
"$Id: discover.c,v 1.11 2007/10/31 15:26:51 gdt Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
"$Id: discover.c,v 1.12 2011/08/15 21:12:43 christos Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -830,6 +830,17 @@ isc_result_t got_one (h)
}
if (result == 0)
return ISC_R_UNEXPECTED;
/*
* If we didn't at least get the fixed portion of the BOOTP
* packet, drop the packet.
* Previously we allowed packets with no sname or filename
* as we were aware of at least one client that did. But
* a bug caused short packets to not work and nobody has
* complained, it seems rational to tighten up that
* restriction.
*/
if (result < DHCP_FIXED_NON_UDP)
return ISC_R_UNEXPECTED;
if (bootp_packet_handler) {
ifrom.len = 4;

View File

@ -34,7 +34,7 @@
#ifndef lint
static char copyright[] =
"$Id: options.c,v 1.6 2006/05/11 09:29:39 mrg Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
"$Id: options.c,v 1.7 2011/08/15 21:12:43 christos Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#define DHCP_OPTION_DATA
@ -499,19 +499,26 @@ int cons_options (inpacket, outpacket, lease, client_state,
honor it. */
if (mms) {
main_buffer_size = mms - DHCP_FIXED_LEN;
if (mms < 576)
/* Enforce a minimum packet size... */
main_buffer_size = mms - DHCP_FIXED_LEN;
else if (mms > 1500)
/*
* TODO: Packets longer than 1500 bytes really
* should be allowed, but it requires upstream
* changes to the way the packet is allocated. For
* now, we forbid them. They won't be needed very
* often anyway.
*/
main_buffer_size = 1500 - DHCP_FIXED_LEN;
else
main_buffer_size = mms - DHCP_FIXED_LEN;
/* Enforce a minimum packet size... */
if (main_buffer_size < (576 - DHCP_FIXED_LEN))
main_buffer_size = 576 - DHCP_FIXED_LEN;
} else if (bootpp) {
if (inpacket) {
main_buffer_size =
inpacket -> packet_length - DHCP_FIXED_LEN;
if (main_buffer_size < 64)
main_buffer_size = 64;
} else
main_buffer_size = 64;
main_buffer_size = 64;
if (inpacket != NULL &&
(inpacket->packet_length >= 64 + DHCP_FIXED_NON_UDP))
main_buffer_size = inpacket->packet_length - DHCP_FIXED_NON_UDP;
} else
main_buffer_size = 576 - DHCP_FIXED_LEN;

View File

@ -34,7 +34,7 @@
#ifndef lint
static char copyright[] =
"$Id: dhcp.c,v 1.11 2009/07/16 22:44:27 tonnerre Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
"$Id: dhcp.c,v 1.12 2011/08/15 21:12:43 christos Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -128,6 +128,7 @@ void dhcp (packet)
if (packet -> packet_type == DHCPREQUEST &&
packet -> raw -> ciaddr.s_addr &&
!packet -> raw -> giaddr.s_addr &&
packet -> options != NULL &&
(packet -> options -> universe_count < agent_universe.index ||
!packet -> options -> universes [agent_universe.index]))
{
@ -1379,6 +1380,7 @@ void nak_lease (packet, cip)
/* If there were agent options in the incoming packet, return
them. */
if (packet -> raw -> giaddr.s_addr &&
packet -> options != NULL &&
packet -> options -> universe_count > agent_universe.index &&
packet -> options -> universes [agent_universe.index]) {
option_chain_head_reference
@ -1536,6 +1538,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
them. Do not return the agent options if they were stashed
on the lease. */
if (packet -> raw -> giaddr.s_addr &&
packet -> options != NULL &&
packet -> options -> universe_count > agent_universe.index &&
packet -> options -> universes [agent_universe.index] &&
(state -> options -> universe_count <= agent_universe.index ||
@ -2179,6 +2182,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
in with the packet, so that we can use them at renewal time when
the packet won't have gone through a relay agent. */
if (packet -> raw -> giaddr.s_addr &&
packet -> options != NULL &&
packet -> options -> universe_count > agent_universe.index &&
packet -> options -> universes [agent_universe.index] &&
(state -> options -> universe_count <= agent_universe.index ||