1+ /*
2+ * ZMap Copyright 2013 Regents of the University of Michigan
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+ * use this file except in compliance with the License. You may obtain a copy
6+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
7+ */
8+
9+ #include <stdlib.h>
10+ #include <stdio.h>
11+ #include <stdint.h>
12+ #include <unistd.h>
13+ #include <string.h>
14+ #include <assert.h>
15+
16+ #include "../../lib/includes.h"
17+ #include "../../lib/logger.h"
18+ #include "../../lib/xalloc.h"
19+ #include "../fieldset.h"
20+ #include "probe_modules.h"
21+ #include "packet.h"
22+ #include "module_udp.h"
23+
24+ #define TFTP_QUERY "\0\1ay9mfwq7xxmd4w6cz\0octet\0" // try to read random filename
25+ static const char * tftp_query = TFTP_QUERY ;
26+ static const long unsigned int tftp_query_len = sizeof (TFTP_QUERY ) - 1 ; // -1 for terminating zero
27+
28+ probe_module_t module_tftp ;
29+
30+ int tftp_global_initialize (struct state_conf * state )
31+ {
32+ int num_ports = state -> source_port_last - state -> source_port_first + 1 ;
33+ udp_set_num_ports (num_ports );
34+ return EXIT_SUCCESS ;
35+ }
36+
37+ int tftp_init_perthread (void * buf , macaddr_t * src , macaddr_t * gw ,
38+ port_h_t dst_port ,
39+ __attribute__((unused )) void * * arg_ptr )
40+ {
41+ memset (buf , 0 , MAX_PACKET_SIZE );
42+ struct ether_header * eth_header = (struct ether_header * )buf ;
43+ make_eth_header (eth_header , src , gw );
44+ struct ip * ip_header = (struct ip * )(& eth_header [1 ]);
45+
46+ uint16_t len = htons (sizeof (struct ip ) + sizeof (struct udphdr ) +
47+ tftp_query_len );
48+ make_ip_header (ip_header , IPPROTO_UDP , len );
49+
50+ struct udphdr * udp_header = (struct udphdr * )(& ip_header [1 ]);
51+ len = sizeof (struct udphdr ) + tftp_query_len ;
52+ make_udp_header (udp_header , dst_port , len );
53+
54+ char * payload = (char * )(& udp_header [1 ]);
55+
56+ assert (sizeof (struct ether_header ) + sizeof (struct ip ) +
57+ sizeof (struct udphdr ) + tftp_query_len <=
58+ MAX_PACKET_SIZE );
59+
60+ assert (MAX_PACKET_SIZE - ((char * )payload - (char * )buf ) >
61+ (int )tftp_query_len );
62+ memcpy (payload , tftp_query , tftp_query_len );
63+
64+ return EXIT_SUCCESS ;
65+ }
66+
67+ int tftp_validate_packet (const struct ip * ip_hdr , uint32_t len ,
68+ uint32_t * src_ip , uint32_t * validation )
69+ {
70+ if (!((ip_hdr -> ip_p != IPPROTO_UDP ) && (ip_hdr -> ip_p != IPPROTO_ICMP )) || !blacklist_is_allowed (* src_ip )) {
71+ return PACKET_INVALID ;
72+ }
73+ return PACKET_VALID ;
74+ }
75+
76+ void tftp_process_packet (const u_char * packet ,
77+ __attribute__((unused )) uint32_t len , fieldset_t * fs ,
78+ __attribute__((unused )) uint32_t * validation )
79+ {
80+ struct ip * ip_hdr = (struct ip * )& packet [sizeof (struct ether_header )];
81+ struct udphdr * udp =
82+ (struct udphdr * )((char * )ip_hdr + ip_hdr -> ip_hl * 4 );
83+ char * payload = (char * )(& udp [1 ]);
84+ uint16_t plen = ntohs (udp -> uh_ulen );
85+
86+ if (ip_hdr -> ip_p == IPPROTO_UDP && plen > 1 && payload [0 ] == 0 && payload [1 ] == 5 ) {
87+ fs_add_string (fs , "classification" , (char * )"TFTP" , 0 );
88+ fs_add_bool (fs , "success" , 1 );
89+ fs_add_binary (fs , "data" ,
90+ (ntohs (udp -> uh_ulen ) - sizeof (struct udphdr )),
91+ (void * )& udp [1 ], 0 );
92+ } else {
93+ fs_add_string (fs , "classification" , (char * )"other" , 0 );
94+ fs_add_bool (fs , "success" , 0 );
95+ fs_add_null (fs , "data" );
96+ }
97+ }
98+
99+ static fielddef_t fields [] = {
100+ {.name = "classification" ,
101+ .type = "string" ,
102+ .desc = "packet classification" },
103+ {.name = "success" ,
104+ .type = "bool" ,
105+ .desc = "is response considered success" },
106+ {.name = "data" , .type = "binary" , .desc = "UDP payload" }};
107+
108+ probe_module_t module_tftp = {
109+ .name = "tftp" ,
110+ .packet_length = 125 ,
111+ .pcap_filter = "udp || icmp" ,
112+ .pcap_snaplen = 2048 ,
113+ .port_args = 1 ,
114+ .global_initialize = & tftp_global_initialize ,
115+ .thread_initialize = & tftp_init_perthread ,
116+ .make_packet = & udp_make_packet ,
117+ .print_packet = & udp_print_packet ,
118+ .process_packet = & tftp_process_packet ,
119+ .validate_packet = & tftp_validate_packet ,
120+ // UPnP isn't actually dynamic, however, we don't handle escaping
121+ // properly in the CSV module and this will force users to use JSON.
122+ .output_type = OUTPUT_TYPE_DYNAMIC ,
123+ .close = NULL ,
124+ .helptext = "Probe module that sends a TFTP read request for random filename and expects TFTP error packet in response." ,
125+ .fields = fields ,
126+ .numfields = sizeof (fields ) / sizeof (fields [0 ])};
0 commit comments