4
* Copyright (C) 2009-2011 by ipoque GmbH
5
* Copyright (C) 2011-13 - ntop.org
7
* This file is part of nDPI, an open source deep packet inspection
8
* library based on the OpenDPI and PACE technology by ipoque GmbH
10
* nDPI is free software: you can redistribute it and/or modify
11
* it under the terms of the GNU Lesser General Public License as published by
12
* the Free Software Foundation, either version 3 of the License, or
13
* (at your option) any later version.
15
* nDPI is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU Lesser General Public License for more details.
20
* You should have received a copy of the GNU Lesser General Public License
21
* along with nDPI. If not, see <http://www.gnu.org/licenses/>.
28
#include "ndpi_protocols.h"
30
#ifdef NDPI_PROTOCOL_GNUTELLA
32
static void ndpi_int_gnutella_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
33
struct ndpi_flow_struct *flow,
34
ndpi_protocol_type_t protocol_type)
37
struct ndpi_packet_struct *packet = &flow->packet;
38
struct ndpi_id_struct *src = flow->src;
39
struct ndpi_id_struct *dst = flow->dst;
41
ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_GNUTELLA, protocol_type);
44
src->gnutella_ts = packet->tick_timestamp;
45
if (packet->udp != NULL) {
46
if (!src->detected_gnutella_udp_port1) {
47
src->detected_gnutella_udp_port1 = (packet->udp->source);
48
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
49
NDPI_LOG_DEBUG, "GNUTELLA UDP PORT1 DETECTED as %u\n",
50
src->detected_gnutella_udp_port1);
52
} else if ((ntohs(packet->udp->source) != src->detected_gnutella_udp_port1)
53
&& !src->detected_gnutella_udp_port2) {
54
src->detected_gnutella_udp_port2 = (packet->udp->source);
55
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
56
NDPI_LOG_DEBUG, "GNUTELLA UDP PORT2 DETECTED as %u\n",
57
src->detected_gnutella_udp_port2);
63
dst->gnutella_ts = packet->tick_timestamp;
67
void ndpi_search_gnutella(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
69
struct ndpi_packet_struct *packet = &flow->packet;
71
struct ndpi_id_struct *src = flow->src;
72
struct ndpi_id_struct *dst = flow->dst;
75
if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_GNUTELLA) {
76
if (src != NULL && ((u_int32_t)
77
(packet->tick_timestamp - src->gnutella_ts) < ndpi_struct->gnutella_timeout)) {
78
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
79
NDPI_LOG_DEBUG, "gnutella : save src connection packet detected\n");
80
src->gnutella_ts = packet->tick_timestamp;
81
} else if (dst != NULL && ((u_int32_t)
82
(packet->tick_timestamp - dst->gnutella_ts) < ndpi_struct->gnutella_timeout)) {
83
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
84
NDPI_LOG_DEBUG, "gnutella : save dst connection packet detected\n");
85
dst->gnutella_ts = packet->tick_timestamp;
87
if (src != NULL && (packet->tick_timestamp - src->gnutella_ts) > ndpi_struct->gnutella_timeout) {
88
src->detected_gnutella_udp_port1 = 0;
89
src->detected_gnutella_udp_port2 = 0;
91
if (dst != NULL && (packet->tick_timestamp - dst->gnutella_ts) > ndpi_struct->gnutella_timeout) {
92
dst->detected_gnutella_udp_port1 = 0;
93
dst->detected_gnutella_udp_port2 = 0;
99
/* skip packets without payload */
100
if (packet->payload_packet_len < 2) {
103
if (packet->tcp != NULL) {
104
/* this case works asymmetrically */
105
if (packet->payload_packet_len > 10 && memcmp(packet->payload, "GNUTELLA/", 9) == 0) {
106
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "GNUTELLA DETECTED\n");
107
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
110
/* this case works asymmetrically */
111
if (packet->payload_packet_len > 17 && memcmp(packet->payload, "GNUTELLA CONNECT/", 17) == 0) {
112
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "GNUTELLA DETECTED\n");
113
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
117
if (packet->payload_packet_len > 50 && ((memcmp(packet->payload, "GET /get/", 9) == 0)
118
|| (memcmp(packet->payload, "GET /uri-res/", 13) == 0)
120
ndpi_parse_packet_line_info(ndpi_struct, flow);
121
for (c = 0; c < packet->parsed_lines; c++) {
122
if ((packet->line[c].len > 19 && memcmp(packet->line[c].ptr, "User-Agent: Gnutella", 20) == 0)
123
|| (packet->line[c].len > 10 && memcmp(packet->line[c].ptr, "X-Gnutella-", 11) == 0)
124
|| (packet->line[c].len > 7 && memcmp(packet->line[c].ptr, "X-Queue:", 8) == 0)
125
|| (packet->line[c].len > 36 && memcmp(packet->line[c].ptr,
126
"Content-Type: application/x-gnutella-", 37) == 0)) {
127
NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG, "DETECTED GNUTELLA GET.\n");
128
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
133
if (packet->payload_packet_len > 50 && ((memcmp(packet->payload, "GET / HTTP", 9) == 0))) {
134
ndpi_parse_packet_line_info(ndpi_struct, flow);
135
if ((packet->user_agent_line.ptr != NULL && packet->user_agent_line.len > 15
136
&& memcmp(packet->user_agent_line.ptr, "BearShare Lite ", 15) == 0)
137
|| (packet->accept_line.ptr != NULL && packet->accept_line.len > 24
138
&& memcmp(packet->accept_line.ptr, "application n/x-gnutella", 24) == 0)) {
139
NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG, "DETECTED GNUTELLA GET.\n");
140
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
144
/* haven't found this pattern in any trace. */
145
if (packet->payload_packet_len > 50 && ((memcmp(packet->payload, "GET /get/", 9) == 0)
146
|| (memcmp(packet->payload, "GET /uri-res/", 13) == 0))) {
148
while (c < (packet->payload_packet_len - 9)) {
149
if (packet->payload[c] == '?')
154
if (c < (packet->payload_packet_len - 9) && memcmp(&packet->payload[c], "urn:sha1:", 9) == 0) {
155
NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE,
156
"detected GET /get/ or GET /uri-res/.\n");
157
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
162
/* answer to this packet is HTTP/1.1 ..... Content-Type: application/x-gnutella-packets,
163
* it is searched in the upper paragraph. */
164
if (packet->payload_packet_len > 30 && memcmp(packet->payload, "HEAD /gnutella/push-proxy?", 26) == 0) {
165
NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "detected HEAD /gnutella/push-proxy?\n");
166
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
169
/* haven't found any trace with this pattern */
170
if (packet->payload_packet_len == 46
171
&& memcmp(packet->payload, "\x50\x55\x53\x48\x20\x67\x75\x69\x64\x3a", 10) == 0) {
172
NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE,
173
"detected \x50\x55\x53\x48\x20\x67\x75\x69\x64\x3a\n");
174
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
177
/* haven't found any trace with this pattern */
178
if (packet->payload_packet_len > 250 && memcmp(packet->payload, "GET /gnutella/", 14) == 0)
179
//PATTERN IS :: GET /gnutella/tigertree/v3?urn:tree:tiger/:
181
const u_int16_t end = packet->payload_packet_len - 3;
185
if ((memcmp(&packet->payload[14], "tigertree/", 10) == 0)
186
|| (end - c > 18 && memcmp(&packet->payload[c], "\r\nUser-Agent: Foxy", 18) == 0)
188
&& memcmp(&packet->payload[c],
189
"\r\nAccept: application/tigertree-breadthfirst",
190
44) == 0) || (end - c > 10 && memcmp(&packet->payload[c], "\r\nX-Queue:", 10) == 0)
191
|| (end - c > 13 && memcmp(&packet->payload[c], "\r\nX-Features:", 13) == 0)) {
193
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA,
194
ndpi_struct, NDPI_LOG_TRACE, "FOXY :: GNUTELLA GET 2 DETECTED\n");
195
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
202
/* haven't found any trace with this pattern */
203
if (packet->payload_packet_len > 1 && packet->payload[packet->payload_packet_len - 1] == 0x0a
204
&& packet->payload[packet->payload_packet_len - 2] == 0x0a) {
205
if (packet->payload_packet_len > 3 && memcmp(packet->payload, "GIV", 3) == 0) {
206
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "MORPHEUS GIV DETECTED\n");
207
/* Not Excludeing the flow now.. We shall Check the next Packet too for Gnutella Patterns */
211
/* might be super tricky new ssl gnutella transmission, but the certificate is strange... */
212
if (packet->payload_packet_len == 46 && get_u_int32_t(packet->payload, 0) == htonl(0x802c0103) &&
213
get_u_int32_t(packet->payload, 4) == htonl(0x01000300) && get_u_int32_t(packet->payload, 8) == htonl(0x00002000) &&
214
get_u_int16_t(packet->payload, 12) == htons(0x0034)) {
215
NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "detected gnutella len == 46.\n");
216
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
219
if (packet->payload_packet_len == 49 &&
220
memcmp(packet->payload, "\x80\x2f\x01\x03\x01\x00\x06\x00\x00\x00\x20\x00\x00\x34\x00\x00\xff\x4d\x6c",
222
NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "detected gnutella len == 49.\n");
223
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
226
if (packet->payload_packet_len == 89 && memcmp(&packet->payload[43], "\x20\x4d\x6c", 3) == 0 &&
227
memcmp(packet->payload, "\x16\x03\x01\x00\x54\x01\x00\x00\x50\x03\x01\x4d\x6c", 13) == 0 &&
228
memcmp(&packet->payload[76], "\x00\x02\x00\x34\x01\x00\x00\x05", 8) == 0) {
229
NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE,
230
"detected gnutella asymmetrically len == 388.\n");
231
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
233
} else if (packet->payload_packet_len == 82) {
234
if (get_u_int32_t(packet->payload, 0) == htonl(0x16030100)
235
&& get_u_int32_t(packet->payload, 4) == htonl(0x4d010000)
236
&& get_u_int16_t(packet->payload, 8) == htons(0x4903)
237
&& get_u_int16_t(packet->payload, 76) == htons(0x0002)
238
&& get_u_int32_t(packet->payload, 78) == htonl(0x00340100)) {
239
NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "detected len == 82.\n");
240
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
244
} else if (packet->udp != NULL) {
245
if (src != NULL && (packet->udp->source == src->detected_gnutella_udp_port1 ||
246
packet->udp->source == src->detected_gnutella_udp_port2) &&
247
(packet->tick_timestamp - src->gnutella_ts) < ndpi_struct->gnutella_timeout) {
248
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG, "port based detection\n\n");
249
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
252
* all the following patterns send out many packets which are the only ones of their flows,
253
* often on the very beginning of the traces, or flows with many packets in one direction only.
254
* but then suddenly, one gets an answer as you can see in netpeker-gnutella-rpc.pcap packet 11483.
255
* Maybe gnutella tries to send out keys?
257
if (packet->payload_packet_len == 23 && packet->payload[15] == 0x00
258
&& packet->payload[16] == 0x41 && packet->payload[17] == 0x01
259
&& packet->payload[18] == 0x00 && packet->payload[19] == 0x00
260
&& packet->payload[20] == 0x00 && packet->payload[21] == 0x00 && packet->payload[22] == 0x00) {
261
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
262
"detected gnutella udp, len = 23.\n");
263
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
267
if (packet->payload_packet_len == 35 && packet->payload[25] == 0x49
268
&& packet->payload[26] == 0x50 && packet->payload[27] == 0x40
269
&& packet->payload[28] == 0x83 && packet->payload[29] == 0x53
270
&& packet->payload[30] == 0x43 && packet->payload[31] == 0x50 && packet->payload[32] == 0x41) {
271
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
272
"detected gnutella udp, len = 35.\n");
273
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
276
if (packet->payload_packet_len == 32
277
&& (memcmp(&packet->payload[16], "\x31\x01\x00\x09\x00\x00\x00\x4c\x49\x4d\x45", 11) == 0)) {
278
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
279
"detected gnutella udp, len = 32.\n");
280
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
283
if (packet->payload_packet_len == 34 && (memcmp(&packet->payload[25], "SCP@", 4) == 0)
284
&& (memcmp(&packet->payload[30], "DNA@", 4) == 0)) {
285
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
286
"detected gnutella udp, len = 34.\n");
287
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
290
if ((packet->payload_packet_len == 73 || packet->payload_packet_len == 96)
291
&& memcmp(&packet->payload[32], "urn:sha1:", 9) == 0) {
292
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
293
"detected gnutella udp, len = 73,96.\n");
294
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
298
if (memcmp(packet->payload, "GND", 3) == 0) {
299
if ((packet->payload_packet_len == 8 && (memcmp(&packet->payload[6], "\x01\x00", 2) == 0))
300
|| (packet->payload_packet_len == 11 && (memcmp(&packet->payload[6], "\x01\x01\x08\x50\x49", 5)
301
== 0)) || (packet->payload_packet_len == 17
304
(&packet->payload[6], "\x01\x01\x4c\x05\x50",
306
|| (packet->payload_packet_len == 28
307
&& (memcmp(&packet->payload[6], "\x01\x01\x54\x0f\x51\x4b\x52\x50\x06\x52", 10) == 0))
308
|| (packet->payload_packet_len == 41
309
&& (memcmp(&packet->payload[6], "\x01\x01\x5c\x1b\x50\x55\x53\x48\x48\x10", 10) == 0))
310
|| (packet->payload_packet_len > 200 && packet->payload_packet_len < 300 && packet->payload[3] == 0x03)
311
|| (packet->payload_packet_len > 300 && (packet->payload[3] == 0x01 || packet->payload[3] == 0x03))) {
312
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
313
"detected gnutella udp, GND.\n");
314
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
319
if ((packet->payload_packet_len == 32)
320
&& memcmp(&packet->payload[16], "\x31\x01\x00\x09\x00\x00\x00", 7) == 0) {
321
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
322
"detected gnutella udp, len = 32 ii.\n");
323
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
326
if ((packet->payload_packet_len == 23)
327
&& memcmp(&packet->payload[16], "\x00\x01\x00\x00\x00\x00\x00", 7) == 0) {
328
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
329
"detected gnutella udp, len = 23 ii.\n");
330
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
334
//neonet detection follows
336
/* haven't found any trace with this pattern */
337
if (packet->tcp != NULL && ntohs(packet->tcp->source) >= 1024 && ntohs(packet->tcp->dest) >= 1024) {
338
if (flow->l4.tcp.gnutella_stage == 0) {
339
if (flow->packet_counter == 1
340
&& (packet->payload_packet_len == 11
341
|| packet->payload_packet_len == 33 || packet->payload_packet_len == 37)) {
342
flow->l4.tcp.gnutella_msg_id[0] = packet->payload[4];
343
flow->l4.tcp.gnutella_msg_id[1] = packet->payload[6];
344
flow->l4.tcp.gnutella_msg_id[2] = packet->payload[8];
345
flow->l4.tcp.gnutella_stage = 1 + packet->packet_direction;
348
} else if (flow->l4.tcp.gnutella_stage == 1 + packet->packet_direction) {
349
if (flow->packet_counter == 2 && (packet->payload_packet_len == 33 || packet->payload_packet_len == 22)
350
&& flow->l4.tcp.gnutella_msg_id[0] == packet->payload[0]
351
&& flow->l4.tcp.gnutella_msg_id[1] == packet->payload[2]
352
&& flow->l4.tcp.gnutella_msg_id[2] == packet->payload[4]
353
&& NDPI_SRC_OR_DST_HAS_PROTOCOL(src, dst, NDPI_PROTOCOL_GNUTELLA)) {
354
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
355
NDPI_LOG_TRACE, "GNUTELLA DETECTED due to message ID match (NEONet protocol)\n");
356
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
359
} else if (flow->l4.tcp.gnutella_stage == 2 - packet->packet_direction) {
360
if (flow->packet_counter == 2 && (packet->payload_packet_len == 10 || packet->payload_packet_len == 75)
361
&& flow->l4.tcp.gnutella_msg_id[0] == packet->payload[0]
362
&& flow->l4.tcp.gnutella_msg_id[1] == packet->payload[2]
363
&& flow->l4.tcp.gnutella_msg_id[2] == packet->payload[4]
364
&& NDPI_SRC_OR_DST_HAS_PROTOCOL(src, dst, NDPI_PROTOCOL_GNUTELLA)) {
365
NDPI_LOG_GNUTELLA(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
366
NDPI_LOG_TRACE, "GNUTELLA DETECTED due to message ID match (NEONet protocol)\n");
367
ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
373
NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_GNUTELLA);