Coverage Report

Created: 2024-01-13 07:07

/src/ndpi/src/lib/protocols/mongodb.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * mongodb.c
3
 *
4
 * Copyright (C) 2018 by Leonn Paiva <leonn.paiva@gmail.com>
5
 *
6
 * This file is part of nDPI, an open source deep packet inspection
7
 * library based on the OpenDPI and PACE technology by ipoque GmbH
8
 *
9
 * nDPI is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Lesser General Public License as published by
11
 * the Free Software Foundation, either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * nDPI is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with nDPI.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "ndpi_protocol_ids.h"
24
25
83.6k
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_MONGODB
26
27
#include "ndpi_api.h"
28
#include "ndpi_private.h"
29
30
/* https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/ */
31
32
enum mongo_opcodes
33
  {
34
    OP_REPLY = 1,
35
    OP_UPDATE = 2001,
36
    OP_INSERT = 2002,
37
    RESERVED = 2003,
38
    OP_QUERY = 2004,
39
    OP_GET_MORE = 2005,
40
    OP_DELETE = 2006,
41
    OP_KILL_CURSORS = 2007,
42
    OP_MSG = 2013
43
  };
44
45
struct mongo_message_header
46
{
47
  uint32_t message_length;
48
  uint32_t request_id;
49
  uint32_t response_to;
50
  uint32_t op_code; /* enum mongo_opcodes */
51
};
52
53
static void set_mongodb_detected(struct ndpi_detection_module_struct *ndpi_struct,
54
55
         struct ndpi_flow_struct *flow) {
55
56
55
  if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
57
55
    ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MONGODB, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
58
55
  }
59
55
}
60
61
62
/*************************************************************************************************/
63
64
static void ndpi_check_mongodb(struct ndpi_detection_module_struct *ndpi_struct,
65
84.0k
             struct ndpi_flow_struct *flow) {
66
84.0k
  struct mongo_message_header mongodb_hdr;
67
84.0k
  struct ndpi_packet_struct *packet = &ndpi_struct->packet;
68
84.0k
  uint32_t responseFlags;
69
70
84.0k
  if (packet->payload_packet_len <= sizeof(mongodb_hdr)) {
71
31.0k
    NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
72
31.0k
    return;
73
31.0k
  }
74
75
52.9k
  memcpy(&mongodb_hdr, packet->payload, sizeof(struct mongo_message_header));
76
77
  /* All MongoDB numbers are in host byte order */
78
  // mongodb_hdr.message_length = ntohl(mongodb_hdr.message_length);
79
80
52.9k
  if((le32toh(mongodb_hdr.message_length) < 4)
81
52.9k
     || (le32toh(mongodb_hdr.message_length) > 1000000) /* Used to avoid false positives */
82
52.9k
     ) {
83
46.9k
    NDPI_LOG_DBG(ndpi_struct, "Invalid MONGODB length");
84
46.9k
    NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
85
46.9k
    return;
86
46.9k
  }
87
88
6.01k
  switch(le32toh(mongodb_hdr.op_code)) {
89
0
  case OP_UPDATE:
90
3
  case OP_INSERT:
91
5
  case RESERVED:
92
37
  case OP_QUERY:
93
38
  case OP_GET_MORE:
94
41
  case OP_DELETE:
95
42
  case OP_KILL_CURSORS:
96
44
  case OP_MSG:
97
44
    set_mongodb_detected(ndpi_struct, flow);
98
44
    break;
99
348
  case OP_REPLY:
100
    /* struct {
101
         MsgHeader header;         // standard message header
102
         int32     responseFlags;  // bit vector - see details below
103
         int64     cursorID;       // cursor id if client needs to do get more's
104
         int32     startingFrom;   // where in the cursor this reply is starting
105
         int32     numberReturned; // number of documents in the reply
106
         document* documents;      // documents
107
       }
108
    */
109
348
    if(packet->payload_packet_len > sizeof(mongodb_hdr) + 20) {
110
64
      responseFlags = le32toh(*(uint32_t *)(packet->payload + sizeof(mongodb_hdr)));
111
64
      if((responseFlags & 0xFFFFFFF0) == 0)
112
11
        set_mongodb_detected(ndpi_struct, flow);
113
64
    }
114
348
    break;
115
116
5.62k
  default:
117
5.62k
    NDPI_LOG_DBG(ndpi_struct, "Invalid MONGODB length");
118
5.62k
    NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
119
5.62k
    break;
120
6.01k
  }
121
6.01k
}
122
123
static void ndpi_search_mongodb(struct ndpi_detection_module_struct *ndpi_struct,
124
        struct ndpi_flow_struct *flow)
125
84.0k
{
126
  // Break after 6 packets.
127
84.0k
  if(flow->packet_counter > 6) {
128
25
    NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
129
25
    return;
130
25
  }
131
132
84.0k
  NDPI_LOG_DBG(ndpi_struct, "search MongoDB\n");
133
84.0k
  ndpi_check_mongodb(ndpi_struct, flow);
134
135
84.0k
  return;
136
84.0k
}
137
138
/* ********************************* */
139
140
141
void init_mongodb_dissector(struct ndpi_detection_module_struct *ndpi_struct,
142
16.7k
          u_int32_t *id) {
143
16.7k
  ndpi_set_bitmask_protocol_detection("MongoDB", ndpi_struct,
144
16.7k
              *id, NDPI_PROTOCOL_MONGODB, ndpi_search_mongodb,
145
16.7k
              NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
146
16.7k
              SAVE_DETECTION_BITMASK_AS_UNKNOWN,
147
16.7k
              ADD_TO_DETECTION_BITMASK);
148
149
16.7k
  *id += 1;
150
16.7k
}