aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni <matzeton@googlemail.com>2021-07-25 21:54:19 +0200
committerGitHub <noreply@github.com>2021-07-25 21:54:19 +0200
commit29ec34f66d91004f460aa6d4f3e28d75b78c9aa5 (patch)
tree5009728c82d671ff11a859782b879801c5b96c37
parenta482e1c0becfa48969e3e01dcab7e76907e0484d (diff)
Improved TFTP detection. Fixes #1242, #1256 (#1262)
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r--python/ndpi.py2
-rw-r--r--python/ndpi_typestruct.py2
-rw-r--r--src/include/ndpi_typedefs.h2
-rw-r--r--src/lib/protocols/tftp.c116
-rw-r--r--tests/pcap/tftp.pcap (renamed from tests/pcap/tftp_rrq.pcap)bin31463 -> 32811 bytes
-rw-r--r--tests/result/tftp.pcap.out10
-rw-r--r--tests/result/tftp_rrq.pcap.out9
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
index 6c5efa8ba..9c3cb2cbf 100644
--- a/tests/pcap/tftp_rrq.pcap
+++ b/tests/pcap/tftp.pcap
Binary files differ
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]