diff options
-rw-r--r-- | python/ndpi.py | 2 | ||||
-rw-r--r-- | python/ndpi_typestruct.py | 2 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 2 | ||||
-rw-r--r-- | src/lib/protocols/tftp.c | 116 | ||||
-rw-r--r-- | tests/pcap/tftp.pcap (renamed from tests/pcap/tftp_rrq.pcap) | bin | 31463 -> 32811 bytes | |||
-rw-r--r-- | tests/result/tftp.pcap.out | 10 | ||||
-rw-r--r-- | tests/result/tftp_rrq.pcap.out | 9 |
7 files changed, 107 insertions, 34 deletions
diff --git a/python/ndpi.py b/python/ndpi.py index 54e12b82b..61376fdbe 100644 --- a/python/ndpi.py +++ b/python/ndpi.py @@ -673,7 +673,7 @@ struct ndpi_flow_udp_struct { uint32_t halflife2_stage:2; // 0 - 2 /* NDPI_PROTOCOL_TFTP */ - uint32_t tftp_stage:1; + uint32_t tftp_stage:2; /* NDPI_PROTOCOL_AIMINI */ uint32_t aimini_stage:5; diff --git a/python/ndpi_typestruct.py b/python/ndpi_typestruct.py index b983a660c..1944a5f3c 100644 --- a/python/ndpi_typestruct.py +++ b/python/ndpi_typestruct.py @@ -426,7 +426,7 @@ class NDPIFlowUdpStruct(Structure): ('snmp_stage', c_uint32, 2), ('ppstream_stage', c_uint32, 3), ('halflife2_stage', c_uint32, 2), - ('tftp_stage', c_uint32, 1), + ('tftp_stage', c_uint32, 2), ('aimini_stage', c_uint32, 5), ('xbox_stage', c_uint32, 1), ('wsus_stage', c_uint32, 1), diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 1237542c6..a63524c8f 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -811,7 +811,7 @@ struct ndpi_flow_udp_struct { u_int32_t halflife2_stage:2; // 0 - 2 /* NDPI_PROTOCOL_TFTP */ - u_int32_t tftp_stage:1; + u_int32_t tftp_stage:2; /* NDPI_PROTOCOL_AIMINI */ u_int32_t aimini_stage:5; 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); } diff --git a/tests/pcap/tftp_rrq.pcap b/tests/pcap/tftp.pcap Binary files differindex 6c5efa8ba..9c3cb2cbf 100644 --- a/tests/pcap/tftp_rrq.pcap +++ b/tests/pcap/tftp.pcap diff --git a/tests/result/tftp.pcap.out b/tests/result/tftp.pcap.out new file mode 100644 index 000000000..9fa439cbe --- /dev/null +++ b/tests/result/tftp.pcap.out @@ -0,0 +1,10 @@ +Guessed flow protos: 0 + +DPI Packets (UDP): 10 (2.50 pkts/flow) + +TFTP 104 31123 4 + + 1 UDP 192.168.0.10:3445 <-> 192.168.0.253:50618 [proto: 96/TFTP][cat: DataTransfer/4][49 pkts/26853 bytes <-> 49 pkts/2940 bytes][Goodput ratio: 92/7][0.18 sec][bytes ratio: 0.803 (Upload)][IAT c2s/s2c min/avg/max/stddev: 2/2 3/3 9/7 2/2][Pkt Len c2s/s2c min/avg/max/stddev: 69/60 548/60 558/60 69/0][Risk: ** Known protocol on non standard port **][Risk Score: 10][PLAIN TEXT (Network Working Group )][Plen Bins: 51,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + 2 UDP 172.28.5.170:62058 <-> 172.28.5.91:44618 [proto: 96/TFTP][cat: DataTransfer/4][2 pkts/92 bytes <-> 2 pkts/1116 bytes][Goodput ratio: 9/92][0.00 sec][Risk: ** Known protocol on non standard port **][Risk Score: 10][PLAIN TEXT (BCCCCCC)][Plen Bins: 50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + 3 UDP 192.168.0.253:50618 -> 192.168.0.10:69 [proto: 96/TFTP][cat: DataTransfer/4][1 pkts/62 bytes -> 0 pkts/0 bytes][Goodput ratio: 32/0][< 1 sec][PLAIN TEXT (1350.txt)][Plen Bins: 100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + 4 UDP 172.28.5.91:44618 -> 172.28.5.170:69 [proto: 96/TFTP][cat: DataTransfer/4][1 pkts/60 bytes -> 0 pkts/0 bytes][Goodput ratio: 30/0][< 1 sec][PLAIN TEXT (zz.bin)][Plen Bins: 100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] diff --git a/tests/result/tftp_rrq.pcap.out b/tests/result/tftp_rrq.pcap.out deleted file mode 100644 index 2d2c1e6b5..000000000 --- a/tests/result/tftp_rrq.pcap.out +++ /dev/null @@ -1,9 +0,0 @@ -Guessed flow protos: 1 - -DPI Packets (UDP): 3 (1.50 pkts/flow) - -STUN 1 62 1 -TFTP 98 29793 1 - - 1 UDP 192.168.0.10:3445 <-> 192.168.0.253:50618 [proto: 96/TFTP][cat: DataTransfer/4][49 pkts/26853 bytes <-> 49 pkts/2940 bytes][Goodput ratio: 92/7][0.18 sec][bytes ratio: 0.803 (Upload)][IAT c2s/s2c min/avg/max/stddev: 2/2 3/3 9/7 2/2][Pkt Len c2s/s2c min/avg/max/stddev: 69/60 548/60 558/60 69/0][Risk: ** Known protocol on non standard port **][Risk Score: 10][PLAIN TEXT (Network Working Group )][Plen Bins: 51,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] - 2 UDP 192.168.0.253:50618 -> 192.168.0.10:69 [proto: 78/STUN][cat: Network/14][1 pkts/62 bytes -> 0 pkts/0 bytes][Goodput ratio: 32/0][< 1 sec][PLAIN TEXT (1350.txt)][Plen Bins: 100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] |