diff options
author | lucasbaile <lucasbaile14@gmail.com> | 2021-09-09 17:47:58 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-09 22:47:58 +0200 |
commit | 1fadf4754a1741e6fd690dbb65ae778fd1dc0313 (patch) | |
tree | d8a6613a5cf512c7bc1c9d6091f2828d3ceebe3f /src/lib/protocols/cassandra.c | |
parent | 36f08b8d2e947ec0877ebd3dcb160def7ec6fc54 (diff) |
Add Cassandra protocol dissector (#1285)
Co-authored-by: Lucas Santos <lucas.santos@zerum.com>
Diffstat (limited to 'src/lib/protocols/cassandra.c')
-rw-r--r-- | src/lib/protocols/cassandra.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/lib/protocols/cassandra.c b/src/lib/protocols/cassandra.c new file mode 100644 index 000000000..1072ed4b5 --- /dev/null +++ b/src/lib/protocols/cassandra.c @@ -0,0 +1,139 @@ +/* + * cassandra.c + * + * Copyright (C) 2021 by Lucas Santos <lfneiva.santos@gmail.com> + * + * This file is part of nDPI, an open source deep packet inspection + * library based on the OpenDPI and PACE technology by ipoque GmbH + * + * nDPI is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * nDPI is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with nDPI. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include "ndpi_protocol_ids.h" +#include "ndpi_api.h" + +#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_CASSANDRA +#define CASSANDRA_HEADER_LEN 9 +#define CASSANDRA_MAX_BODY_SIZE 268435456 //256MB (256 * 1024^2) + +enum cassandra_version +{ + CASSANDRA_V1_REQUEST = 0x01, + CASSANDRA_V1_RESPONSE = 0x81, + CASSANDRA_V2_REQUEST = 0x02, + CASSANDRA_V2_RESPONSE = 0x82, + CASSANDRA_V3_REQUEST = 0x03, + CASSANDRA_V3_RESPONSE = 0x83, + CASSANDRA_V4_REQUEST = 0x04, + CASSANDRA_V4_RESPONSE = 0x84 +}; + +enum cassandra_opcode +{ + CASSANDRA_ERROR = 0x00, + CASSANDRA_STARTUP = 0x01, + CASSANDRA_READY = 0x02, + CASSANDRA_AUTHENTICATE = 0x03, + CASSANDRA_OPTIONS = 0x05, + CASSANDRA_SUPPORTED = 0x06, + CASSANDRA_QUERY = 0x07, + CASSANDRA_RESULT = 0x08, + CASSANDRA_PREPARE = 0x09, + CASSANDRA_EXECUTE = 0x0A, + CASSANDRA_REGISTER = 0x0B, + CASSANDRA_EVENT = 0x0C, + CASSANDRA_BATCH = 0x0D, + CASSANDRA_AUTH_CHALLENGE = 0x0E, + CASSANDRA_AUTH_RESPONSE = 0x0F, + CASSANDRA_AUTH_SUCCESS = 0x10 +}; + +static bool ndpi_check_valid_cassandra_version(uint8_t version) +{ + switch(version) { + case CASSANDRA_V1_REQUEST: + case CASSANDRA_V1_RESPONSE: + case CASSANDRA_V2_REQUEST: + case CASSANDRA_V2_RESPONSE: + case CASSANDRA_V3_REQUEST: + case CASSANDRA_V3_RESPONSE: + case CASSANDRA_V4_REQUEST: + case CASSANDRA_V4_RESPONSE: + return true; + } + return false; +} + +static bool ndpi_check_valid_cassandra_opcode(uint8_t opcode) +{ + switch (opcode) { + case CASSANDRA_ERROR: + case CASSANDRA_STARTUP: + case CASSANDRA_READY: + case CASSANDRA_AUTHENTICATE: + case CASSANDRA_OPTIONS: + case CASSANDRA_SUPPORTED: + case CASSANDRA_QUERY: + case CASSANDRA_RESULT: + case CASSANDRA_PREPARE: + case CASSANDRA_EXECUTE: + case CASSANDRA_REGISTER: + case CASSANDRA_EVENT: + case CASSANDRA_BATCH: + case CASSANDRA_AUTH_CHALLENGE: + case CASSANDRA_AUTH_RESPONSE: + case CASSANDRA_AUTH_SUCCESS: + return true; + } + return false; +} + +void ndpi_search_cassandra(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow) +{ + struct ndpi_packet_struct *packet = &flow->packet; + + if (packet->tcp) { + if (packet->payload_packet_len >= CASSANDRA_HEADER_LEN && + ndpi_check_valid_cassandra_version(get_u_int8_t(packet->payload, 0)) && + ndpi_check_valid_cassandra_opcode(get_u_int8_t(packet->payload, 4)) && + get_u_int32_t(packet->payload, 5) <= CASSANDRA_MAX_BODY_SIZE && + get_u_int32_t(packet->payload, 5) >= (uint32_t) (packet->payload_packet_len - CASSANDRA_HEADER_LEN)) { + ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_CASSANDRA, NDPI_PROTOCOL_UNKNOWN); + return; + } + } + + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); +} + +/* ********************************* */ + + +void init_cassandra_dissector(struct ndpi_detection_module_struct *ndpi_struct, + u_int32_t *id, + NDPI_PROTOCOL_BITMASK *detection_bitmask) { + + ndpi_set_bitmask_protocol_detection("Cassandra", + ndpi_struct, detection_bitmask, + *id, + NDPI_PROTOCOL_CASSANDRA, + ndpi_search_cassandra, + NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD, + SAVE_DETECTION_BITMASK_AS_UNKNOWN, + ADD_TO_DETECTION_BITMASK); + + *id += 1; +} |