ndpi: add ndpi.license configuration option

nDPI 6.0 requires the application to declare under which license the
library is used and, for for-profit use without an agreement with
ntop, does not load its dual-licensed dissectors (DHCP, DNS, QUIC and
TLS as of 6.0), so rules on those protocols never fire.

Expose this as "ndpi.license" with the values not-for-profit (the
default), for-profit and for-profit-dual. An invalid value is fatal.
Older nDPI releases accept and ignore the option with a warning.

Ticket: 8077
pull/16354/head
TripleA150 1 month ago
parent bb3b033506
commit d1e9db7bb8

@ -35,18 +35,30 @@
#error "the nDPI plugin requires nDPI 4.12 or later"
#endif
/**
* \brief Allocate a detection module.
*
* nDPI 6.0 requires the embedding application to declare under which
* license it uses the library. Not-for-profit use enables every dissector.
*/
/* nDPI 6.0 requires the embedding application to declare under which
* license it uses the library; earlier releases have no notion of it. */
#if NDPI_MAJOR >= 6
#define NDPI_COMPAT_HAS_LICENSE 1
typedef enum ndpi_license_type NdpiCompatLicense;
#define NDPI_COMPAT_LICENSE_NOT_FOR_PROFIT NDPI_LICENSE_NOT_FOR_PROFIT_LGPL
#define NDPI_COMPAT_LICENSE_FOR_PROFIT NDPI_LICENSE_FOR_PROFIT_LGPL
#define NDPI_COMPAT_LICENSE_FOR_PROFIT_DUAL NDPI_LICENSE_FOR_PROFIT_DUAL_LICENSE
#else
#define NDPI_COMPAT_HAS_LICENSE 0
/* placeholder so the license plumbing builds, the value is ignored */
typedef int NdpiCompatLicense;
#define NDPI_COMPAT_LICENSE_NOT_FOR_PROFIT 0
#endif
/* Allocate a detection module. The license is ignored on nDPI releases
* predating the declaration. */
static inline struct ndpi_detection_module_struct *NdpiCompatInitModule(
struct ndpi_global_context *g_ctx)
struct ndpi_global_context *g_ctx, NdpiCompatLicense license)
{
#if NDPI_MAJOR >= 6
return ndpi_init_detection_module(g_ctx, NDPI_LICENSE_NOT_FOR_PROFIT_LGPL);
#if NDPI_COMPAT_HAS_LICENSE
return ndpi_init_detection_module(g_ctx, license);
#else
(void)license;
return ndpi_init_detection_module(g_ctx);
#endif
}

@ -22,6 +22,7 @@
#include "suricata-common.h"
#include "suricata-plugin.h"
#include "conf.h"
#include "detect-engine-helper.h"
#include "detect-parse.h"
#include "flow.h"
@ -39,6 +40,7 @@ static SCFlowStorageId flow_storage_id = { .id = -1 };
static int ndpi_protocol_keyword_id = -1;
static int ndpi_risk_keyword_id = -1;
static struct ndpi_global_context *ndpi_g_ctx = NULL;
static NdpiCompatLicense ndpi_license = NDPI_COMPAT_LICENSE_NOT_FOR_PROFIT;
struct NdpiThreadContext {
struct ndpi_detection_module_struct *ndpi;
@ -82,6 +84,43 @@ static inline struct NdpiFlowContext *NdpiGetFlowContext(const Flow *f)
return SCFlowGetStorageById(f, flow_storage_id);
}
/**
* Resolve "ndpi.license". nDPI 6.0 does not load its dual-licensed
* dissectors (DHCP, DNS, QUIC and TLS as of 6.0) for for-profit use
* without an agreement with ntop. Not-for-profit is the default so the
* plugin works out of the box; an invalid value is fatal.
*/
static NdpiCompatLicense NdpiResolveLicense(void)
{
const char *license = NULL;
if (SCConfGet("ndpi.license", &license) != 1 || license == NULL)
return NDPI_COMPAT_LICENSE_NOT_FOR_PROFIT;
#if NDPI_COMPAT_HAS_LICENSE
if (strcmp(license, "not-for-profit") == 0)
return NDPI_COMPAT_LICENSE_NOT_FOR_PROFIT;
if (strcmp(license, "for-profit") == 0) {
SCLogWarning("ndpi.license is \"for-profit\": nDPI will not load its dual-licensed "
"dissectors (DHCP, DNS, QUIC and TLS as of nDPI 6.0)");
return NDPI_COMPAT_LICENSE_FOR_PROFIT;
}
if (strcmp(license, "for-profit-dual") == 0)
return NDPI_COMPAT_LICENSE_FOR_PROFIT_DUAL;
FatalError("invalid ndpi.license value \"%s\": expected \"not-for-profit\", "
"\"for-profit\" or \"for-profit-dual\"",
license);
#else
SCLogWarning("ndpi.license has no effect with nDPI %d.%d, the license declaration was "
"introduced in nDPI 6.0",
NDPI_MAJOR, NDPI_MINOR);
#endif
return NDPI_COMPAT_LICENSE_NOT_FOR_PROFIT;
}
/* nDPI correlates flows through LRU caches (DNS to TLS, STUN to RTP, ...)
* that are private to a detection module unless made global through a
* shared context. Suricata spreads a host's flows over all its workers,
@ -110,7 +149,7 @@ static const char *ndpi_shared_lru_caches[] = {
static struct ndpi_detection_module_struct *NdpiModuleNew(bool shared_caches)
{
struct ndpi_global_context *g_ctx = shared_caches ? ndpi_g_ctx : NULL;
struct ndpi_detection_module_struct *ndpi = NdpiCompatInitModule(g_ctx);
struct ndpi_detection_module_struct *ndpi = NdpiCompatInitModule(g_ctx, ndpi_license);
if (ndpi == NULL)
return NULL;
@ -609,6 +648,8 @@ static void NdpiInit(void)
{
SCLogDebug("Initializing nDPI plugin");
ndpi_license = NdpiResolveLicense();
/* Global context shared by the worker modules, see NdpiModuleNew().
* NULL if nDPI was built without global context support. There is
* no plugin deinit hook, so it is never released. */

@ -85,6 +85,23 @@ plugins:
@ndpi_comment@- @prefix@/lib/@PACKAGE_NAME@/ndpi.so
# - /path/to/plugin.so
# nDPI plugin settings, only used when the nDPI plugin is loaded above.
ndpi:
# nDPI 6.0 and later require the application to declare under which
# license the library is used. Has no effect with older nDPI releases.
#
# not-for-profit : not-for-profit use, every dissector is enabled.
# This is the default.
# for-profit : for-profit use without a license agreement with
# ntop. nDPI does not load its dual-licensed
# dissectors (DHCP, DNS, QUIC and TLS as of nDPI 6.0),
# so rules matching on those protocols never fire.
# for-profit-dual : for-profit use with a license agreement signed
# with ntop for the dual-licensed components.
#
# See https://www.ntop.org/announcing-ndpi-dual-license-change/
#license: not-for-profit
# Configure the type of alert (and other) logging you would like.
outputs:
# a line based alerts log similar to Snort's fast.log

Loading…
Cancel
Save