diff options
author | Toni <matzeton@googlemail.com> | 2021-07-25 21:54:19 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-25 21:54:19 +0200 |
commit | 29ec34f66d91004f460aa6d4f3e28d75b78c9aa5 (patch) | |
tree | 5009728c82d671ff11a859782b879801c5b96c37 /src/lib/protocols/tftp.c | |
parent | a482e1c0becfa48969e3e01dcab7e76907e0484d (diff) |
Improved TFTP detection. Fixes #1242, #1256 (#1262)
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'src/lib/protocols/tftp.c')
-rw-r--r-- | src/lib/protocols/tftp.c | 116 |
1 files changed, 94 insertions, 22 deletions
diff --git a/src/lib/protocols/tftp.c b/src/lib/protocols/tftp.c index 55d5b8cec..f783353d0 100644 --- a/src/lib/protocols/tftp.c +++ b/src/lib/protocols/tftp.c @@ -28,6 +28,8 @@ #include "ndpi_api.h" +/* see: https://datatracker.ietf.org/doc/html/rfc1350 */ + static void ndpi_int_tftp_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { @@ -41,32 +43,102 @@ void ndpi_search_tftp(struct ndpi_detection_module_struct NDPI_LOG_DBG(ndpi_struct, "search TFTP\n"); - if ((packet->payload_packet_len > 3) - && (flow->l4.udp.tftp_stage == 0) - && (ntohl(get_u_int32_t(packet->payload, 0)) == 0x00030001)) { - NDPI_LOG_DBG2(ndpi_struct, "maybe tftp. need next packet\n"); - flow->l4.udp.tftp_stage = 1; + if (packet->payload_packet_len < 4 /* min. header size */ || + get_u_int8_t(packet->payload, 0) != 0x00) + { + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); return; } - if(flow->l4.udp.tftp_stage == 1) { - if (packet->payload_packet_len > 3 && (flow->l4.udp.tftp_stage == 1) - && ntohl(get_u_int32_t(packet->payload, 0)) == 0x00040001) { - - NDPI_LOG_INFO(ndpi_struct, "found tftp\n"); - ndpi_int_tftp_add_connection(ndpi_struct, flow); - return; - } - - if (packet->payload_packet_len > 1 - && ((packet->payload[0] == 0 && packet->payload[packet->payload_packet_len - 1] == 0) - || (packet->payload_packet_len == 4 && ntohl(get_u_int32_t(packet->payload, 0)) == 0x00040000))) { - NDPI_LOG_DBG2(ndpi_struct, "skip initial packet\n"); - return; - } + /* parse TFTP opcode */ + switch (get_u_int8_t(packet->payload, 1)) + { + case 0x01: + /* Read request (RRQ) */ + case 0x02: + /* Write request (WWQ) */ + + if (packet->payload[packet->payload_packet_len - 1] != 0x00 /* last pdu element is a nul terminated string */) + { + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); + return; + } + + { + char const * const possible_modes[] = { "netascii", "octet", "mail" }; + uint8_t mode_found = 0; + for (uint8_t mode_idx = 0; mode_idx < sizeof(possible_modes) / sizeof(possible_modes[0]); ++mode_idx) + { + size_t const mode_len = strlen(possible_modes[mode_idx]); + + if (packet->payload_packet_len < mode_len + 1 /* mode is a nul terminated string */) + { + continue; + } + if (strncasecmp((char const *)&packet->payload[packet->payload_packet_len - 1 - mode_len], + possible_modes[mode_idx], mode_len) == 0) + { + mode_found = 1; + break; + } + } + + if (mode_found == 0) + { + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); + return; + } + + /* We have seen enough and do not need any more TFTP packets. */ + NDPI_LOG_INFO(ndpi_struct, "found tftp (RRQ/WWQ)\n"); + ndpi_int_tftp_add_connection(ndpi_struct, flow); + } + return; + + case 0x03: + /* Data (DATA) */ + if (packet->payload_packet_len > 4 /* DATA header size */ + 512 /* max. block size */) + { + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); + return; + } + break; + + case 0x04: + /* Acknowledgment (ACK) */ + if (packet->payload_packet_len != 4 /* ACK has a fixed packet size */) + { + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); + return; + } + break; + + case 0x05: + /* Error (ERROR) */ + + if (packet->payload_packet_len < 5 || + packet->payload[packet->payload_packet_len - 1] != 0x00 || + packet->payload[2] != 0x00 || packet->payload[3] > 0x07) + { + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); + return; + } + break; + + default: + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); + return; + } + + if (flow->l4.udp.tftp_stage < 3) + { + NDPI_LOG_DBG2(ndpi_struct, "maybe tftp. need next packet\n"); + flow->l4.udp.tftp_stage++; + return; } - - NDPI_EXCLUDE_PROTO(ndpi_struct, flow); + + NDPI_LOG_INFO(ndpi_struct, "found tftp\n"); + ndpi_int_tftp_add_connection(ndpi_struct, flow); } |