aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNardi Ivan <nardi.ivan@gmail.com>2024-01-09 08:41:44 +0100
committerIvan Nardi <12729895+IvanNardi@users.noreply.github.com>2024-01-18 10:21:24 +0100
commitd72a760ac3895dd8a0bd3e55d4b51f9e22e04e6c (patch)
treec00c477a043b58c5c05f4afe6b5ecde5864011df /src
parentca7df1db82e97954724f547c5966a5f99ad86e6b (diff)
New API for library configuration
This is the first step into providing (more) configuration options in nDPI. The idea is to have a simple way to configure (most of) nDPI: only one function (`ndpi_set_config()`) to set any configuration parameters (in the present or on in the future) and we try to keep this function prototype as agnostic as possible. You can configure the library: * via API, using `ndpi_set_config()` * via a configuration file, in a text format This way, anytime we need to add a new configuration parameter: * we don't need to add two public functions (a getter and a setter) * we don't break API/ABI compatibility of the library; even changing the parameter type (from integer to a list of integer, for example) doesn't break the compatibility. The complete list of configuration options is provided in `doc/configuration_parameters.md`. As a first example, two configuration knobs are provided: * the ability to enable/disable the extraction of the sha1 fingerprint of the TLS certificates. * the upper limit on the number of packets per flow that will be subject to inspection
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_api.h9
-rw-r--r--src/include/ndpi_define.h.in1
-rw-r--r--src/include/ndpi_private.h17
-rw-r--r--src/include/ndpi_typedefs.h9
-rw-r--r--src/include/ndpi_win32.h4
-rw-r--r--src/lib/ndpi_main.c454
-rw-r--r--src/lib/protocols/tls.c60
7 files changed, 507 insertions, 47 deletions
diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h
index 8bec8e3eb..3a5c7eccc 100644
--- a/src/include/ndpi_api.h
+++ b/src/include/ndpi_api.h
@@ -2246,6 +2246,15 @@ extern "C" {
/* ******************************* */
+ ndpi_cfg_error ndpi_set_config(struct ndpi_detection_module_struct *ndpi_str,
+ const char *proto, const char *param, const char *value);
+ char *ndpi_get_config(struct ndpi_detection_module_struct *ndpi_str,
+ const char *proto, const char *param, char *buf, int buf_len);
+ char *ndpi_dump_config(struct ndpi_detection_module_struct *ndpi_str,
+ FILE *fd);
+
+ /* ******************************* */
+
/* Can't call libc functions from kernel space, define some stub instead */
#define ndpi_isalpha(ch) (((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z'))
diff --git a/src/include/ndpi_define.h.in b/src/include/ndpi_define.h.in
index 3a5585f12..3ec09ebdd 100644
--- a/src/include/ndpi_define.h.in
+++ b/src/include/ndpi_define.h.in
@@ -153,7 +153,6 @@
/* misc definitions */
#define NDPI_DEFAULT_MAX_TCP_RETRANSMISSION_WINDOW_SIZE 0x10000
-#define NDPI_DEFAULT_MAX_NUM_PKTS_PER_FLOW_TO_DISSECT 32
/* TODO: rebuild all memory areas to have a more aligned memory block here */
diff --git a/src/include/ndpi_private.h b/src/include/ndpi_private.h
index df3bfaf2c..d4ff2461f 100644
--- a/src/include/ndpi_private.h
+++ b/src/include/ndpi_private.h
@@ -144,13 +144,24 @@ typedef struct {
} nbpf_filter;
#endif
+#define CFG_MAX_LEN 256
+
+struct ndpi_detection_module_config_struct {
+ int max_packets_to_process;
+
+ char filename_config[CFG_MAX_LEN];
+
+ /* Protocols */
+
+ int tls_sha1_fingerprint_enabled;
+};
+
struct ndpi_detection_module_struct {
NDPI_PROTOCOL_BITMASK detection_bitmask;
u_int64_t current_ts;
- u_int16_t max_packets_to_process;
u_int16_t num_tls_blocks_to_follow;
- u_int8_t skip_tls_blocks_until_change_cipher:1, _notused:7;
+ u_int8_t skip_tls_blocks_until_change_cipher:1, finalized:1, _notused:6;
u_int8_t tls_certificate_expire_in_x_days;
void *user_data;
@@ -226,6 +237,8 @@ struct ndpi_detection_module_struct {
u_int8_t ip_version_limit;
+ struct ndpi_detection_module_config_struct cfg;
+
/* NDPI_PROTOCOL_TINC */
struct cache *tinc_cache;
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index 792aea9ee..3ed4ee50c 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -234,6 +234,14 @@ typedef enum {
ndpi_leaf
} ndpi_VISIT;
+typedef enum {
+ NDPI_CFG_INVALID_CONTEXT = -1,
+ NDPI_CFG_NOT_FOUND = -2,
+ NDPI_CFG_INVALID_PARAM = -3,
+ NDPI_CFG_CONTEXT_ALREADY_INITIALIZED = -4,
+
+ NDPI_CFG_OK = 0,
+} ndpi_cfg_error;
/* NDPI_MASK_SIZE */
typedef u_int32_t ndpi_ndpi_mask;
@@ -1065,7 +1073,6 @@ typedef enum {
typedef enum {
ndpi_pref_direction_detect_disable = 0,
- ndpi_pref_max_packets_to_process,
ndpi_pref_enable_tls_block_dissection, /* nDPI considers only those blocks past the certificate exchange */
} ndpi_detection_preference;
diff --git a/src/include/ndpi_win32.h b/src/include/ndpi_win32.h
index 2ad8602aa..c6b3290f6 100644
--- a/src/include/ndpi_win32.h
+++ b/src/include/ndpi_win32.h
@@ -59,6 +59,10 @@
#define strdup _strdup
#endif
+#ifndef F_OK
+#define F_OK 0
+#endif
+
extern char* strsep(char **sp, char *sep);
typedef unsigned char u_char;
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 28c53714f..bc850df64 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -224,6 +224,8 @@ static int ndpi_callback_init(struct ndpi_detection_module_struct *ndpi_str);
static void ndpi_enabled_callbacks_init(struct ndpi_detection_module_struct *ndpi_str,
const NDPI_PROTOCOL_BITMASK *dbm, int count_only);
+static void set_default_config(struct ndpi_detection_module_config_struct *cfg);
+
/* ****************************************** */
ndpi_custom_dga_predict_fctn ndpi_dga_function = NULL;
@@ -977,13 +979,6 @@ int ndpi_set_detection_preferences(struct ndpi_detection_module_struct *ndpi_str
ndpi_str->skip_tls_blocks_until_change_cipher = 1;
break;
- case ndpi_pref_max_packets_to_process:
- if(value > 0xFFFF) {
- return(-1);
- }
- ndpi_str->max_packets_to_process = value;
- break;
-
default:
return(-1);
}
@@ -3154,9 +3149,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs
if((ndpi_str->protocols_ptree = ndpi_patricia_new(32 /* IPv4 */)) == NULL ||
(ndpi_str->protocols_ptree6 = ndpi_patricia_new(128 /* IPv6 */)) == NULL) {
NDPI_LOG_ERR(ndpi_str, "[NDPI] Error allocating tree\n");
- if(ndpi_str->protocols_ptree != NULL)
- ndpi_patricia_destroy(ndpi_str->protocols_ptree, free_ptree_data);
- ndpi_free(ndpi_str);
+ ndpi_exit_detection_module(ndpi_str);
return NULL;
}
ndpi_init_ptree_ipv4(ndpi_str, ndpi_str->protocols_ptree, host_protocol_list);
@@ -3297,7 +3290,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs
if((ndpi_str->ip_risk_ptree = ndpi_patricia_new(32 /* IPv4 */)) == NULL ||
(ndpi_str->ip_risk_ptree6 = ndpi_patricia_new(128 /* IPv6 */)) == NULL) {
- NDPI_LOG_ERR(ndpi_str, "[NDPI] Error allocating tree\n");
+ NDPI_LOG_ERR(ndpi_str, "[NDPI] Error allocating risk tree\n");
ndpi_exit_detection_module(ndpi_str);
return NULL;
}
@@ -3315,7 +3308,8 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs
}
}
- ndpi_str->max_packets_to_process = NDPI_DEFAULT_MAX_NUM_PKTS_PER_FLOW_TO_DISSECT;
+
+ set_default_config(&ndpi_str->cfg);
NDPI_BITMASK_SET_ALL(ndpi_str->detection_bitmask);
ndpi_str->user_data = NULL;
@@ -3525,6 +3519,8 @@ void ndpi_finalize_initialization(struct ndpi_detection_module_struct *ndpi_str)
if(!ndpi_str)
return;
+ if(ndpi_str->finalized) /* Already finalized */
+ return;
ndpi_add_domain_risk_exceptions(ndpi_str);
@@ -3608,6 +3604,10 @@ void ndpi_finalize_initialization(struct ndpi_detection_module_struct *ndpi_str)
}
ndpi_str->ac_automa_finalized = 1;
+
+ ndpi_str->finalized = 1;
+
+ return;
}
/* *********************************************** */
@@ -4514,6 +4514,76 @@ static int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,
/*
* Format:
*
+ * <proto,param,value>
+ *
+ * Notes:
+ * - proto might be empty
+ * - empty lines or lines starting with # are ignored
+ */
+int load_config_file_fd(struct ndpi_detection_module_struct *ndpi_str, FILE *fd) {
+ char buffer[512], *line, *proto, *param = NULL, *value, *saveptr;
+ int len, i, num_commas;
+ ndpi_cfg_error rc;
+
+ if(!ndpi_str || !fd)
+ return -1;
+
+ while(1) {
+ line = fgets(buffer, sizeof(buffer), fd);
+
+ if(line == NULL)
+ break;
+
+ len = strlen(line);
+
+ if((len <= 1) || (line[0] == '#'))
+ continue;
+
+ line[len - 1] = '\0';
+
+ /* First parameter might be missing */
+ num_commas = 0;
+ for(i = 0; i < len; i++) {
+ if(line[i] == ',')
+ num_commas++;
+ }
+
+ if(num_commas == 1) {
+ proto = NULL;
+ param = strtok_r(line, ",", &saveptr);
+ } else if(num_commas == 2) {
+ proto = strtok_r(line, ",", &saveptr);
+ if(proto) {
+ param = strtok_r(NULL, ",", &saveptr);
+ }
+ } else {
+ NDPI_LOG_ERR(ndpi_str, "Error parsing [%s]\n", line);
+ continue;
+ }
+
+ if(param) {
+ value = strtok_r(NULL, ",", &saveptr);
+ if(value) {
+ rc = ndpi_set_config(ndpi_str, proto, param, value);
+ if(rc < NDPI_CFG_OK) {
+ NDPI_LOG_ERR(ndpi_str, "Error ndpi_set_config [%s/%s/%s]: %d\n",
+ proto, param, value, rc);
+ return rc;
+ }
+ continue;
+ }
+ }
+ NDPI_LOG_ERR(ndpi_str, "Error parsing [%s]\n", line);
+ return -2;
+ }
+ return 0;
+}
+
+/* ******************************************************************** */
+
+/*
+ * Format:
+ *
* <host|ip> <category_id>
*
* Notes:
@@ -7879,7 +7949,7 @@ static ndpi_protocol ndpi_internal_detection_process_packet(struct ndpi_detectio
memset(&ret, 0, sizeof(ret));
- if((!flow) || (!ndpi_str))
+ if((!flow) || (!ndpi_str) || (ndpi_str->finalized != 1))
return(ret);
packet = &ndpi_str->packet;
@@ -7898,7 +7968,7 @@ static ndpi_protocol ndpi_internal_detection_process_packet(struct ndpi_detectio
return(ret);
}
- if(ndpi_str->max_packets_to_process > 0 && flow->num_processed_pkts >= ndpi_str->max_packets_to_process) {
+ if(ndpi_str->cfg.max_packets_to_process > 0 && flow->num_processed_pkts >= ndpi_str->cfg.max_packets_to_process) {
flow->extra_packets_func = NULL; /* To allow ndpi_extra_dissection_possible() to fail */
flow->fail_with_unknown = 1;
return(ret); /* Avoid spending too much time with this flow */
@@ -10685,3 +10755,359 @@ void *ndpi_get_user_data(struct ndpi_detection_module_struct *ndpi_str)
return ndpi_str->user_data;
return NULL;
}
+
+/* ******************************************************************** */
+
+static u_int16_t __get_proto_id(const char *proto_name_or_id)
+{
+ struct ndpi_detection_module_struct *module;
+ NDPI_PROTOCOL_BITMASK all;
+ u_int16_t proto_id;
+ char *endptr;
+ long val;
+
+ /* Let try to decode the string as numerical protocol id */
+ /* We can't easily use ndpi_strtonum because we want to be sure that there are no
+ others characters after the number */
+ errno = 0; /* To distinguish success/failure after call */
+ val = strtol(proto_name_or_id, &endptr, 10);
+ if(errno == 0 && *endptr == '\0' &&
+ (val >= 0 && val < NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) {
+ return val;
+
+ }
+
+ /* Try to decode the string as protocol name */
+ /* Use a temporary module with all protocols enabled */
+ module = ndpi_init_detection_module(ndpi_no_prefs);
+ if(!module)
+ return -1;
+ NDPI_BITMASK_SET_ALL(all);
+ ndpi_set_protocol_detection_bitmask2(module, &all);
+ /* Try to be fast: we need only the protocol name -> protocol id mapping! */
+ /* TODO */
+ ndpi_set_config(module, "any", "ip_list.load", "0");
+ ndpi_set_config(module, NULL, "flow_risk_lists.load", "0");
+ ndpi_finalize_initialization(module);
+ proto_id = ndpi_get_proto_by_name(module, proto_name_or_id);
+ ndpi_exit_detection_module(module);
+
+ return proto_id;
+}
+
+static ndpi_cfg_error _set_param_enable_disable(struct ndpi_detection_module_struct *ndpi_str,
+ void *_variable, const char *value,
+ const char *min_value, const char *max_value,
+ const char *proto)
+{
+ int *variable = (int *)_variable;
+
+ if(strcmp(value, "1") == 0 ||
+ strcmp(value, "enable") == 0) {
+ *variable = 1;
+ return NDPI_CFG_OK;
+ }
+ if(strcmp(value, "0") == 0 ||
+ strcmp(value, "disable") == 0) {
+ *variable = 0;
+ return NDPI_CFG_OK;
+ }
+ return NDPI_CFG_INVALID_PARAM;
+}
+
+static ndpi_cfg_error _set_param_int(struct ndpi_detection_module_struct *ndpi_str,
+ void *_variable, const char *value,
+ const char *min_value, const char *max_value,
+ const char *proto)
+{
+ int *variable = (int *)_variable;
+ const char *errstrp;
+ long val;
+
+ val = ndpi_strtonum(value, LONG_MIN, LONG_MAX, &errstrp, 0);
+ if(errstrp) {
+ return NDPI_CFG_INVALID_PARAM;
+ }
+
+ *variable = val;
+
+ /* Min and max values are set in the code, so we can convert them
+ to integers without too many checks...*/
+ if(min_value && max_value &&
+ (val < strtol(min_value, NULL, 0) || val > strtol(max_value, NULL, 0)))
+ return NDPI_CFG_INVALID_PARAM;
+
+ return NDPI_CFG_OK;
+}
+
+static char *_get_param_int(void *_variable, const char *proto, char *buf, int buf_len)
+{
+ int *variable = (int *)_variable;
+
+ snprintf(buf, buf_len, "%d", *variable);
+ buf[buf_len - 1] = '\0';
+ return buf;
+}
+
+static char *_get_param_string(void *_variable, const char *proto, char *buf, int buf_len)
+{
+ char *variable = (char *)_variable;
+
+ snprintf(buf, buf_len, "%s", variable);
+ buf[buf_len - 1] = '\0';
+ return buf;
+}
+
+static ndpi_cfg_error _set_param_filename(struct ndpi_detection_module_struct *ndpi_str,
+ void *_variable, const char *value,
+ const char *min_value, const char *max_value,
+ const char *proto)
+{
+ char *variable = (char *)_variable;
+
+ if(value == NULL) { /* Valid value */
+ variable[0] = '\0';
+ return NDPI_CFG_OK;
+ }
+
+ if(access(value, F_OK) != 0)
+ return NDPI_CFG_INVALID_PARAM;
+ strncpy(variable, value, CFG_MAX_LEN);
+ return NDPI_CFG_OK;
+}
+
+static ndpi_cfg_error _set_param_filename_config(struct ndpi_detection_module_struct *ndpi_str,
+ void *_variable, const char *value,
+ const char *min_value, const char *max_value,
+ const char *proto)
+{
+ int rc;
+ FILE *fd;
+
+ rc = _set_param_filename(ndpi_str, _variable, value, min_value, max_value, proto);
+ if(rc != 0 || value == NULL || ndpi_str == NULL)
+ return rc;
+
+ fd = fopen(value, "r");
+ if(fd == NULL)
+ return NDPI_CFG_INVALID_PARAM; /* It shoudn't happen because we already checked it */
+ rc = load_config_file_fd(ndpi_str, fd);
+ fclose(fd);
+ if(rc < 0)
+ return rc;
+
+ return NDPI_CFG_OK;
+}
+
+
+static char *_get_param_protocol_enable_disable(void *_variable, const char *proto, char *buf, int buf_len)
+{
+ NDPI_PROTOCOL_BITMASK *bitmask = (NDPI_PROTOCOL_BITMASK *)_variable;
+ u_int16_t proto_id;
+
+ proto_id = __get_proto_id(proto);
+ if(proto_id == NDPI_PROTOCOL_UNKNOWN)
+ return NULL;
+
+ snprintf(buf, buf_len, "%d", !!NDPI_ISSET(bitmask, proto_id));
+ buf[buf_len - 1] = '\0';
+ return buf;
+}
+
+static ndpi_cfg_error _set_param_protocol_enable_disable(struct ndpi_detection_module_struct *ndpi_str,
+ void *_variable, const char *value,
+ const char *min_value, const char *max_value,
+ const char *proto)
+{
+ NDPI_PROTOCOL_BITMASK *bitmask = (NDPI_PROTOCOL_BITMASK *)_variable;
+ u_int16_t proto_id;
+
+ if(strcmp(proto, "any") == 0 ||
+ strcmp(proto, "all") == 0 ||
+ strcmp(proto, "$PROTO_NAME_OR_ID") == 0) {
+ if(strcmp(value, "1") == 0 ||
+ strcmp(value, "enable") == 0) {
+ NDPI_BITMASK_SET_ALL(*bitmask);
+ return NDPI_CFG_OK;
+ }
+ if(strcmp(value, "0") == 0 ||
+ strcmp(value, "disable") == 0) {
+ NDPI_BITMASK_RESET(*bitmask);
+ return NDPI_CFG_OK;
+ }
+ }
+
+ proto_id = __get_proto_id(proto);
+ if(proto_id == NDPI_PROTOCOL_UNKNOWN)
+ return NDPI_CFG_INVALID_PARAM;
+
+ if(strcmp(value, "1") == 0 ||
+ strcmp(value, "enable") == 0) {
+ NDPI_BITMASK_ADD(*bitmask, proto_id);
+ return NDPI_CFG_OK;
+ }
+ if(strcmp(value, "0") == 0 ||
+ strcmp(value, "disable") == 0) {
+ NDPI_BITMASK_DEL(*bitmask, proto_id);
+ return NDPI_CFG_OK;
+ }
+ return NDPI_CFG_INVALID_PARAM;
+}
+
+
+enum cfg_param_type {
+ CFG_PARAM_ENABLE_DISABLE = 0,
+ CFG_PARAM_INT,
+ CFG_PARAM_PROTOCOL_ENABLE_DISABLE,
+ CFG_PARAM_FILENAME_CONFIG, /* We call ndpi_set_config() immediately for each row in it */
+};
+
+typedef ndpi_cfg_error (*cfg_set)(struct ndpi_detection_module_struct *ndpi_str,
+ void *_variable, const char *value,
+ const char *min_value, const char *max_value,
+ const char *proto);
+typedef char *(*cfg_get)(void *_variable, const char *proto, char *buf, int buf_len);
+
+static const struct cfg_op {
+ enum cfg_param_type type;
+ cfg_set fn_set;
+ cfg_get fn_get;
+} cfg_ops[] = {
+ { CFG_PARAM_ENABLE_DISABLE, _set_param_enable_disable, _get_param_int },
+ { CFG_PARAM_INT, _set_param_int, _get_param_int },
+ { CFG_PARAM_PROTOCOL_ENABLE_DISABLE, _set_param_protocol_enable_disable, _get_param_protocol_enable_disable },
+ { CFG_PARAM_FILENAME_CONFIG, _set_param_filename_config, _get_param_string },
+};
+
+#define __OFF(a) offsetof(struct ndpi_detection_module_config_struct, a)
+
+static const struct cfg_param {
+ char *proto;
+ char *param;
+ char *default_value;
+ char *min_value;
+ char *max_value;
+ enum cfg_param_type type;
+ int offset;
+} cfg_params[] = {
+ /* Per-protocol parameters */
+
+ { "tls", "metadata.sha1_fingerprint.enable", "1", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(tls_sha1_fingerprint_enabled) },
+
+ /* Global parameters */
+
+ { NULL, "packets_limit_per_flow", "32", "0", "255", CFG_PARAM_INT, __OFF(max_packets_to_process) },
+
+ { NULL, "filename.config", NULL, NULL, NULL, CFG_PARAM_FILENAME_CONFIG, __OFF(filename_config) },
+
+ { NULL, NULL, NULL, NULL, NULL, 0, -1 },
+};
+
+#undef __OFF
+
+static void set_default_config(struct ndpi_detection_module_config_struct *cfg)
+{
+ const struct cfg_param *c;
+
+ for(c = &cfg_params[0]; c && c->param; c++) {
+ cfg_ops[c->type].fn_set(NULL, (void *)((char *)cfg + c->offset),
+ c->default_value, c->min_value, c->max_value, c->proto);
+ }
+}
+
+ndpi_cfg_error ndpi_set_config(struct ndpi_detection_module_struct *ndpi_str,
+ const char *proto, const char *param, const char *value)
+{
+ const struct cfg_param *c;
+ ndpi_cfg_error rc;
+
+ if(!ndpi_str || !param || !value)
+ return NDPI_CFG_INVALID_CONTEXT;
+ if(ndpi_str->finalized)
+ return NDPI_CFG_CONTEXT_ALREADY_INITIALIZED;
+
+ NDPI_LOG_DBG(ndpi_str, "Set [%s][%s][%s]\n", proto, param, value);
+
+ for(c = &cfg_params[0]; c && c->param; c++) {
+ if((((proto == NULL && c->proto == NULL) ||
+ (proto && c->proto && strcmp(proto, c->proto) == 0)) &&
+ strcmp(param, c->param) == 0) ||
+ (proto && c->proto &&
+ strcmp(c->proto, "$PROTO_NAME_OR_ID") == 0 &&
+ strcmp(param, c->param) == 0)) {
+
+ rc = cfg_ops[c->type].fn_set(ndpi_str, (void *)((char *)&ndpi_str->cfg + c->offset),
+ value, c->min_value, c->max_value, proto);
+ return rc;
+ }
+ }
+ return NDPI_CFG_NOT_FOUND;
+}
+
+char *ndpi_get_config(struct ndpi_detection_module_struct *ndpi_str,
+ const char *proto, const char *param, char *buf, int buf_len)
+{
+ const struct cfg_param *c;
+
+ if(!ndpi_str || !param || !buf || buf_len <= 0)
+ return NULL;
+
+ NDPI_LOG_ERR(ndpi_str, "Get [%s][%s]\n", proto, param);
+
+ for(c = &cfg_params[0]; c && c->param; c++) {
+ if(((proto == NULL && c->proto == NULL) ||
+ (proto && c->proto && strcmp(proto, c->proto) == 0)) &&
+ strcmp(param, c->param) == 0) {
+
+ return cfg_ops[c->type].fn_get((void *)((char *)&ndpi_str->cfg + c->offset), proto, buf, buf_len);
+ }
+ }
+ return NULL;
+}
+
+char *ndpi_dump_config(struct ndpi_detection_module_struct *ndpi_str,
+ FILE *fd)
+{
+ const struct cfg_param *c;
+ char buf[64];
+
+ if(!ndpi_str || !fd)
+ return NULL;
+
+ fprintf(fd, " Protocol (empty/NULL for global knobs), parameter, value, [default value], [min value, max_value]\n");
+
+ /* TODO */
+ for(c = &cfg_params[0]; c && c->param; c++) {
+ switch(c->type) {
+ case CFG_PARAM_ENABLE_DISABLE:
+ case CFG_PARAM_INT:
+ fprintf(fd, " *) %s %s: %s [%s]",
+ c->proto ? c->proto : "NULL",
+ c->param,
+ _get_param_int((void *)((char *)&ndpi_str->cfg + c->offset), c->proto, buf, sizeof(buf)),
+ c->default_value);
+ if(c->min_value && c->max_value)
+ fprintf(fd, " [%s-%s]", c->min_value, c->max_value);
+ fprintf(fd, "\n");
+ break;
+ case CFG_PARAM_FILENAME_CONFIG:
+ fprintf(fd, " *) %s %s: %s [%s]",
+ c->proto ? c->proto : "NULL",
+ c->param,
+ _get_param_string((void *)((char *)&ndpi_str->cfg + c->offset), c->proto, buf, sizeof(buf)),
+ c->default_value);
+ fprintf(fd, "\n");
+ break;
+ /* TODO */
+ case CFG_PARAM_PROTOCOL_ENABLE_DISABLE:
+ fprintf(fd, " *) %s %s: %s [all %s]",
+ c->proto ? c->proto : "NULL",
+ c->param,
+ /* TODO */ _get_param_protocol_enable_disable((void *)((char *)&ndpi_str->cfg + c->offset), "any", buf, sizeof(buf)),
+ c->default_value);
+ fprintf(fd, "\n");
+ break;
+ }
+ }
+ return NULL;
+}
diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c
index 485357e06..943b817a4 100644
--- a/src/lib/protocols/tls.c
+++ b/src/lib/protocols/tls.c
@@ -772,7 +772,6 @@ int processCertificate(struct ndpi_detection_module_struct *ndpi_struct,
u_int32_t certificates_length, length = (packet->payload[1] << 16) + (packet->payload[2] << 8) + packet->payload[3];
u_int32_t certificates_offset = 7 + (is_dtls ? 8 : 0);
u_int8_t num_certificates_found = 0;
- SHA1_CTX srv_cert_fingerprint_ctx ;
#ifdef DEBUG_TLS
printf("[TLS] %s() [payload_packet_len=%u][direction: %u][%02X %02X %02X %02X %02X %02X...]\n",
@@ -824,9 +823,6 @@ int processCertificate(struct ndpi_detection_module_struct *ndpi_struct,
#endif
if(num_certificates_found++ == 0) /* Dissect only the first certificate that is the one we care */ {
- /* For SHA-1 we take into account only the first certificate and not all of them */
-
- SHA1Init(&srv_cert_fingerprint_ctx);
#ifdef DEBUG_CERTIFICATE_HASH
{
@@ -839,36 +835,42 @@ int processCertificate(struct ndpi_detection_module_struct *ndpi_struct,
}
#endif
- SHA1Update(&srv_cert_fingerprint_ctx,
- &packet->payload[certificates_offset],
- certificate_len);
-
- SHA1Final(flow->protos.tls_quic.sha1_certificate_fingerprint, &srv_cert_fingerprint_ctx);
-
- flow->protos.tls_quic.fingerprint_set = 1;
-
- uint8_t * sha1 = flow->protos.tls_quic.sha1_certificate_fingerprint;
- const size_t sha1_siz = sizeof(flow->protos.tls_quic.sha1_certificate_fingerprint);
- char sha1_str[20 /* sha1_siz */ * 2 + 1];
- static const char hexalnum[] = "0123456789ABCDEF";
- size_t i;
- for (i = 0; i < sha1_siz; ++i) {
- u_int8_t lower = (sha1[i] & 0x0F);
- u_int8_t upper = (sha1[i] & 0xF0) >> 4;
- sha1_str[i*2] = hexalnum[upper];
- sha1_str[i*2 + 1] = hexalnum[lower];
- }
- sha1_str[sha1_siz * 2] = '\0';
+ /* For SHA-1 we take into account only the first certificate and not all of them */
+ if(ndpi_struct->cfg.tls_sha1_fingerprint_enabled) {
+ SHA1_CTX srv_cert_fingerprint_ctx ;
+
+ SHA1Init(&srv_cert_fingerprint_ctx);
+ SHA1Update(&srv_cert_fingerprint_ctx,
+ &packet->payload[certificates_offset],
+ certificate_len);
+
+ SHA1Final(flow->protos.tls_quic.sha1_certificate_fingerprint, &srv_cert_fingerprint_ctx);
+
+ flow->protos.tls_quic.fingerprint_set = 1;
+
+ uint8_t * sha1 = flow->protos.tls_quic.sha1_certificate_fingerprint;
+ const size_t sha1_siz = sizeof(flow->protos.tls_quic.sha1_certificate_fingerprint);
+ char sha1_str[20 /* sha1_siz */ * 2 + 1];
+ static const char hexalnum[] = "0123456789ABCDEF";
+ size_t i;
+ for (i = 0; i < sha1_siz; ++i) {
+ u_int8_t lower = (sha1[i] & 0x0F);
+ u_int8_t upper = (sha1[i] & 0xF0) >> 4;
+ sha1_str[i*2] = hexalnum[upper];
+ sha1_str[i*2 + 1] = hexalnum[lower];
+ }
+ sha1_str[sha1_siz * 2] = '\0';
#ifdef DEBUG_TLS
- printf("[TLS] SHA-1: %s\n", sha1_str);
+ printf("[TLS] SHA-1: %s\n", sha1_str);
#endif
- if(ndpi_struct->malicious_sha1_hashmap != NULL) {
- u_int16_t rc1 = ndpi_hash_find_entry(ndpi_struct->malicious_sha1_hashmap, sha1_str, sha1_siz * 2, NULL);
+ if(ndpi_struct->malicious_sha1_hashmap != NULL) {
+ u_int16_t rc1 = ndpi_hash_find_entry(ndpi_struct->malicious_sha1_hashmap, sha1_str, sha1_siz * 2, NULL);
- if(rc1 == 0)
- ndpi_set_risk(ndpi_struct, flow, NDPI_MALICIOUS_SHA1_CERTIFICATE, sha1_str);
+ if(rc1 == 0)
+ ndpi_set_risk(ndpi_struct, flow, NDPI_MALICIOUS_SHA1_CERTIFICATE, sha1_str);
+ }
}
processCertificateElements(ndpi_struct, flow, certificates_offset, certificate_len);