Coverage Report

Created: 2025-11-06 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ndpi/src/lib/protocols/z3950.c
Line
Count
Source
1
/*
2
 * z3950.c
3
 *
4
 * Copyright (C) 2012-22 - ntop.org
5
 *
6
 * This module is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This module is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License.
17
 * If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 */
20
21
#include "ndpi_protocol_ids.h"
22
23
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_Z3950
24
25
#include "ndpi_api.h"
26
#include "ndpi_private.h"
27
28
/* https://github.com/wireshark/wireshark/blob/master/epan/dissectors/asn1/z3950/z3950.asn */
29
30
static void ndpi_int_z3950_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
31
0
                                          struct ndpi_flow_struct *flow) {
32
0
  ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_Z3950, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
33
0
}
34
35
/* ***************************************************************** */
36
37
static int z3950_parse_sequences(struct ndpi_flow_struct *flow, struct ndpi_packet_struct const * const packet,
38
0
                                 int max_sequences) {
39
0
  size_t payload_offset = 2;
40
0
  int cur_sequences = 0;
41
0
  u_int8_t pdu_type;
42
43
0
  pdu_type = packet->payload[0] & 0x1F;
44
45
0
  if((pdu_type < 20) || ((pdu_type > 36) && ((pdu_type < 43) || (pdu_type > 48))))
46
0
    return(-1);  
47
48
  /* Simple check to avoid false positives: the first pkt after the 3WHS
49
     should be a initRequest or a initResponse */
50
0
  if(ndpi_seen_flow_beginning(flow) && flow->packet_counter == 1 &&
51
0
     pdu_type != 20 && pdu_type != 21)
52
0
    return(-1);
53
54
0
  while(cur_sequences++ < max_sequences) {
55
0
    u_int8_t const * payload;
56
0
    u_int8_t seq_type;
57
0
    u_int8_t seq_length;
58
    
59
0
    if((payload_offset + 2) >= packet->payload_packet_len)
60
0
      return(-1);
61
62
0
    payload = &packet->payload[payload_offset];
63
64
0
    if((payload[0] & 0x1F) == 0x1F)
65
      /* We ignore decoding of complex sequences for now. */
66
0
      return(cur_sequences);
67
0
    else
68
0
      seq_type = payload[0] & 0x1F;
69
      
70
0
    seq_length = payload[1];
71
72
0
    if(seq_type > 51 && (seq_type < 100 || seq_type > 105) &&
73
0
       (seq_type < 110 || seq_type > 112) && (seq_type < 120 || seq_type > 121) &&
74
0
       (seq_type < 201 || seq_type > 221))
75
0
      return(-1);
76
77
0
    if(seq_length >= packet->payload_packet_len - payload_offset + 1)
78
0
      return(-1);
79
80
0
    payload_offset += seq_length + 2;
81
82
0
    if(payload_offset == packet->payload_packet_len)
83
0
      return(cur_sequences);
84
0
  }
85
86
0
  return(cur_sequences - 1);
87
0
}
88
89
/* ***************************************************************** */
90
91
static void ndpi_search_z3950(struct ndpi_detection_module_struct *ndpi_struct,
92
0
                              struct ndpi_flow_struct *flow) {
93
0
  struct ndpi_packet_struct * packet = &ndpi_struct->packet;
94
0
  int const minimum_expected_sequences = 6;
95
96
0
  NDPI_LOG_DBG(ndpi_struct, "search z39.50\n");
97
98
0
  if(packet->tcp != NULL && packet->payload_packet_len >= 6 &&
99
0
     flow->packet_counter >= 1 && flow->packet_counter <= 8) {
100
0
    int ret = z3950_parse_sequences(flow, packet, minimum_expected_sequences);
101
102
0
    if(ret < 0) {
103
0
      NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);
104
0
      return;
105
0
    }
106
107
0
    if(ret < minimum_expected_sequences) {
108
      /* We've seen not enough sequences, wait for the next packet. */
109
0
      return;
110
0
    }
111
112
0
    if(flow->l4.tcp.z3950_stage == 3) {
113
0
      if(flow->packet_direction_counter[0] && flow->packet_direction_counter[1])
114
0
  ndpi_int_z3950_add_connection(ndpi_struct, flow);
115
0
      else
116
0
  NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);  /* Skip if unidirectional traffic */
117
0
    } else
118
0
      flow->l4.tcp.z3950_stage++;
119
120
0
    return;
121
0
  }
122
123
0
  NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);
124
0
}
125
126
/* ***************************************************************** */
127
128
0
void init_z3950_dissector(struct ndpi_detection_module_struct *ndpi_struct) {
129
0
  register_dissector("Z3950", ndpi_struct,
130
0
                     ndpi_search_z3950,
131
0
                     NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
132
0
                     1, NDPI_PROTOCOL_Z3950);
133
0
}