fixed bug #49676 (Possible endless loop when parsing dhcp options) & added unit test for that

This commit is contained in:
goldsimon 2016-11-25 10:03:43 +01:00
parent 2ed755764e
commit 0e07ed4b13
3 changed files with 114 additions and 2 deletions

View File

@ -14,6 +14,9 @@ HISTORY
++ Bugfixes:
2016-11-25: Simon Goldschmidt
* dhcp.c: fixed bug #49676 (Possible endless loop when parsing dhcp options)
2016-11-23: Dirk Ziegelmeier
* udp.c: fixed bug #49662: multicast traffic is now only received on a UDP PCB
(and therefore on a UDP socket/netconn) when the PCB is bound to IP_ADDR_ANY

View File

@ -1541,6 +1541,8 @@ again:
#endif /* LWIP_DHCP_GET_NTP_SRV*/
case(DHCP_OPTION_OVERLOAD):
LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
/* decode overload only in options, not in file/sname: invalid packet */
LWIP_ERROR("overload in file/sname", options_idx == DHCP_OPTIONS_OFS, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_OVERLOAD;
break;
case(DHCP_OPTION_MESSAGE_TYPE):

View File

@ -120,7 +120,8 @@ static enum tcase {
TEST_LWIP_DHCP,
TEST_LWIP_DHCP_NAK,
TEST_LWIP_DHCP_RELAY,
TEST_LWIP_DHCP_NAK_NO_ENDMARKER
TEST_LWIP_DHCP_NAK_NO_ENDMARKER,
TEST_LWIP_DHCP_INVALID_OVERLOAD
} tcase;
static int debug = 0;
@ -904,6 +905,111 @@ START_TEST(test_dhcp_nak_no_endmarker)
}
END_TEST
START_TEST(test_dhcp_invalid_overload)
{
u8_t dhcp_offer_invalid_overload[] = {
0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */
0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */
0x08, 0x00, /* Protocol: IP */
0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */
0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */
0x02, /* Type == Boot reply */
0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */
0x00, /* 0 hops */
0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */
0x00, 0x00, /* 0 seconds elapsed */
0x00, 0x00, /* Flags (unicast) */
0x00, 0x00, 0x00, 0x00, /* Client ip */
0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */
0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */
0x00, 0x00, 0x00, 0x00, /* relay agent */
0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */
/* Empty server name */
0x34, 0x01, 0x02, 0xff, /* Overload: SNAME + END */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Empty boot file name */
0x34, 0x01, 0x01, 0xff, /* Overload FILE + END */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x63, 0x82, 0x53, 0x63, /* Magic cookie */
0x35, 0x01, 0x02, /* Message type: Offer */
0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */
0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */
0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */
0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */
0x34, 0x01, 0x03, /* Overload: FILE + SNAME */
0xff, /* End option */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */
};
ip4_addr_t addr;
ip4_addr_t netmask;
ip4_addr_t gw;
u32_t xid;
LWIP_UNUSED_ARG(_i);
tcase = TEST_LWIP_DHCP_INVALID_OVERLOAD;
setdebug(0);
IP4_ADDR(&addr, 0, 0, 0, 0);
IP4_ADDR(&netmask, 0, 0, 0, 0);
IP4_ADDR(&gw, 0, 0, 0, 0);
netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
netif_set_up(&net_test);
dhcp_start(&net_test);
fail_unless(txpacket == 1); /* DHCP discover sent */
xid = htonl(netif_dhcp_data(&net_test)->xid);
memcpy(&dhcp_offer_invalid_overload[46], &xid, 4); /* insert correct transaction id */
dhcp_offer_invalid_overload[311] = 3;
send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload));
/* IP addresses should be zero */
fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
fail_unless(txpacket == 1); /* Nothing more sent */
dhcp_offer_invalid_overload[311] = 2;
send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload));
/* IP addresses should be zero */
fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
fail_unless(txpacket == 1); /* Nothing more sent */
dhcp_offer_invalid_overload[311] = 1;
send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload));
/* IP addresses should be zero */
fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
fail_unless(txpacket == 1); /* Nothing more sent */
dhcp_offer_invalid_overload[311] = 0;
send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer));
fail_unless(netif_dhcp_data(&net_test)->state == DHCP_STATE_REQUESTING);
fail_unless(txpacket == 2); /* No more sent */
xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */
netif_remove(&net_test);
}
END_TEST
/** Create the suite including all tests for this module */
Suite *
@ -913,7 +1019,8 @@ dhcp_suite(void)
TESTFUNC(test_dhcp),
TESTFUNC(test_dhcp_nak),
TESTFUNC(test_dhcp_relayed),
TESTFUNC(test_dhcp_nak_no_endmarker)
TESTFUNC(test_dhcp_nak_no_endmarker),
TESTFUNC(test_dhcp_invalid_overload)
};
return create_suite("DHCP", tests, sizeof(tests)/sizeof(testfunc), dhcp_setup, dhcp_teardown);
}