More strictly validate ARP responses from remote servers.

This commit is contained in:
Nicholas J. Kain 2011-05-31 11:01:08 -04:00
parent d72b24a2fe
commit 96f640e36c

View File

@ -1,5 +1,5 @@
/* arp.c - arp ping checking /* arp.c - arp ping checking
* Time-stamp: <2011-05-30 10:23:54 njk> * Time-stamp: <2011-05-31 10:03:34 njk>
* *
* Copyright 2010-2011 Nicholas J. Kain <njkain@gmail.com> * Copyright 2010-2011 Nicholas J. Kain <njkain@gmail.com>
* *
@ -226,6 +226,29 @@ void arp_gw_success(struct client_state_t *cs)
cs->dhcpState = cs->arpPrevState; cs->dhcpState = cs->arpPrevState;
} }
static int arp_validate(struct arpMsg *am)
{
if (!am)
return 0;
if (am->h_proto != htons(ETH_P_ARP))
return 0;
if (am->htype != htons(ARPHRD_ETHER))
return 0;
if (am->ptype != htons(ETH_P_IP))
return 0;
if (am->hlen != 6)
return 0;
if (am->plen != 4)
return 0;
if (am->operation != htons(ARPOP_REPLY))
return 0;
if (memcmp(am->h_dest, client_config.arp, 6))
return 0;
if (memcmp(am->tHaddr, client_config.arp, 6))
return 0;
return 1;
}
typedef uint32_t aliased_uint32_t __attribute__((__may_alias__)); typedef uint32_t aliased_uint32_t __attribute__((__may_alias__));
void handle_arp_response(struct client_state_t *cs) void handle_arp_response(struct client_state_t *cs)
{ {
@ -252,13 +275,15 @@ void handle_arp_response(struct client_state_t *cs)
return; return;
} }
if (!arp_validate(&arpreply)) {
log_warning("handle_arp_response: ARP message header is invalid.");
return;
}
++arp_packet_num; ++arp_packet_num;
switch (cs->dhcpState) { switch (cs->dhcpState) {
case DS_ARP_CHECK: case DS_ARP_CHECK:
if (arpreply.operation == htons(ARPOP_REPLY) if (*(aliased_uint32_t*)arpreply.sInaddr == arp_dhcp_packet.yiaddr)
&& !memcmp(arpreply.tHaddr, client_config.arp, 6)
&& *(aliased_uint32_t*)arpreply.sInaddr
== arp_dhcp_packet.yiaddr)
{ {
// Check to see if we replied to our own ARP query. // Check to see if we replied to our own ARP query.
if (!memcmp(client_config.arp, arpreply.sHaddr, 6)) if (!memcmp(client_config.arp, arpreply.sHaddr, 6))
@ -273,9 +298,7 @@ void handle_arp_response(struct client_state_t *cs)
} }
break; break;
case DS_ARP_GW_CHECK: case DS_ARP_GW_CHECK:
if (arpreply.operation == htons(ARPOP_REPLY) if (*(aliased_uint32_t*)arpreply.sInaddr == cs->routerAddr)
&& !memcmp(arpreply.tHaddr, client_config.arp, 6)
&& *(aliased_uint32_t*)arpreply.sInaddr == cs->routerAddr)
{ {
// Success only if the router/gw MAC matches stored value // Success only if the router/gw MAC matches stored value
if (!memcmp(cs->routerArp, arpreply.sHaddr, 6)) if (!memcmp(cs->routerArp, arpreply.sHaddr, 6))
@ -290,9 +313,7 @@ void handle_arp_response(struct client_state_t *cs)
} }
break; break;
case DS_BOUND: case DS_BOUND:
if (arpreply.operation == htons(ARPOP_REPLY) if (*(aliased_uint32_t*)arpreply.sInaddr == cs->routerAddr)
&& !memcmp(arpreply.tHaddr, client_config.arp, 6)
&& *(aliased_uint32_t*)arpreply.sInaddr == cs->routerAddr)
{ {
memcpy(cs->routerArp, arpreply.sHaddr, 6); memcpy(cs->routerArp, arpreply.sHaddr, 6);
arp_close_fd(cs); arp_close_fd(cs);