aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols/tftp.c
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 /src/lib/protocols/tftp.c
parenta482e1c0becfa48969e3e01dcab7e76907e0484d (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.c116
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);
}