From 578770d5e2295adeb548895411c61369bb2764e5 Mon Sep 17 00:00:00 2001 From: Henry Aidan Leta Date: Fri, 2 Sep 2022 09:15:34 -0400 Subject: [PATCH 1/6] extended ndpi dhcp imp --- src/include/ndpi_typedefs.h | 15 +++++++++++++-- src/lib/protocols/dhcp.c | 28 +++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 4f4afe6746e..cdb1fea8251 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1351,8 +1351,19 @@ struct ndpi_flow_struct { } bittorrent; struct { - char fingerprint[48]; - char class_ident[48]; + u_int32_t xid; + u_int32_t yiaddr; + u_int32_t siaddr; + u_int8_t chaddr[6]; + /* DHCP Options */ + char domain_name[256]; /* option 15 limited to 255 chars see RFC 1035 */ + u_int32_t requested_ip; /* option 50 */ + u_int32_t lease_time; /* option 51 */ + u_int8_t msg_type; /* option 53 */ + ndpi_ip_addr_t server_ident; /* option 54 */ + char fingerprint[48]; /* option 55 */ + u_int32_t renew_time; /* option 58 */ + char class_ident[48]; /* option 60 */ } dhcp; struct { diff --git a/src/lib/protocols/dhcp.c b/src/lib/protocols/dhcp.c index 5c59f699994..08d5405bebf 100644 --- a/src/lib/protocols/dhcp.c +++ b/src/lib/protocols/dhcp.c @@ -92,7 +92,6 @@ void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struct, u_int dhcp_options_size = ndpi_min(DHCP_VEND_LEN /* maximum size of options in struct dhcp_packet */, packet->payload_packet_len - 240); - /* Parse options in two steps (since we need first the message type and it seems there is no specific order in the options list) */ @@ -133,7 +132,13 @@ void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struct, /* Ok, we have a valid DHCP packet -> we can write to flow->protos.dhcp */ NDPI_LOG_INFO(ndpi_struct, "found DHCP\n"); ndpi_int_dhcp_add_connection(ndpi_struct, flow); - + + /* Assign basic dhcp information to flow structure */ + flow->protos.dhcp.msg_type = msg_type; /* option 53 msg_type */ + flow->protos.dhcp.xid = dhcp->xid; + flow->protos.dhcp.siaddr = dhcp->siaddr; + flow->protos.dhcp.yiaddr = dhcp->yiaddr; + memcpy(flow->protos.dhcp.chaddr, dhcp->chaddr, sizeof(dhcp->chaddr)); /* Second iteration: parse the interesting options */ while(i + 1 /* for the len */ < dhcp_options_size) { u_int8_t id = dhcp->options[i]; @@ -180,7 +185,24 @@ void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struct, // while(j < len) { printf( "%c", name[j]); j++; }; printf("\n"); #endif ndpi_hostname_sni_set(flow, name, len); - } + } else if(id == 15 /* Domain Name */) { + char *name = (char*)&dhcp->options[i+2]; + int j = 0; + + j = ndpi_min(len, sizeof(flow->protos.dhcp.domain_name)-1); + strncpy((char*)flow->protos.dhcp.domain_name, name, j); + flow->protos.dhcp.domain_name[j] = '\0'; + } else if(id == 50) /* Requested IP */ { + memcpy(&flow->protos.dhcp.requested_ip, (char*)&dhcp->options[i+2], len); + } else if(id == 51) /* Lease Time */ { + memcpy(&flow->protos.dhcp.lease_time, (char*)&dhcp->options[i+2], len); + } else if(id == 54) /* Server Identifier */ { + memcpy(&flow->protos.dhcp.server_ident, (char*)&dhcp->options[i+2], len); + } else if(id == 58) /* Renewal Time */ { + memcpy(&flow->protos.dhcp.renew_time, (char*)&dhcp->options[i+2], len); + } + + i += len + 2; } From 343c44e47cdcccd7dcc1de3375c38146f5e5e92a Mon Sep 17 00:00:00 2001 From: Henry Aidan Leta Date: Mon, 12 Sep 2022 14:11:53 -0400 Subject: [PATCH 2/6] add validation flag for proper dhcp response --- src/include/ndpi_typedefs.h | 1 + src/lib/protocols/dhcp.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index cdb1fea8251..a6004dff4f1 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1360,6 +1360,7 @@ struct ndpi_flow_struct { u_int32_t requested_ip; /* option 50 */ u_int32_t lease_time; /* option 51 */ u_int8_t msg_type; /* option 53 */ + u_int8_t valid; /* signifies valid dhcp resp */ ndpi_ip_addr_t server_ident; /* option 54 */ char fingerprint[48]; /* option 55 */ u_int32_t renew_time; /* option 58 */ diff --git a/src/lib/protocols/dhcp.c b/src/lib/protocols/dhcp.c index 08d5405bebf..00c1cb45291 100644 --- a/src/lib/protocols/dhcp.c +++ b/src/lib/protocols/dhcp.c @@ -113,6 +113,7 @@ void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struct, if(msg_type <= 8) { foundValidMsgType = 1; + flow->protos.dhcp.valid = 1; break; } } From e066297f826e51a0903ed94eddf4ab6d11283f42 Mon Sep 17 00:00:00 2001 From: Henry Aidan Leta Date: Wed, 21 Sep 2022 11:23:11 -0400 Subject: [PATCH 3/6] add upper bounds check on len before memcpy --- src/lib/protocols/dhcp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib/protocols/dhcp.c b/src/lib/protocols/dhcp.c index 00c1cb45291..2db309c5a19 100644 --- a/src/lib/protocols/dhcp.c +++ b/src/lib/protocols/dhcp.c @@ -194,12 +194,20 @@ void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struct, strncpy((char*)flow->protos.dhcp.domain_name, name, j); flow->protos.dhcp.domain_name[j] = '\0'; } else if(id == 50) /* Requested IP */ { + if (len > sizeof(flow->protos.dhcp.requested_ip)) + len = sizeof(flow->protos.dhcp.requested_ip); memcpy(&flow->protos.dhcp.requested_ip, (char*)&dhcp->options[i+2], len); } else if(id == 51) /* Lease Time */ { + if (len > sizeof(flow->protos.dhcp.lease_time)) + len = sizeof(flow->protos.dhcp.lease_time); memcpy(&flow->protos.dhcp.lease_time, (char*)&dhcp->options[i+2], len); } else if(id == 54) /* Server Identifier */ { + if (len > sizeof(flow->protos.dhcp.server_ident)) + len = sizeof(flow->protos.dhcp.server_ident); memcpy(&flow->protos.dhcp.server_ident, (char*)&dhcp->options[i+2], len); } else if(id == 58) /* Renewal Time */ { + if (len > sizeof(flow->protos.dhcp.renew_time)) + len = sizeof(flow->protos.dhcp.renew_time); memcpy(&flow->protos.dhcp.renew_time, (char*)&dhcp->options[i+2], len); } From e4728b3724ee3b625ffcee5d0c7ac1a632cd8318 Mon Sep 17 00:00:00 2001 From: Henry Aidan Leta Date: Wed, 21 Sep 2022 11:28:17 -0400 Subject: [PATCH 4/6] modify check to not touch len to ensure proper iteration and prevent overflow --- src/lib/protocols/dhcp.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/lib/protocols/dhcp.c b/src/lib/protocols/dhcp.c index 2db309c5a19..87fbd1124e6 100644 --- a/src/lib/protocols/dhcp.c +++ b/src/lib/protocols/dhcp.c @@ -195,20 +195,24 @@ void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struct, flow->protos.dhcp.domain_name[j] = '\0'; } else if(id == 50) /* Requested IP */ { if (len > sizeof(flow->protos.dhcp.requested_ip)) - len = sizeof(flow->protos.dhcp.requested_ip); - memcpy(&flow->protos.dhcp.requested_ip, (char*)&dhcp->options[i+2], len); + memcpy(&flow->protos.dhcp.requested_ip, (char*)&dhcp->options[i+2], sizeof(flow->protos.dhcp.requested_ip)); + else + memcpy(&flow->protos.dhcp.requested_ip, (char*)&dhcp->options[i+2], len); } else if(id == 51) /* Lease Time */ { if (len > sizeof(flow->protos.dhcp.lease_time)) - len = sizeof(flow->protos.dhcp.lease_time); - memcpy(&flow->protos.dhcp.lease_time, (char*)&dhcp->options[i+2], len); + memcpy(&flow->protos.dhcp.lease_time, (char*)&dhcp->options[i+2], sizeof(flow->protos.dhcp.lease_time)); + else + memcpy(&flow->protos.dhcp.lease_time, (char*)&dhcp->options[i+2], len); } else if(id == 54) /* Server Identifier */ { if (len > sizeof(flow->protos.dhcp.server_ident)) - len = sizeof(flow->protos.dhcp.server_ident); - memcpy(&flow->protos.dhcp.server_ident, (char*)&dhcp->options[i+2], len); + memcpy(&flow->protos.dhcp.server_ident, (char*)&dhcp->options[i+2], sizeof(flow->protos.dhcp.server_ident)); + else + memcpy(&flow->protos.dhcp.server_ident, (char*)&dhcp->options[i+2], len); } else if(id == 58) /* Renewal Time */ { if (len > sizeof(flow->protos.dhcp.renew_time)) - len = sizeof(flow->protos.dhcp.renew_time); - memcpy(&flow->protos.dhcp.renew_time, (char*)&dhcp->options[i+2], len); + memcpy(&flow->protos.dhcp.renew_time, (char*)&dhcp->options[i+2], sizeof(flow->protos.dhcp.renew_time)); + else + memcpy(&flow->protos.dhcp.renew_time, (char*)&dhcp->options[i+2], len); } From 27681e3fef09ef42cb9a404a513f8e2cc379ffec Mon Sep 17 00:00:00 2001 From: Henry Aidan Leta Date: Thu, 29 Sep 2022 11:46:53 -0400 Subject: [PATCH 5/6] refactor dhcp options length checking and add to dhcp valid bitmap --- src/include/ndpi_typedefs.h | 2 +- src/lib/protocols/dhcp.c | 25 ++++++------------------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index a6004dff4f1..aafd459f869 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1360,7 +1360,7 @@ struct ndpi_flow_struct { u_int32_t requested_ip; /* option 50 */ u_int32_t lease_time; /* option 51 */ u_int8_t msg_type; /* option 53 */ - u_int8_t valid; /* signifies valid dhcp resp */ + u_int8_t valid; /* signifies valid dhcp resp itmap for valid ip addr options as well 50,54 */ ndpi_ip_addr_t server_ident; /* option 54 */ char fingerprint[48]; /* option 55 */ u_int32_t renew_time; /* option 58 */ diff --git a/src/lib/protocols/dhcp.c b/src/lib/protocols/dhcp.c index 87fbd1124e6..593ee660c5b 100644 --- a/src/lib/protocols/dhcp.c +++ b/src/lib/protocols/dhcp.c @@ -194,29 +194,16 @@ void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struct, strncpy((char*)flow->protos.dhcp.domain_name, name, j); flow->protos.dhcp.domain_name[j] = '\0'; } else if(id == 50) /* Requested IP */ { - if (len > sizeof(flow->protos.dhcp.requested_ip)) - memcpy(&flow->protos.dhcp.requested_ip, (char*)&dhcp->options[i+2], sizeof(flow->protos.dhcp.requested_ip)); - else - memcpy(&flow->protos.dhcp.requested_ip, (char*)&dhcp->options[i+2], len); + flow->protos.dhcp.valid |= 0x02 ; + memcpy(&flow->protos.dhcp.requested_ip, (char*)&dhcp->options[i+2], ndpi_min(sizeof(flow->protos.dhcp.requested_ip), len)); } else if(id == 51) /* Lease Time */ { - if (len > sizeof(flow->protos.dhcp.lease_time)) - memcpy(&flow->protos.dhcp.lease_time, (char*)&dhcp->options[i+2], sizeof(flow->protos.dhcp.lease_time)); - else - memcpy(&flow->protos.dhcp.lease_time, (char*)&dhcp->options[i+2], len); + memcpy(&flow->protos.dhcp.lease_time, (char*)&dhcp->options[i+2], ndpi_min(sizeof(flow->protos.dhcp.lease_time),len)); } else if(id == 54) /* Server Identifier */ { - if (len > sizeof(flow->protos.dhcp.server_ident)) - memcpy(&flow->protos.dhcp.server_ident, (char*)&dhcp->options[i+2], sizeof(flow->protos.dhcp.server_ident)); - else - memcpy(&flow->protos.dhcp.server_ident, (char*)&dhcp->options[i+2], len); + flow->protos.dhcp.valid |= 0x04; + memcpy(&flow->protos.dhcp.server_ident, (char*)&dhcp->options[i+2], ndpi_min(sizeof(flow->protos.dhcp.server_ident), len)); } else if(id == 58) /* Renewal Time */ { - if (len > sizeof(flow->protos.dhcp.renew_time)) - memcpy(&flow->protos.dhcp.renew_time, (char*)&dhcp->options[i+2], sizeof(flow->protos.dhcp.renew_time)); - else - memcpy(&flow->protos.dhcp.renew_time, (char*)&dhcp->options[i+2], len); + memcpy(&flow->protos.dhcp.renew_time, (char*)&dhcp->options[i+2], ndpi_min(sizeof(flow->protos.dhcp.renew_time), len)); } - - - i += len + 2; } } From 894707d4f82de879487c06223d8a13d26ae7c428 Mon Sep 17 00:00:00 2001 From: Henry Aidan Leta Date: Thu, 29 Sep 2022 12:02:41 -0400 Subject: [PATCH 6/6] change assignemnt of dhcp.valid to match bitmap format --- src/lib/protocols/dhcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/protocols/dhcp.c b/src/lib/protocols/dhcp.c index 593ee660c5b..c7b31e236d1 100644 --- a/src/lib/protocols/dhcp.c +++ b/src/lib/protocols/dhcp.c @@ -113,7 +113,7 @@ void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struct, if(msg_type <= 8) { foundValidMsgType = 1; - flow->protos.dhcp.valid = 1; + flow->protos.dhcp.valid |= 0x01; break; } }